diff --git a/DEPS b/DEPS
index b018594c..57520e6 100644
--- a/DEPS
+++ b/DEPS
@@ -181,11 +181,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': '6dbd7ff34a496f362163e3f082e3d4cb357808b2',
+  'skia_revision': 'c21316a73b543f0cba5d115d5bed81852d432190',
   # 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': '1ca8124e52e346c6905b3d086a995c981dc16bc0',
+  'v8_revision': '2fff8d9182bd6ac3bace3e691ee404a192281242',
   # 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.
@@ -193,15 +193,15 @@
   # 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': '3311ef65680e5c69e2ea9913eb244b67c2189d91',
+  'angle_revision': '7dfc99e5cf6bd1781b1206ff198e1e9b2ee21f69',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '19b43a602225c5c1743c0576280b6c577deee949',
+  'swiftshader_revision': '068dd89cab31091e2290c99bd8b6c721e1108bda',
   # 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': 'a919e1bd9dd0ed0f8fa7534dfe6659c511fe7a1c',
+  'pdfium_revision': '7d0916bb7588ca5f7f1ae7707edae7b02cbb5c26',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -244,7 +244,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '2478e62054cf81b2bb2981e3d4b03daab112e789',
+  'catapult_revision': '296680f097d19afdeb742119e1d26d97392d78d9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -252,7 +252,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': '77e01616ea7b9584005bcd1424f725713c875740',
+  'devtools_frontend_revision': 'e2db893b1dead2e0b4e55c49269b3abafd8537d8',
   # 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.
@@ -312,7 +312,7 @@
   # 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': '87d31381588b26edb3da1d75dd0588b2df4dd968',
+  'dawn_revision': '5ccecaade259a6f073992c79c694d27dce3f9251',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -762,6 +762,10 @@
               'package': 'chromium/third_party/android_sdk/public/tools-lint',
               'version': Var('android_sdk_tools-lint_version'),
           },
+          {
+              'package': 'chromium/third_party/android_sdk/public/cmdline-tools',
+              'version': 'CR25ixsRhwuRnhdgDpGFyl9S0C_0HO9SUgFrwX46zq8C',
+          },
       ],
       'condition': 'checkout_android_native_support',
       'dep_type': 'cipd',
@@ -900,7 +904,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ed0cc5f6fd8ee57e9219f840d492de3109ba6d83',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1961043388e63c48946322de077bebbb333fde6a',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -925,7 +929,7 @@
   },
 
   'src/third_party/ffmpeg':
-    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '68b4dfdbd607fdd33b9b8e3515f039d97677dd1c',
+    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '252792a1ff65deadc4e627e59ce80b8811c5a5de',
 
   'src/third_party/flac':
     Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
@@ -1494,7 +1498,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '53655df4cde60b121fc530842ba9a6d5dfec1ae1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'cfe75c12ee04d17e7898ebc0a8ad1051b6627e53',
+    Var('webrtc_git') + '/src.git' + '@' + 'c33e4910c5dba2ba51eb95789d885f3eeb7e3d70',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1564,7 +1568,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3a46886a357c7e9a64f0b65ba0dfcebb079eb035',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a8b0b9cbdf854530bcc2f4491cb90ff16c0c823c',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 2f769a3..91f1592 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -274,19 +274,13 @@
   '^chrome/test/',
   '^chrome/tools/',
   '^chrome/utility/',
-  '^chromecast/app/',
-  '^chromecast/browser/',
-  '^chromecast/crash/',
   '^chromecast/media/',
   '^chromecast/metrics/',
   '^chromecast/net/',
   '^chromeos/attestation/',
   '^chromeos/components/',
-  '^chromeos/dbus/',
-  '^chromeos/login/',
   '^chromeos/network/',
   '^chromeos/services/',
-  '^chromeos/settings/',
   '^components/arc/',
   '^components/assist_ranker/',
   '^components/autofill/',
@@ -1341,6 +1335,8 @@
     'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
     'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
     'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
+    ('third_party/blink/renderer/bindings/scripts/'
+     'generate_high_entropy_list.pydeps'),
     'tools/binary_size/sizes.pydeps',
     'tools/binary_size/supersize.pydeps',
 ]
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index b527bb7..81ea5d1e4 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -619,7 +619,9 @@
   return IsTabletMode() && !HasVisibleWindows();
 }
 
-void AppListControllerImpl::OnShelfAlignmentChanged(aura::Window* root_window) {
+void AppListControllerImpl::OnShelfAlignmentChanged(
+    aura::Window* root_window,
+    ShelfAlignment old_alignment) {
   if (!IsTabletMode())
     DismissAppList();
 }
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h
index 462ff3d..88c90c01 100644
--- a/ash/app_list/app_list_controller_impl.h
+++ b/ash/app_list/app_list_controller_impl.h
@@ -225,7 +225,8 @@
   void OnVisibilityWillChange(bool visible, int64_t display_id);
 
   // ShellObserver:
-  void OnShelfAlignmentChanged(aura::Window* root_window) override;
+  void OnShelfAlignmentChanged(aura::Window* root_window,
+                               ShelfAlignment old_alignment) override;
   void OnShellDestroying() override;
 
   // OverviewObserver:
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index 6aca8ea7..6ad84cf 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -60,6 +60,7 @@
 #include "ui/views/paint_info.h"
 #include "ui/views/view_model_utils.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/core/coordinate_conversion.h"
 
 namespace ash {
 
@@ -1121,10 +1122,10 @@
       !event->IsLeftMouseButton()) {
     return;
   }
-
-  gfx::Point point_in_screen = event->location();
-  ConvertPointToScreen(static_cast<views::View*>(event->target()),
-                       &point_in_screen);
+  gfx::PointF point_in_screen = event->root_location_f();
+  auto* view_target = static_cast<views::View*>(event->target());
+  wm::ConvertPointToScreen(view_target->GetWidget()->GetNativeWindow(),
+                           &point_in_screen);
 
   switch (event->type()) {
     case ui::ET_MOUSE_PRESSED:
@@ -1184,8 +1185,8 @@
       const bool should_handle = ShouldHandleDragEvent(*event);
 
       is_in_mouse_drag_ = false;
-      mouse_drag_start_point_ = gfx::Point();
-      last_mouse_drag_point_ = gfx::Point();
+      mouse_drag_start_point_ = gfx::PointF();
+      last_mouse_drag_point_ = gfx::PointF();
 
       if (!should_handle) {
         gfx::Point drag_location_in_app_list = event->location();
@@ -2779,7 +2780,7 @@
 
   // Sets the transform to locate the scrolled content.
   gfx::Size grid_size = GetTileGridSize();
-  gfx::Vector2d translate;
+  gfx::Vector2dF translate;
   const int dir =
       transition.target_page > pagination_model_.selected_page() ? -1 : 1;
   if (pagination_controller_->scroll_axis() ==
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h
index aaaead8..7e6d21c 100644
--- a/ash/app_list/views/apps_grid_view.h
+++ b/ash/app_list/views/apps_grid_view.h
@@ -847,12 +847,12 @@
 
   // The initial mouse drag location in screen coordinate. Updates when drag
   // on AppsGridView starts.
-  gfx::Point mouse_drag_start_point_;
+  gfx::PointF mouse_drag_start_point_;
 
   // The last mouse drag location in screen coordinate. Different from
   // |last_drag_point_|, |last_mouse_drag_point_| is the location of the most
   // recent drag on AppsGridView instead of the app icon.
-  gfx::Point last_mouse_drag_point_;
+  gfx::PointF last_mouse_drag_point_;
 
   DISALLOW_COPY_AND_ASSIGN(AppsGridView);
 };
diff --git a/ash/components/strings/ash_components_strings_fr.xtb b/ash/components/strings/ash_components_strings_fr.xtb
index c0376ba..6f90441 100644
--- a/ash/components/strings/ash_components_strings_fr.xtb
+++ b/ash/components/strings/ash_components_strings_fr.xtb
@@ -13,7 +13,7 @@
 <translation id="1383876407941801731">Rechercher</translation>
 <translation id="1454364489140280055"><ph name="CTRL" /><ph name="SEPARATOR1" /><ph name="SHIFT1" /><ph name="SEPARATOR2" /><ph name="G" /> ou <ph name="SHIFT2" /><ph name="SEPARATOR3" /><ph name="ENTER" /></translation>
 <translation id="1477442857810932985">Accéder à la fin de la ligne</translation>
-<translation id="1499072997694708844">Fermez n'importe quelle fenêtre de recherche ouverte ou arrêtez le chargement de la page actuelle</translation>
+<translation id="1499072997694708844">Fermer n'importe quelle fenêtre de recherche ouverte ou arrêter le chargement de la page actuelle</translation>
 <translation id="1510238584712386396">Lanceur d'applications</translation>
 <translation id="152892567002884378">Augmenter le volume</translation>
 <translation id="1560480564179555003"><ph name="SHIFT" /><ph name="SEPARATOR1" /><ph name="ALT" /><ph name="SEPARATOR2" /><ph name="L" />, puis <ph name="ESC" /></translation>
@@ -122,7 +122,7 @@
 <translation id="5554139136362089836">Rechercher sur la page active</translation>
 <translation id="5563050856984839829">Appuyez sur <ph name="CTRL" /><ph name="SEPARATOR" /><ph name="SHIFT" /> et cliquez sur un lien</translation>
 <translation id="561814908794220892">Ouvrir la page Web dans un nouvel onglet</translation>
-<translation id="5620219513321115856">Déplacez la fenêtre active vers le bureau à droite</translation>
+<translation id="5620219513321115856">Déplacer la fenêtre active vers le bureau à droite</translation>
 <translation id="5710621673935162997"><ph name="CTRL" /><ph name="SEPARATOR1" /><ph name="L" /> ou <ph name="ALT" /><ph name="SEPARATOR2" /><ph name="D" /></translation>
 <translation id="5757111373163288447">Ouvrir le lien dans l'onglet</translation>
 <translation id="5757474750054631686">Réduire la luminosité du clavier (claviers rétroéclairés uniquement)</translation>
@@ -162,7 +162,7 @@
 <translation id="6981982820502123353">Accessibilité</translation>
 <translation id="7020813747703216897">Aucun résultat ne correspond à votre recherche</translation>
 <translation id="7025325401470358758">Volet suivant</translation>
-<translation id="7076878155205969899">Coupe le son</translation>
+<translation id="7076878155205969899">Couper le son</translation>
 <translation id="7077383985738259936">Sélectionner ou mettre en surbrillance la barre de favoris (si elle est affichée)</translation>
 <translation id="7237562915163138771">Saisissez une adresse Web dans la barre d'adresse, puis appuyez sur <ph name="ALT" /><ph name="SEPARATOR" /><ph name="ENTER" /></translation>
 <translation id="7254764037241667478">Mettre l'appareil en mode veille (suspendre)</translation>
@@ -197,7 +197,7 @@
 <translation id="8717459106217102612">Sélectionner la lettre ou le mot précédents</translation>
 <translation id="8727232706774971183">Voir vos notifications</translation>
 <translation id="8855885154700222542">Touche de plein écran</translation>
-<translation id="8881584919399569791">Déplacez la fenêtre active vers le bureau à gauche</translation>
+<translation id="8881584919399569791">Déplacer la fenêtre active vers le bureau à gauche</translation>
 <translation id="88986195241502842">Accéder à la page suivante</translation>
 <translation id="8924883688469390268">Passer à l'utilisateur précédent</translation>
 <translation id="8977648847395357314">Sélectionner le contenu de la barre d'adresse</translation>
diff --git a/ash/components/strings/ash_components_strings_it.xtb b/ash/components/strings/ash_components_strings_it.xtb
index d43db763..2751e3f 100644
--- a/ash/components/strings/ash_components_strings_it.xtb
+++ b/ash/components/strings/ash_components_strings_it.xtb
@@ -13,7 +13,7 @@
 <translation id="1383876407941801731">Cerca</translation>
 <translation id="1454364489140280055"><ph name="CTRL" /><ph name="SEPARATOR1" /><ph name="SHIFT1" /><ph name="SEPARATOR2" /><ph name="G" /> o <ph name="SHIFT2" /><ph name="SEPARATOR3" /><ph name="ENTER" /></translation>
 <translation id="1477442857810932985">Vai alla fine della riga</translation>
-<translation id="1499072997694708844">Chiudi le finestre di ricerca aperte o interrompi il caricamento della pagina attuale</translation>
+<translation id="1499072997694708844">Chiude le finestre di ricerca aperte o interrompe il caricamento della pagina attuale</translation>
 <translation id="1510238584712386396">Avvio applicazioni</translation>
 <translation id="152892567002884378">Alza il volume</translation>
 <translation id="1560480564179555003"><ph name="SHIFT" /><ph name="SEPARATOR1" /><ph name="ALT" /><ph name="SEPARATOR2" /><ph name="L" />, quindi <ph name="ESC" /></translation>
@@ -41,7 +41,7 @@
 <translation id="2397416548179033562">Mostra il menu Chrome</translation>
 <translation id="2424073332829844142">Attiva e disattiva BLOC MAIUSC</translation>
 <translation id="2441202986792279177">Passa velocemente da una finestra all'altra</translation>
-<translation id="2454251766545114447">Diminuisci lo zoom dello schermo</translation>
+<translation id="2454251766545114447">Diminuisce lo zoom dello schermo</translation>
 <translation id="2478303094958140141">Attiva o disattiva ChromeVox (funzione di lettura vocale)</translation>
 <translation id="2480851840841871861">Apri l'Assistente Google</translation>
 <translation id="2488661730534396940">Attiva il desktop a sinistra</translation>
@@ -74,7 +74,7 @@
 <translation id="353037708190149633">Salva tutte le pagine aperte nella finestra corrente come Preferiti in una nuova cartella</translation>
 <translation id="355103131818127604">Apre il link in una nuova scheda in background</translation>
 <translation id="3622741593887335780">Aumenta lo zoom (con lente d’ingrandimento ancorata o a schermo intero attiva)</translation>
-<translation id="3649256019230929621">Riduci la finestra</translation>
+<translation id="3649256019230929621">Riduce la finestra</translation>
 <translation id="3655154169297074232">Schede e finestre</translation>
 <translation id="3668361878347172356">Ripete l'ultima azione</translation>
 <translation id="3710784500737332588">Consente di aprire il Centro assistenza</translation>
@@ -92,7 +92,7 @@
 <translation id="4060703249685950734">Riapre l'ultima scheda o finestra chiusa</translation>
 <translation id="4090342722461256974">Tieni premuto <ph name="ALT" /><ph name="SEPARATOR" /><ph name="SHIFT" />, tocca <ph name="TAB" /> fin quando arrivi alla finestra che vuoi aprire, quindi rilascia.</translation>
 <translation id="4092538597492297615">Copia i contenuti selezionati negli appunti</translation>
-<translation id="4101772068965291327">Apri pagina iniziale</translation>
+<translation id="4101772068965291327">Apre pagina iniziale</translation>
 <translation id="4123108089450197101">Salva il link nei Preferiti</translation>
 <translation id="4141203561740478845">Mette in evidenza la riga con la barra degli indirizzi</translation>
 <translation id="4148761611071495477"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="G" /> o <ph name="ENTER" /></translation>
@@ -145,7 +145,7 @@
 <translation id="6425378783626925378">Consente di fare clic sulle icone 1-8 nella shelf</translation>
 <translation id="6435207348963613811">Mette in evidenza l'elemento precedente sulla shelf</translation>
 <translation id="6445033640292336367">Ripristina la posizione originale della scheda</translation>
-<translation id="6474744297082284761">Diminuisci lo zoom (con lente d’ingrandimento ancorata o a schermo intero attiva)</translation>
+<translation id="6474744297082284761">Diminuisce lo zoom (con lente d’ingrandimento ancorata o a schermo intero attiva)</translation>
 <translation id="649811797655257835">Seleziona il file, quindi premi <ph name="SPACE" /></translation>
 <translation id="6556040137485212400">Consente di aprire la finestra rimasta inutilizzata per più tempo</translation>
 <translation id="666343722268997814">Apre il menu di scelta rapida per l'elemento evidenziato</translation>
@@ -153,7 +153,7 @@
 <translation id="6681606577947445973"><ph name="REFRESH" /> o <ph name="CTRL" /> <ph name="SEPARATOR" /> <ph name="R" /></translation>
 <translation id="6690765639083431875">Aggancia una finestra a sinistra</translation>
 <translation id="6692847073476874842">Visualizza l'anteprima di un file nell'app File</translation>
-<translation id="671928215901716392">Blocco schermo</translation>
+<translation id="671928215901716392">Blocca schermo</translation>
 <translation id="6727005317916125192">Riquadro precedente</translation>
 <translation id="6740781404993465795">Seleziona la parola o la lettera successiva</translation>
 <translation id="6755851152783057058">Passa all'ultimo metodo di immissione utilizzato</translation>
diff --git a/ash/components/strings/ash_components_strings_ja.xtb b/ash/components/strings/ash_components_strings_ja.xtb
index af818b6..e7411420 100644
--- a/ash/components/strings/ash_components_strings_ja.xtb
+++ b/ash/components/strings/ash_components_strings_ja.xtb
@@ -1,19 +1,19 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="ja">
-<translation id="1036550831858290950">現在のタブをブックマークとして保存する</translation>
+<translation id="1036550831858290950">現在のウェブページをブックマークとして保存する</translation>
 <translation id="104962181688258143">ファイルアプリを起動する</translation>
 <translation id="1122869341872663659">「<ph name="QUERY" />」の検索結果 <ph name="N" /> 件を表示しています</translation>
 <translation id="1195667586424773550">リンクをドラッグしてタブのアドレスバーに移動する</translation>
 <translation id="1204450209689312104">新しいウィンドウをシークレット モードで開く</translation>
-<translation id="1251638888133819822">全画面拡大鏡のオンとオフを切り替えます</translation>
-<translation id="1290373024480130896"><ph name="MODIFIER1" /><ph name="SEPARATOR1" /><ph name="MODIFIER2" /><ph name="SEPARATOR2" /><ph name="MODIFIER3" /><ph name="SEPARATOR3" /><ph name="KEY" /></translation>
+<translation id="1251638888133819822">全画面拡大鏡のオンとオフを切り替える</translation>
+<translation id="1290373024480130896"><ph name="MODIFIER1" /><ph name="SEPARATOR1" /><ph name="MODIFIER2" /><ph name="SEPARATOR2" /><ph name="MODIFIER3" /><ph name="SEPARATOR3" /><ph name="KEY" /> キーを押す</translation>
 <translation id="1293699935367580298">Esc</translation>
 <translation id="1299858300159559687">現在のページを印刷する</translation>
 <translation id="1383876407941801731">検索</translation>
 <translation id="1454364489140280055"><ph name="CTRL" /><ph name="SEPARATOR1" /><ph name="SHIFT1" /><ph name="SEPARATOR2" /><ph name="G" /> キーまたは <ph name="SHIFT2" /><ph name="SEPARATOR3" /><ph name="ENTER" /> キーを押す</translation>
-<translation id="1477442857810932985">行の末尾に移動します</translation>
-<translation id="1499072997694708844">開いている検索ウィンドウをすべて閉じるか、現在のページの読み込みを停止します</translation>
+<translation id="1477442857810932985">行の末尾に移動する</translation>
+<translation id="1499072997694708844">開いている検索ウィンドウをすべて閉じるか、現在のページの読み込みを停止する</translation>
 <translation id="1510238584712386396">ランチャー</translation>
 <translation id="152892567002884378">音量を上げる</translation>
 <translation id="1560480564179555003"><ph name="SHIFT" /><ph name="SEPARATOR1" /><ph name="ALT" /><ph name="SEPARATOR2" /><ph name="L" /> キーを押した状態で <ph name="ESC" /> キーを押す</translation>
@@ -23,11 +23,11 @@
 <translation id="169515659049020177">Shift</translation>
 <translation id="1732295673545939435"><ph name="MODIFIER1" /><ph name="SEPARATOR1" /><ph name="MODIFIER2" /><ph name="SEPARATOR2" /><ph name="KEY" /> キーを押す</translation>
 <translation id="1733525068429116555">アドレスバーに入力した語句に www. と .com を追加してページを開く</translation>
-<translation id="1872219238824176091">現在のデスクを削除します</translation>
+<translation id="1872219238824176091">現在のデスクを削除する</translation>
 <translation id="1920446759863417809"><ph name="SHIFT1" /><ph name="SEPARATOR1" /><ph name="ALT" /><ph name="SEPARATOR2" /><ph name="L" /> キーを押した状態で <ph name="SHIFT2" /><ph name="SEPARATOR3" /><ph name="TAB" /> キーまたは <ph name="LEFT" /> キーを押す</translation>
 <translation id="1996162290124031907">次のタブに移動する</translation>
 <translation id="2010818616644390445">ウィンドウ内の最後のタブに移動する</translation>
-<translation id="2040706009561734834">ランチャーを開くか閉じます</translation>
+<translation id="2040706009561734834">ランチャーを開く / 閉じる</translation>
 <translation id="2088054208777350526">キーボード ショートカットを検索</translation>
 <translation id="2125211348069077981"><ph name="ALT" /><ph name="SEPARATOR" /><ph name="E" /> または <ph name="F" /></translation>
 <translation id="2145908266289632567">テキスト編集</translation>
@@ -44,15 +44,15 @@
 <translation id="2454251766545114447">ディスプレイをズームアウト</translation>
 <translation id="2478303094958140141">ChromeVox(音声フィードバック)を有効または無効にする</translation>
 <translation id="2480851840841871861">Google アシスタントを開く</translation>
-<translation id="2488661730534396940">左のデスクを有効にします</translation>
+<translation id="2488661730534396940">左のデスクを有効にする</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2530339807289914946">ウェブページを下にスクロールする</translation>
 <translation id="2574014812750545982">ページのズームレベルをリセット</translation>
-<translation id="2596078834055697711">ウィンドウのスクリーンショットを撮影します</translation>
+<translation id="2596078834055697711">ウィンドウのスクリーンショットを撮影する</translation>
 <translation id="2685170433750953446"><ph name="SHIFT" /><ph name="SEPARATOR1" /><ph name="ALT" /><ph name="SEPARATOR2" /><ph name="L" /> キーを押した状態で <ph name="TAB" /> キーまたは<ph name="RIGHT" />キーを押す</translation>
 <translation id="2750942583782703988">現在のページを再読み込みする</translation>
-<translation id="2764005613199379871">検索アドレスバーにフォーカスします</translation>
-<translation id="2774822903829597107">新しいデスクを作成します</translation>
+<translation id="2764005613199379871">検索アドレスバーにフォーカスする</translation>
+<translation id="2774822903829597107">新しいデスクを作成する</translation>
 <translation id="2789868185375229787">ページを縮小表示する</translation>
 <translation id="2804480015716812239"><ph name="ALT" /> キーを押しながらリンクをクリックする</translation>
 <translation id="2830827904629746450">ウィンドウを右側に固定する</translation>
@@ -66,28 +66,28 @@
 <translation id="3105917916468784889">スクリーンショットを撮る</translation>
 <translation id="3126026824346185272">Ctrl</translation>
 <translation id="3140353188828248647">アドレスバーにフォーカスを移す</translation>
-<translation id="3256109297135787951">シェルフのアイテムのハイライト表示を解除します</translation>
+<translation id="3256109297135787951">シェルフのアイテムのハイライト表示を解除する</translation>
 <translation id="3288816184963444640">現在のウィンドウを閉じる</translation>
 <translation id="3407560819924487926">タスク マネージャを表示する</translation>
 <translation id="3422679037938588196">検索に一致する前の文字列に移動する</translation>
-<translation id="344577624355799426"><ph name="ALT" /> キーまたは<ph name="SEARCH" /><ph name="SEPARATOR" /><ph name="DOWN" />キーを押す</translation>
+<translation id="344577624355799426"><ph name="ALT" /> または<ph name="SEARCH" /><ph name="SEPARATOR" /><ph name="DOWN" />キーを押す</translation>
 <translation id="353037708190149633">現在のウィンドウで開いているすべてのページをブックマークとして新しいフォルダに保存する</translation>
 <translation id="355103131818127604">バックグラウンドの新しいタブでリンクを開く</translation>
 <translation id="3622741593887335780">ズームイン(ドッキングまたは全画面の拡大鏡が有効な場合)</translation>
 <translation id="3649256019230929621">ウィンドウを最小化</translation>
 <translation id="3655154169297074232">タブとウィンドウ</translation>
 <translation id="3668361878347172356">前の操作をやり直す</translation>
-<translation id="3710784500737332588">ヘルプセンターを開きます</translation>
+<translation id="3710784500737332588">ヘルプセンターを開く</translation>
 <translation id="3720939646656082033">新しいタブでリンクを開き、新しいタブに切り替える</translation>
 <translation id="3725795051337497754">現在のタブを閉じる</translation>
 <translation id="3751033133896282964">前の操作を元に戻す</translation>
-<translation id="3792178297143798024">シェルフのハイライト表示されたアイテムを開きます</translation>
+<translation id="3792178297143798024">シェルフのハイライト表示されたアイテムを開く</translation>
 <translation id="379295446891231126"><ph name="CTRL" /><ph name="SEPARATOR" />1〜8 キーを押す</translation>
 <translation id="3837047332182291558">キーボードの明るさを上げる(バックライト付きキーボードのみ)</translation>
 <translation id="3949671998904569433">カンマ</translation>
 <translation id="3976863468609830880">シェルフの最後のアイコンをクリックする</translation>
 <translation id="3994783594793697310">ディスプレイのズームレベルをリセット</translation>
-<translation id="4026843240379844265">アクティブなウィンドウをディスプレイ間で移動します</translation>
+<translation id="4026843240379844265">アクティブなウィンドウをディスプレイ間で移動する</translation>
 <translation id="4035482366624727273">ページ上のすべてを選択する</translation>
 <translation id="4060703249685950734">最後に閉じたタブまたはウィンドウを開く</translation>
 <translation id="4090342722461256974"><ph name="SHIFT" /><ph name="SEPARATOR" /><ph name="ALT" /> キーを押したまま、目的のウィンドウが表示されるまで <ph name="TAB" /> キーを押し、表示されたらキーを放す</translation>
@@ -97,6 +97,7 @@
 <translation id="4141203561740478845">アドレスバーの行をハイライト表示する</translation>
 <translation id="4148761611071495477"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="G" /> キーまたは <ph name="ENTER" /> キーを押す</translation>
 <translation id="4240486403425279990">複数画面モード</translation>
+<translation id="4276530550848325494"><ph name="KEY" /> キーを押す</translation>
 <translation id="4382340674111381977">前のページに戻る</translation>
 <translation id="4458670250301149821">アプリグリッド内のフォルダにアプリアイコンを移動または取り出します</translation>
 <translation id="4472417192667361414">システムと表示の設定</translation>
@@ -104,11 +105,11 @@
 <translation id="4556221320735744018">キーボード ショートカットのヘルプを表示する</translation>
 <translation id="4628718545549558538">ステータス領域(アカウント画像が表示されている部分)を開く</translation>
 <translation id="4642092649622328492">画面の一部のスクリーンショットを撮影する</translation>
-<translation id="4698850295812410683">タッチペン ツールを表示します</translation>
+<translation id="4698850295812410683">タッチペン ツールを表示する</translation>
 <translation id="4801989101741319327">次の単語の末尾に移動する</translation>
-<translation id="4866066940972151697">右のデスクを有効にします</translation>
+<translation id="4866066940972151697">右のデスクを有効にする</translation>
 <translation id="4916163929714267752">新しいウィンドウでリンクを開く</translation>
-<translation id="5030659775136592441">ブックマーク マネージャを表示します</translation>
+<translation id="5030659775136592441">ブックマーク マネージャを表示する</translation>
 <translation id="5034421018520995080">ページの一番上に移動する</translation>
 <translation id="5042305953558921026">概要モード キー</translation>
 <translation id="5104462712192763270">現在のページを保存する</translation>
@@ -117,17 +118,17 @@
 <translation id="5236674127086649162">キャッシュされたコンテンツを使用しないで現在のページを再読み込みする</translation>
 <translation id="526651782186312376">行頭までのテキストを選択する</translation>
 <translation id="5316716239522500219">モニターをミラーリングする</translation>
-<translation id="539072479502328326">ドッキング拡大鏡のオンとオフを切り替えます</translation>
+<translation id="539072479502328326">ドッキング拡大鏡のオンとオフを切り替える</translation>
 <translation id="5541719484267030947">タブをドラッグしながら、<ph name="ESC" /> キーを押す</translation>
 <translation id="5554139136362089836">現在のページ内を検索する</translation>
 <translation id="5563050856984839829"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="SHIFT" /> キーを押しながらリンクをクリックする</translation>
 <translation id="561814908794220892">新しいタブでウェブページを開く</translation>
-<translation id="5620219513321115856">アクティブなウィンドウを右のデスクに移動します</translation>
+<translation id="5620219513321115856">アクティブなウィンドウを右のデスクに移動する</translation>
 <translation id="5710621673935162997"><ph name="CTRL" /><ph name="SEPARATOR1" /><ph name="L" /> キーまたは <ph name="ALT" /><ph name="SEPARATOR2" /><ph name="D" /> キーを押す</translation>
 <translation id="5757111373163288447">ドラッグ先のタブでリンクを開く</translation>
 <translation id="5757474750054631686">キーボードの明るさを下げる(バックライト付きキーボードのみ)</translation>
 <translation id="587531134027443617">前の単語を削除する</translation>
-<translation id="5899919361772749550">デベロッパー ツール コンソールの表示と非表示を切り替えます</translation>
+<translation id="5899919361772749550">デベロッパー ツール コンソールの表示と非表示を切り替える</translation>
 <translation id="5921745308587794300">ウィンドウを回転</translation>
 <translation id="6022924867608035986">検索ボックスのテキストを消去</translation>
 <translation id="6045998054441862242">ハイ コントラスト モードを有効にする</translation>
@@ -147,7 +148,7 @@
 <translation id="6445033640292336367">タブを元の位置に戻す</translation>
 <translation id="6474744297082284761">ズームアウト(ドッキングまたは全画面の拡大鏡が有効な場合)</translation>
 <translation id="649811797655257835">ファイルを選択して <ph name="SPACE" /> キーを押す</translation>
-<translation id="6556040137485212400">最も長く使われていないウィンドウを開きます</translation>
+<translation id="6556040137485212400">最も長く使われていないウィンドウを開く</translation>
 <translation id="666343722268997814">ハイライト表示されたアイテムで右クリックメニューを開く</translation>
 <translation id="6671538777808758331">検索に一致する次の文字列に移動する</translation>
 <translation id="6681606577947445973"><ph name="REFRESH" /> または <ph name="CTRL" /><ph name="SEPARATOR" /><ph name="R" /></translation>
@@ -156,36 +157,36 @@
 <translation id="671928215901716392">画面をロック</translation>
 <translation id="6727005317916125192">前のウィンドウ</translation>
 <translation id="6740781404993465795">次の単語または文字を選択する</translation>
-<translation id="6755851152783057058">最後に使用した入力方法に切り替えます</translation>
+<translation id="6755851152783057058">最後に使用した入力方法に切り替える</translation>
 <translation id="6760706756348334449">音量を下げる</translation>
-<translation id="6941333068993625698">フィードバックを送信します</translation>
+<translation id="6941333068993625698">フィードバックを送信する</translation>
 <translation id="6981982820502123353">ユーザー補助機能</translation>
 <translation id="7020813747703216897">一致する結果は見つかりませんでした</translation>
 <translation id="7025325401470358758">次のウィンドウ</translation>
-<translation id="7076878155205969899">音声をミュートします</translation>
-<translation id="7077383985738259936">ブックマーク バーにフォーカスするかブックマーク バーをハイライト表示します(ブックマーク バーが表示されている場合)</translation>
-<translation id="7237562915163138771">アドレスバーにウェブアドレスを入力して、<ph name="ALT" /><ph name="SEPARATOR" /><ph name="ENTER" /> キーを押します</translation>
-<translation id="7254764037241667478">デバイスをスリープモード(停止)にします</translation>
-<translation id="7379254767514753910"><ph name="ALT" /> キーまたは<ph name="SEARCH" /><ph name="SEPARATOR" /><ph name="UP" />キーを押す</translation>
-<translation id="7422707470576323858">次の入力方法に切り替えます</translation>
-<translation id="743754632698445141">アプリの固定を解除します</translation>
+<translation id="7076878155205969899">音声をミュートする</translation>
+<translation id="7077383985738259936">ブックマーク バーにフォーカスするかブックマーク バーをハイライト表示する(ブックマーク バーが表示されている場合)</translation>
+<translation id="7237562915163138771">アドレスバーにウェブアドレスを入力して、<ph name="ALT" /><ph name="SEPARATOR" /><ph name="ENTER" /> キーを押す</translation>
+<translation id="7254764037241667478">デバイスをスリープモード(停止)にする</translation>
+<translation id="7379254767514753910"><ph name="ALT" /> または<ph name="SEARCH" /><ph name="SEPARATOR" /><ph name="UP" />キーを押す</translation>
+<translation id="7422707470576323858">次の入力方法に切り替える</translation>
+<translation id="743754632698445141">アプリの固定を解除する</translation>
 <translation id="7439718573248533901">次の文字を削除する(カーソルの右側を削除する)</translation>
 <translation id="7500368597227394048">ハイフン</translation>
-<translation id="7611271430932669992">ポップアップとダイアログにフォーカスを移動します</translation>
+<translation id="7611271430932669992">ポップアップとダイアログにフォーカスを移動する</translation>
 <translation id="7635348532214572995">アプリグリッド内でアプリアイコンを移動します</translation>
 <translation id="766326951329901120">クリップボードの内容をプレーン テキストとして貼り付ける</translation>
 <translation id="7703010453515335249">左角かっこ</translation>
 <translation id="7724603315864178912">切り取り</translation>
 <translation id="7730490981846175479"><ph name="SHIFT" /><ph name="SEPARATOR1" /><ph name="ALT" /><ph name="SEPARATOR2" /><ph name="L" /> キーを押した状態で <ph name="SPACE" /> キーまたは <ph name="ENTER" /> キーを押す</translation>
 <translation id="7787242579016742662">ブラウザ内でファイルを開く</translation>
-<translation id="7952165122793773711">1~8 番目のタブに移動します</translation>
+<translation id="7952165122793773711">1~8 番目のタブに移動する</translation>
 <translation id="8026334261755873520">閲覧履歴データの削除</translation>
 <translation id="8130528849632411619">ドキュメントの先頭に移動する</translation>
 <translation id="8147954207400281792"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="K" /> または <ph name="E" /> キーを押す</translation>
-<translation id="8232835244134740473">フォーカスを次の順に切り替えます: アカウント画像が表示されているステータス領域、ランチャー、アドレスバー、ブックマーク バー(表示されている場合)、開いているウェブページ、ダウンロード バー(表示されている場合)</translation>
+<translation id="8232835244134740473">フォーカスを次の順に切り替える: アカウント画像が表示されているステータス領域、ランチャー、アドレスバー、ブックマーク バー(表示されている場合)、開いているウェブページ、ダウンロード バー(表示されている場合)</translation>
 <translation id="8234414138295101081">画面を 90 度回転させる</translation>
 <translation id="8241665785394195545">右角かっこ</translation>
-<translation id="8264941229485248811">デベロッパー ツール インスペクタの表示と非表示を切り替えます</translation>
+<translation id="8264941229485248811">デベロッパー ツール インスペクタの表示と非表示を切り替える</translation>
 <translation id="836869401750819675">ダウンロード ページを開く</translation>
 <translation id="8388247778047144397">リンクをドラッグしてタブストリップの空白領域に移動する</translation>
 <translation id="8389638407792712197">新しいウィンドウを開く</translation>
@@ -197,23 +198,23 @@
 <translation id="8717459106217102612">前の単語または文字を選択する</translation>
 <translation id="8727232706774971183">通知を表示する</translation>
 <translation id="8855885154700222542">全画面表示キー</translation>
-<translation id="8881584919399569791">アクティブなウィンドウを左のデスクに移動します</translation>
+<translation id="8881584919399569791">アクティブなウィンドウを左のデスクに移動する</translation>
 <translation id="88986195241502842">ページ内を下に移動</translation>
-<translation id="8924883688469390268">前のユーザーに切り替えます</translation>
-<translation id="8977648847395357314">アドレスバーの内容を選択します</translation>
-<translation id="8982190978301344584">利用可能な IME のリストをメニューで表示します</translation>
+<translation id="8924883688469390268">前のユーザーに切り替える</translation>
+<translation id="8977648847395357314">アドレスバーの内容を選択する</translation>
+<translation id="8982190978301344584">利用可能な IME のリストをメニューで表示する</translation>
 <translation id="8990356943438003669"><ph name="ALT" /><ph name="SEPARATOR" />1〜8 キーを押す</translation>
-<translation id="9005984960510803406">Crosh ウィンドウを開きます</translation>
-<translation id="9041599225465145264">クリップボードの内容を貼り付けます</translation>
-<translation id="9052808072970550123">次のユーザーに切り替えます</translation>
+<translation id="9005984960510803406">Crosh ウィンドウを開く</translation>
+<translation id="9041599225465145264">クリップボードの内容を貼り付ける</translation>
+<translation id="9052808072970550123">次のユーザーに切り替える</translation>
 <translation id="906458777597946297">ウィンドウを最大化</translation>
 <translation id="9072882242928138086"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="SHIFT" /> キーを押してから、<ph name="LEFT" />、<ph name="RIGHT" />、<ph name="UP" />、<ph name="DOWN" />のいずれかのキーを押します</translation>
-<translation id="9091855755813503076">行の先頭に移動します</translation>
+<translation id="9091855755813503076">行の先頭に移動する</translation>
 <translation id="9106898733795143799">ページとウェブブラウザ</translation>
 <translation id="9162942292291287644">「<ph name="QUERY" />」の検索結果はありません</translation>
 <translation id="9179672198516322668">定番のショートカット</translation>
-<translation id="93603345341560814"><ph name="SHIFT" /> キーを押しながらリンクをクリック</translation>
-<translation id="945383118875625837">リンクをブックマーク バーにドラッグ</translation>
-<translation id="969054500339500113">メニューバーにフォーカスします</translation>
-<translation id="98120814841227350">ドキュメントの末尾に移動します</translation>
+<translation id="93603345341560814"><ph name="SHIFT" /> キーを押しながらリンクをクリックする</translation>
+<translation id="945383118875625837">リンクをブックマーク バーにドラッグする</translation>
+<translation id="969054500339500113">メニューバーにフォーカスする</translation>
+<translation id="98120814841227350">ドキュメントの末尾に移動する</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/ash/components/strings/ash_components_strings_ko.xtb b/ash/components/strings/ash_components_strings_ko.xtb
index fdf806b..7f80f15 100644
--- a/ash/components/strings/ash_components_strings_ko.xtb
+++ b/ash/components/strings/ash_components_strings_ko.xtb
@@ -132,7 +132,7 @@
 <translation id="6022924867608035986">검색창 텍스트 삭제</translation>
 <translation id="6045998054441862242">고대비 모드 사용</translation>
 <translation id="6052614013050385269">마우스 오른쪽 버튼으로 링크 클릭</translation>
-<translation id="6129953537138746214">공백</translation>
+<translation id="6129953537138746214">Space</translation>
 <translation id="6143669479988153888">페이지를 확대</translation>
 <translation id="6185696379715117369">페이지 위로</translation>
 <translation id="6228457605945141550">어둡게</translation>
diff --git a/ash/components/strings/ash_components_strings_nl.xtb b/ash/components/strings/ash_components_strings_nl.xtb
index 2a4dfb4..7540baf 100644
--- a/ash/components/strings/ash_components_strings_nl.xtb
+++ b/ash/components/strings/ash_components_strings_nl.xtb
@@ -41,7 +41,7 @@
 <translation id="2397416548179033562">Chrome-menu weergeven</translation>
 <translation id="2424073332829844142">Caps Lock in- en uitschakelen</translation>
 <translation id="2441202986792279177">Snel schakelen tussen vensters</translation>
-<translation id="2454251766545114447">Display uitzoomen</translation>
+<translation id="2454251766545114447">Uitzoomen scherm</translation>
 <translation id="2478303094958140141">ChromeVox (gesproken feedback) in- of uitschakelen</translation>
 <translation id="2480851840841871861">Google Assistent openen</translation>
 <translation id="2488661730534396940">Het bureaublad aan de linkerkant activeren</translation>
@@ -86,7 +86,7 @@
 <translation id="3837047332182291558">Toetsenbord helderder maken (alleen voor toetsenborden met achtergrondverlichting)</translation>
 <translation id="3949671998904569433">komma</translation>
 <translation id="3976863468609830880">Klikken op het laatste pictogram op de plank</translation>
-<translation id="3994783594793697310">Displayzoomniveau resetten</translation>
+<translation id="3994783594793697310">Zoomniveau scherm resetten</translation>
 <translation id="4026843240379844265">Actief venster verplaatsen tussen schermen</translation>
 <translation id="4035482366624727273">Alles op de pagina selecteren</translation>
 <translation id="4060703249685950734">Het laatste tabblad of venster dat je hebt gesloten, opnieuw openen</translation>
@@ -138,7 +138,7 @@
 <translation id="6228457605945141550">Helderheid verlagen</translation>
 <translation id="6276708887952587684">Paginabron weergeven</translation>
 <translation id="6321940490215594447">De pagina Geschiedenis openen</translation>
-<translation id="6340769215862220182">Display inzoomen</translation>
+<translation id="6340769215862220182">Inzoomen scherm</translation>
 <translation id="6359811074279051077"><ph name="MODIFIER" /><ph name="SEPARATOR" /><ph name="KEY" /></translation>
 <translation id="6395172954772765143">Tekst tot het einde van de regel selecteren</translation>
 <translation id="6419237577786823024"><ph name="CTRL1" /><ph name="SEPARATOR1" /><ph name="LEFT" /> of <ph name="CTRL2" /><ph name="SEPARATOR2" /><ph name="RIGHT" /></translation>
diff --git a/ash/components/strings/ash_components_strings_sv.xtb b/ash/components/strings/ash_components_strings_sv.xtb
index 8bffda1..3394d22b 100644
--- a/ash/components/strings/ash_components_strings_sv.xtb
+++ b/ash/components/strings/ash_components_strings_sv.xtb
@@ -58,16 +58,16 @@
 <translation id="2830827904629746450">Docka ett fönster till höger</translation>
 <translation id="2840766858109427815">Fortsätt till nästa sida</translation>
 <translation id="2872353916818027657">Byt primär bildskärm</translation>
-<translation id="2914313326123580426">Visa och dölj panelen Verktyg för utvecklare</translation>
+<translation id="2914313326123580426">Visa eller dölj panelen Verktyg för programmerare</translation>
 <translation id="292495055542441795">Aktivera och inaktivera helskärm</translation>
 <translation id="3020183492814296499">Genvägar</translation>
 <translation id="3084301071537457911">Markera nästa objekt på hyllan</translation>
 <translation id="309173601632226815">Markera översiktsknappen på hyllan</translation>
-<translation id="3105917916468784889">Ta skärmbild</translation>
+<translation id="3105917916468784889">Ta en skärmdump</translation>
 <translation id="3126026824346185272">Ctrl</translation>
 <translation id="3140353188828248647">Fokusera på adressfältet</translation>
 <translation id="3256109297135787951">Ta bort markeringen från ett objekt på hyllan</translation>
-<translation id="3288816184963444640">Stäng aktuellt fönster</translation>
+<translation id="3288816184963444640">Stäng det aktuella fönstret</translation>
 <translation id="3407560819924487926">Öppna aktivitetshanteraren</translation>
 <translation id="3422679037938588196">Hitta föregående träff för sökningen</translation>
 <translation id="344577624355799426"><ph name="ALT" /> eller <ph name="SEARCH" /><ph name="SEPARATOR" /><ph name="DOWN" /></translation>
@@ -116,7 +116,7 @@
 <translation id="5222676887888702881">Logga ut</translation>
 <translation id="5236674127086649162">Läs in den aktuella sidan igen utan att använda cacheminnet</translation>
 <translation id="526651782186312376">Markera text till radens början</translation>
-<translation id="5316716239522500219">Speglar monitorer</translation>
+<translation id="5316716239522500219">Spegla monitorer</translation>
 <translation id="539072479502328326">Aktivera och inaktivera dockad skärmförstoring</translation>
 <translation id="5541719484267030947">Tryck på <ph name="ESC" /> medan du drar fliken</translation>
 <translation id="5554139136362089836">Sök på den aktuella sidan</translation>
@@ -127,8 +127,8 @@
 <translation id="5757111373163288447">Öppna länken på fliken</translation>
 <translation id="5757474750054631686">Svagare belysning (endast tangentbord med belysning underifrån)</translation>
 <translation id="587531134027443617">Radera föregående ord</translation>
-<translation id="5899919361772749550">Visa eller dölj panelen Utvecklarverktyg</translation>
-<translation id="5921745308587794300">Rotera fönster.</translation>
+<translation id="5899919361772749550">Visa eller dölj konsolen Verktyg för programmerare</translation>
+<translation id="5921745308587794300">Rotera fönstret</translation>
 <translation id="6022924867608035986">Rensa sökrutan</translation>
 <translation id="6045998054441862242">Aktivera högkontrastläge</translation>
 <translation id="6052614013050385269">Högerklicka på en länk</translation>
@@ -180,12 +180,12 @@
 <translation id="7787242579016742662">Öppna en fil i webbläsaren</translation>
 <translation id="7952165122793773711">Öppna flik 1–8</translation>
 <translation id="8026334261755873520">Rensa webbinformation</translation>
-<translation id="8130528849632411619">Till början av dokumentet</translation>
+<translation id="8130528849632411619">Gå till början av dokumentet</translation>
 <translation id="8147954207400281792"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="K" /> eller <ph name="E" /></translation>
 <translation id="8232835244134740473">Flytta fokus mellan: statusfältet (där kontobilden visas), översikten, adressfältet, bokmärkesfältet (om det visas), webbsidan som är öppen, nedladdningsfältet (om det visas)</translation>
 <translation id="8234414138295101081">Rotera skärmen 90 grader</translation>
 <translation id="8241665785394195545">höger parentes</translation>
-<translation id="8264941229485248811">Visa eller dölj Utvecklarverktyg-inspektören</translation>
+<translation id="8264941229485248811">Visa eller dölj inspektören för Verktyg för programmerare</translation>
 <translation id="836869401750819675">Öppna sidan Nedladdningar</translation>
 <translation id="8388247778047144397">Dra länken till ett tomt område i flikhuvudet</translation>
 <translation id="8389638407792712197">Öppna nytt fönster</translation>
diff --git a/ash/components/strings/ash_components_strings_zh-HK.xtb b/ash/components/strings/ash_components_strings_zh-HK.xtb
index 1705a97..447c800 100644
--- a/ash/components/strings/ash_components_strings_zh-HK.xtb
+++ b/ash/components/strings/ash_components_strings_zh-HK.xtb
@@ -97,6 +97,7 @@
 <translation id="4141203561740478845">突顯網址列所在的行</translation>
 <translation id="4148761611071495477"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="G" /> 鍵或 <ph name="ENTER" /> 鍵</translation>
 <translation id="4240486403425279990">概覽模式</translation>
+<translation id="4276530550848325494"><ph name="KEY" /></translation>
 <translation id="4382340674111381977">返回上一頁</translation>
 <translation id="4458670250301149821">將應用程式圖示移入或移出應用程式格線中的資料夾</translation>
 <translation id="4472417192667361414">系統和顯示設定</translation>
diff --git a/ash/components/strings/ash_components_strings_zh-TW.xtb b/ash/components/strings/ash_components_strings_zh-TW.xtb
index 144809c5..df16f59 100644
--- a/ash/components/strings/ash_components_strings_zh-TW.xtb
+++ b/ash/components/strings/ash_components_strings_zh-TW.xtb
@@ -97,6 +97,7 @@
 <translation id="4141203561740478845">醒目顯示網址列所在的行</translation>
 <translation id="4148761611071495477"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="G" /> 鍵或 <ph name="ENTER" /> 鍵</translation>
 <translation id="4240486403425279990">總覽模式</translation>
+<translation id="4276530550848325494"><ph name="KEY" /></translation>
 <translation id="4382340674111381977">返回上一頁</translation>
 <translation id="4458670250301149821">將應用程式圖示移入或移出應用程式格線中的資料夾</translation>
 <translation id="4472417192667361414">系統與顯示設定</translation>
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index cc25e0408..2d340b29 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -1293,11 +1293,17 @@
   // Ignore all metrics except for those listed in |filter|.
   uint32_t filter = DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_WORK_AREA |
                     DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
-                    DISPLAY_METRIC_ROTATION;
+                    DISPLAY_METRIC_ROTATION | DISPLAY_METRIC_PRIMARY;
   if ((filter & changed_metrics) == 0)
     return;
 
   DoLayout();
+
+  // Set bounds here so that the lock screen widget always shows up on the
+  // primary display. Sometimes the widget bounds are incorrect in the case
+  // where multiple external displays are used. See crbug.com/1031571.
+  GetWidget()->SetBounds(
+      display::Screen::GetScreen()->GetPrimaryDisplay().bounds());
 }
 
 void LockContentsView::OnLockStateChanged(bool locked) {
diff --git a/ash/public/cpp/pagination/pagination_controller.cc b/ash/public/cpp/pagination/pagination_controller.cc
index 916af2c..c54645803 100644
--- a/ash/public/cpp/pagination/pagination_controller.cc
+++ b/ash/public/cpp/pagination/pagination_controller.cc
@@ -33,9 +33,9 @@
 
 PaginationController::~PaginationController() = default;
 
-bool PaginationController::OnScroll(const gfx::Vector2d& offset,
+bool PaginationController::OnScroll(const gfx::Vector2dF& offset,
                                     ui::EventType type) {
-  int offset_magnitude;
+  float offset_magnitude;
   if (scroll_axis_ == SCROLL_AXIS_HORIZONTAL) {
     // If the view scrolls horizontally, both horizontal and vertical scroll
     // events are valid (since most mouse wheels only have vertical scrolling).
@@ -95,13 +95,13 @@
   }
 }
 
-void PaginationController::StartMouseDrag(const gfx::Vector2d& offset) {
+void PaginationController::StartMouseDrag(const gfx::Vector2dF& offset) {
   float scroll =
       scroll_axis_ == SCROLL_AXIS_HORIZONTAL ? offset.x() : offset.y();
   StartDrag(scroll);
 }
 
-void PaginationController::UpdateMouseDrag(const gfx::Vector2d& offset,
+void PaginationController::UpdateMouseDrag(const gfx::Vector2dF& offset,
                                            const gfx::Rect& bounds) {
   float scroll =
       scroll_axis_ == SCROLL_AXIS_HORIZONTAL ? offset.x() : offset.y();
diff --git a/ash/public/cpp/pagination/pagination_controller.h b/ash/public/cpp/pagination/pagination_controller.h
index 38e06f23..6b8cd87 100644
--- a/ash/public/cpp/pagination/pagination_controller.h
+++ b/ash/public/cpp/pagination/pagination_controller.h
@@ -12,7 +12,7 @@
 #include "ui/events/event_constants.h"
 
 namespace gfx {
-class Vector2d;
+class Vector2dF;
 class Rect;
 }  // namespace gfx
 
@@ -41,7 +41,7 @@
   // Handles a mouse wheel or touchpad scroll event in the area represented by
   // the PaginationModel. |offset| is the number of units scrolled in each axis.
   // Returns true if the event was captured and there was some room to scroll.
-  bool OnScroll(const gfx::Vector2d& offset, ui::EventType type);
+  bool OnScroll(const gfx::Vector2dF& offset, ui::EventType type);
 
   // Handles a touch gesture event in the area represented by the
   // PaginationModel. Returns true if the event was captured.
@@ -49,8 +49,8 @@
 
   // Handles a mouse event in the area represented by the PaginationModel.
   // |drag_offset| should be in screen coordinates.
-  void StartMouseDrag(const gfx::Vector2d& drag_offset);
-  void UpdateMouseDrag(const gfx::Vector2d& drag_offset,
+  void StartMouseDrag(const gfx::Vector2dF& drag_offset);
+  void UpdateMouseDrag(const gfx::Vector2dF& drag_offset,
                        const gfx::Rect& bounds);
   void EndMouseDrag(const ui::MouseEvent& event);
 
diff --git a/ash/shelf/hotseat_widget.cc b/ash/shelf/hotseat_widget.cc
index 9fabb2c10..9e86d52 100644
--- a/ash/shelf/hotseat_widget.cc
+++ b/ash/shelf/hotseat_widget.cc
@@ -63,11 +63,7 @@
   bool GetHitTestRects(aura::Window* target,
                        gfx::Rect* hit_test_rect_mouse,
                        gfx::Rect* hit_test_rect_touch) const override {
-    // If the hotseat is not extended we can use the normal targeting as the
-    // hidden parts of the hotseat will not block non-shelf items from taking
-    // events.
-    if (target == hotseat_widget_->GetNativeWindow() &&
-        hotseat_widget_->state() == HotseatState::kExtended) {
+    if (target == hotseat_widget_->GetNativeWindow()) {
       // Shrink the hit bounds from the size of the window to the size of the
       // hotseat opaque background.
       gfx::Rect hit_bounds = target->bounds();
@@ -247,9 +243,6 @@
     scrollable_shelf_view_ = GetContentsView()->AddChildView(
         std::make_unique<ScrollableShelfView>(ShelfModel::Get(), shelf));
     scrollable_shelf_view_->Init();
-
-    hotseat_window_targeter_ = std::make_unique<aura::ScopedWindowTargeter>(
-        GetNativeWindow(), std::make_unique<HotseatWindowTargeter>(this));
   } else {
     // The shelf view observes the shelf model and creates icons as items are
     // added to the model.
@@ -390,6 +383,18 @@
     return;
 
   state_ = state;
+
+  if (!IsScrollableShelfEnabled())
+    return;
+
+  // If the hotseat is not extended we can use the normal targeting as the
+  // hidden parts of the hotseat will not block non-shelf items from taking
+  if (state == HotseatState::kExtended) {
+    hotseat_window_targeter_ = std::make_unique<aura::ScopedWindowTargeter>(
+        GetNativeWindow(), std::make_unique<HotseatWindowTargeter>(this));
+  } else {
+    hotseat_window_targeter_.reset();
+  }
 }
 
 }  // namespace ash
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc
index 8c228b3..10cc28d92 100644
--- a/ash/shelf/scrollable_shelf_view.cc
+++ b/ash/shelf/scrollable_shelf_view.cc
@@ -958,7 +958,9 @@
   shelf_view_->ShowContextMenuForViewImpl(shelf_view_, point, source_type);
 }
 
-void ScrollableShelfView::OnShelfAlignmentChanged(aura::Window* root_window) {
+void ScrollableShelfView::OnShelfAlignmentChanged(
+    aura::Window* root_window,
+    ShelfAlignment old_alignment) {
   const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment();
   left_arrow_->set_is_horizontal_alignment(is_horizontal_alignment);
   right_arrow_->set_is_horizontal_alignment(is_horizontal_alignment);
diff --git a/ash/shelf/scrollable_shelf_view.h b/ash/shelf/scrollable_shelf_view.h
index dc3e8b42..78f73b4 100644
--- a/ash/shelf/scrollable_shelf_view.h
+++ b/ash/shelf/scrollable_shelf_view.h
@@ -192,8 +192,9 @@
                                   const gfx::Point& point,
                                   ui::MenuSourceType source_type) override;
 
-  // Overridden from ShellObserver:
-  void OnShelfAlignmentChanged(aura::Window* root_window) override;
+  // ShellObserver:
+  void OnShelfAlignmentChanged(aura::Window* root_window,
+                               ShelfAlignment old_alignment) override;
 
   // ShelfTooltipDelegate:
   bool ShouldShowTooltipForView(const views::View* view) const override;
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc
index bf6e6c98..5a6a90a 100644
--- a/ash/shelf/shelf.cc
+++ b/ash/shelf/shelf.cc
@@ -263,12 +263,14 @@
     return;
   }
 
+  ShelfAlignment old_alignment = alignment_;
   alignment_ = alignment;
   // The ShelfWidget notifies the ShelfView of the alignment change.
   shelf_widget_->OnShelfAlignmentChanged();
   tooltip_->Close();
   shelf_layout_manager_->LayoutShelf();
-  Shell::Get()->NotifyShelfAlignmentChanged(GetWindow()->GetRootWindow());
+  Shell::Get()->NotifyShelfAlignmentChanged(GetWindow()->GetRootWindow(),
+                                            old_alignment);
 }
 
 bool Shelf::IsHorizontalAlignment() const {
diff --git a/ash/shelf/shelf_navigation_widget.cc b/ash/shelf/shelf_navigation_widget.cc
index cc83a13..fd4ed79 100644
--- a/ash/shelf/shelf_navigation_widget.cc
+++ b/ash/shelf/shelf_navigation_widget.cc
@@ -311,7 +311,9 @@
   UpdateLayout(/*animate=*/true);
 }
 
-void ShelfNavigationWidget::OnShelfAlignmentChanged(aura::Window* root_window) {
+void ShelfNavigationWidget::OnShelfAlignmentChanged(
+    aura::Window* root_window,
+    ShelfAlignment old_alignment) {
   UpdateLayout(/*animate=*/false);
 }
 
diff --git a/ash/shelf/shelf_navigation_widget.h b/ash/shelf/shelf_navigation_widget.h
index 1e260178..2539462 100644
--- a/ash/shelf/shelf_navigation_widget.h
+++ b/ash/shelf/shelf_navigation_widget.h
@@ -68,7 +68,8 @@
   void OnTabletModeEnded() override;
 
   // ShellObserver:
-  void OnShelfAlignmentChanged(aura::Window* root_window) override;
+  void OnShelfAlignmentChanged(aura::Window* root_window,
+                               ShelfAlignment old_alignment) override;
 
   // ui::ImplicitAnimationObserver:
   void OnImplicitAnimationsCompleted() override;
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 2982c796..37cce9a 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -540,8 +540,8 @@
   overflow_view->overflow_mode_ = true;
   overflow_view->Init();
   overflow_view->set_owner_overflow_bubble(overflow_bubble_.get());
-  overflow_view->OnShelfAlignmentChanged(
-      GetWidget()->GetNativeWindow()->GetRootWindow());
+  aura::Window* root_window = GetWidget()->GetNativeWindow()->GetRootWindow();
+  overflow_view->OnShelfAlignmentChanged(root_window, shelf_->alignment());
   overflow_view->main_shelf_ = this;
   UpdateOverflowRange(overflow_view);
 
@@ -2408,7 +2408,8 @@
   button->SchedulePaint();
 }
 
-void ShelfView::OnShelfAlignmentChanged(aura::Window* root_window) {
+void ShelfView::OnShelfAlignmentChanged(aura::Window* root_window,
+                                        ShelfAlignment old_alignment) {
   LayoutToIdealBounds();
   for (int i = 0; i < view_model_->view_size(); ++i) {
     if (i >= first_visible_index_ && i <= last_visible_index_)
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index 40577f54..4fa7c2e 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -510,7 +510,8 @@
   void ShelfItemStatusChanged(const ShelfID& id) override;
 
   // Overridden from ShellObserver:
-  void OnShelfAlignmentChanged(aura::Window* root_window) override;
+  void OnShelfAlignmentChanged(aura::Window* root_window,
+                               ShelfAlignment old_alignment) override;
   void OnShelfAutoHideBehaviorChanged(aura::Window* root_window) override;
 
   // Shows a shelf context menu with the given |model|, or a default menu.
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc
index accf088..73e2d9b3 100644
--- a/ash/shelf/shelf_widget_unittest.cc
+++ b/ash/shelf/shelf_widget_unittest.cc
@@ -281,27 +281,9 @@
   }
 }
 
-class ShelfWidgetTestWithoutHotseat : public ShelfWidgetTest {
- public:
-  ShelfWidgetTestWithoutHotseat() = default;
-  ~ShelfWidgetTestWithoutHotseat() override = default;
-
-  void SetUp() override {
-    scoped_features_.InitAndDisableFeature(chromeos::features::kShelfHotseat);
-    ShelfWidgetTest::SetUp();
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_features_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfWidgetTestWithoutHotseat);
-};
-
 // Tests that the shelf lets mouse-events close to the edge fall through to the
 // window underneath.
-// TODO(andrewxu|mmourgos): Fix this test with hotseat feature enabled.
-// crbug.com/1037927
-TEST_F(ShelfWidgetTestWithoutHotseat, ShelfEdgeOverlappingWindowHitTestMouse) {
+TEST_F(ShelfWidgetTest, ShelfEdgeOverlappingWindowHitTestMouse) {
   UpdateDisplay("400x400");
   ShelfWidget* shelf_widget = GetShelfWidget();
   gfx::Rect shelf_bounds = shelf_widget->GetWindowBoundsInScreen();
diff --git a/ash/shell.cc b/ash/shell.cc
index b5e27220d..b1fec30d 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -507,9 +507,10 @@
     observer.OnUserWorkAreaInsetsChanged(root_window);
 }
 
-void Shell::NotifyShelfAlignmentChanged(aura::Window* root_window) {
+void Shell::NotifyShelfAlignmentChanged(aura::Window* root_window,
+                                        ShelfAlignment old_alignment) {
   for (auto& observer : shell_observers_)
-    observer.OnShelfAlignmentChanged(root_window);
+    observer.OnShelfAlignmentChanged(root_window, old_alignment);
 }
 
 void Shell::NotifyShelfAutoHideBehaviorChanged(aura::Window* root_window) {
diff --git a/ash/shell.h b/ash/shell.h
index 964c61af..8aa3d9d6 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -544,7 +544,8 @@
 
   // Notifies observers that |root_window|'s shelf changed alignment.
   // TODO(jamescook): Move to Shelf.
-  void NotifyShelfAlignmentChanged(aura::Window* root_window);
+  void NotifyShelfAlignmentChanged(aura::Window* root_window,
+                                   ShelfAlignment old_alignment);
 
   // Notifies observers that |root_window|'s shelf changed auto-hide behavior.
   // TODO(jamescook): Move to Shelf.
diff --git a/ash/shell_observer.h b/ash/shell_observer.h
index 7914726..92e170d 100644
--- a/ash/shell_observer.h
+++ b/ash/shell_observer.h
@@ -7,6 +7,7 @@
 
 #include "ash/ash_export.h"
 #include "ash/login_status.h"
+#include "ash/public/cpp/shelf_types.h"
 
 namespace aura {
 class Window;
@@ -23,7 +24,8 @@
   virtual void OnRootWindowAdded(aura::Window* root_window) {}
 
   // Invoked when the shelf alignment in |root_window| is changed.
-  virtual void OnShelfAlignmentChanged(aura::Window* root_window) {}
+  virtual void OnShelfAlignmentChanged(aura::Window* root_window,
+                                       ShelfAlignment old_alignment) {}
 
   // Invoked when user work area insets (accessibility panel, docked magnifier,
   // keyboard) in |root_window| changed.
diff --git a/ash/strings/ash_strings_af.xtb b/ash/strings/ash_strings_af.xtb
index eb4a5eba..511f5820 100644
--- a/ash/strings/ash_strings_af.xtb
+++ b/ash/strings/ash_strings_af.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Stop skermdeling?</translation>
 <translation id="5820394555380036790">Chromium-bedryfstelsel</translation>
 <translation id="5837036133683224804">Stop <ph name="ROUTE_TITLE" /> op <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Af</translation>
 <translation id="5895138241574237353">Herbegin</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_am.xtb b/ash/strings/ash_strings_am.xtb
index ecf223a..91694b1 100644
--- a/ash/strings/ash_strings_am.xtb
+++ b/ash/strings/ash_strings_am.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">ማያ ገጽ ማጋራት ይቁም?</translation>
 <translation id="5820394555380036790">Chromium ስርዓተ ክወና</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> ላይ <ph name="ROUTE_TITLE" />ን አስቁም</translation>
-<translation id="5860033963881614850">አጥፋ</translation>
 <translation id="5895138241574237353">እንደገና ጀምር</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ar.xtb b/ash/strings/ash_strings_ar.xtb
index 86033b1..c38dbf9 100644
--- a/ash/strings/ash_strings_ar.xtb
+++ b/ash/strings/ash_strings_ar.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">هل ترغب في إيقاف مشاركة الشاشة؟</translation>
 <translation id="5820394555380036790">‏نظام التشغيل Chromium</translation>
 <translation id="5837036133683224804">إيقاف <ph name="ROUTE_TITLE" /> في <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">غير مفعّل</translation>
 <translation id="5895138241574237353">إعادة التشغيل</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_as.xtb b/ash/strings/ash_strings_as.xtb
index 2486657..298ccd6 100644
--- a/ash/strings/ash_strings_as.xtb
+++ b/ash/strings/ash_strings_as.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">স্ক্ৰীণ শ্বেয়াৰ কৰাটো বন্ধ কৰিবনে?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />ত <ph name="ROUTE_TITLE" /> বন্ধ কৰক</translation>
-<translation id="5860033963881614850">অফ আছে</translation>
 <translation id="5895138241574237353">ৰিষ্টাৰ্ট কৰক</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_az.xtb b/ash/strings/ash_strings_az.xtb
index eb531fae..d57cab77 100644
--- a/ash/strings/ash_strings_az.xtb
+++ b/ash/strings/ash_strings_az.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Ekran paylaşımı dayandırılsın?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> pəncərəsində <ph name="ROUTE_TITLE" /> dayandırma düyməsi</translation>
-<translation id="5860033963881614850">Deaktiv</translation>
 <translation id="5895138241574237353">Yenidən başladın</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_be.xtb b/ash/strings/ash_strings_be.xtb
index d442156..b615dfaa 100644
--- a/ash/strings/ash_strings_be.xtb
+++ b/ash/strings/ash_strings_be.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Спыніць абагульванне экрана?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Спыніць трансляцыю <ph name="ROUTE_TITLE" /> на <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Выключана</translation>
 <translation id="5895138241574237353">Перазапусціць</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_bg.xtb b/ash/strings/ash_strings_bg.xtb
index a482a8f..e2400067 100644
--- a/ash/strings/ash_strings_bg.xtb
+++ b/ash/strings/ash_strings_bg.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Да се спре ли споделянето на екрана?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Спиране на предаването на <ph name="ROUTE_TITLE" /> към „<ph name="RECEIVER_NAME" />“</translation>
-<translation id="5860033963881614850">Изключено</translation>
 <translation id="5895138241574237353">Рестартиране</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_bn.xtb b/ash/strings/ash_strings_bn.xtb
index c66b52f..7a8c11a 100644
--- a/ash/strings/ash_strings_bn.xtb
+++ b/ash/strings/ash_strings_bn.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">স্ক্রিন শেয়ার করা থামাবেন?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />-এ <ph name="ROUTE_TITLE" /> বন্ধ করুন</translation>
-<translation id="5860033963881614850">বন্ধ করুন</translation>
 <translation id="5895138241574237353">পুনর্সূচনা</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_bs.xtb b/ash/strings/ash_strings_bs.xtb
index 1e19ba8..f39c40d 100644
--- a/ash/strings/ash_strings_bs.xtb
+++ b/ash/strings/ash_strings_bs.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Zaustaviti dijeljenje ekrana?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Zaustavi <ph name="ROUTE_TITLE" /> na primaocu <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Isklj.</translation>
 <translation id="5895138241574237353">Ponovo pokreni</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ca.xtb b/ash/strings/ash_strings_ca.xtb
index 826e80cf..625a3e1 100644
--- a/ash/strings/ash_strings_ca.xtb
+++ b/ash/strings/ash_strings_ca.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Vols aturar la compartició de pantalla?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Atura <ph name="ROUTE_TITLE" /> a <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Desactivat</translation>
 <translation id="5895138241574237353">Reinicia</translation>
 <translation id="5901316534475909376">Maj + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_cs.xtb b/ash/strings/ash_strings_cs.xtb
index b8b2f16..9671d6b1 100644
--- a/ash/strings/ash_strings_cs.xtb
+++ b/ash/strings/ash_strings_cs.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Ukončit sdílení obrazovky?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Zastavit <ph name="ROUTE_TITLE" /> na přijímači <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Vypnuto</translation>
 <translation id="5895138241574237353">Restartovat</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> <ph name="MAIL" /></translation>
diff --git a/ash/strings/ash_strings_da.xtb b/ash/strings/ash_strings_da.xtb
index 0cff630..b93bba5 100644
--- a/ash/strings/ash_strings_da.xtb
+++ b/ash/strings/ash_strings_da.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Vil du afslutte skærmdeling?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Stop <ph name="ROUTE_TITLE" /> på <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Fra</translation>
 <translation id="5895138241574237353">Genstart</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_de.xtb b/ash/strings/ash_strings_de.xtb
index 6076c7c..81960e0 100644
--- a/ash/strings/ash_strings_de.xtb
+++ b/ash/strings/ash_strings_de.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Bildschirmfreigabe beenden?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="ROUTE_TITLE" /> auf <ph name="RECEIVER_NAME" /> beenden</translation>
-<translation id="5860033963881614850">Aus</translation>
 <translation id="5895138241574237353">Neu starten</translation>
 <translation id="5901316534475909376">Umschalttaste + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_el.xtb b/ash/strings/ash_strings_el.xtb
index 5daea524..b7c74cd 100644
--- a/ash/strings/ash_strings_el.xtb
+++ b/ash/strings/ash_strings_el.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Θέλετε να σταματήσετε να μοιράζεστε την οθόνη;</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Διακοπή <ph name="ROUTE_TITLE" /> σε <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Απενεργοποιημένη</translation>
 <translation id="5895138241574237353">Επανεκκίνηση</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_en-GB.xtb b/ash/strings/ash_strings_en-GB.xtb
index 404d742..15cdbb5 100644
--- a/ash/strings/ash_strings_en-GB.xtb
+++ b/ash/strings/ash_strings_en-GB.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Stop screen sharing?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Stop <ph name="ROUTE_TITLE" /> on <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Off</translation>
 <translation id="5895138241574237353">Restart</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_es-419.xtb b/ash/strings/ash_strings_es-419.xtb
index f7bcedf..ac770b3 100644
--- a/ash/strings/ash_strings_es-419.xtb
+++ b/ash/strings/ash_strings_es-419.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">¿Dejar de compartir la pantalla?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Detener <ph name="ROUTE_TITLE" /> en <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">No</translation>
 <translation id="5895138241574237353">Reiniciar</translation>
 <translation id="5901316534475909376">Mayúscula + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_es.xtb b/ash/strings/ash_strings_es.xtb
index 99ff1e11..99cbe87 100644
--- a/ash/strings/ash_strings_es.xtb
+++ b/ash/strings/ash_strings_es.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">¿Dejar de compartir la pantalla?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Parar <ph name="ROUTE_TITLE" /> en <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Desactivado</translation>
 <translation id="5895138241574237353">Reiniciar</translation>
 <translation id="5901316534475909376">Mayús+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_et.xtb b/ash/strings/ash_strings_et.xtb
index e69d9ca..1abdf648 100644
--- a/ash/strings/ash_strings_et.xtb
+++ b/ash/strings/ash_strings_et.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Kas peatada ekraani jagamine?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Katkesta <ph name="ROUTE_TITLE" /> asukohas <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Väljas</translation>
 <translation id="5895138241574237353">Taaskäivitamine</translation>
 <translation id="5901316534475909376">Tõstuklahv + ESC</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_eu.xtb b/ash/strings/ash_strings_eu.xtb
index be7aff1..7e6862aa 100644
--- a/ash/strings/ash_strings_eu.xtb
+++ b/ash/strings/ash_strings_eu.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Pantaila-partekatzea gelditu nahi duzu?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Utzi <ph name="ROUTE_TITLE" /> (<ph name="RECEIVER_NAME" />) hargailura igortzeari</translation>
-<translation id="5860033963881614850">Desaktibatuta</translation>
 <translation id="5895138241574237353">Berrabiarazi</translation>
 <translation id="5901316534475909376">Maius + Ihes</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_fa.xtb b/ash/strings/ash_strings_fa.xtb
index 742f0f302..7ca5903 100644
--- a/ash/strings/ash_strings_fa.xtb
+++ b/ash/strings/ash_strings_fa.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">اشتراک‌گذاری صفحه نمایش متوقف شود؟</translation>
 <translation id="5820394555380036790">‏سیستم عامل Chromium </translation>
 <translation id="5837036133683224804">توقف <ph name="ROUTE_TITLE" /> به <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">خاموش</translation>
 <translation id="5895138241574237353">راه‌اندازی مجدد</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_fi.xtb b/ash/strings/ash_strings_fi.xtb
index 21479fc..fd02c0d5a 100644
--- a/ash/strings/ash_strings_fi.xtb
+++ b/ash/strings/ash_strings_fi.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Lopetetaanko näytön jakaminen?</translation>
 <translation id="5820394555380036790">Chromium-käyttöjärjestelmä</translation>
 <translation id="5837036133683224804">Lopeta <ph name="ROUTE_TITLE" /> – <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Pois päältä</translation>
 <translation id="5895138241574237353">Käynnistä uudelleen</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_fil.xtb b/ash/strings/ash_strings_fil.xtb
index 5a7659ea..fbf7734 100644
--- a/ash/strings/ash_strings_fil.xtb
+++ b/ash/strings/ash_strings_fil.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Itigil ang screen sharing?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Ihinto ang <ph name="ROUTE_TITLE" /> sa <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Naka-off</translation>
 <translation id="5895138241574237353">I-restart</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_fr-CA.xtb b/ash/strings/ash_strings_fr-CA.xtb
index 236cb9e..98f56ac 100644
--- a/ash/strings/ash_strings_fr-CA.xtb
+++ b/ash/strings/ash_strings_fr-CA.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Arrêter le partage d'écran?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Arrêter <ph name="ROUTE_TITLE" /> sur <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Désactivé</translation>
 <translation id="5895138241574237353">Redémarrer</translation>
 <translation id="5901316534475909376">Maj+Échap</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_fr.xtb b/ash/strings/ash_strings_fr.xtb
index cf8ead67..e64708b9 100644
--- a/ash/strings/ash_strings_fr.xtb
+++ b/ash/strings/ash_strings_fr.xtb
@@ -36,7 +36,7 @@
 <translation id="1312604459020188865">Force du signal : <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="1316069254387866896">Toujours afficher l'étagère</translation>
 <translation id="1341651618736211726">Dépassement</translation>
-<translation id="1346748346194534595">Vers la droite</translation>
+<translation id="1346748346194534595">À droite</translation>
 <translation id="1351937230027495976">Réduire le menu</translation>
 <translation id="1383876407941801731">Rechercher</translation>
 <translation id="1419738280318246476">Déverrouiller l'appareil pour effectuer l'action de notification</translation>
@@ -44,7 +44,7 @@
 <translation id="1426410128494586442">Oui</translation>
 <translation id="1455242230282523554">Afficher les paramètres de langue</translation>
 <translation id="1460620680449458626">Le volume est désactivé.</translation>
-<translation id="1467432559032391204">Vers la gauche</translation>
+<translation id="1467432559032391204">À gauche</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1516740043221086139">Le mode Ne pas déranger est activé.</translation>
 <translation id="1520303207432623762">{NUM_APPS,plural, =1{Afficher les paramètres de notification. Les notifications sont désactivées pour une application}one{Afficher les paramètres de notification. Les notifications sont désactivées pour # application}other{Afficher les paramètres de notification. Les notifications sont désactivées pour # applications}}</translation>
@@ -160,7 +160,7 @@
 <translation id="3055162170959710888">Vous avez utilisé l'appareil pendant <ph name="USED_TIME" /> aujourd'hui</translation>
 <translation id="3077734595579995578">maj</translation>
 <translation id="3081696990447829002">Développer le menu</translation>
-<translation id="3087734570205094154">Bas</translation>
+<translation id="3087734570205094154">En bas</translation>
 <translation id="3105990244222795498"><ph name="DEVICE_NAME" /> (Bluetooth)</translation>
 <translation id="3126069444801937830">Redémarrer pour mettre à jour</translation>
 <translation id="3139942575505304791">Bureau 1</translation>
@@ -297,7 +297,7 @@
 <translation id="4918086044614829423">Accepter</translation>
 <translation id="4924411785043111640">Redémarrer et réinitialiser</translation>
 <translation id="495046168593986294">Faire défiler vers le haut</translation>
-<translation id="4961318399572185831">Diffuser l'écran</translation>
+<translation id="4961318399572185831">Caster l'écran</translation>
 <translation id="5018302031617932556">Cette fonctionnalité facilite la lecture à l'écran lorsque l'éclairage est faible. Appuyez pour modifier ce paramètre.</translation>
 <translation id="5030687792513154421">Temps écoulé</translation>
 <translation id="5035236842988137213">L'appareil <ph name="DEVICE_NAME" /> est associé à un nouveau téléphone</translation>
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Arrêter le partage d'écran ?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Arrêter <ph name="ROUTE_TITLE" /> vers <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Désactivé</translation>
 <translation id="5895138241574237353">Redémarrer</translation>
 <translation id="5901316534475909376">Maj+Échap</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
@@ -353,7 +352,7 @@
 <translation id="5947494881799873997">Rétablir</translation>
 <translation id="595202126637698455">Suivi des performances activé</translation>
 <translation id="5957083217255311415">Les données mobiles sont désactivées.</translation>
-<translation id="5958529069007801266">Utilisateur supervisé</translation>
+<translation id="5958529069007801266">Utilis. supervisé</translation>
 <translation id="5977415296283489383">Casque</translation>
 <translation id="5978382165065462689">Partager le contrôle de votre écran via l'assistance à distance</translation>
 <translation id="5980301590375426705">Fermer la session Invité</translation>
@@ -380,7 +379,7 @@
 <translation id="6267036997247669271"><ph name="NAME" /> : activation en cours…</translation>
 <translation id="6283712521836204486">Le mode Ne pas déranger est désactivé.</translation>
 <translation id="6284232397434400372">Résolution modifiée</translation>
-<translation id="6297287540776456956">Utiliser le stylet pour sélectionner une zone</translation>
+<translation id="6297287540776456956">Utilisez le stylet pour sélectionner une zone</translation>
 <translation id="6310121235600822547">L'écran "<ph name="DISPLAY_NAME" />" a effectué une rotation de <ph name="ROTATION" />.</translation>
 <translation id="6376931439017688372">Bluetooth activé</translation>
 <translation id="639644700271529076">La touche de verrouillage des majuscules est désactivée.</translation>
@@ -517,7 +516,7 @@
 <translation id="8190698733819146287">Personnaliser les langues et la saisie...</translation>
 <translation id="8192202700944119416">Les notifications sont masquées.</translation>
 <translation id="8203795194971602413">Clic droit</translation>
-<translation id="8236042855478648955">Il est temps de faire une pause</translation>
+<translation id="8236042855478648955">Une pause s'impose !</translation>
 <translation id="8247060538831475781"><ph name="CONNECTION_STATUS" />, force du signal : <ph name="SIGNAL_STRENGTH" />, batterie du téléphone à <ph name="BATTERY_STATUS" /></translation>
 <translation id="826107067893790409">Appuyez sur Entrée pour déverrouiller l'appareil pour <ph name="USER_EMAIL_ADDRESS" /></translation>
 <translation id="8261506727792406068">Supprimer</translation>
@@ -601,7 +600,7 @@
 <translation id="921989828232331238">Ton parent a verrouillé ton appareil pour la journée</translation>
 <translation id="923686485342484400">Appuyez deux fois sur Contrôle + Maj + Q pour vous déconnecter.</translation>
 <translation id="938963181863597773">Qu'y a-t-il dans mon agenda ?</translation>
-<translation id="945522503751344254">Envoyer le commentaire</translation>
+<translation id="945522503751344254">Envoyer un commentaire</translation>
 <translation id="98515147261107953">Paysage</translation>
 <translation id="990277280839877440">Fenêtre <ph name="WINDOW_TITILE" /> fermée.</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/ash/strings/ash_strings_gl.xtb b/ash/strings/ash_strings_gl.xtb
index c68a3f8..2b917b69 100644
--- a/ash/strings/ash_strings_gl.xtb
+++ b/ash/strings/ash_strings_gl.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Queres deter o uso compartido da pantalla?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Deter <ph name="ROUTE_TITLE" /> no receptor <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Non</translation>
 <translation id="5895138241574237353">Reiniciar</translation>
 <translation id="5901316534475909376">Maiúsculas+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_gu.xtb b/ash/strings/ash_strings_gu.xtb
index f57be493..0efba6cf 100644
--- a/ash/strings/ash_strings_gu.xtb
+++ b/ash/strings/ash_strings_gu.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">સ્ક્રીન શેરિંગ રોકીએ?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> પર <ph name="ROUTE_TITLE" />ને રોકો</translation>
-<translation id="5860033963881614850">બંધ</translation>
 <translation id="5895138241574237353">પુનઃપ્રારંભ કરો</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_hi.xtb b/ash/strings/ash_strings_hi.xtb
index 5430711..d12c51b 100644
--- a/ash/strings/ash_strings_hi.xtb
+++ b/ash/strings/ash_strings_hi.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">स्‍क्रीन साझाकरण बंद करें?</translation>
 <translation id="5820394555380036790">क्रोमियम OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> पर <ph name="ROUTE_TITLE" /> बंद करें</translation>
-<translation id="5860033963881614850">बंद</translation>
 <translation id="5895138241574237353">फिर से प्रारंभ करें</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_hr.xtb b/ash/strings/ash_strings_hr.xtb
index 6ff2a42..a7e063b 100644
--- a/ash/strings/ash_strings_hr.xtb
+++ b/ash/strings/ash_strings_hr.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Prekinuti dijeljenje zaslona?</translation>
 <translation id="5820394555380036790">OS Chromium</translation>
 <translation id="5837036133683224804">Zaustavite <ph name="ROUTE_TITLE" /> na uređaju <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Isključeno</translation>
 <translation id="5895138241574237353">Ponovno pokreni</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_hu.xtb b/ash/strings/ash_strings_hu.xtb
index 7e59286..dfaa513 100644
--- a/ash/strings/ash_strings_hu.xtb
+++ b/ash/strings/ash_strings_hu.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Leállítja a képernyőmegosztást?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">A(z) <ph name="ROUTE_TITLE" /> leállítása itt: <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Kikapcsolva</translation>
 <translation id="5895138241574237353">Újraindítás</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_hy.xtb b/ash/strings/ash_strings_hy.xtb
index 5f854431..4f43d68 100644
--- a/ash/strings/ash_strings_hy.xtb
+++ b/ash/strings/ash_strings_hy.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Դադարեցնե՞լ էկրանի համօգտագործումը:</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Դադարեցնել <ph name="ROUTE_TITLE" /> ներդիրի հեռարձակումը «<ph name="RECEIVER_NAME" />» սարքին</translation>
-<translation id="5860033963881614850">Անջատ.</translation>
 <translation id="5895138241574237353">Վերագործարկել</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_id.xtb b/ash/strings/ash_strings_id.xtb
index 008aec3b..409d0c2 100644
--- a/ash/strings/ash_strings_id.xtb
+++ b/ash/strings/ash_strings_id.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Berhenti membagikan layar?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Hentikan <ph name="ROUTE_TITLE" /> di <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Nonaktif</translation>
 <translation id="5895138241574237353">Mulai Ulang</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_is.xtb b/ash/strings/ash_strings_is.xtb
index d31dc44..3a91c83 100644
--- a/ash/strings/ash_strings_is.xtb
+++ b/ash/strings/ash_strings_is.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Stöðva skjádeilingu?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Stöðva <ph name="ROUTE_TITLE" /> í <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Slökkt</translation>
 <translation id="5895138241574237353">Endurræsa</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_it.xtb b/ash/strings/ash_strings_it.xtb
index 9c07066..676f342 100644
--- a/ash/strings/ash_strings_it.xtb
+++ b/ash/strings/ash_strings_it.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Interrompere la condivisione dello schermo?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Interrompi <ph name="ROUTE_TITLE" /> su <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">OFF</translation>
 <translation id="5895138241574237353">Riavvia</translation>
 <translation id="5901316534475909376">MAIUSC+ESC</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_iw.xtb b/ash/strings/ash_strings_iw.xtb
index a95398c..fc75e62 100644
--- a/ash/strings/ash_strings_iw.xtb
+++ b/ash/strings/ash_strings_iw.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">להפסיק את שיתוף המסך?</translation>
 <translation id="5820394555380036790">‏מערכת ההפעלה של Chromium</translation>
 <translation id="5837036133683224804">הפסקת <ph name="ROUTE_TITLE" /> במכשיר <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">כבוי</translation>
 <translation id="5895138241574237353">הפעל מחדש</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ja.xtb b/ash/strings/ash_strings_ja.xtb
index d05d1bd..b3342e4 100644
--- a/ash/strings/ash_strings_ja.xtb
+++ b/ash/strings/ash_strings_ja.xtb
@@ -49,7 +49,7 @@
 <translation id="1516740043221086139">サイレント モードはオンです。</translation>
 <translation id="1520303207432623762">{NUM_APPS,plural, =1{通知設定を表示します。1 件のアプリで通知がオフになっています}other{通知設定を表示します。# 件のアプリで通知がオフになっています}}</translation>
 <translation id="1525508553941733066">閉じる</translation>
-<translation id="15373452373711364">大きいマウス カーソル</translation>
+<translation id="15373452373711364">大きいマウスカーソル</translation>
 <translation id="1546492247443594934">デスク 2</translation>
 <translation id="1550523713251050646">クリックするとその他のオプションが表示されます</translation>
 <translation id="1570871743947603115">Bluetooth を切り替えます。<ph name="STATE_TEXT" /></translation>
@@ -340,12 +340,11 @@
 <translation id="574392208103952083">中</translation>
 <translation id="5744083938413354016">タップによるドラッグ</translation>
 <translation id="5745612484876805746">夜間モードは日の入り時刻に自動的にオンになります</translation>
-<translation id="5750765938512549687">Bluetooth がオフです</translation>
+<translation id="5750765938512549687">Bluetooth はオフです</translation>
 <translation id="576453121877257266">夜間モードはオンです。</translation>
 <translation id="5777841717266010279">画面の共有を解除しますか?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> の「<ph name="ROUTE_TITLE" />」を停止します</translation>
-<translation id="5860033963881614850">オフ</translation>
 <translation id="5895138241574237353">再起動</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" />(<ph name="MAIL" />)</translation>
@@ -382,7 +381,7 @@
 <translation id="6284232397434400372">解像度が変更されました</translation>
 <translation id="6297287540776456956">タッチペンを使って部分を選択してください</translation>
 <translation id="6310121235600822547"><ph name="DISPLAY_NAME" /> を <ph name="ROTATION" /> に回転しました</translation>
-<translation id="6376931439017688372">Bluetooth がオンです</translation>
+<translation id="6376931439017688372">Bluetooth はオンです</translation>
 <translation id="639644700271529076">CapsLock 機能はオフになっています</translation>
 <translation id="6406704438230478924">altgr</translation>
 <translation id="6424520630891723617"><ph name="SECURITY_STATUS" />、信号強度 <ph name="SIGNAL_STRENGTH" /></translation>
@@ -495,14 +494,14 @@
 <translation id="7886277072580235377">ログアウトするとインターネット セッションは終了します。<ph name="LEARN_MORE" /></translation>
 <translation id="788781083998633524">メールを送って</translation>
 <translation id="7897375687985782769">画面回転のキーボード ショートカットを押しました。画面を回転しますか?</translation>
-<translation id="7904094684485781019">このアカウントの管理者がマルチ ログインを許可していません。</translation>
+<translation id="7904094684485781019">このアカウントの管理者がマルチログインを許可していません。</translation>
 <translation id="7933084174919150729">Google アシスタントはメインのプロフィールでのみご利用いただけます。</translation>
 <translation id="79341161159229895">このアカウントは <ph name="FIRST_PARENT_EMAIL" /> と <ph name="SECOND_PARENT_EMAIL" /> により管理されています</translation>
 <translation id="7955885781510802139">ハイコントラスト モード</translation>
 <translation id="7977927628060636163">モバイル ネットワークを検索しています...</translation>
 <translation id="7982789257301363584">ネットワーク</translation>
 <translation id="7984197416080286869">指紋認証の試行回数が上限を超えています</translation>
-<translation id="7994370417837006925">マルチ ログイン</translation>
+<translation id="7994370417837006925">マルチログイン</translation>
 <translation id="8000066093800657092">ネットワーク接続なし</translation>
 <translation id="8030169304546394654">切断済み</translation>
 <translation id="8054466585765276473">バッテリーの残り時間を計算しています。</translation>
diff --git a/ash/strings/ash_strings_ka.xtb b/ash/strings/ash_strings_ka.xtb
index 23fc6f5..933cc46 100644
--- a/ash/strings/ash_strings_ka.xtb
+++ b/ash/strings/ash_strings_ka.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">შევწყვიტოთ ეკრანის გაზიარება?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="ROUTE_TITLE" />-ის შეწყვეტა „<ph name="RECEIVER_NAME" />“-ში</translation>
-<translation id="5860033963881614850">გამორთვა</translation>
 <translation id="5895138241574237353">გადატვირთვა</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_kk.xtb b/ash/strings/ash_strings_kk.xtb
index cb77fe7..a1dad586 100644
--- a/ash/strings/ash_strings_kk.xtb
+++ b/ash/strings/ash_strings_kk.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Экран бөлісуді тоқтату қажет пе?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> қабылдағышында <ph name="ROUTE_TITLE" /> трансляциясын тоқтату</translation>
-<translation id="5860033963881614850">Өшірулі</translation>
 <translation id="5895138241574237353">Қайта іске қосу</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_km.xtb b/ash/strings/ash_strings_km.xtb
index 1570af4..1b437a7 100644
--- a/ash/strings/ash_strings_km.xtb
+++ b/ash/strings/ash_strings_km.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">បញ្ឈប់ការចែករំលែកអេក្រង់?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">បញ្ឈប់ <ph name="ROUTE_TITLE" /> នៅលើ <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">បិទ</translation>
 <translation id="5895138241574237353">ចាប់ផ្តើមឡើងវិញ</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_kn.xtb b/ash/strings/ash_strings_kn.xtb
index 781fb51a..3ece4d52 100644
--- a/ash/strings/ash_strings_kn.xtb
+++ b/ash/strings/ash_strings_kn.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">ಸ್ಕ್ರೀನ್ ಹಂಚಿಕೆ ನಿಲ್ಲಿಸುವುದೇ?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> ನಲ್ಲಿ <ph name="ROUTE_TITLE" /> ನಿಲ್ಲಿಸಿ</translation>
-<translation id="5860033963881614850">ಆಫ್</translation>
 <translation id="5895138241574237353">ಮರುಪ್ರಾರಂಭಿಸಿ</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ko.xtb b/ash/strings/ash_strings_ko.xtb
index c123d88c..3a67d5a 100644
--- a/ash/strings/ash_strings_ko.xtb
+++ b/ash/strings/ash_strings_ko.xtb
@@ -34,7 +34,7 @@
 <translation id="1301069673413256657">GSM</translation>
 <translation id="1302880136325416935">블루투스 설정을 표시합니다. <ph name="STATE_TEXT" /></translation>
 <translation id="1312604459020188865">신호 강도 <ph name="SIGNAL_STRENGTH" /></translation>
-<translation id="1316069254387866896">항상 실행기 표시</translation>
+<translation id="1316069254387866896">실행기 항상 표시</translation>
 <translation id="1341651618736211726">더보기</translation>
 <translation id="1346748346194534595">오른쪽</translation>
 <translation id="1351937230027495976">메뉴 접기</translation>
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">화면 공유를 중단하시겠습니까?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />에서 <ph name="ROUTE_TITLE" /> 중지</translation>
-<translation id="5860033963881614850">사용 안함</translation>
 <translation id="5895138241574237353">다시 시작</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" />(<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ky.xtb b/ash/strings/ash_strings_ky.xtb
index ae7b88a..36aa867 100644
--- a/ash/strings/ash_strings_ky.xtb
+++ b/ash/strings/ash_strings_ky.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Экран бөлүшүү токтотулсунбу?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> бөлмөсүндөгү <ph name="ROUTE_TITLE" /> токтотулсун</translation>
-<translation id="5860033963881614850">Өчүк</translation>
 <translation id="5895138241574237353">Өчүрүп күйгүзүү</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_lo.xtb b/ash/strings/ash_strings_lo.xtb
index 1d12192..b0c359bc 100644
--- a/ash/strings/ash_strings_lo.xtb
+++ b/ash/strings/ash_strings_lo.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">ຢຸດການແຊຣ໌ຫນ້າ​ຈໍບໍ​?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">ຢຸດ <ph name="ROUTE_TITLE" /> ໃນ <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">ປິດ</translation>
 <translation id="5895138241574237353">ເລີ່ມຕົ້ນໃໝ່</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_lt.xtb b/ash/strings/ash_strings_lt.xtb
index 6068982..60945bd 100644
--- a/ash/strings/ash_strings_lt.xtb
+++ b/ash/strings/ash_strings_lt.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Nutraukti ekrano bendrinimą?</translation>
 <translation id="5820394555380036790">„Chromium“ OS</translation>
 <translation id="5837036133683224804">Sustabdyti „<ph name="ROUTE_TITLE" />“ („<ph name="RECEIVER_NAME" />“)</translation>
-<translation id="5860033963881614850">Išjungta</translation>
 <translation id="5895138241574237353">Paleisti iš naujo</translation>
 <translation id="5901316534475909376">„Shift“ + „Esc“</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_lv.xtb b/ash/strings/ash_strings_lv.xtb
index a3b77bc..60e926fb 100644
--- a/ash/strings/ash_strings_lv.xtb
+++ b/ash/strings/ash_strings_lv.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Vai apturēt ekrāna koplietošanu?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Pārtraukt “<ph name="ROUTE_TITLE" />” apraidi ierīcē “<ph name="RECEIVER_NAME" />”</translation>
-<translation id="5860033963881614850">Izsl.</translation>
 <translation id="5895138241574237353">Restartēt</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_mk.xtb b/ash/strings/ash_strings_mk.xtb
index 3676b09e..31c0a47a 100644
--- a/ash/strings/ash_strings_mk.xtb
+++ b/ash/strings/ash_strings_mk.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Запри споделување екран?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Престани со емитување на <ph name="ROUTE_TITLE" /> на <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Исклучено</translation>
 <translation id="5895138241574237353">Рестартирај</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ml.xtb b/ash/strings/ash_strings_ml.xtb
index ac19367..e862bd0 100644
--- a/ash/strings/ash_strings_ml.xtb
+++ b/ash/strings/ash_strings_ml.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">സ്‌ക്രീൻ പങ്കിടൽ നിർത്തണോ?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />-ൽ <ph name="ROUTE_TITLE" /> നിർത്തുക</translation>
-<translation id="5860033963881614850">ഓഫാക്കുക</translation>
 <translation id="5895138241574237353">പുനരാരംഭിക്കുക</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_mn.xtb b/ash/strings/ash_strings_mn.xtb
index ad8b47a..1171aa4a 100644
--- a/ash/strings/ash_strings_mn.xtb
+++ b/ash/strings/ash_strings_mn.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Дэлгэц хуваалцахыг зогсоох уу?</translation>
 <translation id="5820394555380036790">Chromium-н үйлдлийн систем</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />-г <ph name="ROUTE_TITLE" />-д дамжуулахаа зогсоох</translation>
-<translation id="5860033963881614850">Идэвхгүй байна</translation>
 <translation id="5895138241574237353">Дахин асаах</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_mr.xtb b/ash/strings/ash_strings_mr.xtb
index a055645b..aa39f73 100644
--- a/ash/strings/ash_strings_mr.xtb
+++ b/ash/strings/ash_strings_mr.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">स्क्रीन सामायिकरण थांबवायचे?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> वर <ph name="ROUTE_TITLE" /> थांबवा</translation>
-<translation id="5860033963881614850">बंद</translation>
 <translation id="5895138241574237353">रीस्टार्ट करा</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ms.xtb b/ash/strings/ash_strings_ms.xtb
index 7c409f7f..50442cd 100644
--- a/ash/strings/ash_strings_ms.xtb
+++ b/ash/strings/ash_strings_ms.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">Hentikan perkongsian skrin?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Hentikan <ph name="ROUTE_TITLE" /> pada <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Dimatikan</translation>
 <translation id="5895138241574237353">Mulakan Semula</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_my.xtb b/ash/strings/ash_strings_my.xtb
index 5370a67..0f1bc9a6 100644
--- a/ash/strings/ash_strings_my.xtb
+++ b/ash/strings/ash_strings_my.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">မျက်နှာပြင် ဝေမျှနေခြင်း ရပ်လိုပါသလား?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> တွင် <ph name="ROUTE_TITLE" /> ကို ရပ်ရန်</translation>
-<translation id="5860033963881614850">ပိတ်ထား</translation>
 <translation id="5895138241574237353">ပြန်စတင်မည</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ne.xtb b/ash/strings/ash_strings_ne.xtb
index f4185a6..59b77fb 100644
--- a/ash/strings/ash_strings_ne.xtb
+++ b/ash/strings/ash_strings_ne.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">स्क्रिन साझा गर्ने रोक्ने?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> मा <ph name="ROUTE_TITLE" /> बन्द गर्नुहोस्</translation>
-<translation id="5860033963881614850">बन्द</translation>
 <translation id="5895138241574237353">पुन: शुरू गर्नुहोस्</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_nl.xtb b/ash/strings/ash_strings_nl.xtb
index 29c4f6e..d025195 100644
--- a/ash/strings/ash_strings_nl.xtb
+++ b/ash/strings/ash_strings_nl.xtb
@@ -54,7 +54,7 @@
 <translation id="1550523713251050646">Klik voor meer opties</translation>
 <translation id="1570871743947603115">Bluetooth schakelen. <ph name="STATE_TEXT" /></translation>
 <translation id="1589090746204042747">Al je activiteit in deze sessie bekijken</translation>
-<translation id="1608626060424371292">Deze gebruiker verwijderen</translation>
+<translation id="1608626060424371292">Gebruiker verwijderen</translation>
 <translation id="1654477262762802994">Een gesproken zoekopdracht starten</translation>
 <translation id="1658406695958299976">Je wachtwoord kan nog steeds niet worden geverifieerd. Opmerking: Als je je wachtwoord onlangs hebt gewijzigd, wordt je nieuwe wachtwoord doorgevoerd wanneer je uitlogt. Gebruik hier het oude wachtwoord.</translation>
 <translation id="1677472565718498478"><ph name="TIME" /> resterend</translation>
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Stoppen met scherm delen?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="ROUTE_TITLE" /> in <ph name="RECEIVER_NAME" /> stopzetten</translation>
-<translation id="5860033963881614850">Uit</translation>
 <translation id="5895138241574237353">Opnieuw starten</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
@@ -587,7 +586,7 @@
 <translation id="9080206825613744995">Microfoon wordt gebruikt.</translation>
 <translation id="9084606467167974638">Positie van menu wijzigen</translation>
 <translation id="9089416786594320554">Invoermethoden</translation>
-<translation id="9091626656156419976">Display <ph name="DISPLAY_NAME" /> is verwijderd</translation>
+<translation id="9091626656156419976">Scherm <ph name="DISPLAY_NAME" /> is verwijderd</translation>
 <translation id="9151726767154816831">Opnieuw opstarten en de functie Powerwash gebruiken om bij te werken</translation>
 <translation id="9179259655489829027">Met deze functie kun je snel zonder wachtwoord toegang krijgen tot iedere ingelogde gebruiker. Gebruik deze functie alleen met accounts die je vertrouwt.</translation>
 <translation id="9183456764293710005">Vergrootglas voor volledig scherm</translation>
diff --git a/ash/strings/ash_strings_no.xtb b/ash/strings/ash_strings_no.xtb
index 236122f..10bf58e 100644
--- a/ash/strings/ash_strings_no.xtb
+++ b/ash/strings/ash_strings_no.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Vil du stoppe skjermdelingen?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Stopp <ph name="ROUTE_TITLE" /> på <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Av</translation>
 <translation id="5895138241574237353">Start på nytt</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_or.xtb b/ash/strings/ash_strings_or.xtb
index 7de54506..dcf7b44 100644
--- a/ash/strings/ash_strings_or.xtb
+++ b/ash/strings/ash_strings_or.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">ସ୍କ୍ରିନ୍ ସେୟାରିଂ ବନ୍ଦ କରିବେ?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />ରେ <ph name="ROUTE_TITLE" /> ବନ୍ଦ କରନ୍ତୁ</translation>
-<translation id="5860033963881614850">ବନ୍ଦ ଅଛି</translation>
 <translation id="5895138241574237353">ପୁନଃଆରମ୍ଭ</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_pa.xtb b/ash/strings/ash_strings_pa.xtb
index cf032ebb..0527041 100644
--- a/ash/strings/ash_strings_pa.xtb
+++ b/ash/strings/ash_strings_pa.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">ਕੀ ਸਕ੍ਰੀਨ ਸ਼ੇਅਰਿੰਗ ਰੋਕਣੀ ਹੈ?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> 'ਤੇ <ph name="ROUTE_TITLE" /> ਨੂੰ ਬੰਦ ਕਰੋ</translation>
-<translation id="5860033963881614850">ਬੰਦ ਕਰੋ</translation>
 <translation id="5895138241574237353">ਰੀਸਟਾਰਟ ਕਰੋ</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_pl.xtb b/ash/strings/ash_strings_pl.xtb
index 203cb3f9..66188e76 100644
--- a/ash/strings/ash_strings_pl.xtb
+++ b/ash/strings/ash_strings_pl.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Zakończyć udostępnianie ekranu?</translation>
 <translation id="5820394555380036790">System operacyjny Chromium</translation>
 <translation id="5837036133683224804">Zatrzymaj usługę <ph name="ROUTE_TITLE" /> na urządzeniu <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Wyłączone</translation>
 <translation id="5895138241574237353">Uruchom ponownie</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_pt-BR.xtb b/ash/strings/ash_strings_pt-BR.xtb
index 1d0c86f..aabb936 100644
--- a/ash/strings/ash_strings_pt-BR.xtb
+++ b/ash/strings/ash_strings_pt-BR.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Interromper compartilhamento de tela?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Parar <ph name="ROUTE_TITLE" /> para <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Desativado</translation>
 <translation id="5895138241574237353">Reiniciar</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_pt-PT.xtb b/ash/strings/ash_strings_pt-PT.xtb
index c04d452..952a5f9 100644
--- a/ash/strings/ash_strings_pt-PT.xtb
+++ b/ash/strings/ash_strings_pt-PT.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Parar a partilha do ecrã?</translation>
 <translation id="5820394555380036790">SO Chromium</translation>
 <translation id="5837036133683224804">Parar o <ph name="ROUTE_TITLE" /> no recetor <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Desativado</translation>
 <translation id="5895138241574237353">Reiniciar</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ro.xtb b/ash/strings/ash_strings_ro.xtb
index bd964dc..8cf372d 100644
--- a/ash/strings/ash_strings_ro.xtb
+++ b/ash/strings/ash_strings_ro.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Oprești permiterea accesului la ecran?</translation>
 <translation id="5820394555380036790">Sistemul de operare Chromium</translation>
 <translation id="5837036133683224804">Întrerupe <ph name="ROUTE_TITLE" /> pe <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Dezactivat</translation>
 <translation id="5895138241574237353">Reîncepe</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ru.xtb b/ash/strings/ash_strings_ru.xtb
index d23e34417..800ee49 100644
--- a/ash/strings/ash_strings_ru.xtb
+++ b/ash/strings/ash_strings_ru.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Закрыть доступ к экрану?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Остановить трансляцию <ph name="ROUTE_TITLE" /> на устройство "<ph name="RECEIVER_NAME" />"</translation>
-<translation id="5860033963881614850">ВЫКЛ</translation>
 <translation id="5895138241574237353">Перезапустить</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_si.xtb b/ash/strings/ash_strings_si.xtb
index 196a979f..c72c9981 100644
--- a/ash/strings/ash_strings_si.xtb
+++ b/ash/strings/ash_strings_si.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">තිර හවුල්කිරීම නවතන්නද?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> මත <ph name="ROUTE_TITLE" /> නවත්වන්න</translation>
-<translation id="5860033963881614850">අක්‍රීය</translation>
 <translation id="5895138241574237353">නැවත අරඹන්න</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> <ph name="MAIL" /></translation>
diff --git a/ash/strings/ash_strings_sk.xtb b/ash/strings/ash_strings_sk.xtb
index 42c6868..366a521 100644
--- a/ash/strings/ash_strings_sk.xtb
+++ b/ash/strings/ash_strings_sk.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Chcete ukončiť zdieľanie obrazovky?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Zastaviť prenos obsahu <ph name="ROUTE_TITLE" /> do zariadenia <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Vypnuté</translation>
 <translation id="5895138241574237353">Reštartovať</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_sl.xtb b/ash/strings/ash_strings_sl.xtb
index ad726ec..c02a031 100644
--- a/ash/strings/ash_strings_sl.xtb
+++ b/ash/strings/ash_strings_sl.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Želite ustaviti skupno rabo zaslona?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Ustavi zavihek <ph name="ROUTE_TITLE" /> v sprejemniku <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Izklopljeno</translation>
 <translation id="5895138241574237353">Znova zaženi</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_sq.xtb b/ash/strings/ash_strings_sq.xtb
index 94e5ba3..c055b271 100644
--- a/ash/strings/ash_strings_sq.xtb
+++ b/ash/strings/ash_strings_sq.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Dëshiron të ndalosh ndarjen e ekranit?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Ndalo <ph name="ROUTE_TITLE" /> në <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Çaktivizuar</translation>
 <translation id="5895138241574237353">Rinis</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_sr.xtb b/ash/strings/ash_strings_sr.xtb
index 47fe3020..d053304 100644
--- a/ash/strings/ash_strings_sr.xtb
+++ b/ash/strings/ash_strings_sr.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Желите ли да прекинете дељење екрана?</translation>
 <translation id="5820394555380036790">Chromium ОС</translation>
 <translation id="5837036133683224804">Заустави <ph name="ROUTE_TITLE" /> на уређају <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Искључено</translation>
 <translation id="5895138241574237353">Покрени поново</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_sv.xtb b/ash/strings/ash_strings_sv.xtb
index 68a5e11a..83f8fd2 100644
--- a/ash/strings/ash_strings_sv.xtb
+++ b/ash/strings/ash_strings_sv.xtb
@@ -54,7 +54,7 @@
 <translation id="1550523713251050646">Klicka här för fler alternativ</translation>
 <translation id="1570871743947603115">Aktivera och inaktivera Bluetooth. <ph name="STATE_TEXT" /></translation>
 <translation id="1589090746204042747">Få tillgång till all aktivitet i sessionen</translation>
-<translation id="1608626060424371292">Ta bort den här användaren</translation>
+<translation id="1608626060424371292">Ta bort denna användare</translation>
 <translation id="1654477262762802994">Säg en sökfråga</translation>
 <translation id="1658406695958299976">Det gick inte att verifiera lösenordet. Obs! Om du nyligen har bytt lösenord börjar det nya lösenordet att gälla först när du loggar ut. Använd det gamla lösenordet här.</translation>
 <translation id="1677472565718498478"><ph name="TIME" /> kvar</translation>
@@ -99,7 +99,7 @@
 <translation id="2220572644011485463">Pinkod eller lösenord</translation>
 <translation id="2222338659135520253">Inloggning krävs</translation>
 <translation id="225680501294068881">Söker efter enheter ...</translation>
-<translation id="2268130516524549846">Bluetooth inaktiverad</translation>
+<translation id="2268130516524549846">Bluetooth inaktiverat</translation>
 <translation id="2268813581635650749">Logga ut alla</translation>
 <translation id="2277103315734023688">Sök framåt</translation>
 <translation id="2292698582925480719">Skala på skärmen</translation>
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Vill du avbryta skärmdelningen?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Sluta casta <ph name="ROUTE_TITLE" /> till <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Av</translation>
 <translation id="5895138241574237353">Starta om</translation>
 <translation id="5901316534475909376">Skift+Escape</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_sw.xtb b/ash/strings/ash_strings_sw.xtb
index 12a65fc..8b32d9b9 100644
--- a/ash/strings/ash_strings_sw.xtb
+++ b/ash/strings/ash_strings_sw.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Je,ungependa kuacha kushiriki skrini?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">Komesha <ph name="ROUTE_TITLE" /> kwenye <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Kimezimwa</translation>
 <translation id="5895138241574237353">Zzima na uwashe</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ta.xtb b/ash/strings/ash_strings_ta.xtb
index c7bcfba..4ecff32d 100644
--- a/ash/strings/ash_strings_ta.xtb
+++ b/ash/strings/ash_strings_ta.xtb
@@ -132,7 +132,7 @@
 <translation id="2653659639078652383">சமர்ப்பி</translation>
 <translation id="2658778018866295321">கிளிக் செய்து இழுக்கும்</translation>
 <translation id="2700493154570097719">எனது விசைப்பலகையை அமை</translation>
-<translation id="2704781753052663061">பிற வைஃபை நெட்வொர்க்குகளில் இணையுங்கள்</translation>
+<translation id="2704781753052663061">பிற வைஃபை நெட்வொர்க்குகளில் இணை</translation>
 <translation id="2718395828230677721">நைட் லைட்</translation>
 <translation id="2727977024730340865">குறைந்த சக்தியிலான சார்ஜர் செருகப்பட்டுள்ளது. பேட்டரி சார்ஜிங் நம்பகமானதாக இல்லாமல் இருக்கலாம்.</translation>
 <translation id="2761704814324807722">நிலைத் தட்டு, நேரம் <ph name="TIME" />, <ph name="BATTERY" /></translation>
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">திரைப் பகிர்வதை நிறுத்தவா?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />க்கு <ph name="ROUTE_TITLE" />ஐ அனுப்புவதை நிறுத்து</translation>
-<translation id="5860033963881614850">ஆஃப்</translation>
 <translation id="5895138241574237353">மறுதொடக்கம்</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_te.xtb b/ash/strings/ash_strings_te.xtb
index af7a53d..c4dbc60 100644
--- a/ash/strings/ash_strings_te.xtb
+++ b/ash/strings/ash_strings_te.xtb
@@ -346,7 +346,6 @@
 <translation id="5777841717266010279">స్క్రీన్ భాగస్వామ్యాన్ని ఆపివేయాలా?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" />లో <ph name="ROUTE_TITLE" /> ఆపివేయి</translation>
-<translation id="5860033963881614850">ఆఫ్ అయ్యింది</translation>
 <translation id="5895138241574237353">మళ్ళీ ప్రారంభించు</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_th.xtb b/ash/strings/ash_strings_th.xtb
index 2e577fcbc..46ec338 100644
--- a/ash/strings/ash_strings_th.xtb
+++ b/ash/strings/ash_strings_th.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">ต้องการหยุดแชร์หน้าจอไหม</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804">หยุด <ph name="ROUTE_TITLE" /> ใน<ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">ปิด</translation>
 <translation id="5895138241574237353">ปิดแล้วเปิดอีกครั้ง</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_tr.xtb b/ash/strings/ash_strings_tr.xtb
index 50a27514..09d9b8e 100644
--- a/ash/strings/ash_strings_tr.xtb
+++ b/ash/strings/ash_strings_tr.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Ekran paylaşma durdurulsun mu?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> adlı alıcıya <ph name="ROUTE_TITLE" /> yayınını durdur</translation>
-<translation id="5860033963881614850">Kapalı</translation>
 <translation id="5895138241574237353">Yeniden başlat</translation>
 <translation id="5901316534475909376">Üst Karakter+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_uk.xtb b/ash/strings/ash_strings_uk.xtb
index 7a2a0f6..c71a033 100644
--- a/ash/strings/ash_strings_uk.xtb
+++ b/ash/strings/ash_strings_uk.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Скасувати спільний доступ до екрана?</translation>
 <translation id="5820394555380036790">ОС Chromium</translation>
 <translation id="5837036133683224804">Зупинити трансляцію <ph name="ROUTE_TITLE" /> на пристрій "<ph name="RECEIVER_NAME" />"</translation>
-<translation id="5860033963881614850">Вимк.</translation>
 <translation id="5895138241574237353">Перезапустити</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_ur.xtb b/ash/strings/ash_strings_ur.xtb
index d3572b7..e6ea11b 100644
--- a/ash/strings/ash_strings_ur.xtb
+++ b/ash/strings/ash_strings_ur.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">اسکرین کا اشتراک روکیں؟</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="RECEIVER_NAME" /> پر <ph name="ROUTE_TITLE" /> کو روکیں</translation>
-<translation id="5860033963881614850">آف</translation>
 <translation id="5895138241574237353">دوبارہ شروع کریں</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_uz.xtb b/ash/strings/ash_strings_uz.xtb
index 2a050696..4dfe869 100644
--- a/ash/strings/ash_strings_uz.xtb
+++ b/ash/strings/ash_strings_uz.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Ekrandan foydalanish ruxsati to‘xtatilsinmi?</translation>
 <translation id="5820394555380036790">Chromium OS</translation>
 <translation id="5837036133683224804"><ph name="ROUTE_TITLE" /> <ph name="RECEIVER_NAME" /> qurilmasiga translatsiya qilinishi to‘xtatilsin</translation>
-<translation id="5860033963881614850">O‘chiq</translation>
 <translation id="5895138241574237353">Qayta ishga tushirish</translation>
 <translation id="5901316534475909376">Shift + Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_vi.xtb b/ash/strings/ash_strings_vi.xtb
index 9643941..8448312a 100644
--- a/ash/strings/ash_strings_vi.xtb
+++ b/ash/strings/ash_strings_vi.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Bạn muốn dừng chia sẻ màn hình?</translation>
 <translation id="5820394555380036790">Hệ điều hành Chromium</translation>
 <translation id="5837036133683224804">Dừng <ph name="ROUTE_TITLE" /> trên <ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Tắt</translation>
 <translation id="5895138241574237353">Khởi động lại</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_zh-CN.xtb b/ash/strings/ash_strings_zh-CN.xtb
index 83d54a6..485147c 100644
--- a/ash/strings/ash_strings_zh-CN.xtb
+++ b/ash/strings/ash_strings_zh-CN.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">要停止屏幕共享吗?</translation>
 <translation id="5820394555380036790">Chromium 操作系统</translation>
 <translation id="5837036133683224804">停止将“<ph name="ROUTE_TITLE" />”投射至“<ph name="RECEIVER_NAME" />”</translation>
-<translation id="5860033963881614850">关闭</translation>
 <translation id="5895138241574237353">重新启动</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_zh-HK.xtb b/ash/strings/ash_strings_zh-HK.xtb
index dd35ac2..7f4714e 100644
--- a/ash/strings/ash_strings_zh-HK.xtb
+++ b/ash/strings/ash_strings_zh-HK.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">停止共用畫面?</translation>
 <translation id="5820394555380036790">Chromium 作業系統</translation>
 <translation id="5837036133683224804">停止喺<ph name="RECEIVER_NAME" />投放 <ph name="ROUTE_TITLE" /></translation>
-<translation id="5860033963881614850">關閉</translation>
 <translation id="5895138241574237353">重新啟動</translation>
 <translation id="5901316534475909376">Shift + Esc 鍵</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_zh-TW.xtb b/ash/strings/ash_strings_zh-TW.xtb
index a3d4eac..3028940 100644
--- a/ash/strings/ash_strings_zh-TW.xtb
+++ b/ash/strings/ash_strings_zh-TW.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">停止共用螢幕?</translation>
 <translation id="5820394555380036790">Chromium 作業系統</translation>
 <translation id="5837036133683224804">停止透過<ph name="RECEIVER_NAME" />投放「<ph name="ROUTE_TITLE" />」</translation>
-<translation id="5860033963881614850">關閉</translation>
 <translation id="5895138241574237353">重新啟動</translation>
 <translation id="5901316534475909376">Shift + Esc 鍵</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/strings/ash_strings_zu.xtb b/ash/strings/ash_strings_zu.xtb
index 4333776..b2877984 100644
--- a/ash/strings/ash_strings_zu.xtb
+++ b/ash/strings/ash_strings_zu.xtb
@@ -345,7 +345,6 @@
 <translation id="5777841717266010279">Misa ukwabelana kwesikrini?</translation>
 <translation id="5820394555380036790">I-Chromium OS</translation>
 <translation id="5837036133683224804">Misa i-<ph name="ROUTE_TITLE" /> ku-<ph name="RECEIVER_NAME" /></translation>
-<translation id="5860033963881614850">Valiwe</translation>
 <translation id="5895138241574237353">Qalisa kabusha</translation>
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
diff --git a/ash/system/message_center/unified_message_center_bubble_unittest.cc b/ash/system/message_center/unified_message_center_bubble_unittest.cc
index 470aad34..701f10e0 100644
--- a/ash/system/message_center/unified_message_center_bubble_unittest.cc
+++ b/ash/system/message_center/unified_message_center_bubble_unittest.cc
@@ -260,6 +260,7 @@
 TEST_F(UnifiedMessageCenterBubbleTest, CollapseState) {
   EnableMessageCenterRefactor();
   AddNotification();
+  AddNotification();
 
   GetPrimaryUnifiedSystemTray()->ShowBubble(true);
   int small_display_height =
diff --git a/ash/system/message_center/unified_message_center_view.cc b/ash/system/message_center/unified_message_center_view.cc
index 927d987..52a43728 100644
--- a/ash/system/message_center/unified_message_center_view.cc
+++ b/ash/system/message_center/unified_message_center_view.cc
@@ -135,6 +135,11 @@
   if (!GetVisible() || collapsed_)
     return;
 
+  // Do not collapse the message center if notification bar is not visible.
+  // i.e. there is only one notification.
+  if (!notification_bar_->GetVisible())
+    return;
+
   collapsed_ = true;
   if (animate) {
     StartCollapseAnimation();
diff --git a/ash/system/message_center/unified_message_center_view_unittest.cc b/ash/system/message_center/unified_message_center_view_unittest.cc
index 3f7d2fae..b04e4292 100644
--- a/ash/system/message_center/unified_message_center_view_unittest.cc
+++ b/ash/system/message_center/unified_message_center_view_unittest.cc
@@ -737,9 +737,9 @@
 
 TEST_F(UnifiedMessageCenterViewTest, CollapseAndExpand_Animated) {
   AddNotification();
+  AddNotification();
   CreateMessageCenterView();
   EXPECT_TRUE(GetScroller()->GetVisible());
-  EXPECT_FALSE(GetNotificationBar()->GetVisible());
 
   // Set to collapsed state with animation.
   message_center_view()->SetCollapsed(true /* animate */);
@@ -762,7 +762,6 @@
   EXPECT_FALSE(GetNotificationBarExpandAllButton()->GetVisible());
   EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible());
   EXPECT_TRUE(GetScroller()->GetVisible());
-  EXPECT_FALSE(GetNotificationBar()->GetVisible());
 }
 
 TEST_F(UnifiedMessageCenterViewTest, CollapseAndExpand_NoNotifications) {
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 3166164..4eee23e1 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -656,7 +656,7 @@
 }
 
 void OverviewGrid::RearrangeDuringDrag(
-    aura::Window* dragged_window,
+    OverviewItem* dragged_item,
     SplitViewDragIndicators::WindowDraggingState window_dragging_state) {
   OverviewItem* drop_target = GetDropTarget();
 
@@ -673,8 +673,10 @@
       root_window_, base::make_optional(window_dragging_state),
       /*divider_changed=*/false, /*account_for_hotseat=*/true);
   if (bounds_ != wanted_grid_bounds) {
-    SetBoundsAndUpdatePositions(wanted_grid_bounds,
-                                {GetOverviewItemContaining(dragged_window)},
+    base::flat_set<OverviewItem*> ignored_items;
+    if (dragged_item)
+      ignored_items.insert(dragged_item);
+    SetBoundsAndUpdatePositions(wanted_grid_bounds, ignored_items,
                                 /*animate=*/true);
   }
 }
@@ -743,7 +745,7 @@
   DCHECK_EQ(dragged_window_, dragged_window);
   DCHECK_EQ(dragged_window->GetRootWindow(), root_window_);
 
-  RearrangeDuringDrag(dragged_window, window_dragging_state);
+  RearrangeDuringDrag(nullptr, window_dragging_state);
   UpdateDropTargetBackgroundVisibility(nullptr, location_in_screen);
 
   aura::Window* target_window =
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h
index 831adbec..239f32c 100644
--- a/ash/wm/overview/overview_grid.h
+++ b/ash/wm/overview/overview_grid.h
@@ -143,9 +143,10 @@
       bool animate);
 
   // Updates overview bounds and hides the drop target when a preview area is
-  // shown or the drag is currently outside of |root_window_|.
+  // shown or the drag is currently outside of |root_window_|. For dragging from
+  // the top or from the shelf, pass null for |dragged_item|.
   void RearrangeDuringDrag(
-      aura::Window* dragged_window,
+      OverviewItem* dragged_item,
       SplitViewDragIndicators::WindowDraggingState window_dragging_state);
 
   // Sets the dragged window on |split_view_drag_indicators_|.
@@ -160,8 +161,8 @@
   bool MaybeUpdateDesksWidgetBounds();
 
   // Updates the appearance of the drop target to visually indicate when the
-  // dragged window is being dragged over it. For dragging from the top, pass
-  // null for |dragged_item|.
+  // dragged window is being dragged over it. For dragging from the top or from
+  // the shelf, pass null for |dragged_item|.
   void UpdateDropTargetBackgroundVisibility(
       OverviewItem* dragged_item,
       const gfx::PointF& location_in_screen);
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc
index 1833dc3..570c514 100644
--- a/ash/wm/overview/overview_session.cc
+++ b/ash/wm/overview/overview_session.cc
@@ -361,11 +361,11 @@
   }
 }
 
-void OverviewSession::RearrangeDuringDrag(aura::Window* dragged_window) {
+void OverviewSession::RearrangeDuringDrag(OverviewItem* dragged_item) {
   for (std::unique_ptr<OverviewGrid>& grid : grid_list_) {
     DCHECK(grid->split_view_drag_indicators());
     grid->RearrangeDuringDrag(
-        dragged_window,
+        dragged_item,
         grid->split_view_drag_indicators()->current_window_dragging_state());
   }
 }
@@ -967,7 +967,28 @@
   EndOverview();
 }
 
-void OverviewSession::OnShelfAlignmentChanged(aura::Window* root_window) {
+void OverviewSession::OnShelfAlignmentChanged(aura::Window* root_window,
+                                              ShelfAlignment old_alignment) {
+  // Helper to check if a shelf alignment change results in different
+  // visuals for overivew purposes.
+  auto same_effective_alignment = [](ShelfAlignment prev,
+                                     ShelfAlignment curr) -> bool {
+    auto bottom = ShelfAlignment::kBottom;
+    auto locked = ShelfAlignment::kBottomLocked;
+    return (prev == bottom && curr == locked) ||
+           (prev == locked && curr == bottom);
+  };
+
+  // On changing from kBottomLocked to kBottom shelf alignment or vice versa
+  // (usually from entering/exiting lock screen), keep splitview if it's active.
+  // Done here instead of using a SessionObserver so we can skip the
+  // EndOverview() at the end of this function if necessary.
+  ShelfAlignment current_alignment = Shelf::ForWindow(root_window)->alignment();
+  if (SplitViewController::Get(root_window)->InSplitViewMode() &&
+      same_effective_alignment(old_alignment, current_alignment)) {
+    return;
+  }
+
   // When the shelf alignment changes while in overview, the display work area
   // doesn't get updated anyways (see https://crbug.com/834400). In this case,
   // even updating the grid bounds won't make any difference, so we simply exit
diff --git a/ash/wm/overview/overview_session.h b/ash/wm/overview/overview_session.h
index dd864a98..09db7b4 100644
--- a/ash/wm/overview/overview_session.h
+++ b/ash/wm/overview/overview_session.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "ash/ash_export.h"
+#include "ash/public/cpp/shelf_types.h"
 #include "ash/shell_observer.h"
 #include "ash/wm/overview/scoped_overview_hide_windows.h"
 #include "ash/wm/splitview/split_view_controller.h"
@@ -145,7 +146,7 @@
   void ResetSplitViewDragIndicatorsWindowDraggingStates();
 
   // See |OverviewGrid::RearrangeDuringDrag|.
-  void RearrangeDuringDrag(aura::Window* dragged_window);
+  void RearrangeDuringDrag(OverviewItem* dragged_item);
 
   // Updates the appearance of each drop target to visually indicate when the
   // dragged window is being dragged over it.
@@ -304,7 +305,8 @@
 
   // ShelObserver:
   void OnShellDestroying() override;
-  void OnShelfAlignmentChanged(aura::Window* root_window) override;
+  void OnShelfAlignmentChanged(aura::Window* root_window,
+                               ShelfAlignment old_alignment) override;
 
   // ui::EventHandler:
   void OnKeyEvent(ui::KeyEvent* event) override;
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index 975269bf..73a5fcb 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -5441,6 +5441,29 @@
   EXPECT_EQ(grid_bounds, GetGridBounds());
 }
 
+// Tests that overview stays active if we have a snapped window.
+TEST_P(SplitViewOverviewSessionTest, OnScreenLock) {
+  std::unique_ptr<aura::Window> window1 = CreateTestWindow();
+  std::unique_ptr<aura::Window> window2 = CreateTestWindow();
+
+  // Overview should exit if no snapped window after locking/unlocking.
+  ToggleOverview();
+  GetSessionControllerClient()->LockScreen();
+  GetSessionControllerClient()->UnlockScreen();
+  ASSERT_FALSE(InOverviewSession());
+
+  ToggleOverview();
+  split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT);
+
+  // Lock and unlock the machine. Test that we are still in overview and
+  // splitview.
+  GetSessionControllerClient()->LockScreen();
+  GetSessionControllerClient()->UnlockScreen();
+  EXPECT_TRUE(InOverviewSession());
+  EXPECT_EQ(SplitViewController::State::kLeftSnapped,
+            split_view_controller()->state());
+}
+
 // Test the split view and overview functionalities in clamshell mode. Split
 // view is only active when overview is active in clamshell mode.
 class SplitViewOverviewSessionInClamshellTest
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc
index 85e821a..f754a05 100644
--- a/ash/wm/overview/overview_window_drag_controller.cc
+++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -600,7 +600,7 @@
           /*is_dragging=*/true,
           SplitViewDragIndicators::WindowDraggingState::kFromOverview,
           snap_position_));
-  overview_session_->RearrangeDuringDrag(item_->GetWindow());
+  overview_session_->RearrangeDuringDrag(item_);
 }
 
 aura::Window* OverviewWindowDragController::GetRootWindowBeingDraggedIn()
diff --git a/base/files/scoped_temp_dir.cc b/base/files/scoped_temp_dir.cc
index 359b442..ccaa437 100644
--- a/base/files/scoped_temp_dir.cc
+++ b/base/files/scoped_temp_dir.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/logging.h"
+#include "base/macros.h"
 
 namespace base {
 
@@ -18,6 +19,16 @@
 
 ScopedTempDir::ScopedTempDir() = default;
 
+ScopedTempDir::ScopedTempDir(ScopedTempDir&& other) noexcept
+    : path_(other.Take()) {}
+
+ScopedTempDir& ScopedTempDir::operator=(ScopedTempDir&& other) {
+  if (!path_.empty() && !Delete())
+    DLOG(WARNING) << "Could not delete temp dir in operator=().";
+  path_ = other.Take();
+  return *this;
+}
+
 ScopedTempDir::~ScopedTempDir() {
   if (!path_.empty() && !Delete())
     DLOG(WARNING) << "Could not delete temp dir in dtor.";
@@ -75,9 +86,7 @@
 }
 
 FilePath ScopedTempDir::Take() {
-  FilePath ret = path_;
-  path_ = FilePath();
-  return ret;
+  return std::exchange(path_, FilePath());
 }
 
 const FilePath& ScopedTempDir::GetPath() const {
diff --git a/base/files/scoped_temp_dir.h b/base/files/scoped_temp_dir.h
index 872f6f81..548de69 100644
--- a/base/files/scoped_temp_dir.h
+++ b/base/files/scoped_temp_dir.h
@@ -18,8 +18,8 @@
 // intervening calls to Delete or Take, or the calls will fail.
 
 #include "base/base_export.h"
+#include "base/compiler_specific.h"
 #include "base/files/file_path.h"
-#include "base/macros.h"
 
 namespace base {
 
@@ -28,6 +28,9 @@
   // No directory is owned/created initially.
   ScopedTempDir();
 
+  ScopedTempDir(ScopedTempDir&&) noexcept;
+  ScopedTempDir& operator=(ScopedTempDir&&);
+
   // Recursively delete path.
   ~ScopedTempDir();
 
@@ -62,8 +65,6 @@
 
  private:
   FilePath path_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedTempDir);
 };
 
 }  // namespace base
diff --git a/base/files/scoped_temp_dir_unittest.cc b/base/files/scoped_temp_dir_unittest.cc
index 122d138b..a07dbd9 100644
--- a/base/files/scoped_temp_dir_unittest.cc
+++ b/base/files/scoped_temp_dir_unittest.cc
@@ -94,6 +94,20 @@
   EXPECT_FALSE(other_dir.CreateUniqueTempDir());
 }
 
+TEST(ScopedTempDir, Move) {
+  ScopedTempDir dir;
+  EXPECT_TRUE(dir.CreateUniqueTempDir());
+  FilePath dir_path = dir.GetPath();
+  EXPECT_TRUE(DirectoryExists(dir_path));
+  {
+    ScopedTempDir other_dir(std::move(dir));
+    EXPECT_EQ(dir_path, other_dir.GetPath());
+    EXPECT_TRUE(DirectoryExists(dir_path));
+    EXPECT_FALSE(dir.IsValid());
+  }
+  EXPECT_FALSE(DirectoryExists(dir_path));
+}
+
 #if defined(OS_WIN)
 TEST(ScopedTempDir, LockedTempDir) {
   ScopedTempDir dir;
diff --git a/base/message_loop/message_pump_mac.h b/base/message_loop/message_pump_mac.h
index 909b946d..e87a675 100644
--- a/base/message_loop/message_pump_mac.h
+++ b/base/message_loop/message_pump_mac.h
@@ -155,10 +155,6 @@
   // The maximum number of run loop modes that can be monitored.
   static constexpr int kNumModes = 4;
 
-  // All sources of delayed work scheduling converge to this, using TimeDelta
-  // avoids querying Now() for key callers.
-  void ScheduleDelayedWorkImpl(TimeDelta delta);
-
   // Marking timers as invalid at the right time helps significantly reduce
   // power use (see the comment in RunDelayedWorkTimer()), however there is no
   // public API for doing so. CFRuntime.h states that CFRuntimeBase, upon which
@@ -179,32 +175,33 @@
   void SetDelayedWorkTimerValid(bool valid);
 
   // Timer callback scheduled by ScheduleDelayedWork.  This does not do any
-  // work, but it signals |work_source_| so that delayed work can be performed
+  // work, but it signals work_source_ so that delayed work can be performed
   // within the appropriate priority constraints.
   static void RunDelayedWorkTimer(CFRunLoopTimerRef timer, void* info);
 
-  // Perform highest-priority work.  This is associated with |work_source_|
+  // Perform highest-priority work.  This is associated with work_source_
   // signalled by ScheduleWork or RunDelayedWorkTimer.  The static method calls
   // the instance method; the instance method returns true if it resignalled
-  // |work_source_| to be called again from the loop.
+  // work_source_ to be called again from the loop.
   static void RunWorkSource(void* info);
   bool RunWork();
 
   // Perform idle-priority work.  This is normally called by PreWaitObserver,
-  // but is also associated with |idle_work_source_|.  When this function
+  // but is also associated with idle_work_source_.  When this function
   // actually does perform idle work, it will resignal that source.  The
-  // static method calls the instance method.
+  // static method calls the instance method; the instance method returns
+  // true if idle work was done.
   static void RunIdleWorkSource(void* info);
-  void RunIdleWork();
+  bool RunIdleWork();
 
   // Perform work that may have been deferred because it was not runnable
   // within a nested run loop.  This is associated with
-  // |nesting_deferred_work_source_| and is signalled by
+  // nesting_deferred_work_source_ and is signalled by
   // MaybeScheduleNestingDeferredWork when returning from a nested loop,
   // so that an outer loop will be able to perform the necessary tasks if it
   // permits nestable tasks.
   static void RunNestingDeferredWorkSource(void* info);
-  void RunNestingDeferredWork();
+  bool RunNestingDeferredWork();
 
   // Schedules possible nesting-deferred work to be processed before the run
   // loop goes to sleep, exits, or begins processing sources at the top of its
@@ -214,24 +211,24 @@
   void MaybeScheduleNestingDeferredWork();
 
   // Observer callback responsible for performing idle-priority work, before
-  // the run loop goes to sleep.  Associated with |pre_wait_observer_|.
+  // the run loop goes to sleep.  Associated with idle_work_observer_.
   static void PreWaitObserver(CFRunLoopObserverRef observer,
                               CFRunLoopActivity activity, void* info);
 
   // Observer callback called before the run loop processes any sources.
-  // Associated with |pre_source_observer_|.
+  // Associated with pre_source_observer_.
   static void PreSourceObserver(CFRunLoopObserverRef observer,
                                 CFRunLoopActivity activity, void* info);
 
   // Observer callback called when the run loop starts and stops, at the
   // beginning and end of calls to CFRunLoopRun.  This is used to maintain
-  // |nesting_level_|.  Associated with |enter_exit_observer_|.
+  // nesting_level_.  Associated with enter_exit_observer_.
   static void EnterExitObserver(CFRunLoopObserverRef observer,
                                 CFRunLoopActivity activity, void* info);
 
-  // Called by EnterExitObserver after performing maintenance on
-  // |nesting_level_|. This allows subclasses an opportunity to perform
-  // additional processing on the basis of run loops starting and stopping.
+  // Called by EnterExitObserver after performing maintenance on nesting_level_.
+  // This allows subclasses an opportunity to perform additional processing on
+  // the basis of run loops starting and stopping.
   virtual void EnterExitRunLoop(CFRunLoopActivity activity);
 
   // The thread's run loop.
@@ -253,6 +250,12 @@
   // (weak) Delegate passed as an argument to the innermost Run call.
   Delegate* delegate_;
 
+  // The time that delayed_work_timer_ is scheduled to fire.  This is tracked
+  // independently of CFRunLoopTimerGetNextFireDate(delayed_work_timer_)
+  // to be able to reset the timer properly after waking from system sleep.
+  // See PowerStateNotification.
+  CFAbsoluteTime delayed_work_fire_time_;
+
   base::TimerSlack timer_slack_;
 
   // The recursion depth of the currently-executing CFRunLoopRun loop on the
@@ -260,7 +263,7 @@
   // the object was created in.
   int nesting_level_;
 
-  // The recursion depth (calculated in the same way as |nesting_level_|) of the
+  // The recursion depth (calculated in the same way as nesting_level_) of the
   // innermost executing CFRunLoopRun loop started by a call to Run.
   int run_nesting_level_;
 
@@ -303,8 +306,8 @@
   void EnterExitRunLoop(CFRunLoopActivity activity) override;
 
   // True if Quit is called to stop the innermost MessagePump
-  // (|innermost_quittable_|) but some other CFRunLoopRun loop
-  // (|nesting_level_|) is running inside the MessagePump's innermost Run call.
+  // (innermost_quittable_) but some other CFRunLoopRun loop (nesting_level_)
+  // is running inside the MessagePump's innermost Run call.
   bool quit_pending_;
 
   DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoop);
diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm
index 7711944f..b3e5a3d 100644
--- a/base/message_loop/message_pump_mac.mm
+++ b/base/message_loop/message_pump_mac.mm
@@ -208,10 +208,9 @@
 // Must be called on the run loop thread.
 void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
     const TimeTicks& delayed_work_time) {
-  ScheduleDelayedWorkImpl(delayed_work_time - TimeTicks::Now());
-}
+  TimeDelta delta = delayed_work_time - TimeTicks::Now();
+  delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF();
 
-void MessagePumpCFRunLoopBase::ScheduleDelayedWorkImpl(TimeDelta delta) {
   // Flip the timer's validation bit just before setting the new fire time. Do
   // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity
   // of a timer before proceeding to set its fire date. Making the timer valid
@@ -228,8 +227,7 @@
   } else {
     CFRunLoopTimerSetTolerance(delayed_work_timer_, 0);
   }
-  CFRunLoopTimerSetNextFireDate(
-      delayed_work_timer_, CFAbsoluteTimeGetCurrent() + delta.InSecondsF());
+  CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
 }
 
 void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) {
@@ -245,6 +243,7 @@
 // Must be called on the run loop thread.
 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase(int initial_mode_mask)
     : delegate_(NULL),
+      delayed_work_fire_time_(kCFTimeIntervalMax),
       timer_slack_(base::TIMER_SLACK_NONE),
       nesting_level_(0),
       run_nesting_level_(0),
@@ -428,6 +427,9 @@
                                                    void* info) {
   MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
 
+  // The timer won't fire again until it's reset.
+  self->delayed_work_fire_time_ = kCFTimeIntervalMax;
+
   // The message pump's timer needs to fire at changing and unpredictable
   // intervals. Creating a new timer for each firing time is very expensive, so
   // the message pump instead uses a repeating timer with a very large repeat
@@ -453,11 +455,11 @@
   // timer's new firing time.
   self->SetDelayedWorkTimerValid(false);
 
-  // The timer fired, assume we have work and let RunWork() figure out what to
-  // do and what to schedule after.
-  base::mac::CallWithEHFrame(^{
-    self->RunWork();
-  });
+  // CFRunLoopTimers fire outside of the priority scheme for CFRunLoopSources.
+  // In order to establish the proper priority in which work and delayed work
+  // are processed one for one, the timer used to schedule delayed work must
+  // signal a CFRunLoopSource used to dispatch both work and delayed work.
+  CFRunLoopSourceSignal(self->work_source_);
 }
 
 // Called from the run loop.
@@ -469,10 +471,10 @@
   });
 }
 
-// Called by MessagePumpCFRunLoopBase::RunWorkSource and RunDelayedWorkTimer.
+// Called by MessagePumpCFRunLoopBase::RunWorkSource.
 bool MessagePumpCFRunLoopBase::RunWork() {
   if (!delegate_) {
-    // This point can be reached with a nullptr |delegate_| if Run is not on the
+    // This point can be reached with a NULL delegate_ if Run is not on the
     // stack but foreign code is spinning the CFRunLoop.  Arrange to come back
     // here when a delegate is available.
     delegateless_work_ = true;
@@ -488,16 +490,40 @@
   // released promptly even in the absence of UI events.
   MessagePumpScopedAutoreleasePool autorelease_pool(this);
 
-  Delegate::NextWorkInfo next_work_info = delegate_->DoSomeWork();
+  // Call DoWork and DoDelayedWork once, and if something was done, arrange to
+  // come back here again as long as the loop is still running.
+  bool did_work = delegate_->DoWork();
+  bool resignal_work_source = did_work;
 
-  if (next_work_info.is_immediate()) {
-    CFRunLoopSourceSignal(work_source_);
-    return true;
+  TimeTicks next_time;
+  if (keep_running())
+    delegate_->DoDelayedWork(&next_time);
+  if (!did_work) {
+    // Determine whether there's more delayed work, and if so, if it needs to
+    // be done at some point in the future or if it's already time to do it.
+    // Only do these checks if did_work is false. If did_work is true, this
+    // function, and therefore any additional delayed work, will get another
+    // chance to run before the loop goes to sleep.
+    bool more_delayed_work = !next_time.is_null();
+    if (more_delayed_work) {
+      TimeDelta delay = next_time - TimeTicks::Now();
+      if (delay > TimeDelta()) {
+        // There's more delayed work to be done in the future.
+        ScheduleDelayedWork(next_time);
+      } else {
+        // There's more delayed work to be done, and its time is in the past.
+        // Arrange to come back here directly as long as the loop is still
+        // running.
+        resignal_work_source = true;
+      }
+    }
   }
 
-  if (!next_work_info.delayed_run_time.is_max())
-    ScheduleDelayedWorkImpl(next_work_info.remaining_delay());
-  return false;
+  if (resignal_work_source) {
+    CFRunLoopSourceSignal(work_source_);
+  }
+
+  return resignal_work_source;
 }
 
 // Called from the run loop.
@@ -510,27 +536,32 @@
 }
 
 // Called by MessagePumpCFRunLoopBase::RunIdleWorkSource.
-void MessagePumpCFRunLoopBase::RunIdleWork() {
+bool MessagePumpCFRunLoopBase::RunIdleWork() {
   if (!delegate_) {
-    // This point can be reached with a nullptr delegate_ if Run is not on the
+    // This point can be reached with a NULL delegate_ if Run is not on the
     // stack but foreign code is spinning the CFRunLoop.  Arrange to come back
     // here when a delegate is available.
     delegateless_idle_work_ = true;
-    return;
+    return false;
   }
   if (!keep_running())
-    return;
+    return false;
+
   // The NSApplication-based run loop only drains the autorelease pool at each
   // UI event (NSEvent).  The autorelease pool is not drained for each
   // CFRunLoopSource target that's run.  Use a local pool for any autoreleased
   // objects if the app is not currently handling a UI event to ensure they're
   // released promptly even in the absence of UI events.
   MessagePumpScopedAutoreleasePool autorelease_pool(this);
+
   // Call DoIdleWork once, and if something was done, arrange to come back here
   // again as long as the loop is still running.
   bool did_work = delegate_->DoIdleWork();
-  if (did_work)
+  if (did_work) {
     CFRunLoopSourceSignal(idle_work_source_);
+  }
+
+  return did_work;
 }
 
 // Called from the run loop.
@@ -543,22 +574,27 @@
 }
 
 // Called by MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource.
-void MessagePumpCFRunLoopBase::RunNestingDeferredWork() {
+bool MessagePumpCFRunLoopBase::RunNestingDeferredWork() {
   if (!delegate_) {
-    // This point can be reached with a nullptr |delegate_| if Run is not on the
+    // This point can be reached with a NULL delegate_ if Run is not on the
     // stack but foreign code is spinning the CFRunLoop.  There's no sense in
     // attempting to do any work or signalling the work sources because
     // without a delegate, work is not possible.
-    return;
+    return false;
   }
 
-  if (RunWork()) {
+  // Immediately try work in priority order.
+  if (!RunWork()) {
+    if (!RunIdleWork()) {
+      return false;
+    }
+  } else {
     // Work was done.  Arrange for the loop to try non-nestable idle work on
     // a subsequent pass.
     CFRunLoopSourceSignal(idle_work_source_);
-  } else {
-    RunIdleWork();
   }
+
+  return true;
 }
 
 // Called before the run loop goes to sleep or exits, or processes sources.
diff --git a/base/message_loop/message_pump_unittest.cc b/base/message_loop/message_pump_unittest.cc
index 5c58790e..f7e6ed91 100644
--- a/base/message_loop/message_pump_unittest.cc
+++ b/base/message_loop/message_pump_unittest.cc
@@ -35,11 +35,21 @@
 bool PumpTypeUsesDoSomeWork(MessagePumpType type) {
   switch (type) {
     case MessagePumpType::DEFAULT:
+#if defined(OS_IOS)
+      // iOS uses a MessagePumpCFRunLoop instead of MessagePumpDefault for
+      // TYPE_DEFAULT. TODO(gab): migrate MessagePumpCFRunLoop too.
+      return false;
+#else
       return true;
+#endif
 
     case MessagePumpType::UI:
-#if defined(OS_WIN) || defined(OS_ANDROID) || defined(USE_GLIB) || \
-    defined(OS_MACOSX)
+#if defined(OS_IOS)
+      // iOS uses a MessagePumpCFRunLoop for UI in unit tests, ref.
+      // test_support_ios.mm::CreateMessagePumpForUIForTests(). TODO(gab):
+      // migrate MessagePumpCFRunLoop too.
+      return false;
+#elif defined(OS_WIN) || defined(OS_ANDROID) || defined(USE_GLIB)
       return true;
 #elif defined(OS_POSIX) && !defined(OS_NACL_SFI)
       // MessagePumpLibevent was migrated (ref. message_pump_for_ui.h and
@@ -52,7 +62,7 @@
 #endif
 
     case MessagePumpType::IO:
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
       return true;
 #elif defined(OS_POSIX) && !defined(OS_NACL_SFI)
       // MessagePumpLibevent was migrated (ref. message_pump_for_io.h and
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index b488cbb2..bd6a96d0 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -259,17 +259,23 @@
   CheckThreadPriority(bool check_thread_priority_at_test_end)
       : check_thread_priority_at_test_end_(check_thread_priority_at_test_end) {
     CHECK_EQ(base::PlatformThread::GetCurrentThreadPriority(),
-             base::ThreadPriority::NORMAL);
+             base::ThreadPriority::NORMAL)
+        << " -- The thread priority of this process is not the default. This "
+           "usually indicates nice has been used, which is not supported.";
   }
 
   void OnTestStart(const testing::TestInfo& test) override {
     EXPECT_EQ(base::PlatformThread::GetCurrentThreadPriority(),
-              base::ThreadPriority::NORMAL);
+              base::ThreadPriority::NORMAL)
+        << " -- The thread priority of this process is not the default. This "
+           "usually indicates nice has been used, which is not supported.";
   }
   void OnTestEnd(const testing::TestInfo& test) override {
     if (check_thread_priority_at_test_end_) {
       EXPECT_EQ(base::PlatformThread::GetCurrentThreadPriority(),
-                base::ThreadPriority::NORMAL);
+                base::ThreadPriority::NORMAL)
+          << " -- The thread priority of this process is not the default. This "
+             "usually indicates nice has been used, which is not supported.";
     }
   }
 
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index e0d5e1a..cbd235d 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -840,33 +840,6 @@
   }
 }
 
-template("stack_script") {
-  generate_wrapper(target_name) {
-    forward_variables_from(invoker,
-                           [
-                             "deps",
-                             "testonly",
-                           ])
-    _stack_target_name = invoker.stack_target_name
-
-    data_deps = [
-      "//third_party/android_platform/development/scripts:stack_py",
-    ]
-    if (defined(invoker.data_deps)) {
-      data_deps += invoker.data_deps
-    }
-
-    executable = "//third_party/android_platform/development/scripts/stack"
-    wrapper_script = "$root_build_dir/bin/stack_${_stack_target_name}"
-
-    executable_args = [
-      "--output-directory",
-      "@WrappedPath(.)",
-      "--arch=$target_cpu",
-    ]
-  }
-}
-
 if (enable_java_templates) {
   android_sdk_jar = "$android_sdk/android.jar"
   android_default_aapt_path = "$android_sdk_build_tools/aapt"
@@ -3045,12 +3018,7 @@
     }
 
     _java_files = []
-    if (defined(invoker.java_files)) {
-      _java_files = invoker.java_files
-    } else if (defined(invoker.sources)) {
-      # TODO(crbug.com/917196): Migrate all usages of "java_files" to "sources".
-      # To support transition, use "sources" variable as valid substitute for
-      # "java_files" for now.
+    if (defined(invoker.sources)) {
       _java_files = invoker.sources
     }
     _srcjar_deps = []
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 578dd7c3..b35472b 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1272,7 +1272,7 @@
   #
   # Example
   #   java_binary("foo") {
-  #     java_files = [ "org/chromium/foo/FooMain.java" ]
+  #     sources = [ "org/chromium/foo/FooMain.java" ]
   #     deps = [ ":bar_java" ]
   #     main_class = "org.chromium.foo.FooMain"
   #   }
@@ -1296,14 +1296,14 @@
   # Declare a Java Annotation Processor.
   #
   # Supports all variables of java_library(), plus:
-  #   jar_path: Path to a prebuilt jar. Mutually exclusive with java_files &
+  #   jar_path: Path to a prebuilt jar. Mutually exclusive with sources &
   #     srcjar_deps.
   #   main_class: The fully-quallified class name of the processor's entry
   #       point.
   #
   # Example
   #   java_annotation_processor("foo_processor") {
-  #     java_files = [ "org/chromium/foo/FooProcessor.java" ]
+  #     sources = [ "org/chromium/foo/FooProcessor.java" ]
   #     deps = [ ":bar_java" ]
   #     main_class = "org.chromium.foo.FooProcessor"
   #   }
@@ -1333,7 +1333,7 @@
   #
   # Example
   #   junit_binary("foo") {
-  #     java_files = [ "org/chromium/foo/FooTest.java" ]
+  #     sources = [ "org/chromium/foo/FooTest.java" ]
   #     deps = [ ":bar_java" ]
   #   }
   template("junit_binary") {
@@ -1446,11 +1446,11 @@
   #   annotation_processor_deps: List of java_annotation_processor targets to
   #     use when compiling.
   #
-  #   jar_path: Path to a prebuilt jar. Mutually exclusive with java_files &
+  #   jar_path: Path to a prebuilt jar. Mutually exclusive with sources &
   #     srcjar_deps.
-  #   java_files: List of .java files included in this library.
+  #   sources: List of .java files included in this library.
   #   srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
-  #     will be added to java_files and be included in this library.
+  #     will be added to sources and be included in this library.
   #
   #   input_jars_paths: A list of paths to the jars that should be included
   #     in the compile-time classpath. These are in addition to library .jars
@@ -1488,7 +1488,7 @@
   #
   # Example
   #   java_library("foo_java") {
-  #     java_files = [
+  #     sources = [
   #       "org/chromium/foo/Foo.java",
   #       "org/chromium/foo/FooInterface.java",
   #       "org/chromium/foo/FooService.java",
@@ -1851,7 +1851,7 @@
   #
   # Example
   #   android_library("foo_java") {
-  #     java_files = [
+  #     sources = [
   #       "android/org/chromium/foo/Foo.java",
   #       "android/org/chromium/foo/FooInterface.java",
   #       "android/org/chromium/foo/FooService.java",
@@ -2140,9 +2140,9 @@
   #     step.
   #   disable_r8_outlining: Turn off outlining during the proguard step.
   #   annotation_processor_deps: List of java_annotation_processor targets to
-  #     use when compiling the java_files given to this target (optional).
+  #     use when compiling the sources given to this target (optional).
   #   processor_args_javac: List of args to pass to annotation processors when
-  #     compiling java_files given to this target (optional).
+  #     compiling sources given to this target (optional).
   template("android_apk_or_module") {
     forward_variables_from(invoker, [ "testonly" ])
     assert(defined(invoker.android_manifest))
@@ -2810,7 +2810,6 @@
                                "base_module_target",
                                "chromium_code",
                                "jacoco_never_instrument",
-                               "java_files",
                                "javac_args",
                                "manifest_package",
                                "native_lib_placeholders",
@@ -3113,15 +3112,6 @@
       }
     }
 
-    if (_native_libs_deps != []) {
-      _create_stack_script_rule_name = "${_template_name}__stack_script"
-      _final_deps += [ ":${_create_stack_script_rule_name}" ]
-      stack_script(_create_stack_script_rule_name) {
-        stack_target_name = invoker.target_name
-        deps = _native_libs_deps
-      }
-    }
-
     _all_native_libs_deps = _native_libs_deps + _loadable_modules_deps +
                             _secondary_abi_native_libs_deps
     if (_all_native_libs_deps != []) {
@@ -3448,7 +3438,7 @@
   # Example
   #   android_apk("foo_apk") {
   #     android_manifest = "AndroidManifest.xml"
-  #     java_files = [
+  #     sources = [
   #       "android/org/chromium/foo/FooApplication.java",
   #       "android/org/chromium/foo/FooActivity.java",
   #     ]
@@ -3494,7 +3484,6 @@
                                "input_jars_paths",
                                "use_modern_linker",
                                "jacoco_never_instrument",
-                               "java_files",
                                "javac_args",
                                "jni_registration_header",
                                "jni_sources_blacklist",
@@ -3626,7 +3615,6 @@
                                "input_jars_paths",
                                "is_base_module",
                                "jacoco_never_instrument",
-                               "java_files",
                                "javac_args",
                                "jni_registration_header",
                                "jni_sources_blacklist",
@@ -3764,7 +3752,7 @@
   #     android_manifest = "AndroidManifest.xml"
   #     apk_name = "FooTest"
   #     apk_under_test = "Foo"
-  #     java_files = [
+  #     sources = [
   #       "android/org/chromium/foo/FooTestCase.java",
   #       "android/org/chromium/foo/FooExampleTest.java",
   #     ]
@@ -4121,7 +4109,7 @@
 
     android_library(target_name) {
       chromium_code = false
-      java_files = []
+      sources = []
       srcjar_deps = [ ":${_template_name}__protoc_java" ]
       deps = [
         _proto_runtime,
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index d7b38c92..2354f1b9 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -143,11 +143,10 @@
   # rest with 0xAA. This makes behavior of uninitialized memory bugs consistent,
   # recognizeble in debugger, and crashes memory accesses by uninitialized
   # pointers.
-  # TODO(vitalybuka): investigate why some debug windows bots fail tests.
+  # TODO(vitalybuka):
   # 'is_android' breaks content_shell_test_apk on android-kitkat-arm-rel.
   # 'use_xcode_clang' may call old clang.
-  init_stack_vars = !is_android && !(is_win && is_debug) && !use_xcode_clang &&
-                    !is_official_build
+  init_stack_vars = !is_android && !use_xcode_clang && !is_official_build
 }
 
 declare_args() {
diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni
index ba0c606..597200f 100644
--- a/build_overrides/dawn.gni
+++ b/build_overrides/dawn.gni
@@ -4,11 +4,12 @@
 
 # The paths to Dawn's dependencies
 dawn_glfw_dir = "//third_party/glfw/src"
-dawn_jinja2_dir = "//third_party/jinja2"
 dawn_googletest_dir = "//third_party/googletest/src"
+dawn_jinja2_dir = "//third_party/jinja2"
 dawn_jsoncpp_dir = "//third_party/jsoncpp"
 dawn_shaderc_dir = "//third_party/shaderc/src"
 dawn_spirv_cross_dir = "//third_party/spirv-cross/spirv-cross"
 dawn_spirv_tools_dir = "//third_party/SPIRV-Tools/src"
+dawn_swiftshader_dir = "//third_party/swiftshader"
 dawn_vulkan_validation_layers_dir =
     "//third_party/angle/third_party/vulkan-validation-layers/src"
diff --git a/cc/benchmarks/rasterize_and_record_benchmark.cc b/cc/benchmarks/rasterize_and_record_benchmark.cc
index 120203ca..a5f74f3b 100644
--- a/cc/benchmarks/rasterize_and_record_benchmark.cc
+++ b/cc/benchmarks/rasterize_and_record_benchmark.cc
@@ -84,6 +84,12 @@
 
 void RasterizeAndRecordBenchmark::DidUpdateLayers(
     LayerTreeHost* layer_tree_host) {
+  // It is possible that this will be called before NotifyDone is called, in the
+  // event that a BeginMainFrame was scheduled before NotifyDone for example.
+  // This check prevents the benchmark from being run a second time redundantly.
+  if (main_thread_benchmark_done_)
+    return;
+
   layer_tree_host_ = layer_tree_host;
   for (auto* layer : *layer_tree_host)
     layer->RunMicroBenchmark(this);
diff --git a/chrome/VERSION b/chrome/VERSION
index ea27187..864b85b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=81
 MINOR=0
-BUILD=4020
+BUILD=4021
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 04fede7..4d21d27 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1885,11 +1885,6 @@
       android_manifest_dep = ":trichrome_library_64_32_android_manifest"
       is_64_bit_browser = true
       include_32_bit_webview = true
-
-      if (trichrome_synchronized_proguard) {
-        webview_target = "//android_webview:trichrome_webview_64_32_apk"
-        chrome_target = ":trichrome_chrome_64_32_bundle"
-      }
     }
 
     trichrome_library_apk_tmpl("trichrome_library_64_apk") {
@@ -2464,11 +2459,9 @@
                              "include_64_bit_webview",
                              "static_library_provider",
                              "static_library_synchronized_proguard",
+                             "resource_ids_provider_dep",
                              "use_trichrome_library",
                            ])
-    if (!_is_trichrome || !trichrome_synchronized_proguard) {
-      bundle_target = ":${invoker.target_name}"
-    }
     target_type = "android_app_bundle_module"
     is_base_module = true
     version_code = _version_code
@@ -2480,8 +2473,10 @@
           "monochrome_public_bundle.android_manifest.failed"
     }
 
-    if (_is_trichrome && trichrome_synchronized_proguard) {
-      resource_ids_provider_dep = "//android_webview:trichrome_webview_apk"
+    if (!_is_trichrome ||
+        !defined(invoker.static_library_synchronized_proguard) ||
+        !invoker.static_library_synchronized_proguard) {
+      bundle_target = ":${invoker.target_name}"
     }
   }
 
@@ -2557,6 +2552,9 @@
     static_library_provider = ":trichrome_library_apk"
     if (!is_java_debug) {
       static_library_synchronized_proguard = trichrome_synchronized_proguard
+      if (trichrome_synchronized_proguard) {
+        resource_ids_provider_dep = "//android_webview:trichrome_webview_apk"
+      }
     }
     if (android_64bit_target_cpu) {
       is_64_bit_browser = false
diff --git a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fr.xtb b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fr.xtb
index d90bef02..31cfdf6 100644
--- a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fr.xtb
+++ b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fr.xtb
@@ -15,5 +15,5 @@
 <translation id="6973932557599545801">Malheureusement, je ne peux pas vous aider. Veuillez continuer manuellement.</translation>
 <translation id="7658239707568436148">Annuler</translation>
 <translation id="8253702004019660079">Assistant Google dans Chrome.</translation>
-<translation id="945522503751344254">Envoyer le commentaire</translation>
+<translation id="945522503751344254">Envoyer un commentaire</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_ta.xtb b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_ta.xtb
index af9cb11d..6a6b40be 100644
--- a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_ta.xtb
+++ b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_ta.xtb
@@ -10,7 +10,7 @@
 <translation id="4850886885716139402">காட்சி</translation>
 <translation id="4952448020231702394">இணையத்தில் தேடல், செக் அவுட் போன்றவற்றைச் செய்ய உதவுவதன் மூலம் Google அசிஸ்டண்ட் உங்கள் நேரத்தை மிச்சப்படுத்தும்.</translation>
 <translation id="5267269112080050255">'Chromeமில் Google அசிஸ்டண்ட்' திரையின் முழு அளவிற்குத் திறக்கப்பட்டுள்ளது.</translation>
-<translation id="6235816755461937614">Google அசிஸ்டண்ட் வினவல்களை (உரை மற்றும் குரல்) Chromeமிற்கு அனுப்பும். தளத்தின் URL மற்றும் உள்ளடக்கத்துடன் தொடர்புடைய தனிப்பட்ட தகவலையும் Googleளுக்கு Chrome அனுப்பும். வினவலின் அடிப்படையில் இதில் மின்னஞ்சல் மற்றும் கிரெடிட் கார்டு வகை அடங்கக்கூடும். இதை Chrome அமைப்புகளில் முடக்கலாம். <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" /></translation>
+<translation id="6235816755461937614">Google அசிஸ்டண்ட் வினவல்களை (உரை மற்றும் குரல்) Chromeமிற்கு அனுப்பும். தளத்தின் URL மற்றும் உள்ளடக்கத்தையும் தொடர்புடைய தனிப்பட்ட தகவலையும் Googleளுக்கு Chrome அனுப்பும். வினவலின் அடிப்படையில் இதில் மின்னஞ்சல் மற்றும் கிரெடிட் கார்டு வகை அடங்கக்கூடும். இதை Chrome அமைப்புகளில் முடக்கலாம். <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" /></translation>
 <translation id="6555233628095991027">'Chromeமில் Google அசிஸ்டண்ட்' திரையின் பாதி அளவிற்குத் திறக்கப்பட்டுள்ளது.</translation>
 <translation id="6973932557599545801">மன்னிக்கவும், என்னால் உதவ இயலவில்லை. நீங்களே செய்யுங்கள்.</translation>
 <translation id="7658239707568436148">ரத்து செய்</translation>
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
index ec22c62c..d88123ed 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
@@ -6,9 +6,14 @@
 
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withParent;
 
+import static org.hamcrest.core.AllOf.allOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
@@ -55,7 +60,10 @@
 import org.chromium.chrome.browser.flags.FeatureUtilities;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabFeatureUtilities;
+import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorTestingRobot;
+import org.chromium.chrome.browser.tasks.tab_management.TabSuggestionMessageService;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCoordinator;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -696,6 +704,75 @@
                 mUrl, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR, tab);
     }
 
+    @Test
+    @MediumTest
+    @Feature("TabSuggestion")
+    // clang-format off
+    @Features.EnableFeatures(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study")
+    @Features.DisableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
+    @CommandLineFlags.Add({BASE_PARAMS + "/close_tab_suggestions_stale_time_ms/0"})
+    public void testTabSuggestionMessageCard_dismiss() throws InterruptedException {
+        // clang-format on
+        prepareTabs(3, 0, null);
+
+        // TODO(meiliang): Avoid using static variable for tracking state,
+        // TabSuggestionMessageService.isSuggestionAvailableForTesting(). Instead, we can add a
+        // dummy MessageObserver to track the availability of the suggestions.
+        CriteriaHelper.pollInstrumentationThread(
+                ()
+                        -> TabSuggestionMessageService.isSuggestionAvailableForTesting()
+                        && mActivityTestRule.getActivity()
+                                        .getTabModelSelector()
+                                        .getCurrentModel()
+                                        .getCount()
+                                == 3);
+
+        enterGTSWithThumbnailChecking();
+
+        // TODO(meiliang): Avoid using static variable for tracking state,
+        // TabSwitcherCoordinator::hasAppendedMessagesForTesting. Instead, we can query the number
+        // of items that the inner model of the TabSwitcher has.
+        CriteriaHelper.pollInstrumentationThread(
+                TabSwitcherCoordinator::hasAppendedMessagesForTesting);
+        onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
+        onView(allOf(withId(R.id.close_button), withParent(withId(R.id.tab_grid_message_item))))
+                .perform(click());
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
+    }
+
+    @Test
+    @MediumTest
+    @Feature("TabSuggestion")
+    // clang-format off
+    @Features.EnableFeatures(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study")
+    @Features.DisableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
+    @CommandLineFlags.Add({BASE_PARAMS + "/close_tab_suggestions_stale_time_ms/0"})
+    public void testTabSuggestionMessageCard_review() throws InterruptedException {
+        // clang-format on
+        prepareTabs(3, 0, null);
+
+        CriteriaHelper.pollInstrumentationThread(
+                ()
+                        -> TabSuggestionMessageService.isSuggestionAvailableForTesting()
+                        && mActivityTestRule.getActivity()
+                                        .getTabModelSelector()
+                                        .getCurrentModel()
+                                        .getCount()
+                                == 3);
+
+        enterGTSWithThumbnailChecking();
+
+        CriteriaHelper.pollInstrumentationThread(
+                TabSwitcherCoordinator::hasAppendedMessagesForTesting);
+        onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
+        onView(allOf(withId(R.id.action_button), withParent(withId(R.id.tab_grid_message_item))))
+                .perform(click());
+
+        TabSelectionEditorTestingRobot tabSelectionEditorTestingRobot =
+                new TabSelectionEditorTestingRobot();
+        tabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsVisible();
+    }
+
     private static class TabCountAssertion implements ViewAssertion {
         private int mExpectedCount;
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
index 8a84c75..f8c8007 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
@@ -6,8 +6,6 @@
 
 import android.content.Context;
 
-import org.chromium.base.LifetimeAssert;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -18,7 +16,6 @@
  * {@link MessageService}.
  */
 public class MessageCardProviderCoordinator {
-    private final LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this);
     private final MessageCardProviderMediator mMediator;
     private final List<MessageService> mMessageServices = new ArrayList<>();
 
@@ -53,8 +50,5 @@
         for (int i = 0; i < mMessageServices.size(); i++) {
             mMessageServices.get(i).removeObserver(mMediator);
         }
-        // If mLifetimeAssert is GC'ed before this is called, it will throw an exception
-        // with a stack trace showing the stack during LifetimeAssert.create().
-        LifetimeAssert.setSafeToGc(mLifetimeAssert, true);
     }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinder.java
index 9c0ccfa3..89a15932 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinder.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinder.java
@@ -56,4 +56,4 @@
             });
         }
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java
index 06e1ee8..5ff0c884 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewProperties.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.MODEL_TYPE;
+
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -36,8 +38,9 @@
             .WritableObjectPropertyKey<String> DISMISS_BUTTON_CONTENT_DESCRIPTION =
             new PropertyModel.WritableObjectPropertyKey<>();
 
-    public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {ACTION_TEXT, DESCRIPTION_TEXT,
-            DESCRIPTION_TEXT_TEMPLATE, MESSAGE_TYPE, ICON_PROVIDER, UI_ACTION_PROVIDER,
-            UI_DISMISS_ACTION_PROVIDER, MESSAGE_SERVICE_ACTION_PROVIDER,
-            MESSAGE_SERVICE_DISMISS_ACTION_PROVIDER, DISMISS_BUTTON_CONTENT_DESCRIPTION};
+    public static final PropertyKey[] ALL_KEYS =
+            new PropertyKey[] {ACTION_TEXT, DESCRIPTION_TEXT, DESCRIPTION_TEXT_TEMPLATE,
+                    MESSAGE_TYPE, ICON_PROVIDER, UI_ACTION_PROVIDER, UI_DISMISS_ACTION_PROVIDER,
+                    MESSAGE_SERVICE_ACTION_PROVIDER, MESSAGE_SERVICE_DISMISS_ACTION_PROVIDER,
+                    DISMISS_BUTTON_CONTENT_DESCRIPTION, MODEL_TYPE};
 }
\ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
index 14efc42..a212a3e1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -23,6 +23,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.FeatureUtilities;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -225,8 +226,11 @@
                     false));
         }
 
+        // TODO(crbug.com/1004570) : Support drag and drop, and swipe to dismiss when
+        // CLOSE_TAB_SUGGESTIONS is enabled.
         if ((mMode == TabListMode.GRID || mMode == TabListMode.LIST)
-                && selectionDelegateProvider == null) {
+                && selectionDelegateProvider == null
+                && !ChromeFeatureList.isEnabled(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS)) {
             ItemTouchHelper touchHelper = new ItemTouchHelper(mMediator.getItemTouchHelperCallback(
                     context.getResources().getDimension(R.dimen.swipe_to_dismiss_threshold),
                     context.getResources().getDimension(R.dimen.tab_grid_merge_threshold),
@@ -369,4 +373,18 @@
     void addSpecialListItem(int index, @UiType int uiType, PropertyModel model) {
         mMediator.addSpecialItemToModel(index, uiType, model);
     }
+
+    /**
+     * Removes a special {@link org.chromium.ui.modelutil.MVCListAdapter.ListItem} that
+     * has the given {@code uiType} and/or its {@link PropertyModel} has the given
+     * {@code itemIdentifier}.
+     *
+     * @param uiType The uiType to match.
+     * @param itemIdentifier The itemIdentifier to match. This can be obsoleted if the {@link
+     *         org.chromium.ui.modelutil.MVCListAdapter.ListItem} does not need additional
+     *         identifier.
+     */
+    void removeSpecialListItem(@UiType int uiType, int itemIdentifier) {
+        mMediator.removeSpecialItemFromModel(uiType, itemIdentifier);
+    }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index ec67126a..544e8f0 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -4,6 +4,10 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.MODEL_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.ModelType.TAB;
+
 import android.app.Activity;
 import android.content.ComponentCallbacks;
 import android.content.Context;
@@ -845,6 +849,8 @@
         assert mVisible;
         int count = 0;
         for (int i = 0; i < mModel.size(); i++) {
+            if (mModel.get(i).model.get(MODEL_TYPE) != TAB) continue;
+
             if (mModel.get(i).model.get(TabProperties.IS_SELECTED)) count++;
             mModel.get(i).model.set(TabProperties.IS_SELECTED, false);
         }
@@ -859,7 +865,10 @@
         }
         if (tabs.size() != mModel.size()) return false;
         for (int i = 0; i < tabs.size(); i++) {
-            if (tabs.get(i).getId() != mModel.get(i).model.get(TabProperties.TAB_ID)) return false;
+            if (mModel.get(i).model.get(MODEL_TYPE) == TAB
+                    && mModel.get(i).model.get(TabProperties.TAB_ID) != tabs.get(i).getId()) {
+                return false;
+            }
         }
         return true;
     }
@@ -923,7 +932,9 @@
     void softCleanup() {
         assert !mVisible;
         for (int i = 0; i < mModel.size(); i++) {
-            mModel.get(i).model.set(TabProperties.THUMBNAIL_FETCHER, null);
+            if (mModel.get(i).model.get(MODEL_TYPE) == TAB) {
+                mModel.get(i).model.set(TabProperties.THUMBNAIL_FETCHER, null);
+            }
         }
     }
 
@@ -1130,6 +1141,7 @@
                         .with(TabProperties.TABSTRIP_FAVICON_BACKGROUND_COLOR_ID,
                                 tabstripFaviconBackgroundDrawableId)
                         .with(TabProperties.ACCESSIBILITY_DELEGATE, mAccessibilityDelegate)
+                        .with(MODEL_TYPE, TAB)
                         .build();
 
         if (mUiType == UiType.SELECTABLE) {
@@ -1284,6 +1296,37 @@
         mModel.add(index, new SimpleRecyclerViewAdapter.ListItem(uiType, model));
     }
 
+    /**
+     * Removes a special {@link @link org.chromium.ui.modelutil.MVCListAdapter.ListItem} that
+     * has the given {@code uiType} and/or its {@link PropertyModel} has the given
+     * {@code itemIdentifier} from the current {@link TabListModel}.
+     *
+     * @param uiType The uiType to match.
+     * @param itemIdentifier The itemIdentifier to match. This can be obsoleted if the {@link @link
+     *         org.chromium.ui.modelutil.MVCListAdapter.ListItem} does not need additional
+     *         identifier.
+     */
+    void removeSpecialItemFromModel(@UiType int uiType, int itemIdentifier) {
+        int index = TabModel.INVALID_TAB_INDEX;
+        if (uiType == UiType.MESSAGE) {
+            index = mModel.lastIndexForMessageItemFromType(itemIdentifier);
+        }
+
+        if (index == TabModel.INVALID_TAB_INDEX) return;
+
+        assert validateItemAt(index, uiType, itemIdentifier);
+        mModel.removeAt(index);
+    }
+
+    private boolean validateItemAt(int index, @UiType int uiType, int itemIdentifier) {
+        if (uiType == UiType.MESSAGE) {
+            return mModel.get(index).type == uiType
+                    && mModel.get(index).model.get(MESSAGE_TYPE) == itemIdentifier;
+        }
+
+        return false;
+    }
+
     @VisibleForTesting
     View.AccessibilityDelegate getAccessibilityDelegateForTesting() {
         return mAccessibilityDelegate;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java
index b7173a6..a706e179 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java
@@ -4,15 +4,26 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.MODEL_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.ModelType.MESSAGE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.ModelType.OTHERS;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.ModelType.TAB;
 import static org.chromium.chrome.browser.tasks.tab_management.TabProperties.TAB_ID;
 
 import android.util.Pair;
 
+import androidx.annotation.IntDef;
+
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.ui.modelutil.MVCListAdapter;
 import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyListModel;
+import org.chromium.ui.modelutil.PropertyModel;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
 /**
@@ -21,18 +32,66 @@
  */
 class TabListModel extends ModelList {
     /**
+     * Required properties for each {@link PropertyModel} managed by this {@link ModelList}.
+     */
+    static class TabListModelProperties {
+        /** Supported Model type within this ModelList. */
+        @IntDef({TAB, MESSAGE, OTHERS})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface ModelType {
+            int TAB = 0;
+            int MESSAGE = 1;
+            int OTHERS = 2;
+        }
+
+        public static final PropertyModel.ReadableIntPropertyKey MODEL_TYPE =
+                new PropertyModel.ReadableIntPropertyKey();
+    }
+
+    /**
      * Convert the given tab ID to an index to match during partial updates.
      * @param tabId The tab ID to search for.
      * @return The index within the model {@link org.chromium.ui.modelutil.SimpleList}.
      */
     public int indexFromId(int tabId) {
         for (int i = 0; i < size(); i++) {
-            if (get(i).model.get(TAB_ID) == tabId) return i;
+            PropertyModel model = get(i).model;
+            if (model.get(MODEL_TYPE) == TAB && model.get(TAB_ID) == tabId) return i;
         }
         return TabModel.INVALID_TAB_INDEX;
     }
 
     /**
+     * Get the index that matches a message item that has the given message type.
+     * @param messageType The message type to match.
+     * @return The index within the model.
+     */
+    public int lastIndexForMessageItemFromType(int messageType) {
+        for (int i = size() - 1; i >= 0; i--) {
+            PropertyModel model = get(i).model;
+            if (model.get(MODEL_TYPE) == MESSAGE && model.get(MESSAGE_TYPE) == messageType) {
+                return i;
+            }
+        }
+        return TabModel.INVALID_TAB_INDEX;
+    }
+
+    @Override
+    public void add(int position, MVCListAdapter.ListItem item) {
+        assert validateListItem(item);
+        super.add(position, item);
+    }
+
+    private boolean validateListItem(MVCListAdapter.ListItem item) {
+        try {
+            item.model.get(MODEL_TYPE);
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Sync the {@link TabListModel} with updated information. Update tab id of
      * the item in {@code index} with the current selected {@code tab} of the group.
      * @param selectedTab   The current selected tab in the group.
@@ -80,8 +139,9 @@
         int status = isSelected ? ClosableTabGridView.AnimationStatus.SELECTED_CARD_ZOOM_IN
                                 : ClosableTabGridView.AnimationStatus.SELECTED_CARD_ZOOM_OUT;
         if (index < 0 || index >= size()
-                || get(index).model.get(TabProperties.CARD_ANIMATION_STATUS) == status)
+                || get(index).model.get(TabProperties.CARD_ANIMATION_STATUS) == status) {
             return;
+        }
 
         get(index).model.set(TabProperties.CARD_ANIMATION_STATUS, status);
         get(index).model.set(TabProperties.ALPHA, isSelected ? 0.8f : 1f);
@@ -99,8 +159,10 @@
         int status = isHovered ? ClosableTabGridView.AnimationStatus.HOVERED_CARD_ZOOM_IN
                                : ClosableTabGridView.AnimationStatus.HOVERED_CARD_ZOOM_OUT;
         if (index < 0 || index >= size()
-                || get(index).model.get(TabProperties.CARD_ANIMATION_STATUS) == status)
+                || get(index).model.get(TabProperties.CARD_ANIMATION_STATUS) == status) {
             return;
+        }
+
         get(index).model.set(TabProperties.CARD_ANIMATION_STATUS, status);
     }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
index d36822d..6b04f49 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.MODEL_TYPE;
+
 import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
 import android.view.View.AccessibilityDelegate;
@@ -103,7 +105,8 @@
             CARD_ANIMATION_STATUS, SELECTABLE_TAB_CLICKED_LISTENER, TAB_SELECTION_DELEGATE,
             IS_INCOGNITO, SELECTED_TAB_BACKGROUND_DRAWABLE_ID, TABSTRIP_FAVICON_BACKGROUND_COLOR_ID,
             SELECTABLE_TAB_ACTION_BUTTON_BACKGROUND,
-            SELECTABLE_TAB_ACTION_BUTTON_SELECTED_BACKGROUND, URL, ACCESSIBILITY_DELEGATE};
+            SELECTABLE_TAB_ACTION_BUTTON_SELECTED_BACKGROUND, URL, ACCESSIBILITY_DELEGATE,
+            MODEL_TYPE};
 
     public static final PropertyKey[] ALL_KEYS_TAB_STRIP =
             new PropertyKey[] {TAB_ID, TAB_SELECTED_LISTENER, TAB_CLOSED_LISTENER, FAVICON,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
index c910e131..db6638fe 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
@@ -4,6 +4,9 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.MODEL_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.ModelType.OTHERS;
+
 import android.content.Context;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
@@ -171,10 +174,9 @@
     void resetWithListOfTabs(@Nullable List<Tab> tabs, int preSelectedCount) {
         mTabListCoordinator.resetWithListOfTabs(tabs);
 
-        if (tabs != null && preSelectedCount > 0) {
-            assert preSelectedCount < tabs.size();
-            mTabListCoordinator.addSpecialListItem(
-                    preSelectedCount, TabProperties.UiType.DIVIDER, new PropertyModel());
+        if (tabs != null && preSelectedCount > 0 && preSelectedCount < tabs.size()) {
+            mTabListCoordinator.addSpecialListItem(preSelectedCount, TabProperties.UiType.DIVIDER,
+                    new PropertyModel.Builder(MODEL_TYPE).with(MODEL_TYPE, OTHERS).build());
         }
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
index 1866df3..7138e5d 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
@@ -4,6 +4,9 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.MODEL_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.ModelType.MESSAGE;
+
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 
@@ -48,6 +51,7 @@
                 .with(MessageCardViewProperties.ACTION_TEXT, actionText)
                 .with(MessageCardViewProperties.DISMISS_BUTTON_CONTENT_DESCRIPTION,
                         dismissButtonContextDescription)
+                .with(MODEL_TYPE, MESSAGE)
                 .build();
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java
index 2e9255e..fcd525593 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java
@@ -32,6 +32,7 @@
  */
 public class TabSuggestionMessageService extends MessageService implements TabSuggestionsObserver {
     static final int CLOSE_SUGGESTION_ACTION_ENABLING_THRESHOLD = 1;
+    private static boolean sSuggestionAvailableForTesting;
 
     /**
      * This is the data type that this MessageService is serving to its Observer.
@@ -209,6 +210,7 @@
             Callback<TabSuggestionFeedback> tabSuggestionFeedback) {
         if (tabSuggestions.size() == 0) return;
 
+        sSuggestionAvailableForTesting = true;
         mCurrentBestTabSuggestion = tabSuggestions.get(0);
         mCurrentTabSuggestionFeedback = tabSuggestionFeedback;
         sendAvailabilityNotification(new TabSuggestionMessageData(
@@ -218,6 +220,12 @@
     @Override
     public void onTabSuggestionInvalidated() {
         mCurrentBestTabSuggestion = null;
+        sSuggestionAvailableForTesting = false;
         sendInvalidNotification();
     }
+
+    @VisibleForTesting
+    public static boolean isSuggestionAvailableForTesting() {
+        return sSuggestionAvailableForTesting;
+    }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
index 6d4114f..461b8bd 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -32,6 +32,7 @@
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabList;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.tab_management.suggestions.TabSuggestionsOrchestrator;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -51,6 +52,7 @@
     // TODO(crbug.com/982018): Rename 'COMPONENT_NAME' so as to add different metrics for carousel
     // tab switcher.
     static final String COMPONENT_NAME = "GridTabSwitcher";
+    private static boolean sAppendedMessagesForTesting;
     private final PropertyModelChangeProcessor mContainerViewChangeProcessor;
     private final ActivityLifecycleDispatcher mLifecycleDispatcher;
     private final MenuOrKeyboardActionController mMenuOrKeyboardActionController;
@@ -62,6 +64,8 @@
     private final UndoGroupSnackbarController mUndoGroupSnackbarController;
     private final TabModelSelector mTabModelSelector;
     private final @TabListCoordinator.TabListMode int mMode;
+    private final MessageCardProviderCoordinator mMessageCardProviderCoordinator;
+    private TabSuggestionsOrchestrator mTabSuggestionsOrchestrator;
 
     private final MenuOrKeyboardActionController
             .MenuOrKeyboardActionHandler mTabSwitcherMenuActionHandler =
@@ -121,6 +125,11 @@
         mContainerViewChangeProcessor = PropertyModelChangeProcessor.create(containerViewModel,
                 mTabListCoordinator.getContainerView(), TabListContainerViewBinder::bind);
 
+        mMessageCardProviderCoordinator = new MessageCardProviderCoordinator(context,
+                (identifier)
+                        -> mTabListCoordinator.removeSpecialListItem(
+                                TabProperties.UiType.MESSAGE, identifier));
+
         if (FeatureUtilities.isTabGroupsAndroidUiImprovementsEnabled()) {
             mTabGridDialogCoordinator = new TabGridDialogCoordinator(context, tabModelSelector,
                     tabContentManager, tabCreatorManager,
@@ -151,6 +160,15 @@
                     return (ViewGroup) LayoutInflater.from(context).inflate(
                             R.layout.tab_grid_message_card_item, container, false);
                 }, MessageCardViewBinder::bind);
+
+                mTabSuggestionsOrchestrator =
+                        new TabSuggestionsOrchestrator(mTabModelSelector, lifecycleDispatcher);
+                TabSuggestionMessageService tabSuggestionMessageService =
+                        new TabSuggestionMessageService(context, tabModelSelector,
+                                mTabSelectionEditorCoordinator.getController());
+                mTabSuggestionsOrchestrator.addObserver(tabSuggestionMessageService);
+                mMessageCardProviderCoordinator.subscribeMessageService(
+                        tabSuggestionMessageService);
             }
 
             assert mTabListCoordinator.getContainerView().getLayoutManager()
@@ -179,6 +197,11 @@
         mLifecycleDispatcher.register(this);
     }
 
+    @VisibleForTesting
+    public static boolean hasAppendedMessagesForTesting() {
+        return sAppendedMessagesForTesting;
+    }
+
     // TabSwitcher implementation.
     @Override
     public void setOnTabSelectingListener(OnTabSelectingListener listener) {
@@ -283,6 +306,7 @@
     // ResetHandler implementation.
     @Override
     public boolean resetWithTabList(@Nullable TabList tabList, boolean quickMode, boolean mruMode) {
+        sAppendedMessagesForTesting = false;
         List<Tab> tabs = null;
         if (tabList != null) {
             tabs = new ArrayList<>();
@@ -292,7 +316,21 @@
         }
 
         mMediator.registerFirstMeaningfulPaintRecorder();
-        return mTabListCoordinator.resetWithListOfTabs(tabs, quickMode, mruMode);
+        boolean showQuickly = mTabListCoordinator.resetWithListOfTabs(tabs, quickMode, mruMode);
+
+        if (tabs != null && tabs.size() > 0) appendMessagesTo(tabs.size());
+
+        return showQuickly;
+    }
+
+    private void appendMessagesTo(int index) {
+        List<MessageCardProviderMediator.Message> messages =
+                mMessageCardProviderCoordinator.getMessageItems();
+        for (int i = 0; i < messages.size(); i++) {
+            mTabListCoordinator.addSpecialListItem(
+                    index + i, TabProperties.UiType.MESSAGE, messages.get(i).model);
+        }
+        if (messages.size() > 0) sAppendedMessagesForTesting = true;
     }
 
     private View getTabGridDialogAnimationSourceView(int tabId) {
@@ -318,6 +356,7 @@
         mMenuOrKeyboardActionController.unregisterMenuOrKeyboardActionHandler(
                 mTabSwitcherMenuActionHandler);
         mTabListCoordinator.destroy();
+        mMessageCardProviderCoordinator.destroy();
         mContainerViewChangeProcessor.destroy();
         if (mTabGridDialogCoordinator != null) {
             mTabGridDialogCoordinator.destroy();
diff --git a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb
index 7193ba35..09385f8 100644
--- a/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb
+++ b/chrome/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings_ta.xtb
@@ -4,7 +4,7 @@
 <translation id="1075622780330595106">உங்கள் <ph name="NUMBER_OF_TABS" /> தாவல்கள் சமீபத்தில் பயன்படுத்தவில்லை. அவற்றை மூடவா?</translation>
 <translation id="1181037720776840403">அகற்று</translation>
 <translation id="125153950246128346">வேறொரு தாவலைப் பார்க்க, தட்டவும்</translation>
-<translation id="1657719826150349398">தாவலைக் கீழே நகரத்து</translation>
+<translation id="1657719826150349398">தாவலைக் கீழே நகர்த்து</translation>
 <translation id="1869137256605757565">{TABS_COUNT,plural, =1{<ph name="TABS_COUNT_ONE" /> தாவல்}other{<ph name="TABS_COUNT_MANY" /> தாவல்கள்}}</translation>
 <translation id="2569352796411618312">பரிந்துரை: உங்களின் <ph name="NUMBER_OF_TABS" /> தாவல்கள் சமீபத்தில் பயன்படுத்தவில்லை. அவற்றை மூட வேண்டுமா?</translation>
 <translation id="257674075312929031">குழு</translation>
@@ -21,13 +21,13 @@
 <translation id="58326064309361797">தாவல்களை இழுப்பதன் மூலம் அவற்றைக் குழுவாக்கலாம்</translation>
 <translation id="6040143037577758943">மூடு</translation>
 <translation id="6193448654517602979">தாவல்களைத் தேர்ந்தெடுக்கவும்</translation>
-<translation id="6562820390860419811">தாவலை இடப்புறம் நகரத்து</translation>
+<translation id="6562820390860419811">தாவலை இடப்புறம் நகர்த்து</translation>
 <translation id="6615455863669487791">எனக்கு காண்பி</translation>
 <translation id="6840760312327750441">தாவல்களைக் குழுவாக்க தாவலைத் தொட்டுப் பிடித்திருக்கவும். பிறகு அதை மற்றொரு தாவலுக்கு இழுத்துச்சென்று விடவும்.</translation>
 <translation id="7151209024774799310">குழுவிலிருந்து தாவல்களை அகற்று</translation>
 <translation id="7559245342362162951">குழு தாவல்களை முழுத்திரை கட்டத்தில் காட்டு</translation>
 <translation id="7792771145871471484">பரிந்துரைகளை சரிபார்க்கும்.</translation>
-<translation id="7885132941432959125">தாவலை வலதுபுறம் நகரத்து</translation>
+<translation id="7885132941432959125">தாவலை வலதுபுறம் நகர்த்து</translation>
 <translation id="7966321538264951561">பரிந்துரைகளை நிராகரிக்கும்.</translation>
 <translation id="83556505225171773">{TABS_COUNT,plural, =1{தேர்ந்தெடுத்த <ph name="TABS_COUNT_ONE" /> தாவலை மூடும்}other{தேர்ந்தெடுத்த <ph name="TABS_COUNT_MANY" /> தாவல்களை மூடும்}}</translation>
 <translation id="9150694013019234766">திரையின் கீழ்ப்பகுதிக்கு அருகில் உங்கள் தாவல் குழுவிலுள்ள தாவல்களுக்கு இடையே மாறலாம்</translation>
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
index 04fc3a7e..7976458 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
@@ -132,7 +132,7 @@
     public final TabSelectionEditorTestingRobot.Result resultRobot;
     public final TabSelectionEditorTestingRobot.Action actionRobot;
 
-    TabSelectionEditorTestingRobot() {
+    public TabSelectionEditorTestingRobot() {
         resultRobot = new TabSelectionEditorTestingRobot.Result();
         actionRobot = new TabSelectionEditorTestingRobot.Action();
     }
@@ -140,15 +140,15 @@
     /**
      * This Robot is used to perform action within the TabSelectionEditor.
      */
-    class Action {
-        TabSelectionEditorTestingRobot.Action clickItemAtAdapterPosition(int position) {
+    public class Action {
+        public TabSelectionEditorTestingRobot.Action clickItemAtAdapterPosition(int position) {
             onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .inRoot(isTabSelectionEditorPopup())
                     .perform(actionOnItemAtPosition(position, click()));
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Action clickToolbarActionButton() {
+        public TabSelectionEditorTestingRobot.Action clickToolbarActionButton() {
             onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.action_button),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.action_bar))))
                     .inRoot(isTabSelectionEditorPopup())
@@ -156,7 +156,7 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Action clickToolbarNavigationButton() {
+        public TabSelectionEditorTestingRobot.Action clickToolbarNavigationButton() {
             onView(allOf(withContentDescription(org.chromium.chrome.tab_ui.R.string.close),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.action_bar))))
                     .inRoot(isTabSelectionEditorPopup())
@@ -168,15 +168,15 @@
     /**
      * This Robot is used to verify result within the TabSelectionEditor.
      */
-    class Result {
-        TabSelectionEditorTestingRobot.Result verifyTabSelectionEditorIsVisible() {
+    public class Result {
+        public TabSelectionEditorTestingRobot.Result verifyTabSelectionEditorIsVisible() {
             onView(withId(org.chromium.chrome.tab_ui.R.id.selectable_list))
                     .inRoot(isTabSelectionEditorPopup())
                     .check(matches(isDisplayed()));
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyTabSelectionEditorIsHidden() {
+        public TabSelectionEditorTestingRobot.Result verifyTabSelectionEditorIsHidden() {
             try {
                 onView(withId(org.chromium.chrome.tab_ui.R.id.selectable_list))
                         .inRoot(isTabSelectionEditorPopup())
@@ -189,7 +189,7 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyToolbarSelectionTextWithResourceId(
+        public TabSelectionEditorTestingRobot.Result verifyToolbarSelectionTextWithResourceId(
                 int resourceId) {
             onView(withText(resourceId))
                     .inRoot(isTabSelectionEditorPopup())
@@ -197,14 +197,14 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyToolbarSelectionText(String text) {
+        public TabSelectionEditorTestingRobot.Result verifyToolbarSelectionText(String text) {
             onView(withText(text))
                     .inRoot(isTabSelectionEditorPopup())
                     .check(matches(isDisplayed()));
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonWithResourceId(
+        public TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonWithResourceId(
                 int resourceId) {
             onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.action_button),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.action_bar))))
@@ -213,7 +213,8 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonWithText(String text) {
+        public TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonWithText(
+                String text) {
             onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.action_button),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.action_bar))))
                     .inRoot(isTabSelectionEditorPopup())
@@ -221,7 +222,7 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonDisabled() {
+        public TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonDisabled() {
             onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.action_button),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.action_bar))))
                     .inRoot(isTabSelectionEditorPopup())
@@ -229,7 +230,7 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonEnabled() {
+        public TabSelectionEditorTestingRobot.Result verifyToolbarActionButtonEnabled() {
             onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.action_button),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.action_bar))))
                     .inRoot(isTabSelectionEditorPopup())
@@ -237,7 +238,7 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyHasAtLeastNItemVisible(int count) {
+        public TabSelectionEditorTestingRobot.Result verifyHasAtLeastNItemVisible(int count) {
             onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .inRoot(isTabSelectionEditorPopup())
                     .check((v, noMatchException) -> {
@@ -249,14 +250,15 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyAdapterHasItemCount(int count) {
+        public TabSelectionEditorTestingRobot.Result verifyAdapterHasItemCount(int count) {
             onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .inRoot(isTabSelectionEditorPopup())
                     .check(matches(RecyclerViewMatcherUtils.adapterHasItemCount(count)));
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyItemNotSelectedAtAdapterPosition(int position) {
+        public TabSelectionEditorTestingRobot.Result verifyItemNotSelectedAtAdapterPosition(
+                int position) {
             onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .inRoot(isTabSelectionEditorPopup())
                     .check(matches(
@@ -264,7 +266,8 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyItemSelectedAtAdapterPosition(int position) {
+        public TabSelectionEditorTestingRobot.Result verifyItemSelectedAtAdapterPosition(
+                int position) {
             onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .inRoot(isTabSelectionEditorPopup())
                     .check(matches(
@@ -272,12 +275,13 @@
             return this;
         }
 
-        TabSelectionEditorTestingRobot.Result verifyUndoSnackbarWithTextIsShown(String text) {
+        public TabSelectionEditorTestingRobot.Result verifyUndoSnackbarWithTextIsShown(
+                String text) {
             onView(withText(text)).check(matches(isDisplayed()));
             return this;
         }
 
-        Result verifyDividerAlwaysStartsAtTheEdgeOfScreen() {
+        public Result verifyDividerAlwaysStartsAtTheEdgeOfScreen() {
             onView(allOf(isDivider(),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))))
                     .inRoot(isTabSelectionEditorPopup())
@@ -291,7 +295,7 @@
             return this;
         }
 
-        Result verifyDividerAlwaysStartsAtTheEdgeOfScreenAtPosition(int position) {
+        public Result verifyDividerAlwaysStartsAtTheEdgeOfScreenAtPosition(int position) {
             onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .inRoot(isTabSelectionEditorPopup())
                     .perform(scrollToPosition(position));
@@ -309,7 +313,7 @@
             return this;
         }
 
-        Result verifyDividerNotClickableNotFocusable() {
+        public Result verifyDividerNotClickableNotFocusable() {
             onView(allOf(isDivider(),
                            withParent(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))))
                     .inRoot(isTabSelectionEditorPopup())
@@ -329,7 +333,7 @@
          * @param targetItemViewType The item view type to be matched.
          * @return {@link Result} to do chain verification.
          */
-        Result verifyHasItemViewTypeAtAdapterPosition(int position, int targetItemViewType) {
+        public Result verifyHasItemViewTypeAtAdapterPosition(int position, int targetItemViewType) {
             onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .inRoot(isTabSelectionEditorPopup())
                     .perform(scrollToPosition(position));
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
index 5dc98fe..598fd81c 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
@@ -121,4 +121,4 @@
         Assert.assertEquals(MessageService.MessageType.TAB_SUGGESTION,
                 model.get(MessageCardViewProperties.MESSAGE_TYPE));
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 3686d8f..581af90 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -28,6 +28,11 @@
 
 import static org.chromium.chrome.browser.ChromeFeatureList.TAB_GROUPS_ANDROID;
 import static org.chromium.chrome.browser.ChromeFeatureList.TAB_GROUPS_UI_IMPROVEMENTS_ANDROID;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageType.FOR_TESTING;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageType.TAB_SUGGESTION;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.MODEL_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.TabListModelProperties.ModelType.MESSAGE;
 
 import android.app.Activity;
 import android.content.ComponentCallbacks;
@@ -1399,7 +1404,9 @@
 
     @Test
     public void addSpecialItem() {
-        mMediator.addSpecialItemToModel(0, TabProperties.UiType.DIVIDER, new PropertyModel());
+        PropertyModel model = mock(PropertyModel.class);
+        when(model.get(MODEL_TYPE)).thenReturn(MESSAGE);
+        mMediator.addSpecialItemToModel(0, TabProperties.UiType.DIVIDER, model);
 
         assertTrue(mModel.size() > 0);
         assertEquals(TabProperties.UiType.DIVIDER, mModel.get(0).type);
@@ -1407,7 +1414,9 @@
 
     @Test
     public void addSpecialItem_notPersistOnReset() {
-        mMediator.addSpecialItemToModel(0, TabProperties.UiType.DIVIDER, new PropertyModel());
+        PropertyModel model = mock(PropertyModel.class);
+        when(model.get(MODEL_TYPE)).thenReturn(MESSAGE);
+        mMediator.addSpecialItemToModel(0, TabProperties.UiType.DIVIDER, model);
         assertEquals(TabProperties.UiType.DIVIDER, mModel.get(0).type);
 
         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2));
@@ -1416,11 +1425,33 @@
         assertNotEquals(TabProperties.UiType.DIVIDER, mModel.get(0).type);
         assertNotEquals(TabProperties.UiType.DIVIDER, mModel.get(1).type);
 
-        mMediator.addSpecialItemToModel(1, TabProperties.UiType.DIVIDER, new PropertyModel());
+        mMediator.addSpecialItemToModel(1, TabProperties.UiType.DIVIDER, model);
         assertThat(mModel.size(), equalTo(3));
         assertEquals(TabProperties.UiType.DIVIDER, mModel.get(1).type);
     }
 
+    @Test(expected = AssertionError.class)
+    public void addSpecialItem_withoutTabListModelProperties() {
+        mMediator.addSpecialItemToModel(0, TabProperties.UiType.DIVIDER, new PropertyModel());
+    }
+
+    @Test
+    public void removeSpecialItem_Message() {
+        PropertyModel model = mock(PropertyModel.class);
+        int expectedMessageType = FOR_TESTING;
+        int wrongMessageType = TAB_SUGGESTION;
+        when(model.get(MODEL_TYPE)).thenReturn(MESSAGE);
+        when(model.get(MESSAGE_TYPE)).thenReturn(expectedMessageType);
+        mMediator.addSpecialItemToModel(0, TabProperties.UiType.MESSAGE, model);
+        assertEquals(1, mModel.size());
+
+        mMediator.removeSpecialItemFromModel(TabProperties.UiType.MESSAGE, wrongMessageType);
+        assertEquals(1, mModel.size());
+
+        mMediator.removeSpecialItemFromModel(TabProperties.UiType.MESSAGE, expectedMessageType);
+        assertEquals(0, mModel.size());
+    }
+
     @Test
     @Features.DisableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
     public void testUrlUpdated_forSingleTab_GTS_GroupNotEnabled() {
diff --git a/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_eu.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_eu.xtb
index c40f18f..ed308bd 100644
--- a/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_eu.xtb
+++ b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_eu.xtb
@@ -1,10 +1,10 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="eu">
-<translation id="1729516292547892356">Errealitate birtualeko edukia ikusteko, eguneratu Google EB zerbitzuak</translation>
+<translation id="1729516292547892356">Errealitate birtualeko edukia ikusteko, eguneratu Google-ren EBko zerbitzuak</translation>
 <translation id="1938981467853765413">Eman iritzia</translation>
 <translation id="360207483134687714">Lagundu Chrome-ko EB modua hobetzen</translation>
 <translation id="3789841737615482174">Instalatu</translation>
 <translation id="473775607612524610">Eguneratu</translation>
-<translation id="9071742570345586758">Errealitate birtualeko edukia ikusteko, instalatu Google EB zerbitzuak</translation>
+<translation id="9071742570345586758">Errealitate birtualeko edukia ikusteko, instalatu Google-ren EBko zerbitzuak</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 4cdf821..aec1291 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -278,7 +278,7 @@
     <dimen name="location_bar_action_icon_width">48dp</dimen>
     <dimen name="location_bar_start_icon_width">28dp</dimen>
     <dimen name="location_bar_start_icon_margin_end">4dp</dimen>
-    <dimen name="location_bar_lateral_padding">11dp</dimen>
+    <dimen name="location_bar_lateral_padding">10dp</dimen>
     <!--  When the url action container is shown, the location bar end padding is built in to its
     actions, so the action container itself uses a negative offset to properly align with the end
      of the location bar. -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationServiceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationServiceBridge.java
index 0c8c164..e3a1512 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationServiceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationServiceBridge.java
@@ -32,6 +32,9 @@
  */
 @JNINamespace("updates")
 public class UpdateNotificationServiceBridge implements UpdateNotificationController, Destroyable {
+    private static final String PREF_UPDATE_NOTIFICATION_THROTTLE_INTERVAL_KEY =
+            "pref_update_notification_throttle_interval_key";
+
     private final Callback<UpdateStatusProvider.UpdateStatus> mObserver = status -> {
         mUpdateStatus = status;
         processUpdateStatus();
@@ -96,4 +99,27 @@
         editor.putLong(PREF_LAST_TIME_UPDATE_NOTIFICATION_KEY, timestamp);
         editor.apply();
     }
+
+    /**
+     * Gets the throttle interval in milliseconds from {@link SharedPreferences}.
+     * return 0 if not exists.
+     */
+    @CalledByNative
+    public static long getThrottleInterval() {
+        SharedPreferences preferences = OmahaBase.getSharedPreferences();
+        return preferences.getLong(PREF_UPDATE_NOTIFICATION_THROTTLE_INTERVAL_KEY, 0);
+    }
+
+    /**
+     * Updates the throttle interval to show Chrome update notification in {@link
+     * SharedPreferences}.
+     * @param interval Throttle interval in milliseconds.
+     */
+    @CalledByNative
+    private static void updateThrottleInterval(long interval) {
+        SharedPreferences preferences = OmahaBase.getSharedPreferences();
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putLong(PREF_UPDATE_NOTIFICATION_THROTTLE_INTERVAL_KEY, interval);
+        editor.apply();
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 7dadff1..afdc8b2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -84,6 +84,7 @@
 
     protected ImageButton mDeleteButton;
     protected ImageButton mMicButton;
+    private boolean mShouldShowMicButtonWhenUnfocused;
     protected UrlBar mUrlBar;
     private final boolean mIsTablet;
 
@@ -100,24 +101,21 @@
     private WindowAndroid mWindowAndroid;
     private WindowDelegate mWindowDelegate;
 
-    protected String mSearchEngineUrl = "";
     private String mOriginalUrl = "";
 
-    protected boolean mUrlFocusChangeInProgress;
+    private boolean mUrlFocusChangeInProgress;
     protected boolean mNativeInitialized;
-    protected boolean mShouldShowSearchEngineLogo;
-    protected boolean mIsSearchEngineGoogle;
     private boolean mUrlHasFocus;
     private boolean mUrlFocusedFromFakebox;
     private boolean mUrlFocusedWithoutAnimations;
-    private boolean mVoiceSearchEnabled;
+    protected boolean mVoiceSearchEnabled;
 
     private OmniboxPrerender mOmniboxPrerender;
 
     protected float mUrlFocusChangePercent;
     protected LinearLayout mUrlActionContainer;
 
-    protected LocationBarVoiceRecognitionHandler mVoiceRecognitionHandler;
+    private LocationBarVoiceRecognitionHandler mVoiceRecognitionHandler;
 
     protected CompositeTouchDelegate mCompositeTouchDelegate;
 
@@ -327,7 +325,7 @@
 
         updateVisualsForState();
 
-        updateMicButtonVisibility(mUrlFocusChangePercent);
+        updateMicButtonVisibility();
     }
 
     /**
@@ -418,7 +416,7 @@
             // The accessibility bounding box is not properly updated when focusing the Omnibox
             // from the NTP fakebox.  Clearing/re-requesting focus triggers the bounding box to
             // be recalculated.
-            if (didFocusUrlFromFakebox() && !inProgress && mUrlHasFocus
+            if (didFocusUrlFromFakebox() && mUrlHasFocus
                     && AccessibilityUtil.isAccessibilityEnabled()) {
                 String existingText = mUrlCoordinator.getTextWithoutAutocomplete();
                 mUrlBar.clearFocus();
@@ -443,12 +441,12 @@
      * Triggered when the URL input field has gained or lost focus.
      * @param hasFocus Whether the URL field has gained focus.
      */
-    public void onUrlFocusChange(boolean hasFocus) {
+    protected void onUrlFocusChange(boolean hasFocus) {
         mUrlHasFocus = hasFocus;
         updateButtonVisibility();
         updateShouldAnimateIconChanges();
 
-        if (hasFocus) {
+        if (mUrlHasFocus) {
             if (mNativeInitialized) RecordUserAction.record("FocusLocation");
             UrlBarData urlBarData = mToolbarDataProvider.getUrlBarData();
             if (urlBarData.editingText != null) {
@@ -486,9 +484,9 @@
 
         mStatusViewCoordinator.onUrlFocusChange(mUrlHasFocus);
 
-        if (!mUrlFocusedWithoutAnimations) handleUrlFocusAnimation(hasFocus);
+        if (!mUrlFocusedWithoutAnimations) handleUrlFocusAnimation(mUrlHasFocus);
 
-        if (hasFocus && mToolbarDataProvider.hasTab() && !mToolbarDataProvider.isIncognito()) {
+        if (mUrlHasFocus && mToolbarDataProvider.hasTab() && !mToolbarDataProvider.isIncognito()) {
             if (mNativeInitialized
                     && TemplateUrlServiceFactory.get().isDefaultSearchEngineGoogle()) {
                 GeolocationHeader.primeLocationForGeoHeader();
@@ -776,7 +774,7 @@
 
             RecordUserAction.record("MobileOmniboxDeleteUrl");
             return;
-        } else if (v == mMicButton && mVoiceRecognitionHandler != null) {
+        } else if (v == mMicButton) {
             RecordUserAction.record("MobileOmniboxVoiceSearch");
             mVoiceRecognitionHandler.startVoiceRecognition(
                     LocationBarVoiceRecognitionHandler.VoiceInteractionSource.OMNIBOX);
@@ -972,12 +970,8 @@
     @Override
     public void updateSearchEngineStatusIcon(boolean shouldShowSearchEngineLogo,
             boolean isSearchEngineGoogle, String searchEngineUrl) {
-        mSearchEngineUrl = searchEngineUrl;
-        mIsSearchEngineGoogle = isSearchEngineGoogle;
-        mShouldShowSearchEngineLogo = shouldShowSearchEngineLogo;
-
         mStatusViewCoordinator.updateSearchEngineStatusIcon(
-                mShouldShowSearchEngineLogo, mIsSearchEngineGoogle, mSearchEngineUrl);
+                shouldShowSearchEngineLogo, isSearchEngineGoogle, searchEngineUrl);
     }
 
     @Override
@@ -1063,17 +1057,24 @@
 
     /**
      * Updates the display of the mic button.
-     *
-     * @param urlFocusChangePercent The completion percentage of the URL focus change animation.
      */
-    protected void updateMicButtonVisibility(float urlFocusChangePercent) {
+    protected void updateMicButtonVisibility() {
         boolean visible = !shouldShowDeleteButton();
         boolean showMicButton = mVoiceSearchEnabled && visible
-                && (mUrlBar.hasFocus() || mUrlFocusChangeInProgress || urlFocusChangePercent > 0f);
+                && (mUrlBar.hasFocus() || mUrlFocusChangeInProgress || mUrlFocusChangePercent > 0f
+                        || mShouldShowMicButtonWhenUnfocused);
         mMicButton.setVisibility(showMicButton ? VISIBLE : GONE);
     }
 
     /**
+     * Value determines if mic button should be shown when location bar is not focused. By default
+     * mic button is not shown. It is only shown for SearchActivityLocationBarLayout.
+     */
+    protected void setShouldShowMicButtonWhenUnfocused(boolean shouldShowMicButtonWhenUnfocused) {
+        mShouldShowMicButtonWhenUnfocused = shouldShowMicButtonWhenUnfocused;
+    }
+
+    /**
      * Call to force the UI to update the state of various buttons based on whether or not the
      * current tab is incognito.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index 681f42a9..0b93ad4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -338,7 +338,7 @@
     @Override
     protected void updateButtonVisibility() {
         super.updateButtonVisibility();
-        updateMicButtonVisibility(mUrlFocusChangePercent);
+        updateMicButtonVisibility();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
index c196326..8cc45263 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
@@ -251,7 +251,7 @@
         if (showSaveOfflineButton) mSaveOfflineButton.setEnabled(isSaveOfflineButtonEnabled());
 
         if (!mShouldShowButtonsWhenUnfocused) {
-            updateMicButtonVisibility(mUrlFocusChangePercent);
+            updateMicButtonVisibility();
         } else {
             mMicButton.setVisibility(shouldShowMicButton() ? View.VISIBLE : View.GONE);
         }
@@ -423,7 +423,7 @@
 
         if (shouldShowSaveOfflineButton() && mSaveOfflineButton.getVisibility() == View.VISIBLE) {
             animators.add(createHideButtonAnimator(mSaveOfflineButton));
-        } else if (!(mUrlBar.isFocused() && mDeleteButton.getVisibility() != View.VISIBLE)) {
+        } else if (!(mUrlBar.hasFocus() && mDeleteButton.getVisibility() != View.VISIBLE)) {
             // If the save offline button isn't enabled, the microphone button always shows when
             // buttons are shown in the unfocused location bar. When buttons are hidden in the
             // unfocused location bar, the microphone shows if the location bar is focused and the
@@ -543,13 +543,13 @@
 
         // There are two actions, bookmark and save offline, and they should be shown if the
         // omnibox isn't focused.
-        return !(mUrlBar.hasFocus() || mUrlFocusChangeInProgress);
+        return !(mUrlBar.hasFocus() || isUrlFocusChangeInProgress());
     }
 
     private boolean shouldShowMicButton() {
         // If the download UI is enabled, the mic button should be only be shown when the url bar
         // is focused.
-        return mVoiceRecognitionHandler != null && mVoiceRecognitionHandler.isVoiceSearchEnabled()
-                && mNativeInitialized && (mUrlBar.hasFocus() || mUrlFocusChangeInProgress);
+        return mVoiceSearchEnabled && mNativeInitialized
+                && (mUrlBar.hasFocus() || isUrlFocusChangeInProgress());
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java
index 2c168922..638df077 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java
@@ -41,6 +41,7 @@
         super(context, attrs, R.layout.location_bar_base);
         setUrlBarFocusable(true);
         setBackground(ToolbarPhone.createModernLocationBarBackground(getResources()));
+        setShouldShowMicButtonWhenUnfocused(true);
 
         mPendingSearchPromoDecision = LocaleManager.getInstance().needToCheckForSearchEnginePromo();
         getAutocompleteCoordinator().setShouldPreventOmniboxAutocomplete(
@@ -82,10 +83,8 @@
     void onDeferredStartup(boolean isVoiceSearchIntent) {
         getAutocompleteCoordinator().prefetchZeroSuggestResults();
 
-        if (mVoiceRecognitionHandler != null) {
-            SearchWidgetProvider.updateCachedVoiceSearchAvailability(
-                    mVoiceRecognitionHandler.isVoiceSearchEnabled());
-        }
+        SearchWidgetProvider.updateCachedVoiceSearchAvailability(
+                getLocationBarVoiceRecognitionHandler().isVoiceSearchEnabled());
         if (isVoiceSearchIntent && mUrlBar.isFocused()) onUrlFocusChange(true);
 
         assert !LocaleManager.getInstance().needToCheckForSearchEnginePromo();
@@ -128,9 +127,8 @@
     private void beginQueryInternal(boolean isVoiceSearchIntent) {
         assert !mPendingSearchPromoDecision;
 
-        if (mVoiceRecognitionHandler != null && mVoiceRecognitionHandler.isVoiceSearchEnabled()
-                && isVoiceSearchIntent) {
-            mVoiceRecognitionHandler.startVoiceRecognition(
+        if (getLocationBarVoiceRecognitionHandler().isVoiceSearchEnabled() && isVoiceSearchIntent) {
+            getLocationBarVoiceRecognitionHandler().startVoiceRecognition(
                     LocationBarVoiceRecognitionHandler.VoiceInteractionSource.SEARCH_WIDGET);
         } else {
             focusTextBox();
@@ -140,7 +138,7 @@
     @Override
     protected void updateButtonVisibility() {
         super.updateButtonVisibility();
-        updateMicButtonVisibility(1.0f);
+        updateMicButtonVisibility();
         findViewById(R.id.url_action_container).setVisibility(View.VISIBLE);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
index 5e70b663..f30c7054 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
@@ -49,7 +49,6 @@
         try {
             ContextUtils.getApplicationContext().startActivity(dialIntent);
             ClickToCallUma.recordDialerPresent(true);
-            ClickToCallUma.recordDialerShown(TextUtils.isEmpty(phoneNumber));
         } catch (ActivityNotFoundException activityNotFound) {
             // Notify the user that no dialer app was available.
             ClickToCallUma.recordDialerPresent(false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java
index 0fe13e26..e034793 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java
@@ -111,13 +111,11 @@
                 .record(timeFromDialerToCallMs);
     }
 
-    public static void recordDialerShown(boolean emptyPhoneNumber) {
-        CallMetricListener.startMetric(ContextUtils.getApplicationContext());
-        new CachedMetrics.BooleanHistogramSample("Sharing.ClickToCallDialIntent")
-                .record(emptyPhoneNumber);
-    }
-
     public static void recordDialerPresent(boolean isDialerPresent) {
+        if (isDialerPresent) {
+            // We successfully launched the dialer intent, lets record if a call is made.
+            CallMetricListener.startMetric(ContextUtils.getApplicationContext());
+        }
         new CachedMetrics.BooleanHistogramSample("Sharing.ClickToCallDialerPresent")
                 .record(isDialerPresent);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
index bd40ba8..b19ede78 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -288,7 +288,7 @@
         }
 
         @Override
-        public void didChangeThemeColor(int color) {
+        public void didChangeThemeColor() {
             TabThemeColorHelper.get(mTab).updateIfNeeded(true);
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index 269293b0..4318c13 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -2134,7 +2134,7 @@
     @Test
     @LargeTest
     @Feature({"ContextualSearch"})
-    @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.O_MR1, message = "crbug.com/1036414")
+    @FlakyTest(message = "crbug.com/1036414, crbug.com/1039488")
     public void testTapALot() throws InterruptedException, TimeoutException {
         for (int i = 0; i < 50; i++) {
             clickToTriggerPrefetch();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 9ce461bb..bfa38b5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -1636,6 +1636,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
+    @DisabledTest(message = "https://crbug.com/692025")
     @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP) // Details in https://crbug.com/709681.
     public void testPostMessageReceivedFromPageWithLateRequest() throws Exception {
         final CallbackHelper messageChannelHelper = new CallbackHelper();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
index ffa09ae..159ab4f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
@@ -38,6 +38,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.task.PostTask;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeFeatureList;
@@ -155,6 +156,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1039491")
     public void testLaunchingActivity() {
         TestThreadUtils.runOnUiThreadBlocking(() -> { setUpUi(); });
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java
index eece6e3..72d8cc7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java
@@ -207,6 +207,7 @@
     @MediumTest
     @Feature({"Browser", "PushMessaging"})
     @RetryOnFailure
+    @DisabledTest(message = "https://crbug.com/707528")
     public void testPushAndShowNotification() throws TimeoutException {
         mNotificationTestRule.setNotificationContentSettingForOrigin(
                 ContentSettingValues.ALLOW, mEmbeddedTestServerRule.getOrigin());
@@ -228,6 +229,7 @@
     @LargeTest
     @Feature({"Browser", "PushMessaging"})
     @RetryOnFailure
+    @DisabledTest(message = "https://crbug.com/707528")
     public void testDefaultNotification() throws TimeoutException {
         // Start off using the tab loaded in setUp().
         Assert.assertEquals(1, mNotificationTestRule.getActivity().getCurrentTabModel().getCount());
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 0773119..5388c4d 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -3607,6 +3607,18 @@
   <message name="IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_MESSAGE" desc="Text shown by the Crostini upgrader when the container backup completed successfully, prior to the main upgrade.">
     Linux apps and files have been successfully backed up. Upgrade will begin shortly.
   </message>
+  <message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_TITLE" desc="Title of the Crostini upgrader when the upgrade prechecks failed.">
+    Error starting upgrade
+  </message>
+  <message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_NETWORK" desc="Text shown by the Crostini upgrader when the upgrade did not start because there was no network connection.">
+    A network connection is required to upgrade Linux. Please connect to the internet and try again.
+  </message>
+  <message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_POWER" desc="Text shown by the Crostini upgrader when the upgrade did not start because there wasn't enough power.">
+    Upgrading Linux can drain your battery significantly. Please connect your device to a charger and try again.
+  </message>
+  <message name="IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_SPACE" desc="Text shown by the Crostini upgrader when the upgrade did not start because there wasn't enough free disk space.">
+    At least <ph name="REQUIRED_SPACE">$1<ex>1GB</ex></ph> of free disk space is required to upgrade Linux. Please free some space on your device and try again.
+  </message>
   <message name="IDS_CROSTINI_UPGRADER_UPGRADING_TITLE" desc="Title of the Crostini upgrader when the upgrade is in progress.">
     Upgrading Linux
   </message>
diff --git a/chrome/app/resources/chromium_strings_ar.xtb b/chrome/app/resources/chromium_strings_ar.xtb
index 08db4b96..3314103 100644
--- a/chrome/app/resources/chromium_strings_ar.xtb
+++ b/chrome/app/resources/chromium_strings_ar.xtb
@@ -19,7 +19,7 @@
 <translation id="1929939181775079593">‏لا يستجيب Chromium. هل تريد إعادة التشغيل الآن؟</translation>
 <translation id="1966382378801805537">‏يتعذَّر على Chromium تحديد المتصفح التلقائي أو تعيينه</translation>
 <translation id="2008474315282236005">‏سيعمل هذا على حذف عنصر واحد من هذا الجهاز. لاسترداد بياناتك لاحقًا، سجّل الدخول إلى Chromium كـ <ph name="USER_EMAIL" />.</translation>
-<translation id="2147976119693222405">‏تعذر على نظام تشغيل Chromium مزامنة بياناتك. إصلاح المشكلة الآن.</translation>
+<translation id="2147976119693222405">‏تعذّر على نظام التشغيل Chromium مزامنة بياناتك. إصلاح المشكلة الآن</translation>
 <translation id="2241627712206172106">‏إذا كنت تشارك الكمبيوتر مع أصدقائك وعائلتك، فبإمكانهم التصفح على حدة وإعداد Chromium على النحو الذي يريدونه.</translation>
 <translation id="2347108572062610441">‏غيّرت هذه الإضافة الصفحة التي تظهر عند بدء Chromium.</translation>
 <translation id="2396765026452590966">‏غيّرت الإضافة "<ph name="EXTENSION_NAME" />" الصفحة التي تظهر عند بدء Chromium.</translation>
@@ -35,7 +35,7 @@
 <translation id="2718390899429598676">‏لمزيد من الأمان، سيشفر Chromium بياناتك</translation>
 <translation id="2770231113462710648">تغيير المتصفح التلقائي إلى:</translation>
 <translation id="2799223571221894425">إعادة تشغيل</translation>
-<translation id="2805036593126168338">‏تعذّر على نظام تشغيل Chromium مزامنة كلمات المرور. إصلاح المشكلة الآن.</translation>
+<translation id="2805036593126168338">‏تعذّر على نظام التشغيل Chromium مزامنة كلمات المرور. إصلاح المشكلة الآن</translation>
 <translation id="2838154144102149890">‏يجب إيقاف تشغيل Chromium على جهاز الكمبيوتر هذا لإجراء التحديث. وجرّاء ذلك، إنّ المستخدمين الآخرين الذين سجَّلوا الدخول إلى جهاز الكمبيوتر هذا قد يفقدون التغييرات غير المحفوظة.</translation>
 <translation id="2847479871509788944">‏إزالة من Chromium</translation>
 <translation id="2886012850691518054">‏اختياري: ساعد في تحسين Chromium عن طريق إرسال إحصائيات الاستخدام وتقارير الأعطال إلى Google تلقائيًا.</translation>
diff --git a/chrome/app/resources/generated_resources_af.xtb b/chrome/app/resources/generated_resources_af.xtb
index 181adb0..5a998cb3 100644
--- a/chrome/app/resources/generated_resources_af.xtb
+++ b/chrome/app/resources/generated_resources_af.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Geen netwerke nie</translation>
 <translation id="1056898198331236512">Waarskuwing</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Winkel-programme</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> bevat sensitiewe inhoud en is geblokkeer.</translation>
 <translation id="1061904396131502319">Dis amper tyd vir 'n blaaskans</translation>
 <translation id="1067048845568873861">Geskep</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Hierdie bladsy is vertaal</translation>
 <translation id="3177909033752230686">Bladsytaal:</translation>
 <translation id="3179982752812949580">Tekslettertipe</translation>
+<translation id="3181825792072797598">Skakel Sinkronisering aan</translation>
 <translation id="3181954750937456830">Veiligblaai (beskerm jou en jou toestel teen gevaarlike werwe)</translation>
 <translation id="3182749001423093222">Speltoets</translation>
 <translation id="3183139917765991655">Profielinvoerder</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Aktiveer die Android-ontfoutingsbrug (ADB) om jou programme te skep en te toets. Let daarop dat hierdie handeling dit moontlik maak om Android-programme te installeer wat nie deur Google geverifieer is nie, en 'n fabriekterugstelling is nodig om dit te deaktiveer.</translation>
 <translation id="7685049629764448582">JavaScript-geheue</translation>
 <translation id="7685087414635069102">PIN word vereis</translation>
+<translation id="768549422429443215">Voeg tale by of herrangskik lys.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bevestig nuwe wagwoord</translation>
 <translation id="7690378713476594306">Kies uit lys</translation>
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index 6c6cd75..35f70acd 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ምንም አውታረ መረቦች የሉም</translation>
 <translation id="1056898198331236512">ማስጠንቀቂያ</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">የPlay መደብር መተግበሪያዎች</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> ሚስጥራዊነት ያለው ይዘት አለው፣ እና ታግዷል።</translation>
 <translation id="1061904396131502319">የእረፍት ጊዜ ሊደርስ ነው</translation>
 <translation id="1067048845568873861">ተፈጥሯል</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">ይህ ገጽ ተተርጉሟል</translation>
 <translation id="3177909033752230686">የገጽ ቋንቋ፦</translation>
 <translation id="3179982752812949580">የጽሑፍ ቅርጸ ቁምፊ</translation>
+<translation id="3181825792072797598">አስምርን አብራ</translation>
 <translation id="3181954750937456830">ደኅንነቱ የተጠበቀ አሰሳ (እርስዎን እና የእርስዎን መሣሪያ ከአደገኛ ጣቢያዎች ጥበቃ ያደርግላችኋል)</translation>
 <translation id="3182749001423093222">ፊደል አራሚ</translation>
 <translation id="3183139917765991655">የመገለጫ አስመጪ</translation>
@@ -4650,6 +4650,7 @@
 <translation id="7684718995427157417">መተግበሪያዎችዎን ለመፍጠርና ለመሞከር የAndroid ማረሚያ ድልድይን (ADB) ያንቁት። ይህ እርምጃ በGoogle ያልተረጋገጡ የAndroid መተግበሪያዎች መጫንን እንደሚፈቅድ፣ እና ለማሰናከል ወደ የፋብሪካ ዳግም ማስጀመር እንደሚያስፈልግ ልብ ይበሉ።</translation>
 <translation id="7685049629764448582">ጃቫስክሪፕት ማህደረ ትውስታ</translation>
 <translation id="7685087414635069102">ፒን ያስፈልጋል</translation>
+<translation id="768549422429443215">ቋንቋዎችን ያክሉ ወይም ዝርዝርን ዳግም ያደራጁ።</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">አዲስ የይለፍ ቃል ያረጋግጡ</translation>
 <translation id="7690378713476594306">ከዝርዝር ይምረጡ</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 04f997a..dea17d6 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -36,7 +36,7 @@
 <translation id="1041175011127912238">الصفحة لا تستجيب.</translation>
 <translation id="1041263367839475438">الأجهزة المتوفِّرة</translation>
 <translation id="1042174272890264476">‏يأتي جهاز الكمبيوتر أيضًا مزودًا بمكتبة RLZ مضمنة للمنتج <ph name="SHORT_PRODUCT_NAME" />. تعيّن RLZ علامة غير فريدة وغير متعلقة بتحديد الشخصية من أجل قياس عمليات البحث ومعدل استخدام <ph name="SHORT_PRODUCT_NAME" /> الذي تؤثر فيه حملة ترويجية محددة. تظهر هذه التصنيفات أحيانًا في طلبات بحث Google في <ph name="PRODUCT_NAME" />.</translation>
-<translation id="1043818413152647937">محو البيانات من هذه التطبيقات أيضًا؟</translation>
+<translation id="1043818413152647937">هل تريد محو البيانات من هذه التطبيقات أيضًا؟</translation>
 <translation id="1045692658517323508">{0,plural, =1{يجب التحديث في غضون دقيقة واحدة}zero{يجب التحديث في غضون # دقيقة}two{يجب التحديث في غضون دقيقتين}few{يجب التحديث في غضون # دقائق}many{يجب التحديث في غضون # دقيقةً}other{يجب التحديث في غضون # دقيقة}}</translation>
 <translation id="1046635659603195359">‏يبدو أنه سبق لك إعداد ميزة Voice Match في "مساعد Google "على جهاز آخر. ويمكن استخدام هذه التسجيلات السابقة لإنشاء نموذج صوتي على هذا الجهاز. ويستغرق ذلك أقل من دقيقة.</translation>
 <translation id="1047431265488717055">نسخ ن&amp;ص الرابط</translation>
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">لم يتم العثور على أي شبكات.</translation>
 <translation id="1056898198331236512">تحذير</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">‏تطبيقات "متجر Play"</translation>
 <translation id="1061745542578250838">يشتمل الملف <ph name="FILE_NAME" /> على محتوى حسّاس وتم حظره.</translation>
 <translation id="1061904396131502319">سيتم قفل الجهاز بعد قليل</translation>
 <translation id="1067048845568873861">تم الإنشاء</translation>
@@ -516,7 +515,7 @@
 <translation id="1709217939274742847">اختَر تذكرة لاستخدامها في المصادقة. <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
 <translation id="1712349894969001173">‏الحصول على كلمة المرور هذه على جهاز iPhone</translation>
 <translation id="1712552549805331520">يريد <ph name="URL" /> تخزين بيانات على جهاز الكمبيوتر المحلي بشكل دائم.</translation>
-<translation id="1714644264617423774">تفعيل ميزات إمكانية الدخول لتسهيل استخدام الجهاز. <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
+<translation id="1714644264617423774">تفعيل ميزات إمكانية الدخول لتسهيل طريقة استخدام الجهاز <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
 <translation id="1717218214683051432">مستشعرات الحركة</translation>
 <translation id="171824261579749339">أسترالي<ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
 <translation id="1718835860248848330">آخر ساعة</translation>
@@ -1569,10 +1568,11 @@
 <translation id="3172808215939929606">تمت ترجمة هذه الصفحة</translation>
 <translation id="3177909033752230686">لغة الصفحة:</translation>
 <translation id="3179982752812949580">خط النص</translation>
+<translation id="3181825792072797598">تشغيل المزامنة</translation>
 <translation id="3181954750937456830">التصفُّح الآمن (يحميك ويحمي جهازك من مواقع الويب الضارة)</translation>
 <translation id="3182749001423093222">التدقيق الإملائي</translation>
 <translation id="3183139917765991655">مستورد الملف الشخصي</translation>
-<translation id="3184536091884214176">‏إعداد طابعات CUPS أو إدارتها. <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
+<translation id="3184536091884214176">‏إعداد طابعات CUPS أو إدارتها <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
 <translation id="3188257591659621405">ملفاتي</translation>
 <translation id="3188465121994729530">معدل الانتقال</translation>
 <translation id="3190558889382726167">تم حفظ كلمة المرور</translation>
@@ -2745,7 +2745,7 @@
 <translation id="4900392736118574277">تم تغيير صفحة بدء التشغيل إلى <ph name="URL" />.</translation>
 <translation id="4902546322522096650">الشبكة <ph name="NETWORK_INDEX" /> من <ph name="NETWORK_COUNT" />، الشبكة <ph name="NETWORK_NAME" />، حالة الأمان <ph name="SECURITY_STATUS" />، قوة الإشارة <ph name="SIGNAL_STRENGTH" />%، الاتصال</translation>
 <translation id="49027928311173603">السياسة التي تم تنزيلها من الخادم غير صالحة: <ph name="VALIDATION_ERROR" />.</translation>
-<translation id="4906490889887219338">إعداد مشاركات ملفات الشبكة أو إدارتها <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
+<translation id="4906490889887219338">إعداد خوادم مشاركة الملفات على الشبكة أو إدارتها <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
 <translation id="4907161631261076876">لا يتم تنزيل هذا الملف بشكل شائع وقد يكون ضارًا.</translation>
 <translation id="4907306957610201395">فئة الإذن</translation>
 <translation id="4908811072292128752">فتح علامة تبويب جديدة لتصفح موقعي ويب في وقت واحد</translation>
@@ -3143,7 +3143,7 @@
 <translation id="5496587651328244253">تنظيم</translation>
 <translation id="5499313591153584299">قد يلحق هذا الملف الضرر بجهاز الكمبيوتر.</translation>
 <translation id="5502500733115278303">تمّ الاستيراد من متصفّح فايرفوكس</translation>
-<translation id="5505264765875738116">منع المواقع الإلكترونية من طلب إرسال إشعارات.</translation>
+<translation id="5505264765875738116">منع المواقع الإلكترونية من طلب إرسال إشعارات</translation>
 <translation id="5505307013568720083">نفد الحبر</translation>
 <translation id="5507756662695126555">عدم الإنكار</translation>
 <translation id="5509693895992845810">&amp;حفظ باسم...</translation>
@@ -3671,7 +3671,7 @@
 <translation id="6233154960150021497">الخيار التلقائي لاستخدام الصوت بدلاً من لوحة المفاتيح</translation>
 <translation id="6234474535228214774">التثبيت معلّق</translation>
 <translation id="6237816943013845465">تسمح لك بضبط دقة الشاشة</translation>
-<translation id="6238624845858322552">اتصال بجهاز البلوتوث</translation>
+<translation id="6238624845858322552">الاتصال بجهاز البلوتوث</translation>
 <translation id="6238767809035845642">‏النص الذي تمت مشاركته من Other Device (جهاز آخر)</translation>
 <translation id="6238923052227198598">إبقاء آخر ملاحظة على شاشة التأمين</translation>
 <translation id="6239558157302047471">إعادة تحميل الإطار</translation>
@@ -3698,7 +3698,7 @@
 <translation id="6267547857941397424">الشبكة <ph name="NETWORK_INDEX" /> من <ph name="NETWORK_COUNT" />، الهاتف <ph name="PHONE_NAME" />، قوة الإشارة <ph name="SIGNAL_STRENGTH" />%، بطارية الهاتف <ph name="BATTERY_STATUS" />%، الاتصال</translation>
 <translation id="6268252012308737255">فتح باستخدام <ph name="APP" /></translation>
 <translation id="6268718011101775129">‏الاتصالات القصيرة المدى (NFC)</translation>
-<translation id="6270391203985052864">السماح للمواقع الإلكترونية طلب إرسال إشعارات.</translation>
+<translation id="6270391203985052864">السماح للمواقع الإلكترونية بطلب إرسال إشعارات</translation>
 <translation id="6270770586500173387">إرسال <ph name="BEGIN_LINK1" />معلومات النظام والتطبيق<ph name="END_LINK1" />، و<ph name="BEGIN_LINK2" />المقاييس<ph name="END_LINK2" /></translation>
 <translation id="6272643420381259437">حدث خطأ (<ph name="ERROR" />) أثناء تنزيل المكوِّن الإضافي</translation>
 <translation id="6273677812470008672">الجودة</translation>
@@ -3890,7 +3890,7 @@
 <translation id="6555810572223193255">إزالة البرامج غير متاحة حاليًا</translation>
 <translation id="6556866813142980365">إعادة</translation>
 <translation id="6557290421156335491">اختصاراتي</translation>
-<translation id="6561560012278703671">استخدام طريقة أقل بروزًا لإرسال الإشعارات (منع رسائل الإشعارات من إزعاجك).</translation>
+<translation id="6561560012278703671">استخدام طريقة أقل بروزًا لإرسال الإشعارات (منع رسائل الإشعارات من إزعاجك)</translation>
 <translation id="6561726789132298588">إدخال</translation>
 <translation id="656293578423618167">اسم الملف أو مساره طويل جدًا. يُرجى الحفظ باستخدام اسم أقصر أو في مكان آخر.</translation>
 <translation id="6563469144985748109">لم يوافق عليه مديرك حتى الآن</translation>
@@ -4074,7 +4074,7 @@
 <translation id="6840155290835956714">السؤال قبل الإرسال</translation>
 <translation id="6840184929775541289">ليس مرجعًا مصدقًا</translation>
 <translation id="6841186874966388268">أخطاء</translation>
-<translation id="6843267103192918276">‏سجّل الدخول للحصول على الإشارات المرجعية، والسجل، وكلمات المرور، والإعدادات الأخرى على كل أجهزتك. كما سيتم أيضًا تسجيل دخولك تلقائيًا إلى "خدمات Google" <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
+<translation id="6843267103192918276">‏سجِّل الدخول للحصول على الإشارات المرجعية، والسجلّ، وكلمات المرور، والإعدادات الأخرى على كل أجهزتك. وسيتم أيضًا تسجيل دخولك تلقائيًا إلى "خدمات Google". <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
 <translation id="6843423766595476978">‏Ok Google جاهز تمامًا</translation>
 <translation id="6845038076637626672">فتح في وضع التكبير</translation>
 <translation id="6845325883481699275">‏المساعدة في تحسين أمان Chrome</translation>
@@ -4281,7 +4281,7 @@
 <translation id="7133578150266914903">‏يعمل المشرف على إعادة النسخة السابقة من نظام التشغيل Chrome إلى هذا الجهاز(<ph name="PROGRESS_PERCENT" />)</translation>
 <translation id="7134098520442464001">لتصغير النص</translation>
 <translation id="7135729336746831607">هل تريد تشغيل البلوتوث؟</translation>
-<translation id="7136694880210472378">تعيين كافتراضي</translation>
+<translation id="7136694880210472378">جعل الخيار تلقائيًا</translation>
 <translation id="7136984461011502314">مرحبًا بك في <ph name="PRODUCT_NAME" /></translation>
 <translation id="7136993520339022828">حدث خطأ. يُرجى إعادة المحاولة عن طريق اختيار صور أخرى.</translation>
 <translation id="7138678301420049075">أخرى</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">‏لإنشاء تطبيقاتك واختبارها، فعِّل (Android Debug Bridge (ADB. تجدر الإشارة إلى أنه يسمح هذا الإجراء بتثبيت تطبيقات متوافقة مع Android لم يتم إثبات ملكيتها من خلال Google، ويتطلب إعادة الضبط على الإعدادات الأصلية للإيقاف.</translation>
 <translation id="7685049629764448582">ذاكرة جافا سكريبت</translation>
 <translation id="7685087414635069102">رقم التعريف الشخصي مطلوب</translation>
+<translation id="768549422429443215">يمكنك إضافة اللغات أو إعادة ترتيب القائمة.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">تأكيد كلمة المرور الجديدة</translation>
 <translation id="7690378713476594306">اختيار من القائمة</translation>
@@ -5757,7 +5758,7 @@
 <translation id="9214520840402538427">عفوًا!  لقد انتهت مهلة بدء تشغيل سمات وقت التثبيت. يُرجى الاتصال بممثل الدعم.</translation>
 <translation id="9214695392875603905">كب كيك</translation>
 <translation id="9215293857209265904">تمت إضافة "<ph name="EXTENSION_NAME" />"</translation>
-<translation id="9218430445555521422">تعيين كافتراضي</translation>
+<translation id="9218430445555521422">الضبط على الإعداد التلقائي</translation>
 <translation id="9219103736887031265">الصور</translation>
 <translation id="9220525904950070496">إزالة الحساب</translation>
 <translation id="9220820413868316583">ارفع إصبعك ثم أعد المحاولة.</translation>
diff --git a/chrome/app/resources/generated_resources_as.xtb b/chrome/app/resources/generated_resources_as.xtb
index 74f4bdd6..82a3c8d0 100644
--- a/chrome/app/resources/generated_resources_as.xtb
+++ b/chrome/app/resources/generated_resources_as.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">নেটৱৰ্ক নাই</translation>
 <translation id="1056898198331236512">সতর্কবার্তা</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store এপ্‌সমূহ</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" />ত সংবেদনশীল সমল আছে আৰু সেয়া অৱৰোধ কৰা হৈছে।</translation>
 <translation id="1061904396131502319">ডিভাইচ লক হওঁ হওঁ</translation>
 <translation id="1067048845568873861">সৃষ্টি কৰা হ’ল</translation>
@@ -4616,6 +4615,7 @@
 <translation id="7684718995427157417">আপোনাৰ এপ্‌সমূহ সৃষ্টি আৰু পৰীক্ষা কৰিবলৈ Android Debug Bridge (ADB) সক্ষম কৰক। মন কৰক যে এই কাৰ্যটোৱে Googleএ সত্যাপন নকৰা Android এপ্‌সমূহ ইনষ্টল কৰিবলৈ অনুমতি দিয়ে আৰু ইয়াক অক্ষম কৰিবলৈ ফেক্টৰী ৰিছেট কৰাৰ আৱশ্যক।</translation>
 <translation id="7685049629764448582">JavaScript মেম’ৰী</translation>
 <translation id="7685087414635069102">পিনৰ প্ৰয়োজন</translation>
+<translation id="768549422429443215">ভাষাবোৰ যোগ কৰক অথবা সূচীখনৰ ক্ৰম সলনি কৰক।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">নতুন পাছৱর্ড নিশ্চিত কৰক</translation>
 <translation id="7690378713476594306">সূচীৰ পৰা বাছনি কৰক</translation>
diff --git a/chrome/app/resources/generated_resources_az.xtb b/chrome/app/resources/generated_resources_az.xtb
index 48cfe4e..e8e17eb 100644
--- a/chrome/app/resources/generated_resources_az.xtb
+++ b/chrome/app/resources/generated_resources_az.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Şəbəkə yoxdur</translation>
 <translation id="1056898198331236512">Xəbərdarlıq</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Market tətbiqləri</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> həssas məzmun ehtiva edir və bloklanıb.</translation>
 <translation id="1061904396131502319">Fasilə vaxtıdır</translation>
 <translation id="1067048845568873861">Yaradılıb</translation>
@@ -1564,6 +1563,7 @@
 <translation id="3172808215939929606">Bu səhifə tərcümə edilmişdir</translation>
 <translation id="3177909033752230686">Səhifə Dili:</translation>
 <translation id="3179982752812949580">Mətn şrifti</translation>
+<translation id="3181825792072797598">Sinxronizasiyanı aktiv edin</translation>
 <translation id="3181954750937456830">Təhlükəsiz Axtarış (Sizi və cihazınızı təhlükəli saytlardan qoruyur)</translation>
 <translation id="3182749001423093222">Orfoqrafik yoxlanış</translation>
 <translation id="3183139917765991655">Profil İmporter</translation>
@@ -4644,6 +4644,7 @@
 <translation id="7684718995427157417">Yaratmaq və tətbiqlərinizi sınamaq üçün Android Debug Bridge'i (ADB) aktiv edin. Nəzərə alın ki, bu əməliyyat Google tərəfindən doğrulanmamış Android tətbiqlərinin quraşdırılmasına icazə verir və deaktiv etmək üçün zavod ayarlarının bərpasını tələb edir.</translation>
 <translation id="7685049629764448582">JavaScript yaddaşı</translation>
 <translation id="7685087414635069102">PIN tələb olunur</translation>
+<translation id="768549422429443215">Dillər əlavə edin və ya siyahını yenidən sıralayın.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Yeni parolu təsdiq edin</translation>
 <translation id="7690378713476594306">Siyahıdan seçin</translation>
diff --git a/chrome/app/resources/generated_resources_be.xtb b/chrome/app/resources/generated_resources_be.xtb
index 609851c..a5d18ee 100644
--- a/chrome/app/resources/generated_resources_be.xtb
+++ b/chrome/app/resources/generated_resources_be.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Няма сетак</translation>
 <translation id="1056898198331236512">Папярэджанне</translation>
 <translation id="1058262162121953039">PUK-код</translation>
-<translation id="1060881073479695738">Праграмы з Крамы Play</translation>
 <translation id="1061745542578250838">Файл "<ph name="FILE_NAME" />" быў заблакіраваны: ён змяшчае канфідэнцыяльнае змесціва.</translation>
 <translation id="1061904396131502319">Набліжаецца час блакіроўкі</translation>
 <translation id="1067048845568873861">Створаны</translation>
@@ -4653,6 +4652,7 @@
 <translation id="7684718995427157417">Каб ствараць і тэсціраваць праграмы, уключыце Android Debug Bridge (ADB). Звярніце ўвагу, што, уключыўшы ADB, вы дазваляеце ўсталёўваць праграмы для Android, якія не былі спраўджаны Google, а для выключэння ADB патрабуецца скід налад да заводскіх значэнняў.</translation>
 <translation id="7685049629764448582">Памяць JavaScript</translation>
 <translation id="7685087414635069102">Патрабуецца PIN-код</translation>
+<translation id="768549422429443215">Дадайце мовы або змяніце іх парадак у спісе.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Пацвердзіце новы пароль</translation>
 <translation id="7690378713476594306">Выбраць са спіса</translation>
diff --git a/chrome/app/resources/generated_resources_bg.xtb b/chrome/app/resources/generated_resources_bg.xtb
index 4165381..684e125 100644
--- a/chrome/app/resources/generated_resources_bg.xtb
+++ b/chrome/app/resources/generated_resources_bg.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Няма мрежи</translation>
 <translation id="1056898198331236512">Предупреждение</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Приложения от Google Play Магазин</translation>
 <translation id="1061745542578250838">Файлът „<ph name="FILE_NAME" />“ съдържа поверителна информация и бе блокиран.</translation>
 <translation id="1061904396131502319">Скоро ще е време за почивка</translation>
 <translation id="1067048845568873861">Дата на създаване</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">Тази страница е преведена</translation>
 <translation id="3177909033752230686">Език на страницата:</translation>
 <translation id="3179982752812949580">Шрифт на текста</translation>
+<translation id="3181825792072797598">Включване на синхронизирането</translation>
 <translation id="3181954750937456830">„Безопасно сърфиране“ (защитава вас и устройството ви от опасни сайтове)</translation>
 <translation id="3182749001423093222">Проверка на правописа</translation>
 <translation id="3183139917765991655">Импортиране на потребителски профили</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">За да създавате и тествате приложения, активирайте моста на Android за отстраняване на грешки (ADB). Обърнете внимание, че това действие позволява инсталирането на приложения за Android, които не са удостоверени от Google. За деактивирането на ADB е необходимо да бъдат възстановени фабричните настройки.</translation>
 <translation id="7685049629764448582">Памет за JavaScript</translation>
 <translation id="7685087414635069102">Изисква се ПИН код</translation>
+<translation id="768549422429443215">Добавяне на езици или пренареждане на списъка.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Потвърдете новата парола</translation>
 <translation id="7690378713476594306">Избиране от списъка</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index d43041d..77e281b 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">কোনও নেটওয়ার্ক নেই</translation>
 <translation id="1056898198331236512">সতর্কতা</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store অ্যাপ</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" />-এ অতি গোপনীয় কন্টেন্ট রয়েছে এবং এটি ব্লক করে দেওয়া হয়েছে।</translation>
 <translation id="1061904396131502319">বিরতির সময় হতে চলেছে</translation>
 <translation id="1067048845568873861">তৈরি হয়েছে</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">এই পৃষ্ঠাটির অনুবাদ করা হয়েছে</translation>
 <translation id="3177909033752230686">পৃষ্ঠার ভাষা:</translation>
 <translation id="3179982752812949580">টেক্সটের ফন্ট</translation>
+<translation id="3181825792072797598">সিঙ্ক চালু করুন</translation>
 <translation id="3181954750937456830">নিরাপদ ব্রাউজিং (বিপজ্জনক সাইট থেকে আপনাকে এবং আপনার ডিভাইসকে রক্ষা করে)</translation>
 <translation id="3182749001423093222">বানান পরীক্ষা</translation>
 <translation id="3183139917765991655">প্রোফাইল আমদানিকারক</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">আপনার অ্যাপ তৈরি এবং পরীক্ষা করে দেখতে, Android ডিবাগ ব্রিজ টুলটি চালু করুন (ADB)। মনে রাখবেন এই অ্যাকশন Google-এ যাচাই করা হয়নি এমন Android অ্যাপ ইনস্টলের অনুমতি দেয় এবং এটি বন্ধ করতে হলে ডিভাইসটিকে ফ্যাক্টরি রিসেট করতে হয়।</translation>
 <translation id="7685049629764448582">জাভাস্ক্রিপ্ট মেমরি</translation>
 <translation id="7685087414635069102">পিন প্রয়োজন</translation>
+<translation id="768549422429443215">ভাষা যোগ করুন বা তালিকাটি আবার সাজান।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">নতুন পাসওয়ার্ড নিশ্চিত করুন</translation>
 <translation id="7690378713476594306">তালিকা থেকে বেছে নিন</translation>
diff --git a/chrome/app/resources/generated_resources_bs.xtb b/chrome/app/resources/generated_resources_bs.xtb
index bb31d55..1e8dea9 100644
--- a/chrome/app/resources/generated_resources_bs.xtb
+++ b/chrome/app/resources/generated_resources_bs.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nema nijedne mreže</translation>
 <translation id="1056898198331236512">Upozorenje</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikacije u Play trgovini</translation>
 <translation id="1061745542578250838">Fajl <ph name="FILE_NAME" /> sadrži osjetljiv sadržaj i blokiran je.</translation>
 <translation id="1061904396131502319">Uskoro će vrijeme za odmor</translation>
 <translation id="1067048845568873861">Kreirano</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Ova je stranica prevedena</translation>
 <translation id="3177909033752230686">Jezik stranice:</translation>
 <translation id="3179982752812949580">Font teksta</translation>
+<translation id="3181825792072797598">Uključi Sinkronizaciju</translation>
 <translation id="3181954750937456830">Sigurno pregledavanje (štiti vas i vaš uređaj od opasnih web-lokacija)</translation>
 <translation id="3182749001423093222">Provjera pravopisa</translation>
 <translation id="3183139917765991655">Proces za uvoz profila</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Da kreirate i testirate aplikacije, omogućite Alat za uklanjanje grešaka na Androidu (ADB). Važno je napomenuti da ova radnja omogućava instaliranje Android aplikacija koje nije potvrdio Google, a za onemogućavanje je potrebno vraćanje na fabričke postavke.</translation>
 <translation id="7685049629764448582">JavaScript memorija</translation>
 <translation id="7685087414635069102">Potreban je PIN</translation>
+<translation id="768549422429443215">Dodajte jezike ili preuredite listu.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrdite novu lozinku</translation>
 <translation id="7690378713476594306">Odaberite s liste</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb
index 80a881a..a11f4a5 100644
--- a/chrome/app/resources/generated_resources_ca.xtb
+++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Cap xarxa</translation>
 <translation id="1056898198331236512">Advertiment</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplicacions de Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> inclou contingut sensible i s'ha bloquejat.</translation>
 <translation id="1061904396131502319">Ja gairebé és l'hora de fer una pausa</translation>
 <translation id="1067048845568873861">Creada</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">Aquesta pàgina s'ha traduït</translation>
 <translation id="3177909033752230686">Idioma de la pàgina:</translation>
 <translation id="3179982752812949580">Tipus de lletra del text</translation>
+<translation id="3181825792072797598">Activa l'opció Sincronització</translation>
 <translation id="3181954750937456830">Navegació segura (et protegeix a tu i al teu dispositiu de llocs web perillosos)</translation>
 <translation id="3182749001423093222">Corrector ortogràfic</translation>
 <translation id="3183139917765991655">Importador de perfils</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">Per crear aplicacions i provar-les, activa Android Debug Bridge (ADB). Tingues en compte que aquesta acció permet instal·lar aplicacions d'Android que Google no ha verificat. Per desactivar ADB, hauràs de restablir la configuració de fàbrica del dispositiu.</translation>
 <translation id="7685049629764448582">Memòria de JavaScript </translation>
 <translation id="7685087414635069102">PIN obligatori</translation>
+<translation id="768549422429443215">Afegeix idiomes o torna a ordenar la llista.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirma la contrasenya nova</translation>
 <translation id="7690378713476594306">Tria de la llista</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index 05e1949c..6b91f442 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Žádné sítě</translation>
 <translation id="1056898198331236512">Upozornění</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikace z Obchodu Play</translation>
 <translation id="1061745542578250838">Soubor <ph name="FILE_NAME" /> obsahuje citlivý obsah a byl zablokován.</translation>
 <translation id="1061904396131502319">Brzy bude čas na přestávku</translation>
 <translation id="1067048845568873861">Vytvořeno</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">Tato stránka byla přeložena</translation>
 <translation id="3177909033752230686">Jazyk stránky:</translation>
 <translation id="3179982752812949580">Písmo textu</translation>
+<translation id="3181825792072797598">Zapnout synchronizaci</translation>
 <translation id="3181954750937456830">Bezpečné prohlížení (chrání vás a vaše zařízení před nebezpečnými weby)</translation>
 <translation id="3182749001423093222">Kontrola pravopisu</translation>
 <translation id="3183139917765991655">Nástroj na import profilů</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">Chcete-li vytvořit a otestovat aplikace, zapněte Android Debug Bridge (ADB). Upozorňujeme, že tato akce povoluje instalaci aplikací pro Android, které Google neověřil, a že je k její deaktivaci potřeba obnovení továrního nastavení.</translation>
 <translation id="7685049629764448582">Paměť JavaScriptu</translation>
 <translation id="7685087414635069102">Je vyžadován kód PIN</translation>
+<translation id="768549422429443215">Přidejte jazyky nebo přeuspořádejte seznam.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrďte nové heslo</translation>
 <translation id="7690378713476594306">Vybrat ze seznamu</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index 8436f7ea..fb057bdf7 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Der er ingen netværk</translation>
 <translation id="1056898198331236512">Advarsel</translation>
 <translation id="1058262162121953039">PUK-kode</translation>
-<translation id="1060881073479695738">Play Butik-apps</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> har følsomt indhold og er blevet blokeret.</translation>
 <translation id="1061904396131502319">Det er snart tid til en pause</translation>
 <translation id="1067048845568873861">Oprettet</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Denne side er oversat</translation>
 <translation id="3177909033752230686">Sidens sprog:</translation>
 <translation id="3179982752812949580">Tekstskrifttype</translation>
+<translation id="3181825792072797598">Aktivér synkronisering</translation>
 <translation id="3181954750937456830">Beskyttet browsing (beskytter dig og din enhed mod farlige websites)</translation>
 <translation id="3182749001423093222">Stavekontrol</translation>
 <translation id="3183139917765991655">Profilimport</translation>
@@ -2394,7 +2394,7 @@
 <translation id="4364327530094270451">Melon</translation>
 <translation id="4364567974334641491"><ph name="APP_NAME" /> deler et vindue.</translation>
 <translation id="4364830672918311045">Vis notifikationer</translation>
-<translation id="436499142539576997">Der kunne ikke hentes appdata, men kørsel af appen forsøges stadig ...</translation>
+<translation id="436499142539576997">Der kunne ikke hentes appdata, men kørsel af appen forsøges stadig...</translation>
 <translation id="4370975561335139969">Den mail og adgangskode, du indtastede, stemmer ikke overens</translation>
 <translation id="437184764829821926">Avancerede indstillinger for skrifttype</translation>
 <translation id="4374831787438678295">Linux-installationsprogram</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Hvis du vil oprette og teste dine apps, skal du aktivere Android Debug Bridge (ADB). Bemærk! Denne handling tillader, at Android-apps, der ikke er blevet bekræftet af Google, kan installeres. Du skal gendanne fabriksindstillingerne for at deaktivere dette.</translation>
 <translation id="7685049629764448582">JavaScript-hukommelse</translation>
 <translation id="7685087414635069102">Der skal angives en pinkode</translation>
+<translation id="768549422429443215">Tilføj sprog, eller omorganiser listen.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bekræft den nye adgangskode</translation>
 <translation id="7690378713476594306">Vælg på listen</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index e70d2a3..d43fe97a 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Keine Netzwerke</translation>
 <translation id="1056898198331236512">Warnung</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store-Apps</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> enthält vertrauliche Inhalte und wurde blockiert.</translation>
 <translation id="1061904396131502319">Bald ist es Zeit für eine Pause</translation>
 <translation id="1067048845568873861">Erstellt</translation>
@@ -1565,6 +1564,7 @@
 <translation id="3172808215939929606">Diese Seite wurde übersetzt</translation>
 <translation id="3177909033752230686">Sprache der Seite:</translation>
 <translation id="3179982752812949580">Schriftart für Text</translation>
+<translation id="3181825792072797598">Synchronisierung aktivieren</translation>
 <translation id="3181954750937456830">Safe Browsing (mich und mein Gerät vor schädlichen Websites schützen)</translation>
 <translation id="3182749001423093222">Rechtschreibprüfung</translation>
 <translation id="3183139917765991655">Profilimport</translation>
@@ -4649,6 +4649,7 @@
 <translation id="7684718995427157417">Aktivieren Sie zum Erstellen und Testen Ihrer Apps Android Debug Bridge (ADB). Durch diese Aktion können Android-Apps installiert werden, die nicht von Google geprüft wurden. Zum Deaktivieren ist das Zurücksetzen auf die Werkseinstellungen erforderlich.</translation>
 <translation id="7685049629764448582">JavaScript-Speicher</translation>
 <translation id="7685087414635069102">PIN erforderlich</translation>
+<translation id="768549422429443215">Sie können Sprachen hinzufügen oder die Liste neu anordnen.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Neues Passwort bestätigen</translation>
 <translation id="7690378713476594306">Aus Liste auswählen</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index f4ea763..422e58fe 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Δεν βρέθηκαν δίκτυα</translation>
 <translation id="1056898198331236512">Προειδοποίηση</translation>
 <translation id="1058262162121953039">Κωδικός PUK</translation>
-<translation id="1060881073479695738">Εφαρμογές Play Store</translation>
 <translation id="1061745542578250838">Το αρχείο <ph name="FILE_NAME" /> περιέχει ευαίσθητο περιεχόμενο και έχει αποκλειστεί.</translation>
 <translation id="1061904396131502319">Πλησιάζει η ώρα για διάλειμμα</translation>
 <translation id="1067048845568873861">Δημιουργήθηκε</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Αυτή η σελίδα έχει μεταφραστεί</translation>
 <translation id="3177909033752230686">Γλώσσα σελίδας:</translation>
 <translation id="3179982752812949580">Γραμματοσειρά κειμένου</translation>
+<translation id="3181825792072797598">Ενεργοποίηση συγχρονισμού</translation>
 <translation id="3181954750937456830">Ασφαλής περιήγηση (προστατεύει εσάς και τη συσκευή σας από επικίνδυνους ιστοτόπους)</translation>
 <translation id="3182749001423093222">Ορθογραφικός έλεγχος</translation>
 <translation id="3183139917765991655">Εργαλείο εισαγωγής προφίλ</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Για να δημιουργήσετε και να δοκιμάσετε τις εφαρμογές σας, ενεργοποιήστε το Android Debug Bridge (ADB). Σημειώστε ότι αυτή η ενέργεια επιτρέπει την εγκατάσταση εφαρμογών Android που δεν έχουν επαληθευτεί από τη Google. Επιπλέον, απαιτείται εργοστασιακή επαναφορά για την απενεργοποίησή της.</translation>
 <translation id="7685049629764448582">Μνήμη JavaScript</translation>
 <translation id="7685087414635069102">Απαιτείται PIN</translation>
+<translation id="768549422429443215">Προσθέστε γλώσσες ή κάντε αναδιάταξη της λίστας.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Επιβεβαίωση νέου κωδικού πρόσβασης</translation>
 <translation id="7690378713476594306">Επιλογή από τη λίστα</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb
index 1e2d1ac..5edbb33b 100644
--- a/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">No networks</translation>
 <translation id="1056898198331236512">Warning</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store apps</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> contains sensitive content, and has been blocked.</translation>
 <translation id="1061904396131502319">Almost time for a break</translation>
 <translation id="1067048845568873861">Created</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">This page has been translated</translation>
 <translation id="3177909033752230686">Page language:</translation>
 <translation id="3179982752812949580">Text font</translation>
+<translation id="3181825792072797598">Turn on Sync</translation>
 <translation id="3181954750937456830">Safe Browsing (protects you and your device from dangerous sites)</translation>
 <translation id="3182749001423093222">Spell check</translation>
 <translation id="3183139917765991655">Profile Importer</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">To create and test your apps, enable the Android Debug Bridge (ADB). Note that this action allows installation of Android apps that haven't been verified by Google, and requires a factory reset to disable.</translation>
 <translation id="7685049629764448582">JavaScript memory</translation>
 <translation id="7685087414635069102">PIN required</translation>
+<translation id="768549422429443215">Add languages or reorder list.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirm new password</translation>
 <translation id="7690378713476594306">Choose from list</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index b1ac978f..78c5ad72 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">No hay redes</translation>
 <translation id="1056898198331236512">Advertencia</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Apps de Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> incluye contenido sensible y se bloqueó.</translation>
 <translation id="1061904396131502319">Casi es hora de un descanso</translation>
 <translation id="1067048845568873861">Creada</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">Se tradujo esta página</translation>
 <translation id="3177909033752230686">Idioma de la página:</translation>
 <translation id="3179982752812949580">Fuente del texto</translation>
+<translation id="3181825792072797598">Activar la sincronización</translation>
 <translation id="3181954750937456830">Navegación segura (te protege a ti y tu dispositivo de sitios peligrosos)</translation>
 <translation id="3182749001423093222">Corrector ortográfico</translation>
 <translation id="3183139917765991655">Importador de perfiles</translation>
@@ -4650,6 +4650,7 @@
 <translation id="7684718995427157417">Si quieres crear y probar apps, habilita Android Debug Bridge (ADB). Ten en cuenta que esta acción permite la instalación de apps para Android que Google no verificó. Si quieres inhabilitar ADB, deberás restablecer la configuración de fábrica.</translation>
 <translation id="7685049629764448582">Memoria de JavaScript</translation>
 <translation id="7685087414635069102">Se requiere el PIN</translation>
+<translation id="768549422429443215">Agrega idiomas o cambia el orden de la lista.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar contraseña nueva</translation>
 <translation id="7690378713476594306">Elegir de la lista</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index 7e49b42..c149a33 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">No hay redes</translation>
 <translation id="1056898198331236512">Advertencia</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplicaciones de Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> incluye contenido sensible y se ha bloqueado.</translation>
 <translation id="1061904396131502319">Ya casi es la hora de hacer un descanso</translation>
 <translation id="1067048845568873861">Creada</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Esta página se ha traducido</translation>
 <translation id="3177909033752230686">Idioma de la página:</translation>
 <translation id="3179982752812949580">Fuente del texto</translation>
+<translation id="3181825792072797598">Activar sincronización</translation>
 <translation id="3181954750937456830">Navegación Segura (te protege a ti y a tu dispositivo frente a sitios web peligrosos)</translation>
 <translation id="3182749001423093222">Revisión ortográfica</translation>
 <translation id="3183139917765991655">Importador de perfiles</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">Para crear y probar tus aplicaciones, habilita Android Debug Bridge (ADB). Ten en cuenta que esta función permitirá la instalación de aplicaciones Android que no han sido verificadas por Google y para inhabilitarlas es necesario restablecer la configuración de fábrica.</translation>
 <translation id="7685049629764448582">Memoria de JavaScript</translation>
 <translation id="7685087414635069102">PIN necesario</translation>
+<translation id="768549422429443215">Añadir o reordenar idiomas</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirma la nueva contraseña</translation>
 <translation id="7690378713476594306">Elegir una opción de la lista</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb
index 01f4a6f..7b4c814 100644
--- a/chrome/app/resources/generated_resources_et.xtb
+++ b/chrome/app/resources/generated_resources_et.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Võrke ei ole</translation>
 <translation id="1056898198331236512">Hoiatus</translation>
 <translation id="1058262162121953039">PUK-kood</translation>
-<translation id="1060881073479695738">Play poe rakendused</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> sisaldab tundlikku sisu ja see on blokeeritud.</translation>
 <translation id="1061904396131502319">Pausiaeg on peagi käes</translation>
 <translation id="1067048845568873861">Loodud</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">See leht on tõlgitud</translation>
 <translation id="3177909033752230686">Lehe keel:</translation>
 <translation id="3179982752812949580">Teksti font</translation>
+<translation id="3181825792072797598">Lülita sünkroonimine sisse</translation>
 <translation id="3181954750937456830">Ohutu sirvimine (kaitseb teid ja teie seadet ohtlike saitide eest)</translation>
 <translation id="3182749001423093222">Õigekirjakontroll</translation>
 <translation id="3183139917765991655">Profiili importija</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Rakenduste loomiseks ja testimiseks lubage Android Debug Bridge (ADB). Pange tähele, et see toiming võimaldab selliste Androidi rakenduste installimist, mida Google pole kontrollinud, ja tööriista keelamiseks on nõutav tehaseseadetele lähtestamine.</translation>
 <translation id="7685049629764448582">JavaScripti mälu</translation>
 <translation id="7685087414635069102">PIN-kood on kohustuslik</translation>
+<translation id="768549422429443215">Saate keeli lisada või nende loendit ümber järjestada.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Kinnitage uus parool</translation>
 <translation id="7690378713476594306">Vali loendist</translation>
diff --git a/chrome/app/resources/generated_resources_eu.xtb b/chrome/app/resources/generated_resources_eu.xtb
index ce57780c..3b869c52 100644
--- a/chrome/app/resources/generated_resources_eu.xtb
+++ b/chrome/app/resources/generated_resources_eu.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Ez dago sarerik</translation>
 <translation id="1056898198331236512">Abisua</translation>
 <translation id="1058262162121953039">PUK kodea</translation>
-<translation id="1060881073479695738">Play Store-ko aplikazioak</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> fitxategiak kontuzko edukia du, eta blokeatu egin da.</translation>
 <translation id="1061904396131502319">Atseden hartzeko garaia izango da laster</translation>
 <translation id="1067048845568873861">Sortze-data</translation>
@@ -408,7 +407,7 @@
 <translation id="15662109988763471">Hautatutako inprimagailua ez dago erabilgarri edo ez da instalatu behar bezala. Egiaztatu inprimagailua edo hautatu beste bat.</translation>
 <translation id="1567387640189251553">Beste teklatu bat konektatu duzu pasahitza azkenekoz idatzi zenuenetik. Agian sakatzen ari zaren teklak erregistratzen ari da, pasahitzak lapurtzeko asmoz.</translation>
 <translation id="1567750922576943685">Zure identitatea egiaztatzen baduzu, babestuago izango duzu informazio pertsonala</translation>
-<translation id="1567993339577891801">JavaScript kontsola</translation>
+<translation id="1567993339577891801">JavaScript-en kontsola</translation>
 <translation id="1568323446248056064">Ireki pantailaren ezarpenak</translation>
 <translation id="1572139610531470719"><ph name="WINDOW_TITLE" /> (gonbidatua)</translation>
 <translation id="1572266655485775982">Gaitu Wi-Fi konexioa</translation>
@@ -602,7 +601,7 @@
 <translation id="1817871734039893258">Microsoft-en fitxategiak berreskuratzeko sistema</translation>
 <translation id="1818007989243628752">Ezabatu <ph name="USERNAME" /> erabiltzailearen pasahitza</translation>
 <translation id="1818913467757368489">Kargatzen ari da erregistroa.</translation>
-<translation id="1819721979226826163">Sakatu Aplikazioen jakinarazpenak &gt; Google Play zerbitzuak.</translation>
+<translation id="1819721979226826163">Sakatu Aplikazioen jakinarazpenak &gt; Google Play-ren zerbitzuak.</translation>
 <translation id="1820028137326691631">Idatzi administratzaileak emandako pasahitza</translation>
 <translation id="1822140782238030981">Chrome erabiltzen duzu dagoeneko? Hasi saioa</translation>
 <translation id="1826516787628120939">Egiaztatzen</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Itzuli da orria</translation>
 <translation id="3177909033752230686">Orriaren hizkuntza:</translation>
 <translation id="3179982752812949580">Testuaren letra-tipoa</translation>
+<translation id="3181825792072797598">Aktibatu sinkronizazioa</translation>
 <translation id="3181954750937456830">Arakatze segurua (webgune arriskutsuen aurka babesten zaituzte gailua eta zu)</translation>
 <translation id="3182749001423093222">Ortografia-zuzentzailea</translation>
 <translation id="3183139917765991655">Profil-inportatzailea</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Zeure aplikazioak sortu eta probatzeko, gaitu Android Debug Bridge (ADB). Kontuan izan ekintza honekin baimendu egiten dela Google-k egiaztatu ez dituen Android-erako aplikazioak instalatzeko aukera eta, inoiz tresna hori desgaitu nahi izanez gero, jatorrizko datuak berrezarri beharko direla.</translation>
 <translation id="7685049629764448582">JavaScript memoria</translation>
 <translation id="7685087414635069102">PIN kodea behar da</translation>
+<translation id="768549422429443215">Gehitu hizkuntzak edo aldatu zerrendako elementuen ordena.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Berretsi pasahitz berria</translation>
 <translation id="7690378713476594306">Aukeratu zerrendatik</translation>
@@ -4720,7 +4721,7 @@
 <translation id="778330624322499012">Ezin izan da kargatu <ph name="PLUGIN_NAME" /></translation>
 <translation id="7784067724422331729">Fitxategia blokeatu da ordenagailuan dituzun segurtasun-ezarpenen ondorioz</translation>
 <translation id="7784796923038949829">Ezin dira irakurri edo aldatu webgunearen datuak</translation>
-<translation id="778480864305029524">Konexioaren partekatze bizkorra erabiltzeko, aktibatu Google Play zerbitzuen jakinarazpenak.</translation>
+<translation id="778480864305029524">Konexioaren partekatze bizkorra erabiltzeko, aktibatu Google Play-ren zerbitzuen jakinarazpenak.</translation>
 <translation id="7786207843293321886">Irten gonbidatu saiotik</translation>
 <translation id="7786889348652477777">Kar&amp;gatu berriro aplikazioa</translation>
 <translation id="7787308148023287649">Erakutsi beste pantaila batean</translation>
@@ -5794,7 +5795,7 @@
 <translation id="964439421054175458">{NUM_APLLICATIONS,plural, =1{Aplikazioa}other{Aplikazioak}}</translation>
 <translation id="965211523698323809">Bidali eta jaso testu-mezuak <ph name="DEVICE_TYPE" /> gailua erabilita. <ph name="LINK_BEGIN" />Lortu informazio gehiago<ph name="LINK_END" /></translation>
 <translation id="967624055006145463">Gordetako datuak</translation>
-<translation id="968000525894980488">Aktibatu Google Play zerbitzuak.</translation>
+<translation id="968000525894980488">Aktibatu Google Play-ren zerbitzuak.</translation>
 <translation id="968037381421390582">It&amp;satsi eta bilatu "<ph name="SEARCH_TERMS" />"</translation>
 <translation id="968174221497644223">Aplikazioen cachea</translation>
 <translation id="969096075394517431">Aldatu hizkuntza</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index c56cff91..908f600 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">شبکه‌ای وجود ندارد</translation>
 <translation id="1056898198331236512">اخطار</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">‏برنامه‌های فروشگاه Play</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> حاوی محتوای حساس است و مسدود شده است.</translation>
 <translation id="1061904396131502319">تقریباً زمان استراحت است</translation>
 <translation id="1067048845568873861">ایجاد شد</translation>
@@ -342,7 +341,7 @@
 <translation id="1476607407192946488">&amp;تنظیمات زبان</translation>
 <translation id="1478340334823509079">جزئیات: <ph name="FILE_NAME" /></translation>
 <translation id="1478607704480248626">نصب فعال نشده است</translation>
-<translation id="1482626744466814421">نشانک گذاشتن این برگه…</translation>
+<translation id="1482626744466814421">نشانک‌گذاری این برگه…</translation>
 <translation id="1483493594462132177">ارسال</translation>
 <translation id="1484979925941077974">سایت درحال استفاده از بلوتوث است</translation>
 <translation id="1485015260175968628">هم‌اکنون این می‌تواند:</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">این صفحه ترجمه شده است</translation>
 <translation id="3177909033752230686">زبان صفحه:</translation>
 <translation id="3179982752812949580">قلم نوشتار</translation>
+<translation id="3181825792072797598">روشن کردن همگام‌سازی</translation>
 <translation id="3181954750937456830">مرور ایمن (از شما و دستگاهتان درمقابل سایت‌های خطرناک محافظت می‌کند)</translation>
 <translation id="3182749001423093222">غلط‌گیر املا</translation>
 <translation id="3183139917765991655">واردکننده نمایه</translation>
@@ -4650,6 +4650,7 @@
 <translation id="7684718995427157417">‏برای ایجاد و آزمایش برنامه‌ها، پل اشکال‌زدایی Android‏ (ADB) را فعال کنید. توجه داشته باشید که این کنش نصب برنامه‌های Android را که Google تأیید نکرده است مجاز می‌کند و برای غیرفعال شدن به بازنشانی کارخانه‌ای نیاز دارد.</translation>
 <translation id="7685049629764448582">حافطه جاوا اسکریپت</translation>
 <translation id="7685087414635069102">پین موردنیاز است</translation>
+<translation id="768549422429443215">افزودن زبان یا مرتب‌سازی مجدد فهرست.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> <ph name="DEVICE_PATH" /></translation>
 <translation id="7690294790491645610">تأیید گذرواژه جدید</translation>
 <translation id="7690378713476594306">انتخاب از فهرست</translation>
@@ -5638,7 +5639,7 @@
 <translation id="9021662811137657072">ویروس شناسایی شد</translation>
 <translation id="9022847679183471841">این حساب درحال‌حاضر در این رایانه توسط <ph name="AVATAR_NAME" /> درحال استفاده است.</translation>
 <translation id="9023009238991294202">سایر کاربران این دستگاه می‌توانند از این شبکه استفاده کنند.</translation>
-<translation id="9023015617655685412">نشانک گذاشتن این برگه…</translation>
+<translation id="9023015617655685412">نشانک‌گذاری این برگه…</translation>
 <translation id="9024127637873500333">باز کردن در &amp;برگه جدید</translation>
 <translation id="9024158959543687197">هنگام نشاندن دستگاه ذخیره‌سازی متصل به شبکه خطایی روی داد. لطفاً نشانی وب دستگاه ذخیره‌سازی متصل به شبکه را بررسی کنید و دوباره امتحان کنید.</translation>
 <translation id="9026731007018893674">بارگیری</translation>
diff --git a/chrome/app/resources/generated_resources_fi.xtb b/chrome/app/resources/generated_resources_fi.xtb
index 5920d46..09fe518 100644
--- a/chrome/app/resources/generated_resources_fi.xtb
+++ b/chrome/app/resources/generated_resources_fi.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Ei verkkoja</translation>
 <translation id="1056898198331236512">Varoitus</translation>
 <translation id="1058262162121953039">PUK-koodi</translation>
-<translation id="1060881073479695738">Play Kaupan sovellukset</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> sisältää arkaluontoista sisältöä ja on estetty.</translation>
 <translation id="1061904396131502319">Pian on tauon paikka</translation>
 <translation id="1067048845568873861">Luotu</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Käännetty sivu</translation>
 <translation id="3177909033752230686">Sivun kieli:</translation>
 <translation id="3179982752812949580">Tekstin fontti</translation>
+<translation id="3181825792072797598">Ota synkronointi käyttöön</translation>
 <translation id="3181954750937456830">Selaussuoja (suojaa sinua ja laitettasi vaarallisilta sivustoilta)</translation>
 <translation id="3182749001423093222">Oikeinkirjoituksen tarkistus</translation>
 <translation id="3183139917765991655">Profiilien tuoja</translation>
@@ -2435,7 +2435,7 @@
 <translation id="442397852638519243"><ph name="USER_NAME" />, järjestelmänvalvojasi vaatii sinua vaihtamaan salasanasi.</translation>
 <translation id="4430019312045809116">Äänenvoimakkuus</translation>
 <translation id="4430369329743628066">Kirjanmerkki lisättiin</translation>
-<translation id="4434045419905280838">Ponn.ikkunat ja uudelleenohj.</translation>
+<translation id="4434045419905280838">Ponn.ikkunat ja uudelleenohjaus</translation>
 <translation id="443454694385851356">Vanha (suojaamaton)</translation>
 <translation id="443475966875174318">Päivitä yhteensopimattomat sovellukset tai poista ne</translation>
 <translation id="4438043733494739848">Läpinäkyvä</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">Jos haluat luoda ja testata sovelluksia, ota käyttöön Android Debug Bridge (ADB). Huomaa, että tämä sallii sellaisten Android-sovellusten asentamisen, joita Google ei ole vahvistanut. Ominaisuuden käytöstä poistaminen edellyttää tehdasasetusten palautusta.</translation>
 <translation id="7685049629764448582">JavaScriptin käyttämä muisti</translation>
 <translation id="7685087414635069102">PIN-koodi vaaditaan</translation>
+<translation id="768549422429443215">Lisää kieliä tai järjestä lista uudelleen.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Vahvista uusi salasana</translation>
 <translation id="7690378713476594306">Valitse luettelosta</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb
index ec05b59e..69c06a6 100644
--- a/chrome/app/resources/generated_resources_fil.xtb
+++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Walang network</translation>
 <translation id="1056898198331236512">Babala</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Mga app sa Play Store</translation>
 <translation id="1061745542578250838">Naglalaman ang <ph name="FILE_NAME" /> ng sensitibong content, at na-block ito.</translation>
 <translation id="1061904396131502319">Halos oras na para magpahinga</translation>
 <translation id="1067048845568873861">Ginawa</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Naisalin na ang page na ito</translation>
 <translation id="3177909033752230686">Wika ng Page:</translation>
 <translation id="3179982752812949580">Font ng text</translation>
+<translation id="3181825792072797598">I-on ang I-sync</translation>
 <translation id="3181954750937456830">Ligtas na Pag-browse (pinoprotektahan ka at ang iyong device mula sa mga mapanganib na site)</translation>
 <translation id="3182749001423093222">Pang-check ng pagbabaybay</translation>
 <translation id="3183139917765991655">Pang-import ng Profile</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Para gumawa at subukan ang iyong mga app, i-enable ang Android Debug Bridge (ADB). Tandaang binibigyang-daan ng pagkilos na ito ang pag-install ng mga Android app na hindi pa na-verify ng Google, at nangangailangan ito ng factory reset para ma-disable.</translation>
 <translation id="7685049629764448582">Memorya sa JavaScript</translation>
 <translation id="7685087414635069102">Kailangan ng PIN</translation>
+<translation id="768549422429443215">Magdagdag ng mga wika o baguhin ang pagkakasunud-sunod ng listahan.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Kumpirmahin ang bagong password</translation>
 <translation id="7690378713476594306">Pumili sa listahan</translation>
diff --git a/chrome/app/resources/generated_resources_fr-CA.xtb b/chrome/app/resources/generated_resources_fr-CA.xtb
index 0cc3921..38635fe 100644
--- a/chrome/app/resources/generated_resources_fr-CA.xtb
+++ b/chrome/app/resources/generated_resources_fr-CA.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Aucun réseau</translation>
 <translation id="1056898198331236512">Avertissement</translation>
 <translation id="1058262162121953039">Clé PUK</translation>
-<translation id="1060881073479695738">Applications Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> contient des éléments sensibles et a été bloqué.</translation>
 <translation id="1061904396131502319">C'est bientôt le moment de prendre une pause</translation>
 <translation id="1067048845568873861">Créé</translation>
@@ -1570,6 +1569,7 @@
 <translation id="3172808215939929606">Cette page a été traduite</translation>
 <translation id="3177909033752230686">Langue de la page :</translation>
 <translation id="3179982752812949580">Police du texte</translation>
+<translation id="3181825792072797598">Activer la synchronisation</translation>
 <translation id="3181954750937456830">Navigation sécurisée (vous protège, vous et votre appareil, des sites dangereux)</translation>
 <translation id="3182749001423093222">Correcteur orthographique</translation>
 <translation id="3183139917765991655">Importateur de profils</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Pour créer et tester vos applications, activez le pont de débogage Android (PDA). Prenez note que cette action permet d'installer des applications Android qui n'ont pas été vérifiées par Google. Pour désactiver cette fonctionnalité, vous devrez réinitialiser l'appareil.</translation>
 <translation id="7685049629764448582">Mémoire pour JavaScript</translation>
 <translation id="7685087414635069102">NIP requis</translation>
+<translation id="768549422429443215">Ajoutez des langues ou triez la liste de nouveau.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmez le nouveau mot de passe</translation>
 <translation id="7690378713476594306">Choisir dans la liste</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index 887f984..b98a9d5 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Aucun réseau</translation>
 <translation id="1056898198331236512">Avertissement</translation>
 <translation id="1058262162121953039">Clé PUK</translation>
-<translation id="1060881073479695738">Applications Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> contient du contenu sensible et a donc été bloqué.</translation>
 <translation id="1061904396131502319">Il est presque temps de faire une pause</translation>
 <translation id="1067048845568873861">Date de création</translation>
@@ -179,7 +178,7 @@
 <translation id="1234808891666923653">Service Workers</translation>
 <translation id="1235458158152011030">Réseaux connus</translation>
 <translation id="123578888592755962">Disque saturé.</translation>
-<translation id="1238191093934674082">Ouvrir le VPN</translation>
+<translation id="1238191093934674082">Open VPN</translation>
 <translation id="1239594683407221485">Explorez le contenu de l'appareil dans l'application Fichiers.</translation>
 <translation id="124116460088058876">Plus de langues</translation>
 <translation id="1241753985463165747">Accéder à toutes vos données sur le site Web actuellement consulté et les modifier</translation>
@@ -1058,7 +1057,7 @@
 <translation id="2470702053775288986">Désactivation des extensions non compatibles</translation>
 <translation id="2473195200299095979">Traduire cette page</translation>
 <translation id="2475982808118771221">Une erreur s'est produite.</translation>
-<translation id="2476578072172137802">Paramètres du site</translation>
+<translation id="2476578072172137802">Paramètres des sites</translation>
 <translation id="2478176599153288112">Autorisations de fichier média pour "<ph name="EXTENSION" />"</translation>
 <translation id="247949520305900375">Partager le contenu audio</translation>
 <translation id="2480868415629598489">Modifier les données que vous copiez-collez</translation>
@@ -1117,7 +1116,7 @@
 <translation id="2541002089857695151">Optimiser la diffusion en plein écran ?</translation>
 <translation id="2541706104884128042">Nouvelle heure de coucher définie</translation>
 <translation id="2544853746127077729">Certificat d'authentification rejeté par le réseau.</translation>
-<translation id="2546283357679194313">Cookies et données de site</translation>
+<translation id="2546283357679194313">Cookies et données de sites</translation>
 <translation id="2549985041256363841">Démarrer l'enregistrement</translation>
 <translation id="2550212893339833758">Espace mémoire d'échange</translation>
 <translation id="2550596535588364872">Autoriser <ph name="EXTENSION_NAME" /> à ouvrir le fichier <ph name="FILE_NAME" /> ?</translation>
@@ -1140,7 +1139,7 @@
 <translation id="257779572837908839">Configurer en tant que Chromebox pour la visioconférence</translation>
 <translation id="2580889980133367162">Toujours autoriser <ph name="HOST" /> à télécharger plusieurs fichiers</translation>
 <translation id="2580924999637585241">Total : <ph name="NUMBER_OF_SHEETS" /> <ph name="SHEETS_LABEL" /></translation>
-<translation id="258095186877893873">Longue</translation>
+<translation id="258095186877893873">Long</translation>
 <translation id="2582253231918033891"><ph name="PRODUCT_NAME" /> <ph name="PRODUCT_VERSION" /> (Plate-forme <ph name="PLATFORM_VERSION" />) <ph name="DEVICE_SERIAL_NUMBER" /></translation>
 <translation id="2584109212074498965">Impossible de récupérer le ticket Kerberos. Veuillez réessayer ou contacter l'administrateur des appareils de votre organisation. (Code d'erreur : <ph name="ERROR_CODE" />).</translation>
 <translation id="2585724835339714757">Votre écran est partagé par cet onglet.</translation>
@@ -1257,7 +1256,7 @@
 <translation id="2731710757838467317">Création de l'utilisateur supervisé en cours. Cette opération peut prendre quelques instants…</translation>
 <translation id="2731971182069536520">La prochaine fois que vous redémarrerez votre appareil, l'administrateur effectuera une mise à jour exceptionnelle qui entraînera la suppression de vos données locales.</translation>
 <translation id="2734760316755174687">Les sites appartenant à <ph name="SITE_GROUP_NAME" /> seront également réinitialisés.</translation>
-<translation id="2735712963799620190">Calendrier</translation>
+<translation id="2735712963799620190">Horaires</translation>
 <translation id="2737363922397526254">Réduire...</translation>
 <translation id="2738771556149464852">Pas après le</translation>
 <translation id="2739191690716947896">Déboguer</translation>
@@ -1265,7 +1264,7 @@
 <translation id="274029851662193272">Bord en retrait</translation>
 <translation id="2741912629735277980">Afficher l'UI sur l'écran de connexion</translation>
 <translation id="274290345632688601">Restauration des applications et fichiers Linux</translation>
-<translation id="2743387203779672305">Copier dans le Presse-papier</translation>
+<translation id="2743387203779672305">Copier dans le presse-papiers</translation>
 <translation id="2745080116229976798">Subordination qualifiée Microsoft</translation>
 <translation id="2749756011735116528">Connexion à <ph name="PRODUCT_NAME" /></translation>
 <translation id="2749881179542288782">Vérifier la grammaire et l'orthographe</translation>
@@ -1297,7 +1296,7 @@
 <translation id="2788135150614412178">+</translation>
 <translation id="2789486458103222910">OK</translation>
 <translation id="2791952154587244007">Une erreur s'est produite. Impossible de lancer automatiquement l'application kiosque sur cet appareil.</translation>
-<translation id="2792290659606763004">Supprimer des applications Android ?</translation>
+<translation id="2792290659606763004">Supprimer les applications Android ?</translation>
 <translation id="2794233252405721443">Site bloqué</translation>
 <translation id="2796424461616874739">Expiration du délai d'authentification lors de la connexion à l'appareil "<ph name="DEVICE_NAME" />".</translation>
 <translation id="2796740370559399562">Continuer à autoriser les cookies</translation>
@@ -1442,7 +1441,7 @@
 <translation id="2989474696604907455">non connecté</translation>
 <translation id="2989786307324390836">Certificat unique binaire codé DER</translation>
 <translation id="2992931425024192067">Afficher tout le contenu des notifications</translation>
-<translation id="2993517869960930405">Informations relatives à l'application</translation>
+<translation id="2993517869960930405">Infos sur l'appli</translation>
 <translation id="2996286169319737844">Les données ont été chiffrées avec votre phrase secrète de synchronisation. Ceci ne s'applique pas aux modes de paiement et adresses Google Pay.</translation>
 <translation id="2996722619877761919">Retourner sur les bords longs</translation>
 <translation id="3003144360685731741">Réseaux préférés</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Cette page a été traduite</translation>
 <translation id="3177909033752230686">Langue de la page :</translation>
 <translation id="3179982752812949580">Police du texte</translation>
+<translation id="3181825792072797598">Activer la synchronisation</translation>
 <translation id="3181954750937456830">Navigation sécurisée (assure votre protection et celle de votre appareil contre les sites dangereux)</translation>
 <translation id="3182749001423093222">Correcteur orthographique</translation>
 <translation id="3183139917765991655">Importation de profils</translation>
@@ -1666,7 +1666,7 @@
 <translation id="3325910708063135066">Caméra et micro désactivés dans les préférences système Mac</translation>
 <translation id="3328489342742826322">La restauration depuis une sauvegarde entraîne la suppression des applications et des données Linux existantes de votre dossier Fichiers Linux.</translation>
 <translation id="3331321258768829690">(<ph name="UTCOFFSET" />) <ph name="LONGTZNAME" /> (<ph name="EXEMPLARCITY" />)</translation>
-<translation id="3331974543021145906">Informations relatives à l'application</translation>
+<translation id="3331974543021145906">Infos sur l'appli</translation>
 <translation id="3334632933872291866"><ph name="WINDOW_TITLE" /> – Vidéo diffusée en mode PIP</translation>
 <translation id="3335947283844343239">Rouvrir l'onglet fermé</translation>
 <translation id="3336664756920573711">Déverrouillez votre <ph name="DEVICE_TYPE" /> avec votre téléphone Android</translation>
@@ -1787,7 +1787,7 @@
 <translation id="3511200754045804813">Nouvelle recherche</translation>
 <translation id="3511307672085573050">Copier l'adr&amp;esse du lien</translation>
 <translation id="351152300840026870">Police à largeur fixe</translation>
-<translation id="3511528412952710609">Courte</translation>
+<translation id="3511528412952710609">Court</translation>
 <translation id="3514373592552233661">Les réseaux préférés priment sur les autres réseaux connus lorsque plusieurs réseaux sont disponibles</translation>
 <translation id="3515983984924808886">Appuyez à nouveau sur votre clé de sécurité pour confirmer la réinitialisation. Cette opération effacera toutes les informations stockées sur la clé de sécurité, y compris son code.</translation>
 <translation id="3518985090088779359">Accepter et continuer</translation>
@@ -2531,7 +2531,7 @@
 <translation id="4567772783389002344">Ajouter le mot</translation>
 <translation id="4568025708905928793">Demande de clé de sécurité…</translation>
 <translation id="4568213207643490790">Désolé, les comptes Google ne sont pas autorisés sur cet appareil.</translation>
-<translation id="4569747168316751899">Au repos</translation>
+<translation id="4569747168316751899">En cas d'inactivité</translation>
 <translation id="4570387585180509432">Adresses, numéros de téléphone, etc.</translation>
 <translation id="4572659312570518089">Annulation de l'authentification lors de la connexion à l'appareil "<ph name="DEVICE_NAME" />".</translation>
 <translation id="4572779512957829735">Saisissez le code associé à votre clé de sécurité</translation>
@@ -2761,7 +2761,7 @@
 <translation id="4918086044614829423">Accepter</translation>
 <translation id="4918221908152712722">Installer <ph name="APP_NAME" /> (aucun téléchargement requis)</translation>
 <translation id="4920887663447894854">Le suivi de votre position géographique sur cette page a été bloqué pour les sites suivants :</translation>
-<translation id="492299503953721473">Supprimer des applications Android</translation>
+<translation id="492299503953721473">Supprimer les applications Android</translation>
 <translation id="4923279099980110923">Je souhaite apporter mon aide</translation>
 <translation id="4924352752174756392">12x</translation>
 <translation id="4925542575807923399">L'administrateur de ce compte a configuré ce dernier de sorte qu'il soit le premier compte à être connecté lors de sessions de connexion multicompte.</translation>
@@ -2783,7 +2783,7 @@
 <translation id="4952981627953231344">Plugin VM n'est pas autorisé sur cet appareil. Veuillez contacter l'administrateur des appareils de votre organisation.</translation>
 <translation id="4953689047182316270">Répondre aux événements d'accessibilité</translation>
 <translation id="4953808748584563296">Avatar orange par défaut</translation>
-<translation id="4955710816792587366">Sélectionner un code</translation>
+<translation id="4955710816792587366">Configurer un code</translation>
 <translation id="4959262764292427323">Les mots de passe sont enregistrés dans votre compte Google, afin que vous puissiez les utiliser sur tous vos appareils</translation>
 <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> – <ph name="PROFILE_NAME" /></translation>
 <translation id="496185450405387901">Cette application a été installée par votre administrateur.</translation>
@@ -2815,7 +2815,7 @@
 <translation id="4996978546172906250">Partager via</translation>
 <translation id="4997086284911172121">Aucune connexion Internet.</translation>
 <translation id="4998873842614926205">Confirmer les modifications</translation>
-<translation id="5000922062037820727">Bloquée (recommandé)</translation>
+<translation id="5000922062037820727">Bloqué (recommandé)</translation>
 <translation id="5008936837313706385">Nom de l'activité</translation>
 <translation id="5010043101506446253">Autorité de certification</translation>
 <translation id="5015344424288992913">Résolution du proxy...</translation>
@@ -2874,10 +2874,10 @@
 <translation id="5088172560898466307">Nom d'hôte du serveur</translation>
 <translation id="5088534251099454936">PKCS #1 SHA-512 avec chiffrement RSA</translation>
 <translation id="5094721898978802975">Communiquer avec les applications natives associées</translation>
-<translation id="5097002363526479830">Échec de la connexion au réseau "<ph name="NAME" />" : <ph name="DETAILS" />.</translation>
+<translation id="5097002363526479830">Échec de la connexion au réseau "<ph name="NAME" />" : <ph name="DETAILS" /></translation>
 <translation id="5101042277149003567">Ouvrir tous les favoris</translation>
 <translation id="5101839224773798795">Cliquer automatiquement en cas d'arrêt du curseur</translation>
-<translation id="5108967062857032718">Paramètres – Supprimer des applications Android</translation>
+<translation id="5108967062857032718">Paramètres – Supprimer les applications Android</translation>
 <translation id="5109044022078737958">Mia</translation>
 <translation id="5111646998522066203">Quitter le mode navigation privée</translation>
 <translation id="5111692334209731439">&amp;Gestionnaire de favoris</translation>
@@ -2901,7 +2901,7 @@
 <translation id="5133483819862530305">Du coucher au lever du soleil</translation>
 <translation id="5135085122826131075">Accédez à l'Assistant en disant "Ok Google".</translation>
 <translation id="5135533361271311778">Impossible de créer le favori.</translation>
-<translation id="5137501176474113045">Supprimer cet article</translation>
+<translation id="5137501176474113045">Supprimer cet élément</translation>
 <translation id="5139112070765735680"><ph name="QUERY_NAME" />, recherche dans <ph name="DEFAULT_SEARCH_ENGINE_NAME" /></translation>
 <translation id="5139823398361067371">Saisissez le code de votre clé de sécurité. Si vous ne le connaissez pas, vous devez réinitialiser la clé de sécurité.</translation>
 <translation id="5139955368427980650">&amp;Ouvrir</translation>
@@ -3476,7 +3476,7 @@
 <translation id="5956585768868398362">Est-ce la page de recherche que vous attendiez ?</translation>
 <translation id="5957613098218939406">Plus d'options</translation>
 <translation id="5957987129450536192">Appuyez sur l'icône Sélectionner pour prononcer, située à côté de votre image de profil, puis choisissez ce que vous voulez entendre.</translation>
-<translation id="5958529069007801266">Utilisateur supervisé</translation>
+<translation id="5958529069007801266">Utilis. supervisé</translation>
 <translation id="5959471481388474538">Réseau indisponible</translation>
 <translation id="595959584676692139">Actualiser la page pour utiliser cette extension</translation>
 <translation id="5963453369025043595"><ph name="NUM_HANDLES" /> (pic : <ph name="NUM_KILOBYTES_LIVE" />)</translation>
@@ -3486,7 +3486,7 @@
 <translation id="5972017421290582825">Gérer les paramètres MIDI…</translation>
 <translation id="597235323114979258">Voir plus de destinations</translation>
 <translation id="5972666587303800813">Service expérimental</translation>
-<translation id="5972708806901999743">Déplacer vers le haut</translation>
+<translation id="5972708806901999743">Placer en premier</translation>
 <translation id="5972826969634861500">Lancer <ph name="PRODUCT_NAME" /></translation>
 <translation id="5973605538625120605">Modifier un code</translation>
 <translation id="5975792506968920132">Pourcentage de chargement de la batterie</translation>
@@ -3835,7 +3835,7 @@
 <translation id="6466988389784393586">&amp;Ouvrir tous les favoris</translation>
 <translation id="6467304607960172345">Optimiser les vidéos en plein écran</translation>
 <translation id="6468485451923838994">Polices</translation>
-<translation id="6472207088655375767">Mot passe usage unique</translation>
+<translation id="6472207088655375767">Mot de passe à usage unique</translation>
 <translation id="6472893788822429178">Afficher le bouton Accueil</translation>
 <translation id="6473842110411557830">Illustration Powerwash</translation>
 <translation id="6474884162850599008">Déconnecter le compte Google Drive</translation>
@@ -3964,7 +3964,7 @@
 <translation id="6676212663108450937">Nous vous recommandons d'utiliser un casque pour l'enregistrement de votre voix</translation>
 <translation id="6678717876183468697">URL de requête</translation>
 <translation id="6680442031740878064">Espace disponible : <ph name="AVAILABLE_SPACE" /></translation>
-<translation id="6680650203439190394">Noter</translation>
+<translation id="6680650203439190394">Cadence</translation>
 <translation id="6681668084120808868">Prendre une photo</translation>
 <translation id="6681964764822470072">L'application "<ph name="APP_NAME" />" va être désinstallée.</translation>
 <translation id="668599234725812620">Ouvrir Google Play</translation>
@@ -4169,7 +4169,7 @@
 <translation id="6978121630131642226">Moteurs de recherche</translation>
 <translation id="6979044105893951891">Lancer et quitter les sessions Invité gérées</translation>
 <translation id="6979440798594660689">Coupé (par défaut)</translation>
-<translation id="6979737339423435258">Toutes les périodes</translation>
+<translation id="6979737339423435258">Toutes les données</translation>
 <translation id="6981982820502123353">Accessibilité</translation>
 <translation id="6983783921975806247">OID enregistré</translation>
 <translation id="6984299437918708277">Choisissez une image à associer à votre compte, laquelle s'affichera sur l'écran de connexion</translation>
@@ -4208,7 +4208,7 @@
 <translation id="703001695939087067">Mode de présentation de la fenêtre activé. Appuyez sur la touche Tabulation pour naviguer.</translation>
 <translation id="7031608529463141342"><ph name="WINDOW_TITLE" /> (port de série connecté)</translation>
 <translation id="7031962166228839643">Préparation du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, l'opération peut prendre quelques minutes.</translation>
-<translation id="7037509989619051237">Texte à prévisualiser</translation>
+<translation id="7037509989619051237">Texte de test</translation>
 <translation id="7039326228527141150">Accéder aux appareils USB de <ph name="VENDOR_NAME" /></translation>
 <translation id="7039912931802252762">Ouverture de session par carte à puce Microsoft</translation>
 <translation id="7040230719604914234">Opérateur</translation>
@@ -4496,7 +4496,7 @@
 <translation id="744341768939279100">Créer un profil</translation>
 <translation id="7443806024147773267">Accédez à vos mots de passe chaque fois que vous êtes connecté à votre compte Google</translation>
 <translation id="7444983668544353857">Désactiver <ph name="NETWORKDEVICE" /></translation>
-<translation id="7448430327655618736">Installer automatiquement les applications</translation>
+<translation id="7448430327655618736">Installer automatiquement des applications</translation>
 <translation id="7450761244949417357">Ouverture dans <ph name="ALTERNATIVE_BROWSER_NAME" /> maintenant</translation>
 <translation id="7453008956351770337">En sélectionnant cette imprimante, vous autorisez l'extension suivante à y accéder :</translation>
 <translation id="7456142309650173560">développeur</translation>
@@ -4571,7 +4571,7 @@
 <translation id="7561196759112975576">Toujours</translation>
 <translation id="756445078718366910">Ouvrir une fenêtre du navigateur</translation>
 <translation id="7564847347806291057">Arrêter le processus</translation>
-<translation id="7566118625369982896">Gérer les liens de l'application Play</translation>
+<translation id="7566118625369982896">Gérer les liens des applications Play</translation>
 <translation id="756809126120519699">Données de Chrome effacées</translation>
 <translation id="7568790562536448087">Mise à jour en cours</translation>
 <translation id="7569983096843329377">Noir</translation>
@@ -4654,9 +4654,10 @@
 <translation id="7684718995427157417">Pour créer et tester vos applications, activez Android Debug Bridge (ADB). Notez que cette action autorise l'installation d'applications Android non vérifiées par Google et ne pourra être désactivée qu'en rétablissant la configuration d'usine.</translation>
 <translation id="7685049629764448582">Mémoire JavaScript </translation>
 <translation id="7685087414635069102">Veuillez saisir un code</translation>
+<translation id="768549422429443215">Ajoutez des langues ou réorganisez la liste.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmer le nouveau mot de passe</translation>
-<translation id="7690378713476594306">Effectuer une sélection dans la liste</translation>
+<translation id="7690378713476594306">Choisir dans la liste</translation>
 <translation id="7690853182226561458">Ajouter un &amp;dossier...</translation>
 <translation id="7691077781194517083">Impossible de réinitialiser cette clé de sécurité. Erreur <ph name="ERROR_CODE" />.</translation>
 <translation id="7696063401938172191">Sur votre <ph name="PHONE_NAME" /> :</translation>
@@ -5049,7 +5050,7 @@
 <translation id="8199300056570174101">Propriétés du réseau (service) et de l'appareil</translation>
 <translation id="8200772114523450471">Reprendre</translation>
 <translation id="8202160505685531999">Saisissez à nouveau votre mot de passe pour modifier votre profil <ph name="DEVICE_TYPE" /></translation>
-<translation id="8203732864715032075">Vous envoyer des notifications et mémoriser cet ordinateur pour les messages. <ph name="LINK_BEGIN" />En savoir plus<ph name="LINK_END" /></translation>
+<translation id="8203732864715032075">Vous envoyer des notifications et mémoriser cet ordinateur pour l'utilisation de l'appli Messages. <ph name="LINK_BEGIN" />En savoir plus<ph name="LINK_END" /></translation>
 <translation id="820568752112382238">Sites les plus consultés</translation>
 <translation id="8206354486702514201">Ce paramètre est appliqué par votre administrateur.</translation>
 <translation id="8206581664590136590">Envoyer des données d'utilisation et de diagnostic. Contribuez à l'amélioration de l'expérience de votre enfant sur Android en envoyant automatiquement à Google des données relatives aux diagnostics et à l'utilisation de l'appareil et des applications. Ces informations ne seront pas utilisées pour identifier votre enfant, mais elles nous aideront à améliorer, entre autres, la stabilité du système et des applications. Certaines données globales seront également utiles aux développeurs des applications Google et à nos partenaires, tels que les développeurs Android. Si vous activez le paramètre relatif à l'activité supplémentaire sur le Web et les applications pour votre enfant, ces données peuvent être enregistrées dans son compte Google. <ph name="BEGIN_LINK1" />En savoir plus<ph name="END_LINK1" /></translation>
@@ -5675,7 +5676,7 @@
 <translation id="9063208415146866933">Erreur de la ligne <ph name="ERROR_LINE_START" /> à la ligne <ph name="ERROR_LINE_END" /></translation>
 <translation id="9064142312330104323">Photo du profil Google (chargement en cours)</translation>
 <translation id="9064275926664971810">Activer la saisie automatique pour remplir les formulaires d'un simple clic</translation>
-<translation id="9065203028668620118">Édition</translation>
+<translation id="9065203028668620118">Modifier</translation>
 <translation id="9066773882585798925">Écouter un texte lu à voix haute</translation>
 <translation id="9066782832737749352">Synthèse vocale</translation>
 <translation id="9067559831321817373">Gérez les comptes auxquels vous êtes connecté. Les sites Web, les applications ainsi que les extensions Chrome et Google Play peuvent utiliser ces comptes pour personnaliser votre expérience, en fonction des autorisations accordées. &lt;a&gt;En savoir plus&lt;/a&gt;</translation>
@@ -5783,7 +5784,7 @@
 <translation id="939598580284253335">Saisir la phrase secrète</translation>
 <translation id="939736085109172342">Nouveau dossier</translation>
 <translation id="942532530371314860"><ph name="APP_NAME" /> partage un onglet Chrome et un contenu audio.</translation>
-<translation id="945522503751344254">Envoyer le commentaire</translation>
+<translation id="945522503751344254">Envoyer un commentaire</translation>
 <translation id="947329552760389097">&amp;Examiner les éléments</translation>
 <translation id="952992212772159698">Désactivé</translation>
 <translation id="957960681186851048">Une tentative de téléchargement automatique de plusieurs fichiers a été initiée via ce site</translation>
diff --git a/chrome/app/resources/generated_resources_gl.xtb b/chrome/app/resources/generated_resources_gl.xtb
index 6a93060..56f06130 100644
--- a/chrome/app/resources/generated_resources_gl.xtb
+++ b/chrome/app/resources/generated_resources_gl.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Non se atoparon redes</translation>
 <translation id="1056898198331236512">Advertencia</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplicacións da Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> inclúe contido confidencial e bloqueouse.</translation>
 <translation id="1061904396131502319">Xa case é hora de facer unha pausa</translation>
 <translation id="1067048845568873861">Creada</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">Traduciuse esta páxina</translation>
 <translation id="3177909033752230686">Idioma da páxina:</translation>
 <translation id="3179982752812949580">Tipo de letra do texto</translation>
+<translation id="3181825792072797598">Activar sincronización</translation>
 <translation id="3181954750937456830">Navegación segura (protección para ti e o teu dispositivo contra os sitios perigosos)</translation>
 <translation id="3182749001423093222">Corrector ortográfico</translation>
 <translation id="3183139917765991655">Importador de perfís</translation>
@@ -4107,7 +4107,7 @@
 <translation id="6892812721183419409">Abrir ligazón como <ph name="USER" /></translation>
 <translation id="6895032998810961280">Informar a Google do software, a configuración do sistema e os procesos daniños atopados no ordenador durante esta limpeza</translation>
 <translation id="6896758677409633944">Copiar</translation>
-<translation id="6897363604023044284">Escoller sitios cuxos datos se borrarán</translation>
+<translation id="6897363604023044284">Escoller sitios dos que borrar datos</translation>
 <translation id="6898440773573063262">Xa se poden configurar as aplicacións de quiosco para que se inicien automaticamente neste dispositivo.</translation>
 <translation id="6898699227549475383">Organización (O)</translation>
 <translation id="6900284862687837908">Aplicación en segundo plano: <ph name="BACKGROUND_APP_URL" /></translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">Activa Android Debug Bridge (ADB) para poder crear e probar as túas aplicacións. Ten en conta que esta acción permite a instalación de aplicacións de Android non verificadas por Google e que require un restablecemento dos valores de fábrica para desactivarse.</translation>
 <translation id="7685049629764448582">Memoria JavaScript</translation>
 <translation id="7685087414635069102">PIN obrigatorio</translation>
+<translation id="768549422429443215">Engade idiomas ou reordena a lista.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar contrasinal novo</translation>
 <translation id="7690378713476594306">Escoller unha opción da lista</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index 1980307..9abe9ed 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">કોઈ નેટવર્ક નથી</translation>
 <translation id="1056898198331236512">ચેતવણી</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play સ્ટોર ઍપ</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" />માં સંવેદનશીલ કન્ટેન્ટ શામેલ છે અને બ્લૉક કરવામાં આવી છે.</translation>
 <translation id="1061904396131502319">વિરામનો સમય થવા જ આવ્યો છે</translation>
 <translation id="1067048845568873861">બનાવ્યું</translation>
@@ -1565,6 +1564,7 @@
 <translation id="3172808215939929606">આ પેજનો અનુવાદ કરવામાં આવ્યો છે</translation>
 <translation id="3177909033752230686">પૃષ્ઠ ભાષા:</translation>
 <translation id="3179982752812949580">ટેક્સ્ટ ફોન્ટ</translation>
+<translation id="3181825792072797598">સિંક ચાલુ કરો</translation>
 <translation id="3181954750937456830">Safe Browsing (તમારું અને તમારા ડિવાઇસનું જોખમી સાઇટથી રક્ષણ કરે છે)</translation>
 <translation id="3182749001423093222">જોડણીની તપાસ</translation>
 <translation id="3183139917765991655">પ્રોફાઇલ આયાતકાર</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">ઍપ બનાવવા અને તેનું પરીક્ષણ કરવા માટે, Android ડીબગ બ્રિજ (ADB) ચાલુ કરો. ધ્યાનમાં રાખો કે આ ક્રિયા દ્વારા ચકાસણી થઈ ન હોય એવી Android ઍપના ઇન્સ્ટૉલેશનની મંજૂરી આપે છે અને ફેક્ટરી રીસેટ બંધ કરવું જરૂરી છે.</translation>
 <translation id="7685049629764448582">JavaScript મેમરી</translation>
 <translation id="7685087414635069102">પિન જરૂરી છે</translation>
+<translation id="768549422429443215">ભાષાઓ ઉમેરો અથવા સૂચિને પુનઃક્રમાંકિત કરો.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">નવા પાસવર્ડની પુષ્ટિ કરો</translation>
 <translation id="7690378713476594306">સૂચિમાંથી પસંદ કરો</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index 58ce6b7f..c7babae 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">कोई नेटवर्क नहीं</translation>
 <translation id="1056898198331236512">चेतावनी</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play स्टोर ऐप्लिकेशन</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> में संवेदनशील सामग्री है और इसे ब्लॉक किया गया है.</translation>
 <translation id="1061904396131502319">ब्रेक लेने का समय होने वाला है</translation>
 <translation id="1067048845568873861">निर्मित</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">इस पेज का अनुवाद किया गया है</translation>
 <translation id="3177909033752230686">पेज की भाषा:</translation>
 <translation id="3179982752812949580">टेक्स्ट का फ़ॉन्ट</translation>
+<translation id="3181825792072797598">सिंक सुविधा चालू करें</translation>
 <translation id="3181954750937456830">सुरक्षित ब्राउज़िंग (आपकी और आपके डिवाइस की खतरनाक साइट से सुरक्षा करती है)</translation>
 <translation id="3182749001423093222">वर्तनी जांच</translation>
 <translation id="3183139917765991655">प्रोफ़ाइल आयातकर्ता</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">ऐप्लिकेशन बनाने और उसकी जांच करने के लिए, Android डीबग ब्रिज (ADB) चालू करें. ध्यान दें कि इस कार्रवाई के लिए ऐसे Android ऐप्लिकेशन इंस्टॉल करने की अनुमति दी जाती है जिनकी पुष्टि Google ने नहीं की है. साथ ही, फ़ैक्ट्री रीसेट को बंद करना ज़रूरी है.</translation>
 <translation id="7685049629764448582">JavaScript मेमोरी</translation>
 <translation id="7685087414635069102">पिन की ज़रूरत है</translation>
+<translation id="768549422429443215">भाषाएं जोड़ें या सूची का क्रम बदलें.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">नए पासवर्ड की पुष्टि करें</translation>
 <translation id="7690378713476594306">सूची में से चुनें</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index e037f3aa..3cf4f1b 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nema mreža</translation>
 <translation id="1056898198331236512">Upozorenje</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikacije iz Trgovine Play</translation>
 <translation id="1061745542578250838">Datoteka <ph name="FILE_NAME" /> blokirana je zbog osjetljivog sadržaja.</translation>
 <translation id="1061904396131502319">Ubrzo je vrijeme za pauzu</translation>
 <translation id="1067048845568873861">Izrađeno</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Ova je stranica prevedena</translation>
 <translation id="3177909033752230686">Jezik stranice:</translation>
 <translation id="3179982752812949580">Font teksta</translation>
+<translation id="3181825792072797598">Uključi Sinkronizaciju</translation>
 <translation id="3181954750937456830">Sigurno pregledavanje (štiti vas i vaš uređaj od opasnih web-lokacija)</translation>
 <translation id="3182749001423093222">Provjera pravopisa</translation>
 <translation id="3183139917765991655">Uvoz profila</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Da biste izrađivali i testirali aplikacije, omogućite Android Debug Bridge (ADB). Napominjemo da se time omogućuje instaliranje Android aplikacija koje Google nije potvrdio i da je za onemogućivanje potrebno vraćanje na tvorničke postavke.</translation>
 <translation id="7685049629764448582">Memorija JavaScripta</translation>
 <translation id="7685087414635069102">Potreban je PIN</translation>
+<translation id="768549422429443215">Dodajte jezike ili promijenite redoslijed popisa.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrdite novu zaporku</translation>
 <translation id="7690378713476594306">Odaberi s popisa</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index 621e549cd..e5ddc12 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nincs hálózat</translation>
 <translation id="1056898198331236512">Figyelmeztetés</translation>
 <translation id="1058262162121953039">PUK-kód</translation>
-<translation id="1060881073479695738">Play Áruház-alkalmazások</translation>
 <translation id="1061745542578250838">A(z) <ph name="FILE_NAME" /> fájlban kényes tartalom található, ezért a rendszer letiltotta.</translation>
 <translation id="1061904396131502319">Lassan ideje szünetet tartani</translation>
 <translation id="1067048845568873861">Létrehozva</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Az oldal fordítása megtörtént</translation>
 <translation id="3177909033752230686">Az oldal nyelve</translation>
 <translation id="3179982752812949580">Szöveg betűtípusa</translation>
+<translation id="3181825792072797598">Szinkronizálás bekapcsolása</translation>
 <translation id="3181954750937456830">Biztonságos Böngészés (megvédi Önt és eszközét a veszélyes webhelyekkel szemben)</translation>
 <translation id="3182749001423093222">Helyesírás-ellenőrzés</translation>
 <translation id="3183139917765991655">Profilimportáló</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Alkalmazások létrehozásához és teszteléséhez engedélyezze az Android Debug Bridge (ADB) eszközt. Ne feledje, hogy ez a művelet engedélyezi a Google által nem jóváhagyott Android-alkalmazások telepítését, és az eszköz letiltásához szükség van az eszköz gyári beállításainak visszaállítására.</translation>
 <translation id="7685049629764448582">JavaScript memória</translation>
 <translation id="7685087414635069102">PIN-kód megadása kötelező</translation>
+<translation id="768549422429443215">Hozzáadhat nyelveket és átrendezheti a listát.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Új jelszó megerősítése</translation>
 <translation id="7690378713476594306">Választás listából</translation>
diff --git a/chrome/app/resources/generated_resources_hy.xtb b/chrome/app/resources/generated_resources_hy.xtb
index 7d19895..9b12c72a 100644
--- a/chrome/app/resources/generated_resources_hy.xtb
+++ b/chrome/app/resources/generated_resources_hy.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Ցանց չկա</translation>
 <translation id="1056898198331236512">Զգուշացում</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Խանութի հավելվածներ</translation>
 <translation id="1061745542578250838">«<ph name="FILE_NAME" />» ֆայլը պարունակում է գաղտնի բովանդակություն, ինչի պատճառով այն արգելափակվել է:</translation>
 <translation id="1061904396131502319">Շուտով ընդմիջման ժամն է</translation>
 <translation id="1067048845568873861">Ստեղծվել է</translation>
@@ -1570,6 +1569,7 @@
 <translation id="3172808215939929606">Այս էջը թարգմանվել է</translation>
 <translation id="3177909033752230686">Էջի լեզուն՝</translation>
 <translation id="3179982752812949580">Տեքստի տառատեսակը</translation>
+<translation id="3181825792072797598">Միացնել համաժամացումը</translation>
 <translation id="3181954750937456830">Անվտանգ դիտարկում (պաշտպանում է ձեզ և ձեր սարքը վտանգավոր կայքերից)</translation>
 <translation id="3182749001423093222">Ուղղագրության ստուգում</translation>
 <translation id="3183139917765991655">Պրոֆիլի ներմուծիչ</translation>
@@ -4657,6 +4657,7 @@
 <translation id="7684718995427157417">Հավելվածներ ստեղծելու և փորձարկելու համար միացրեք Android Debug Bridge-ը (ADB)։ Նկատի ունեցեք, որ այս գործողությունը թույլ է տալիս այն Android հավելվածների տեղադրումը, որոնք չեն ստուգվել Google-ի կողմից։ Դրա համար անհրաժեշտ է վերականգնել սարքի գործարանային կարգավորումները։</translation>
 <translation id="7685049629764448582">JavaScript հիշողություն</translation>
 <translation id="7685087414635069102">Պահանջվում է PIN կոդ</translation>
+<translation id="768549422429443215">Ավելացրեք լեզուներ կամ վերադասավորեք ցանկը։</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Հաստատեք նոր գաղտնաբառը</translation>
 <translation id="7690378713476594306">Ընտրել ցանկից</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index 68446a6a..d329792d 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Tidak ada jaringan</translation>
 <translation id="1056898198331236512">Peringatan</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikasi Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> berisi konten sensitif, dan telah diblokir.</translation>
 <translation id="1061904396131502319">Hampir waktunya istirahat</translation>
 <translation id="1067048845568873861">Dibuat</translation>
@@ -1567,6 +1566,7 @@
 <translation id="3172808215939929606">Halaman ini telah diterjemahkan</translation>
 <translation id="3177909033752230686">Bahasa Halaman:</translation>
 <translation id="3179982752812949580">Font teks</translation>
+<translation id="3181825792072797598">Aktifkan Sinkronisasi</translation>
 <translation id="3181954750937456830">Safe Browsing (melindungi Anda dan perangkat dari situs berbahaya)</translation>
 <translation id="3182749001423093222">Periksa ejaan</translation>
 <translation id="3183139917765991655">Pengimpor Profil</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">Untuk membuat dan menguji aplikasi, aktifkan Android Debug Bridge (ADB). Perhatikan bahwa tindakan ini dapat menginstal aplikasi Android yang belum diverifikasi oleh Google, dan perlu penyetelan ulang ke setelan pabrik untuk menonaktifkannya.</translation>
 <translation id="7685049629764448582">Memori JavaScript</translation>
 <translation id="7685087414635069102">Perlu PIN</translation>
+<translation id="768549422429443215">Tambahkan bahasa atau urutkan ulang daftar.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Konfirmasi sandi baru</translation>
 <translation id="7690378713476594306">Pilih dari daftar</translation>
diff --git a/chrome/app/resources/generated_resources_is.xtb b/chrome/app/resources/generated_resources_is.xtb
index 276aa33..f8f82890 100644
--- a/chrome/app/resources/generated_resources_is.xtb
+++ b/chrome/app/resources/generated_resources_is.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Ekkert net í boði</translation>
 <translation id="1056898198331236512">Viðvörun</translation>
 <translation id="1058262162121953039">PUK-númer</translation>
-<translation id="1060881073479695738">Forrit úr Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> inniheldur viðkvæmt efni og hefur verið útilokuð.</translation>
 <translation id="1061904396131502319">Það fer að koma tími til að taka sér hlé</translation>
 <translation id="1067048845568873861">Búið til</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Þessi síða hefur verið þýdd</translation>
 <translation id="3177909033752230686">Tungumál síðu:</translation>
 <translation id="3179982752812949580">Leturgerð texta</translation>
+<translation id="3181825792072797598">Kveikja á samstillingu</translation>
 <translation id="3181954750937456830">Örugg vefnotkun (verndar þig og tækið þitt fyrir hættulegum vefsvæðum)</translation>
 <translation id="3182749001423093222">Villuleit</translation>
 <translation id="3183139917765991655">Innflutningur prófíla</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Kveiktu á villuleitarbrú Android (ADB) til að búa til og prófa forritin þín. Hafðu í huga að þessi aðgerð gerir þér kleift að setja upp Android forrit sem eru ekki staðfest af Google. Núllstilla þarf tækið til að slökkva á þessu.</translation>
 <translation id="7685049629764448582">JavaScript-minni</translation>
 <translation id="7685087414635069102">PIN-númers krafist</translation>
+<translation id="768549422429443215">Bæta við tungumálum eða endurraða lista.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Staðfestu nýtt aðgangsorð</translation>
 <translation id="7690378713476594306">Velja af lista</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index dffedc55..c44329d1 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nessuna rete</translation>
 <translation id="1056898198331236512">Avviso</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">App Play Store</translation>
 <translation id="1061745542578250838">Il file <ph name="FILE_NAME" /> include contenuti sensibili, quindi è stato bloccato.</translation>
 <translation id="1061904396131502319">È quasi ora di fare una pausa</translation>
 <translation id="1067048845568873861">Data creazione</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">Questa pagina è stata tradotta</translation>
 <translation id="3177909033752230686">Lingua della pagina:</translation>
 <translation id="3179982752812949580">Carattere testo</translation>
+<translation id="3181825792072797598">Attiva la funzione Sincronizzazione</translation>
 <translation id="3181954750937456830">Navigazione sicura (protegge te e il tuo dispositivo da siti pericolosi)</translation>
 <translation id="3182749001423093222">Controllo ortografico</translation>
 <translation id="3183139917765991655">Profile Importer</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">Per creare e testare le tue app, attiva Android Debug Bridge (ADB). Tieni presente che questa azione consente l'installazione di app Android che non sono state verificate da Google. Per disattivare la funzionalità è necessario ripristinare le impostazioni di fabbrica.</translation>
 <translation id="7685049629764448582">Memoria JavaScript</translation>
 <translation id="7685087414635069102">PIN obbligatorio</translation>
+<translation id="768549422429443215">Aggiungi lingue o cambia l'ordine dell'elenco.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Conferma nuova password</translation>
 <translation id="7690378713476594306">Scegli dall'elenco</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index 9a6f8957..0594126f 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">אין רשתות</translation>
 <translation id="1056898198331236512">אזהרה</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">‏אפליקציות מחנות Play</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> מכיל תוכן רגיש, ולכן נחסם.</translation>
 <translation id="1061904396131502319">עוד מעט זמן להפסקה</translation>
 <translation id="1067048845568873861">נוצר</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">הדף הזה תורגם</translation>
 <translation id="3177909033752230686">שפת הדף:</translation>
 <translation id="3179982752812949580">גופן הטקסט</translation>
+<translation id="3181825792072797598">הפעלת סינכרון</translation>
 <translation id="3181954750937456830">גלישה בטוחה (מגנה עליך ועל המכשיר מפני אתרים מסוכנים)</translation>
 <translation id="3182749001423093222">בדיקת איות</translation>
 <translation id="3183139917765991655">מייבא פרופילים</translation>
@@ -4650,6 +4650,7 @@
 <translation id="7684718995427157417">‏כדי ליצור ולבדוק אפליקציות, יש להפעיל את ממשק הגישור של Android‏ (ADB). הערה: לאחר ביצוע הפעולה הזו יתאפשר להתקין אפליקציות ל-Android שלא אומתו על-ידי Google. כמו כן, כדי להשבית את התכונה, יש לאפס את המכשיר להגדרות היצרן.</translation>
 <translation id="7685049629764448582">‏זיכרון JavaScript</translation>
 <translation id="7685087414635069102">נדרש קוד אימות</translation>
+<translation id="768549422429443215">הוספת שפות או שינוי סדר הרשימה.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">אישור הסיסמה החדשה</translation>
 <translation id="7690378713476594306">בחירה מתוך רשימה</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 38980d87..623decf 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ネットワークが見つかりません</translation>
 <translation id="1056898198331236512">警告</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play ストアのアプリ</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> は機密性の高い内容を含んでいるためブロックされました。</translation>
 <translation id="1061904396131502319">もうすぐ休憩の時間です</translation>
 <translation id="1067048845568873861">作成日</translation>
@@ -202,7 +201,7 @@
 <translation id="1272293450992660632">PIN の値が一致しません。</translation>
 <translation id="1272978324304772054">このユーザー アカウントは、デバイスが登録されているドメインに属していません。別のドメインに登録する場合は、まず、デバイス リカバリ操作を行う必要があります。</translation>
 <translation id="1274977772557788323">Adobe Flash Player のストレージ設定</translation>
-<translation id="1274997165432133392">Cookie と他のサイト データ</translation>
+<translation id="1274997165432133392">Cookie と他のサイトデータ</translation>
 <translation id="127668050356036882">すべてのウィンドウを閉じる</translation>
 <translation id="1280820357415527819">モバイル ネットワークを検索しています</translation>
 <translation id="1282420830958964167">あなたの保護者が設定した制限時間に達したため、今日はこれ以上「<ph name="APP_NAME" />」を使えません。明日は <ph name="TIME_LIMIT" />まで使えます。</translation>
@@ -389,7 +388,7 @@
 <translation id="1531004739673299060">アプリケーション ウィンドウ</translation>
 <translation id="1531275250079031713">[新しい Wi-Fi を追加] ダイアログを表示</translation>
 <translation id="1536754031901697553">切断しています...</translation>
-<translation id="15373452373711364">大きいマウス カーソル</translation>
+<translation id="15373452373711364">大きいマウスカーソル</translation>
 <translation id="1540605929960647700">デモモードの有効化</translation>
 <translation id="1541396123399225659">新しいグループに追加</translation>
 <translation id="1542514202066550870">このタブは VR コンテンツをヘッドセットに配信しています。</translation>
@@ -564,7 +563,7 @@
 <translation id="1768278914020124551">ログイン サーバーへの接続中に問題が発生しました。ネットワーク接続とドメイン名を確認してもう一度お試しください。</translation>
 <translation id="1769104665586091481">新しいウインドウで開く(&amp;W)</translation>
 <translation id="1773212559869067373">認証証明書がローカルで拒否されました</translation>
-<translation id="177336675152937177">ホストされているアプリ データ</translation>
+<translation id="177336675152937177">ホストされているアプリデータ</translation>
 <translation id="1776712937009046120">ユーザーを追加</translation>
 <translation id="1776883657531386793"><ph name="OID" />: <ph name="INFO" /></translation>
 <translation id="1777310661937894236">このデバイスは <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> によって管理されています。
@@ -1050,7 +1049,7 @@
 <translation id="2462752602710430187"><ph name="PRINTER_NAME" /> を追加しました</translation>
 <translation id="2464089476039395325">HTTP プロキシ</translation>
 <translation id="2467267713099745100"><ph name="NETWORK_TYPE" /> ネットワーク、無効</translation>
-<translation id="2468205691404969808">Cookie を使って設定を保存する(これらのページにアクセスしない場合も Cookie が保持されます)</translation>
+<translation id="2468205691404969808">Cookie を使って設定を保存します(これらのページにアクセスしない場合も Cookie が保持されます)</translation>
 <translation id="2468402215065996499">たまごっち</translation>
 <translation id="2469259292033957819">保存済みのプリンタはありません。</translation>
 <translation id="2469375675106140201">スペルチェックをカスタマイズ</translation>
@@ -1192,7 +1191,7 @@
 <translation id="2653275834716714682">テキストの置換</translation>
 <translation id="2653659639078652383">送信</translation>
 <translation id="265390580714150011">フィールド値</translation>
-<translation id="2654166010170466751">サイトに支払いハンドラのインストールを許可</translation>
+<translation id="2654166010170466751">サイトに支払いハンドラのインストールを許可する</translation>
 <translation id="2659381484350128933"><ph name="FOOTNOTE_POINTER" />機能はデバイスによって異なります</translation>
 <translation id="2660779039299703961">イベント</translation>
 <translation id="266079277508604648">プリンタに接続できません。プリンタの電源が入っていて、Wi-Fi または USB 経由で Chromebook に接続されていることを確認してください。</translation>
@@ -1201,7 +1200,7 @@
 <translation id="2663302507110284145">言語</translation>
 <translation id="2665394472441560184">新しい単語を追加</translation>
 <translation id="2665647207431876759">期限切れ</translation>
-<translation id="2665717534925640469">現在このページは全画面表示で、マウス カーソルは無効になります。</translation>
+<translation id="2665717534925640469">現在このページは全画面表示で、マウスカーソルは無効になります。</translation>
 <translation id="2665919335226618153">フォーマット中にエラーが発生しました。</translation>
 <translation id="2666990579225592931">ゲスト ウィンドウを開く</translation>
 <translation id="2667463864537187133">スペルチェックの管理</translation>
@@ -1435,7 +1434,7 @@
 <translation id="2977480621796371840">グループから削除</translation>
 <translation id="2979520980928493164">Chrome をより快適に</translation>
 <translation id="2979639724566107830">新しいウィンドウで開く</translation>
-<translation id="2981113813906970160">大きいマウス カーソルを表示する</translation>
+<translation id="2981113813906970160">大きいマウスカーソルを表示する</translation>
 <translation id="2982970937345031">匿名で報告</translation>
 <translation id="2986010903908656993">このページは MIDI デバイスのフル コントロールが許可されていません。</translation>
 <translation id="2987620471460279764">他のデバイスからテキストが共有されました</translation>
@@ -1530,7 +1529,7 @@
 <translation id="3127860049873093642">充電やパフォーマンスに関する問題を回避するには、対応する Dell または USB Type-C の電源アダプターを使用してください。</translation>
 <translation id="3129173833825111527">左余白</translation>
 <translation id="3130528281680948470">デバイスをリセットし、すべてのユーザー アカウントとローカルデータを削除します。この操作は元に戻せません。</translation>
-<translation id="313205617302240621">パスワードをお忘れの場合</translation>
+<translation id="313205617302240621">パスワードを忘れた場合</translation>
 <translation id="3132996321662585180">毎日更新する</translation>
 <translation id="313963229645891001">ダウンロードしています。<ph name="STATUS" /></translation>
 <translation id="3139925690611372679">デフォルトの黄のアバター</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">このページは翻訳済みです</translation>
 <translation id="3177909033752230686">ページの言語:</translation>
 <translation id="3179982752812949580">テキストのフォント</translation>
+<translation id="3181825792072797598">同期を有効にする</translation>
 <translation id="3181954750937456830">セーフ ブラウジング(危険なサイトからユーザーとデバイスを保護します)</translation>
 <translation id="3182749001423093222">スペルチェック</translation>
 <translation id="3183139917765991655">プロフィール インポーター</translation>
@@ -2280,7 +2280,7 @@
 <translation id="4157869833395312646">Microsoft SGC(Server Gated Cryptography)</translation>
 <translation id="4159681666905192102">これは <ph name="CUSTODIAN_EMAIL" /> と <ph name="SECOND_CUSTODIAN_EMAIL" /> によって管理されている子供向けのアカウントです。</translation>
 <translation id="4163560723127662357">不明なキーボード</translation>
-<translation id="4168015872538332605"><ph name="PRIMARY_EMAIL" /> に帰属する設定の一部を共有しています。これらの設定は、マルチ ログインを使用した場合にのみこのアカウントに適用されます。</translation>
+<translation id="4168015872538332605"><ph name="PRIMARY_EMAIL" /> に帰属する設定の一部を共有しています。これらの設定は、マルチログインを使用した場合にのみこのアカウントに適用されます。</translation>
 <translation id="4170314459383239649">終了時に削除</translation>
 <translation id="4172051516777682613">常に表示</translation>
 <translation id="4175137578744761569">明るい紫と白</translation>
@@ -2459,7 +2459,7 @@
 <translation id="4460014764210899310">グループを解除</translation>
 <translation id="4462159676511157176">カスタム ネーム サーバー</translation>
 <translation id="4465725236958772856"><ph name="NETWORK_INDEX" /> 番目のネットワーク(全 <ph name="NETWORK_COUNT" /> 件)、<ph name="NETWORK_NAME" />、管理者によって管理、接続</translation>
-<translation id="4469477701382819144">煩わしい広告や誤解を招く広告が表示されるサイトでブロックされています</translation>
+<translation id="4469477701382819144">煩わしい広告や誤解を招く広告が表示されるサイトでブロック中</translation>
 <translation id="4469762931504673593"><ph name="ORIGIN" /> は「<ph name="FOLDERNAME" />」のファイルを編集できます</translation>
 <translation id="4470957202018033307">外部ストレージの設定</translation>
 <translation id="447252321002412580">Chrome の機能と動作の改善に協力する</translation>
@@ -3001,7 +3001,7 @@
 <translation id="52895863590846877"><ph name="LANGUAGE" />のページではない場合</translation>
 <translation id="52912272896845572">秘密鍵ファイルが無効です。</translation>
 <translation id="529175790091471945">このデバイスをフォーマット</translation>
-<translation id="5293170712604732402">設定を元の既定値に戻します</translation>
+<translation id="5293170712604732402">設定を元の既定値に戻す</translation>
 <translation id="5296471962619441686">同期を再開するにはエラーを解決してください</translation>
 <translation id="5297082477358294722">パスワードが保存されました。保存パスワードの表示と管理は <ph name="SAVED_PASSWORDS_STORE" /> で行えます。</translation>
 <translation id="5298219193514155779">テーマの作成者:</translation>
@@ -3816,7 +3816,7 @@
 <translation id="6445450263907939268">この変更を受け入れない場合は、以前の設定を復元できます。</translation>
 <translation id="6447842834002726250">Cookie</translation>
 <translation id="6450876761651513209">プライバシー関連の設定の変更</translation>
-<translation id="6451180435462401570">クラウド プリントデバイスを管理</translation>
+<translation id="6451180435462401570">クラウド プリントデバイスを管理する</translation>
 <translation id="6451689256222386810">パスフレーズを忘れた場合や、この設定を変更する場合は、<ph name="BEGIN_LINK" />同期をリセット<ph name="END_LINK" />します。</translation>
 <translation id="6452181791372256707">拒否</translation>
 <translation id="6452961788130242735">ネットワークに問題があるか、レルムが正しくありません</translation>
@@ -3861,7 +3861,7 @@
 <translation id="6509207748479174212">メディア ライセンス</translation>
 <translation id="6513247462497316522">他のネットワークに接続していない場合、Google Chrome はモバイル データを使用します。</translation>
 <translation id="6514010653036109809">接続可能なデバイス:</translation>
-<translation id="6514565641373682518">このページではマウス カーソルが無効になります。</translation>
+<translation id="6514565641373682518">このページではマウスカーソルが無効になります。</translation>
 <translation id="6518014396551869914">画像をコピー(&amp;Y)</translation>
 <translation id="6518133107902771759">確認</translation>
 <translation id="651942933739530207">画面と音声出力を <ph name="APP_NAME" /> と共有しますか?</translation>
@@ -4225,7 +4225,7 @@
 <translation id="7062222374113411376">最近閉じたサイトがデータの送受信を完了できるようにする(推奨)</translation>
 <translation id="7063129466199351735">ショートカットを処理しています...</translation>
 <translation id="7063311912041006059">URL(<ph name="SPECIAL_SYMBOL" />=検索語句)</translation>
-<translation id="7063957500469387217">Google クラウド プリントのプリンタを設定または管理</translation>
+<translation id="7063957500469387217">Google クラウド プリントのプリンタを設定または管理する。</translation>
 <translation id="7065223852455347715">このデバイスは企業の登録を防止するモードでロックされています。このデバイスを登録するにはまずデバイスの復元を行ってください。</translation>
 <translation id="7065534935986314333">システムについて</translation>
 <translation id="706626672220389329">共有フォルダのマウントエラー。指定された共有フォルダはすでにマウントされています。</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">アプリを作成してテストするには、Android Debug Bridge(ADB)を有効にします。この操作を行うと、Google が確認していない Android アプリのインストールが許可されます。無効にする場合は、出荷時の設定へのリセットが必要になります。</translation>
 <translation id="7685049629764448582">JavaScript メモリ</translation>
 <translation id="7685087414635069102">PIN が必要です</translation>
+<translation id="768549422429443215">言語を追加するか、リストを並べ替えます。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" />(<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">新しいパスワードの確認入力</translation>
 <translation id="7690378713476594306">リストから選択</translation>
@@ -4830,7 +4831,7 @@
 <translation id="7903345046358933331">ページが応答していません。応答があるまで待つか、終了することができます。</translation>
 <translation id="7903742244674067440">これらの認証局を識別する証明書がファイルに格納されています</translation>
 <translation id="7903925330883316394">ユーティリティ: <ph name="UTILITY_TYPE" /></translation>
-<translation id="7904094684485781019">このアカウントの管理者がマルチ ログインを許可していません。</translation>
+<translation id="7904094684485781019">このアカウントの管理者がマルチログインを許可していません。</translation>
 <translation id="7908378463497120834">外部ストレージ デバイスの少なくとも 1 つのパーティションがマウントできませんでした。</translation>
 <translation id="7909969815743704077">シークレット モードでダウンロード</translation>
 <translation id="7910768399700579500">新しいフォルダ(&amp;N)</translation>
@@ -4887,7 +4888,7 @@
 <translation id="7978412674231730200">秘密鍵</translation>
 <translation id="7978450511781612192">この操作を行うと Google アカウントからログアウトし、ブックマーク、履歴、パスワードなどの設定は同期されなくなります。</translation>
 <translation id="7980084013673500153">アセット ID: <ph name="ASSET_ID" /></translation>
-<translation id="7981313251711023384">ページをプリロードして、閲覧と検索をすばやく行えるようにします</translation>
+<translation id="7981313251711023384">ページをプリロードして、閲覧と検索をすばやく行えるようにする</translation>
 <translation id="798145602633458219">検索ボックスに候補<ph name="SUGGESTION_NAME" />を追加します</translation>
 <translation id="7982083145464587921">このエラーを修正するには、デバイスを再起動してください。</translation>
 <translation id="7982789257301363584">ネットワーク</translation>
@@ -5048,7 +5049,7 @@
 <translation id="8199300056570174101">ネットワーク(サービス)とデバイスのプロパティ</translation>
 <translation id="8200772114523450471">再開</translation>
 <translation id="8202160505685531999"><ph name="DEVICE_TYPE" /> のプロフィールを更新するにはパスワードを再入力してください。</translation>
-<translation id="8203732864715032075">デフォルトでこのパソコンにメッセージの通知を送信します。<ph name="LINK_BEGIN" />詳細<ph name="LINK_END" /></translation>
+<translation id="8203732864715032075">デフォルトでこのパソコンにメッセージの通知を送信する<ph name="LINK_BEGIN" />詳細<ph name="LINK_END" /></translation>
 <translation id="820568752112382238">よくアクセスするサイト</translation>
 <translation id="8206354486702514201">この設定は管理者によって制御されています。</translation>
 <translation id="8206581664590136590">使用状況データや診断データを送信します。診断データやデバイスとアプリの使用状況データを Google に自動送信して、お子様向けの Android 機能の向上にご協力ください。この情報を使ってお子様個人が特定されることはありません。この情報は、システムとアプリの安定性の向上やその他の機能の改善に役立てられます。また、Google のアプリやパートナー(Android デベロッパーなど)も、集計データとしてこの情報を活用します。お子様の [その他のウェブとアプリのアクティビティ] の設定がオンになっている場合、このデータはお子様の Google アカウントに保存されます。<ph name="BEGIN_LINK1" />詳細<ph name="END_LINK1" /></translation>
@@ -5098,7 +5099,7 @@
 <translation id="8260864402787962391">マウス</translation>
 <translation id="8261378640211443080">この拡張機能は <ph name="IDS_EXTENSION_WEB_STORE_TITLE" />で提供されていません。知らないうちに追加された可能性があります。</translation>
 <translation id="8261506727792406068">削除</translation>
-<translation id="8263744495942430914"><ph name="FULLSCREEN_ORIGIN" /> でマウス カーソルが無効になりました。</translation>
+<translation id="8263744495942430914"><ph name="FULLSCREEN_ORIGIN" /> でマウスカーソルが無効になりました。</translation>
 <translation id="8264718194193514834">「<ph name="EXTENSION_NAME" />」によって全画面表示になりました。</translation>
 <translation id="8267961145111171918"><ph name="BEGIN_PARAGRAPH1" />これは、お使いのデバイスとその使用状況(電池残量、システムとアプリのアクティビティ、エラーなど)に関する一般的な情報です。このデータは、Android の改善に使用されます。また一部の集計情報は、Google のアプリのほか、Android デベロッパーなどのパートナーが開発するアプリやサービスの品質改善にも役立てられます。<ph name="END_PARAGRAPH1" />
     <ph name="BEGIN_PARAGRAPH2" />この機能をオフにした場合でも、システム アップデートやセキュリティなどの重要なサービスで必要となる情報は、デバイスからこれまでどおり送信されます。<ph name="END_PARAGRAPH2" />
@@ -5158,7 +5159,7 @@
 <translation id="8351419472474436977">この拡張機能によってプロキシ設定が制御されています。オンラインで行う操作は、この拡張機能によって変更、遮断、傍受される可能性があります。この変更が行われた理由に心当たりがない場合、これは不正な変更と考えられます。</translation>
 <translation id="8351630282875799764">充電は行われていません</translation>
 <translation id="835238322900896202">アンインストール中にエラーが発生しました。ターミナルからアンインストールしてください。</translation>
-<translation id="8352772353338965963">マルチ ログインにアカウントを追加します。ログインしているすべてのアカウントにパスワードなしでアクセスできるようになるため、この機能は信頼できるアカウントでのみ使用してください。</translation>
+<translation id="8352772353338965963">マルチログインにアカウントを追加します。ログインしているすべてのアカウントにパスワードなしでアクセスできるようになるため、この機能は信頼できるアカウントでのみ使用してください。</translation>
 <translation id="8353683614194668312">次の権限にアクセス可能:</translation>
 <translation id="8356197132883132838"><ph name="TITLE" /> - <ph name="COUNT" /></translation>
 <translation id="8358685469073206162">ページを復元しますか?</translation>
@@ -5374,7 +5375,7 @@
 <translation id="8665180165765946056">バックアップが完了しました</translation>
 <translation id="866611985033792019">メールユーザーの識別でこの証明書を信頼します</translation>
 <translation id="8666584013686199826">サイトから USB デバイスへのアクセス許可を求められたときに確認する</translation>
-<translation id="8667328578593601900">現在 <ph name="FULLSCREEN_ORIGIN" /> は全画面表示で、マウス カーソルは無効です。</translation>
+<translation id="8667328578593601900">現在 <ph name="FULLSCREEN_ORIGIN" /> は全画面表示で、マウスカーソルは無効です。</translation>
 <translation id="8669284339312441707">暖色</translation>
 <translation id="867085395664725367">一時的なサーバーエラーが発生しました。</translation>
 <translation id="8673026256276578048">ウェブ検索...</translation>
@@ -5444,7 +5445,7 @@
 <translation id="8757090071857742562">デスクトップをキャストできません。画面共有の開始を確認するメッセージで同意したかどうかを確認してください。</translation>
 <translation id="8757803915342932642">Google クラウド デバイス上のデバイス</translation>
 <translation id="8758418656925882523">音声入力を有効にする</translation>
-<translation id="8759408218731716181">マルチ ログインを設定できません</translation>
+<translation id="8759408218731716181">マルチログインを設定できません</translation>
 <translation id="8759753423332885148">詳細</translation>
 <translation id="8761945298804995673">このユーザーはすでに存在しています</translation>
 <translation id="8762886931014513155">ご利用の <ph name="DEVICE_TYPE" /> は更新が必要です</translation>
@@ -5602,7 +5603,7 @@
 <translation id="8966870118594285808">間違って閉じたタブをもう一度開きます</translation>
 <translation id="8967866634928501045">Alt+Shift+A キーで表示します</translation>
 <translation id="8968766641738584599">カードを保存</translation>
-<translation id="89720367119469899">エスケープ</translation>
+<translation id="89720367119469899">Esc</translation>
 <translation id="8972513834460200407">ファイアウォールが Google のサーバーからのダウンロードをブロックしていないかどうかをネットワーク管理者に確認してください。</translation>
 <translation id="8973557916016709913">拡大縮小値の指定を削除</translation>
 <translation id="8973596347849323817">このデバイスを必要に応じてカスタマイズできます。このユーザー補助機能は後から [設定] で変更できます。</translation>
diff --git a/chrome/app/resources/generated_resources_ka.xtb b/chrome/app/resources/generated_resources_ka.xtb
index 702306a..368b53fee 100644
--- a/chrome/app/resources/generated_resources_ka.xtb
+++ b/chrome/app/resources/generated_resources_ka.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ქსელები არ არის</translation>
 <translation id="1056898198331236512">გაფრთხილება</translation>
 <translation id="1058262162121953039">PUK კოდი</translation>
-<translation id="1060881073479695738">Play Store აპები</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> შეიცავს სენსიტიურ კონტენტს, ამიტომ ის დაიბლოკა.</translation>
 <translation id="1061904396131502319">შესვენების დრო ახლოვდება</translation>
 <translation id="1067048845568873861">შექმნის თარიღი</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">ეს გვერდი ითარგმნა</translation>
 <translation id="3177909033752230686">გვერდის ენა:</translation>
 <translation id="3179982752812949580">ტექსტის შრიფტი</translation>
+<translation id="3181825792072797598">სინქრონიზაციის ჩართვა</translation>
 <translation id="3181954750937456830">Safe Browsing (თქვენ და თქვენს მოწყობილობებს გიცავთ სახიფათო საიტებისგან)</translation>
 <translation id="3182749001423093222">მართლწერის შემოწმება</translation>
 <translation id="3183139917765991655">პროფილის იმპორტიორი</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">აპების შესაქმნელად და ტესტირებისთვის ჩართეთ Android Debug Bridge (ADB). გაითვალისწინეთ, რომ აღნიშნულის შემდეგ შესაძლებელი იქნება Google-ის მიერ შეუმოწმებელი Android აპების ინსტალაცია, ხოლო მის გამოსართავად საჭირო იქნება ქარხნული პარამეტრების დაბრუნება.</translation>
 <translation id="7685049629764448582">JavaScript მეხსიერება</translation>
 <translation id="7685087414635069102">საჭიროა PIN-კოდი</translation>
+<translation id="768549422429443215">დაამატეთ ენები, ან შეცვალეთ სიის მიმდევრობა.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">დაადასტურეთ ახალი პაროლი</translation>
 <translation id="7690378713476594306">სიიდან არჩევა</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb
index ef9331e..063700f 100644
--- a/chrome/app/resources/generated_resources_kk.xtb
+++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Бірде-бір желі табылмады</translation>
 <translation id="1056898198331236512">Ескерту</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store қолданбалары</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> файлында құпия мазмұн бар және оған тыйым салынған.</translation>
 <translation id="1061904396131502319">Үзіліс уақыты келіп қалды</translation>
 <translation id="1067048845568873861">Жасалған</translation>
@@ -244,7 +243,7 @@
 <translation id="1329584516321524826">Жаңа ғана жаңартылды</translation>
 <translation id="1330145147221172764">Экрандағы пернетақтаны қосу</translation>
 <translation id="1331977651797684645">Бұл мен едім.</translation>
-<translation id="1333489022424033687">Басқа сайттар құрылғыңызда сақтаған деректер жойылмайынша, <ph name="ORIGIN" /> сайтындағы кейбір функциялар жұмыс істемейді.</translation>
+<translation id="1333489022424033687">Құрылғыңызға басқа сайттар сақтаған деректер жойылмайынша, <ph name="ORIGIN" /> сайтындағы кейбір функциялар жұмыс істемейді.</translation>
 <translation id="133535873114485416">Қалаған енгізу әдісі</translation>
 <translation id="1335929031622236846">Құрылғыны тіркеу</translation>
 <translation id="1338802252451106843"><ph name="ORIGIN" /> осы қолданбаны ашқысы келеді.</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">Бет аударылды</translation>
 <translation id="3177909033752230686">Бет тілі:</translation>
 <translation id="3179982752812949580">Мәтін қарпі</translation>
+<translation id="3181825792072797598">"Синхрондау" функциясын қосу</translation>
 <translation id="3181954750937456830">Safe Browsing қызметі (сізді және құрылғыңызды қауіпті сайттардан қорғайды)</translation>
 <translation id="3182749001423093222">Емле тексеру</translation>
 <translation id="3183139917765991655">Profile Importer</translation>
@@ -4650,6 +4650,7 @@
 <translation id="7684718995427157417">Қолданбалар жасау және тексеру үшін Android Debug Bridge (ADB) құралын іске қосу керек. Бұл — Google растамаған Android қолданбаларының орнатылуына мүмкіндік беретінін ескеріңіз. Құралды өшіру үшін зауыттық параметрлерге қайтару қажет болады.</translation>
 <translation id="7685049629764448582">JavaScript жады</translation>
 <translation id="7685087414635069102">PIN коды қажет</translation>
+<translation id="768549422429443215">Тілдерді енгізіңіз немесе тізімнің ретін өзгертіңіз.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Жаңа құпия сөзді қайталаңыз</translation>
 <translation id="7690378713476594306">Тізімнен таңдау</translation>
diff --git a/chrome/app/resources/generated_resources_km.xtb b/chrome/app/resources/generated_resources_km.xtb
index 30be61e..81894ad 100644
--- a/chrome/app/resources/generated_resources_km.xtb
+++ b/chrome/app/resources/generated_resources_km.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">មិនមានបណ្ដាញទេ</translation>
 <translation id="1056898198331236512">ការព្រមាន</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">កម្មវិធី​នៅលើ Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> មានខ្លឹមសាររសើប និងត្រូវបានទប់ស្កាត់។</translation>
 <translation id="1061904396131502319">ជិតដល់ពេលសម្រាកហើយ</translation>
 <translation id="1067048845568873861">បានបង្កើត</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">ទំព័រ​នេះត្រូវ​បាន​បកប្រែ​រួច​ហើយ</translation>
 <translation id="3177909033752230686">ភាសាទំព័រ៖</translation>
 <translation id="3179982752812949580">ពុម្ព​អក្សរ​</translation>
+<translation id="3181825792072797598">បើក​សមកាលកម្ម</translation>
 <translation id="3181954750937456830">មុខងាររុករក​ដោយ​សុវត្ថិភាព (ការពារអ្នក​ និងឧបករណ៍​របស់អ្នក​ពីគេហទំព័រ​គ្រោះថ្នាក់)</translation>
 <translation id="3182749001423093222">ពិនិត្យអក្ខរាវិរុទ្ធ</translation>
 <translation id="3183139917765991655">កម្មវិធីនាំចូលប្រវត្តិរូប</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">ដើម្បី​បង្កើត និងធ្វើតេស្ត​កម្មវិធី​របស់អ្នក សូមបើក Android Debug Bridge (ADB)។ សូម​ចំណាំថា សកម្មភាពនេះ​អនុញ្ញាតការដំឡើង​កម្មវិធី Android ដែល​មិនមាន​ការផ្ទៀងផ្ទាត់ពី Google និងតម្រូវឱ្យ​កំណត់ដូចដើមឡើងវិញ ដើម្បី​បិទ។</translation>
 <translation id="7685049629764448582">មេម៉ូរី JavaScript</translation>
 <translation id="7685087414635069102">តម្រូវឱ្យមានកូដ PIN</translation>
+<translation id="768549422429443215">បញ្ចូលភាសា ឬ​តម្រៀបបញ្ជី​ឡើងវិញ។</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">បញ្ជាក់​ពាក្យ​សម្ងាត់​ថ្មី</translation>
 <translation id="7690378713476594306">ជ្រើសរើស​ពី​បញ្ជី</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb
index 08c69c2..c1740a04 100644
--- a/chrome/app/resources/generated_resources_kn.xtb
+++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ಯಾವುದೇ ನೆಟ್‌ವರ್ಕ್‌ಗಳಿಲ್ಲ</translation>
 <translation id="1056898198331236512">ಎಚ್ಚರಿಕೆ</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play ಸ್ಟೋರ್ ಆ್ಯಪ್‌ಗಳು</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> ಫೈಲ್ ಸೂಕ್ಷ್ಮ ವಿಷಯವನ್ನು ಒಳಗೊಂಡಿದೆ ಹಾಗೂ ಅದನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ.</translation>
 <translation id="1061904396131502319">ಬಹುತೇಕ ವಿರಾಮದ ಸಮಯ</translation>
 <translation id="1067048845568873861">ರಚಿಸಲಾಗಿದೆ</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">ಈ ಪುಟವನ್ನು ಅನುವಾದಿಸಲಾಗಿದೆ</translation>
 <translation id="3177909033752230686">ಪುಟದ ಭಾಷೆ:</translation>
 <translation id="3179982752812949580">ಪಠ್ಯದ ಫಾಂಟ್</translation>
+<translation id="3181825792072797598">ಸಿಂಕ್‌ ಆನ್‌ ಮಾಡಿ</translation>
 <translation id="3181954750937456830">ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್ (ಅಪಾಯಕಾರಿ ಸೈಟ್‌ಗಳಿಂದ ನಿಮ್ಮನ್ನು ಮತ್ತು ನಿಮ್ಮ ಸಾಧನವನ್ನು ರಕ್ಷಿಸುತ್ತದೆ)</translation>
 <translation id="3182749001423093222">ಕಾಗುಣಿತ ಪರಿಶೀಲನೆ</translation>
 <translation id="3183139917765991655">ಪ್ರೊಫೈಲ್ ಆಮದುದಾರ</translation>
@@ -4656,6 +4656,7 @@
 <translation id="7684718995427157417">ನಿಮ್ಮ ಆ್ಯಪ್‌ಗಳನ್ನು ರಚಿಸಲು ಮತ್ತು ಪರೀಕ್ಷಿಸಲು, Android ಡೀಬಗ್ ಬ್ರಿಡ್ಜ್ (ADB) ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ. ಇದು Google ನಿಂದ ದೃಢೀಕರಿಸದ Android ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ಅನುಮತಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಗಮನಿಸಿ ಹಾಗೂ ಇದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಫ್ಯಾಕ್ಟರಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಮರುಹೊಂದಿಸುವ ಅಗತ್ಯವಿದೆ.</translation>
 <translation id="7685049629764448582">JavaScript ಸ್ಮರಣೆ</translation>
 <translation id="7685087414635069102">ಪಿನ್ ಅಗತ್ಯವಿದೆ</translation>
+<translation id="768549422429443215">ಭಾಷೆಗಳನ್ನು ಸೇರಿಸಿ ಅಥವಾ ಪಟ್ಟಿಯನ್ನು ಮರುಕ್ರಮಗೊಳಿಸಿ.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ಹೊಸ ಪಾಸ್‌ವರ್ಡ್ ಖಚಿತಪಡಿಸಿ</translation>
 <translation id="7690378713476594306">ಪಟ್ಟಿಯಿಂದ ಆರಿಸಿ</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index b781f8ae..6c9b996 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">네트워크 없음</translation>
 <translation id="1056898198331236512">경고</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play 스토어 앱</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" />에 민감한 콘텐츠가 포함되어 있어 차단되었습니다.</translation>
 <translation id="1061904396131502319">곧 휴식 시간입니다</translation>
 <translation id="1067048845568873861">생성됨</translation>
@@ -132,7 +131,7 @@
 <translation id="117445914942805388">동기화된 모든 기기 및 Google 계정에서 인터넷 사용 기록을 삭제하려면 <ph name="BEGIN_LINK" />동기화 설정을 방문<ph name="END_LINK" />하세요.</translation>
 <translation id="1175364870820465910">인쇄(&amp;P)</translation>
 <translation id="1177138678118607465">검색, 광고 및 다른 Google 서비스를 맞춤설정하기 위하여 Google에서 인터넷 사용 기록을 사용할 수 있습니다. 이 설정은 언제든지 myaccount.google.com/activitycontrols/search에서 변경할 수 있습니다.</translation>
-<translation id="1177863135347784049">맞춤</translation>
+<translation id="1177863135347784049">맞춤설정</translation>
 <translation id="1178581264944972037">일시중지</translation>
 <translation id="117916940443676133">보안 키가 PIN으로 보호되어 있지 않습니다. 로그인 데이터를 관리하려면 PIN을 만드세요.</translation>
 <translation id="1181037720776840403">삭제</translation>
@@ -313,7 +312,7 @@
 <translation id="1431188203598586230">마지막 소프트웨어 업데이트</translation>
 <translation id="1432581352905426595">검색엔진 관리</translation>
 <translation id="1433811987160647649">액세스하기 전에 확인</translation>
-<translation id="1434696352799406980">시작 페이지, 새 탭 페이지, 검색엔진, 고정 탭이 재설정됩니다. 또한 모든 확장 프로그램이 사용 중지되고 쿠키와 같은 임시 데이터가 삭제됩니다. 북마크, 기록, 저장된 비밀번호는 삭제되지 않습니다.</translation>
+<translation id="1434696352799406980">시작 페이지, 새 탭 페이지, 검색엔진, 고정 탭이 초기화됩니다. 또한 모든 확장 프로그램이 사용 중지되고 쿠키와 같은 임시 데이터가 삭제됩니다. 북마크, 기록, 저장된 비밀번호는 삭제되지 않습니다.</translation>
 <translation id="1434886155212424586">홈페이지가 새 탭 페이지입니다.</translation>
 <translation id="1436390408194692385"><ph name="TICKET_TIME_LEFT" />동안 유효</translation>
 <translation id="1436671784520050284">설정 계속하기</translation>
@@ -379,7 +378,7 @@
 <translation id="1515909359182093592"><ph name="INPUT_LABEL" /> - 호스트</translation>
 <translation id="1521442365706402292">인증서 관리</translation>
 <translation id="1521774566618522728">오늘 사용</translation>
-<translation id="152234381334907219">저장되지 않음</translation>
+<translation id="152234381334907219">저장하지 않음</translation>
 <translation id="1524430321211440688">키보드</translation>
 <translation id="1524563461097350801">아니요</translation>
 <translation id="1525740877599838384">위치 파악에 Wi-Fi만 사용</translation>
@@ -586,7 +585,7 @@
 <translation id="1799071797295057738">'<ph name="EXTENSION_NAME" />' 확장 프로그램 자동으로 사용 중지되었습니다.</translation>
 <translation id="1802624026913571222">커버를 닫으면 절전 모드 진입</translation>
 <translation id="1802687198411089702">페이지가 응답하지 않습니다. 페이지가 응답할 때까지 기다리거나 종료할 수 있습니다.</translation>
-<translation id="1802931390041703523">이 페이지에서 플래시가 차단되었습니다</translation>
+<translation id="1802931390041703523">이 페이지에서 Flash가 차단되었습니다</translation>
 <translation id="1803531841600994172">번역 타겟 언어</translation>
 <translation id="1803545009660609783">재교육</translation>
 <translation id="1805472176602625930">보안 키의 버튼을 누르세요.</translation>
@@ -812,7 +811,7 @@
 <translation id="2138398485845393913"><ph name="DEVICE_NAME" />에 연결 중입니다.</translation>
 <translation id="2139545522194199494">네트워크 <ph name="NETWORK_INDEX" />/<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, 신호 강도 <ph name="SIGNAL_STRENGTH" />%, 관리자가 관리함, 연결</translation>
 <translation id="2139919072249842737">설정 버튼</translation>
-<translation id="214169863967063661">표시 설정 열기</translation>
+<translation id="214169863967063661">모양 설정 열기</translation>
 <translation id="2142328300403846845">다음으로 링크 열기</translation>
 <translation id="2143765403545170146">전체화면에서 툴바 항상 표시</translation>
 <translation id="2143778271340628265">수동 프록시 설정</translation>
@@ -1365,7 +1364,7 @@
 <translation id="2874939134665556319">이전 트랙</translation>
 <translation id="2875698561019555027">(Chrome 오류 페이지)</translation>
 <translation id="2876336351874743617">손가락 2</translation>
-<translation id="2876369937070532032">보안상의 위험이 있을 때 일부 방문 페이지의 URL을 Google로 전송함</translation>
+<translation id="2876369937070532032">보안상의 위험이 있을 때 일부 방문 페이지의 URL을 Google로 전송합니다.</translation>
 <translation id="2878782256107578644">검사가 진행 중입니다. 지금 여시겠습니까?</translation>
 <translation id="288042212351694283">Universal 2nd Factor 기기에 액세스</translation>
 <translation id="2881076733170862447">확장 프로그램을 클릭할 경우</translation>
@@ -1402,7 +1401,7 @@
 <translation id="2921081876747860777">비밀번호를 만들어 로컬 데이터 보호</translation>
 <translation id="2923234477033317484">계정 삭제</translation>
 <translation id="2926085873880284723">기본 바로가기 복원</translation>
-<translation id="2927017729816812676">캐시 저장 공간</translation>
+<translation id="2927017729816812676">캐시 저장공간</translation>
 <translation id="2931157624143513983">인쇄 가능 영역에 맞춤</translation>
 <translation id="2932085390869194046">비밀번호 추천...</translation>
 <translation id="2932330436172705843"><ph name="PROFILE_DISPLAY_NAME" />(어린이용 계정)</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">페이지가 번역됨</translation>
 <translation id="3177909033752230686">페이지 언어:</translation>
 <translation id="3179982752812949580">텍스트 글꼴</translation>
+<translation id="3181825792072797598">동기화 사용 설정</translation>
 <translation id="3181954750937456830">세이프 브라우징(사용자와 사용자의 기기를 위험한 사이트로부터 보호)</translation>
 <translation id="3182749001423093222">맞춤법 검사</translation>
 <translation id="3183139917765991655">프로필 가져오기 도구</translation>
@@ -1736,7 +1736,7 @@
 <translation id="3439970425423980614">미리보기에서 PDF 여는 중</translation>
 <translation id="3440663250074896476"><ph name="BOOKMARK_NAME" />의 작업 메뉴 더보기</translation>
 <translation id="3440761377721825626">사이트에서 플러그인을 사용하여 내 컴퓨터에 액세스하려고 할 때 확인</translation>
-<translation id="3441653493275994384">차단</translation>
+<translation id="3441653493275994384">화면</translation>
 <translation id="3445925074670675829">USB-C 기기</translation>
 <translation id="344630545793878684">다수의 웹사이트에서 데이터 읽기</translation>
 <translation id="3448492834076427715">계정 업데이트</translation>
@@ -1965,7 +1965,7 @@
 <translation id="3737536731758327622">다운로드 항목이 여기에 표시됩니다.</translation>
 <translation id="3738924763801731196"><ph name="OID" />:</translation>
 <translation id="3739254215541673094"><ph name="APPLICATION" />을(를) 여시겠습니까?</translation>
-<translation id="3742055079367172538">찍은 캡처화면</translation>
+<translation id="3742055079367172538">찍은 스크린샷</translation>
 <translation id="3742666961763734085">해당 이름의 조직 단위를 찾을 수 없습니다. 다시 시도해 보세요.</translation>
 <translation id="3744111561329211289">백그라운드 동기화</translation>
 <translation id="3748026146096797577">연결되어 있지 않음</translation>
@@ -2256,7 +2256,7 @@
 <translation id="4124823734405044952">보안 키가 재설정되었습니다.</translation>
 <translation id="4124935795427217608">유니콘</translation>
 <translation id="412730574613779332">스판덱스</translation>
-<translation id="412940972494182898">이번에만 플래시 실행</translation>
+<translation id="412940972494182898">이번에만 Flash 실행</translation>
 <translation id="4130199216115862831">기기 로그</translation>
 <translation id="4130207949184424187">검색주소창에서 검색하면 표시되는 페이지가 이 확장 프로그램으로 인해 변경되었습니다.</translation>
 <translation id="4130750466177569591">동의함</translation>
@@ -2288,7 +2288,7 @@
 <translation id="4181602000363099176">20배</translation>
 <translation id="4181841719683918333">언어</translation>
 <translation id="4184885522552335684">디스플레이를 이동하려면 드래그하세요.</translation>
-<translation id="4194570336751258953">두드려서 클릭</translation>
+<translation id="4194570336751258953">탭하여 클릭 사용</translation>
 <translation id="4194595472342532425">구성 문제로 인해 Plugin VM을 설정할 수 없습니다. 조직의 기기 관리자에게 문의하세요. 오류 코드: <ph name="ERROR_CODE" />.</translation>
 <translation id="4195643157523330669">새 탭에서 열기</translation>
 <translation id="4195814663415092787">중단한 위치에서 계속하기</translation>
@@ -2323,7 +2323,7 @@
 <translation id="4249248555939881673">네트워크 연결 대기 중...</translation>
 <translation id="4249373718504745892">카메라와 마이크 액세스가 차단된 페이지입니다.</translation>
 <translation id="424963718355121712">앱은 영향을 미치는 호스트에서 제공되어야 합니다</translation>
-<translation id="4250229828105606438">캡처화면</translation>
+<translation id="4250229828105606438">스크린샷</translation>
 <translation id="4250680216510889253">아니요</translation>
 <translation id="4252852543720145436">보호된 콘텐츠 식별자</translation>
 <translation id="4252899949534773101">블루투스가 사용 중지됨</translation>
@@ -2342,7 +2342,7 @@
 <translation id="4275663329226226506">미디어</translation>
 <translation id="4275830172053184480">기기 다시 시작</translation>
 <translation id="4278101229438943600">어시스턴트 이용 가능</translation>
-<translation id="4278390842282768270">허용됨</translation>
+<translation id="4278390842282768270">허용</translation>
 <translation id="4281844954008187215">서비스 약관</translation>
 <translation id="4282196459431406533">Smart Lock이 사용 설정됨</translation>
 <translation id="4285418559658561636">비밀번호 업데이트</translation>
@@ -2493,7 +2493,7 @@
 <translation id="4522600456902129422">이 사이트에서 클립보드를 볼 수 있도록 계속 허용</translation>
 <translation id="4524832533047962394">제공된 등록 모드는 이 버전의 운영체제에서 지원되지 않습니다. 최신 버전을 실행하고 있는지 확인하세요.</translation>
 <translation id="4525382759303819021">Play 스토어 앱에서 최신 업데이트 및 추천받기</translation>
-<translation id="4530494379350999373">오리진</translation>
+<translation id="4530494379350999373">출처</translation>
 <translation id="4532646538815530781">사이트에서 움직임 감지 센서를 사용하고 있습니다.</translation>
 <translation id="4533846798469727141">이제 "Hey Google"이라고 말하세요.</translation>
 <translation id="4533985347672295764">CPU 시간</translation>
@@ -2609,7 +2609,7 @@
 <translation id="4694024090038830733">프린터 구성은 관리자가 처리합니다.</translation>
 <translation id="4694604912444486114">원숭이</translation>
 <translation id="4697551882387947560">탐색 세션이 종료될 때</translation>
-<translation id="4699172675775169585">캐시된 이미지 또는 파일</translation>
+<translation id="4699172675775169585">캐시된 이미지 및 파일</translation>
 <translation id="4699357559218762027">(자동 실행)</translation>
 <translation id="470074695271471509">로그아웃하여 완료하시겠습니까?</translation>
 <translation id="4707302005824653064">chrome.com 페이지에서 관리자(<ph name="CUSTODIAN_EMAIL" />)가 이용 및 방문 기록을 조회할 수 있습니다.</translation>
@@ -2808,7 +2808,7 @@
 <translation id="4992066212339426712">음소거 해제</translation>
 <translation id="4992458225095111526">Powerwash 확인</translation>
 <translation id="4992473555164495036">관리자가 사용 가능한 입력 방법을 제한했습니다.</translation>
-<translation id="4994474651455208930">사이트에서 프로토콜에 대한 기본 핸들러가 될지 여부를 묻도록 허용</translation>
+<translation id="4994474651455208930">사이트에서 프로토콜 기본 핸들러로 사용할지 여부를 묻도록 허용</translation>
 <translation id="4994754230098574403">설정 중입니다.</translation>
 <translation id="4996978546172906250">공유 방법</translation>
 <translation id="4997086284911172121">인터넷에 연결되지 않았습니다.</translation>
@@ -2912,7 +2912,7 @@
 <translation id="5151354047782775295">디스크 저장 공간을 확보하지 않으면 일부 데이터가 자동으로 삭제됩니다.</translation>
 <translation id="5153234146675181447">휴대전화 지우기</translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" /> 고급 설정</translation>
-<translation id="5154702632169343078">제목</translation>
+<translation id="5154702632169343078">대상</translation>
 <translation id="5157635116769074044">이 페이지를 시작 화면에 고정...</translation>
 <translation id="5158983316805876233">모든 프로토콜에 같은 프록시 사용</translation>
 <translation id="5160857336552977725"><ph name="DEVICE_TYPE" />에 로그인</translation>
@@ -3120,7 +3120,7 @@
 <translation id="5464660706533281090">이 설정은 자녀 사용자가 변경할 수 없습니다.</translation>
 <translation id="5466374726908360271">'<ph name="SEARCH_TERMS" />' 붙여넣기 및 검색(&amp;S)</translation>
 <translation id="5468173180030470402">파일 공유 찾는 중</translation>
-<translation id="5470735824776589490">기기를 파워워시로 초기화하기 전에 다시 시작해야 합니다. <ph name="LINK_BEGIN" />자세히 알아보기<ph name="LINK_END" /></translation>
+<translation id="5470735824776589490">기기를 파워워시로 재설정하기 전에 다시 시작해야 합니다. <ph name="LINK_BEGIN" />자세히 알아보기<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">안녕하세요. 텍스트 음성 변환의 음성입니다.</translation>
 <translation id="5472133193607270166">사용 설정하면 사이트에서 사용자의 타 사이트 탐색 활동 정보를 이용해 광고를 맞춤설정할 수 없습니다. 일부 사이트는 제대로 작동하지 않을 수 있습니다.</translation>
 <translation id="5473333559083690127">새 PIN 다시 입력</translation>
@@ -3274,7 +3274,7 @@
 <translation id="5671658447180261823"><ph name="SUGGESTION_NAME" /> 추천 검색어를 삭제합니다.</translation>
 <translation id="567643736130151854">로그인 후 동기화를 사용 설정하여 모든 기기에서 내 북마크, 비밀번호 등을 사용하세요.</translation>
 <translation id="5677503058916217575">페이지 언어:</translation>
-<translation id="5677928146339483299">차단됨</translation>
+<translation id="5677928146339483299">차단</translation>
 <translation id="5678293144564424498">앱이 일시중지됨</translation>
 <translation id="5678550637669481956"><ph name="VOLUME_NAME" />에 대한 읽기/쓰기 액세스 권한이 부여되었습니다.</translation>
 <translation id="5678955352098267522"><ph name="WEBSITE_1" />에서 데이터 읽기</translation>
@@ -3601,7 +3601,7 @@
 <translation id="6125479973208104919">이 <ph name="DEVICE_TYPE" />에 계정을 다시 추가해야 합니다.</translation>
 <translation id="6129691635767514872">선택한 데이터가 Chrome 및 동기화된 기기에서 삭제되었습니다. <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />에서 검색이나 기타 Google 서비스에서의 활동 등 내 Google 계정에 있는 다른 형식의 탐색 기록을 확인할 수 있습니다.</translation>
 <translation id="6129938384427316298">Netscape Certificate Comment</translation>
-<translation id="6129953537138746214">공백</translation>
+<translation id="6129953537138746214">Space</translation>
 <translation id="6136114942382973861">다운로드바 닫기</translation>
 <translation id="6137767437444130246">사용자 인증서</translation>
 <translation id="6138680304137685902">SHA-384를 포함한 X9.62 ECDSA 서명</translation>
@@ -3844,7 +3844,7 @@
 <translation id="648927581764831596">사용할 수 없음</translation>
 <translation id="6490471652906364588">USB-C 기기(오른쪽 포트)</translation>
 <translation id="6491376743066338510">승인에 실패했습니다.</translation>
-<translation id="6492313032770352219">디스크 크기:</translation>
+<translation id="6492313032770352219">디스크에서 차지하는 용량:</translation>
 <translation id="6494445798847293442">인증 기관이 아닙니다.</translation>
 <translation id="649454645705377674">닫기</translation>
 <translation id="6495925982925244349">네트워크 <ph name="NETWORK_INDEX" />/<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, 신호 강도 <ph name="SIGNAL_STRENGTH" />%, 관리자가 관리함, 세부정보</translation>
@@ -3961,7 +3961,7 @@
 <translation id="6676212663108450937">음성을 학습시킬 때 헤드폰 사용을 고려해 보세요.</translation>
 <translation id="6678717876183468697">쿼리 URL</translation>
 <translation id="6680442031740878064">사용 가능한 저장용량: <ph name="AVAILABLE_SPACE" /></translation>
-<translation id="6680650203439190394">평가</translation>
+<translation id="6680650203439190394">속도</translation>
 <translation id="6681668084120808868">사진 찍기</translation>
 <translation id="6681964764822470072">'<ph name="APP_NAME" />'이(가) 제거됩니다.</translation>
 <translation id="668599234725812620">Google Play 열기</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">앱을 만들고 테스트하려면 Android 디버그 브리지(ADB)를 사용 설정하세요. 이렇게 하면 Google에서 확인하지 않은 Android 앱을 설치할 수 있게 되며, 사용 중지하려면 초기화가 필요합니다.</translation>
 <translation id="7685049629764448582">자바스크립트 메모리</translation>
 <translation id="7685087414635069102">PIN 필요</translation>
+<translation id="768549422429443215">언어 추가 또는 목록 재정렬</translation>
 <translation id="7686938547853266130"><ph name="DEVICE_PATH" /> <ph name="FRIENDLY_NAME" /></translation>
 <translation id="7690294790491645610">새 비밀번호 확인</translation>
 <translation id="7690378713476594306">목록에서 선택</translation>
@@ -4691,7 +4692,7 @@
 <translation id="7744047395460924128">인쇄 기록 보기</translation>
 <translation id="7746457520633464754">Chrome은 위험한 앱 및 사이트를 감지하기 위해 일부 방문 페이지의 URL, 제한적인 시스템 정보, 페이지 콘텐츠 일부를 Google로 전송합니다.</translation>
 <translation id="7750228210027921155">PIP 모드</translation>
-<translation id="7751260505918304024">전체 보기</translation>
+<translation id="7751260505918304024">모두 표시</translation>
 <translation id="7754704193130578113">다운로드 전에 각 파일의 저장 위치 확인</translation>
 <translation id="7755287808199759310">부모님이 차단 해제할 수 있습니다.</translation>
 <translation id="7757787379047923882"><ph name="DEVICE_NAME" />에서 공유된 텍스트</translation>
@@ -4777,7 +4778,7 @@
 <translation id="7831491651892296503">네트워크를 설정하는 중에 오류가 발생했습니다</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
 <translation id="7832084384634357321">종료 시간</translation>
-<translation id="783214144752121388">사이트의 플래시 실행 차단(권장)</translation>
+<translation id="783214144752121388">사이트의 Flash 실행 차단(권장)</translation>
 <translation id="7833720883933317473">저장한 맞춤 단어가 여기에 표시됩니다.</translation>
 <translation id="7835178595033117206">북마크가 삭제됨</translation>
 <translation id="7837776265184002579">홈페이지가 <ph name="URL" />(으)로 변경되었습니다.</translation>
@@ -4835,7 +4836,7 @@
 <translation id="7911118814695487383">Linux</translation>
 <translation id="7912080627461681647">서버에서 비밀번호가 변경되었습니다. 로그아웃한 다음 다시 로그인해 주세요.</translation>
 <translation id="7915457674565721553">자녀 보호 기능을 설정하려면 인터넷에 연결하세요.</translation>
-<translation id="7915471803647590281">의견을 보내기 전에 현재 상황을 입력해 주세요.</translation>
+<translation id="7915471803647590281">의견을 보내기 전에 어떤 문제인지 알려주세요.</translation>
 <translation id="7918257978052780342">등록</translation>
 <translation id="7919210519031517829"><ph name="DURATION" />초</translation>
 <translation id="792514962475806987">고정 돋보기 확대/축소 수준:</translation>
@@ -5041,7 +5042,7 @@
 <translation id="8188389033983459049">계속하려면 기기 설정을 확인하고 사용 설정하세요.</translation>
 <translation id="8190193592390505034"><ph name="PROVIDER_NAME" />에 연결 중</translation>
 <translation id="8191230140820435481">앱, 확장 프로그램 및 테마 관리</translation>
-<translation id="8195027750202970175">디스크 크기</translation>
+<translation id="8195027750202970175">디스크에서 차지하는 용량</translation>
 <translation id="8198323535106903877">앱 <ph name="NUMBER_OF_APPS" />개는 자동으로 설치됩니다</translation>
 <translation id="8199300056570174101">네트워크(서비스) 및 기기 속성</translation>
 <translation id="8200772114523450471">다시 시작</translation>
@@ -5441,7 +5442,7 @@
 <translation id="8756969031206844760">비밀번호를 업데이트하시겠습니까?</translation>
 <translation id="8757090071857742562">데스크톱을 전송할 수 없습니다. 화면 공유 시작 메시지를 확인했는지 알아보세요.</translation>
 <translation id="8757803915342932642">Google 클라우드 기기에서 사용하는 기기</translation>
-<translation id="8758418656925882523">받아쓰기 사용(말하여 입력)</translation>
+<translation id="8758418656925882523">음성기록 사용(말하여 입력)</translation>
 <translation id="8759408218731716181">멀티 로그인을 설정할 수 없음</translation>
 <translation id="8759753423332885148">자세히 알아보기</translation>
 <translation id="8761945298804995673">이미 존재하는 사용자입니다.</translation>
@@ -5607,7 +5608,7 @@
 <translation id="897414447285476047">연결 문제로 인해 대상 파일 다운로드를 완료하지 못했습니다.</translation>
 <translation id="897525204902889653">격리 서비스</translation>
 <translation id="8975562453115131273">{NUM_OTHER_TABS,plural, =0{‘<ph name="TAB_TITLE" />’}=1{‘<ph name="TAB_TITLE" />’ 외 탭 1개}other{‘<ph name="TAB_TITLE" />’ 외 탭 #개}}</translation>
-<translation id="8976520271376534479">이 페이지에서 플래시가 차단되었습니다.</translation>
+<translation id="8976520271376534479">이 페이지에서 Flash가 차단되었습니다.</translation>
 <translation id="8977811652087512276">잘못된 비밀번호이거나 손상된 파일입니다.</translation>
 <translation id="8978154919215542464">사용 - 모든 항목 동기화</translation>
 <translation id="897939795688207351"><ph name="ORIGIN" />에서</translation>
@@ -5673,7 +5674,7 @@
 <translation id="9064142312330104323">Google 프로필 사진(로드 중)</translation>
 <translation id="9064275926664971810">클릭 한 번으로 양식을 작성하는 자동 완성 사용</translation>
 <translation id="9065203028668620118">수정</translation>
-<translation id="9066773882585798925">소리 내어 읽은 텍스트 듣기</translation>
+<translation id="9066773882585798925">텍스트 소리 내어 읽기</translation>
 <translation id="9066782832737749352">텍스트 음성 변환</translation>
 <translation id="9067559831321817373">로그인된 계정을 관리합니다. 웹사이트, 앱, Chrome 확장 프로그램 및 Google Play에서 권한에 따라 이 계정을 사용하여 사용 환경을 맞춤설정할 수 있습니다. &lt;a&gt;자세히 알아보기&lt;/a&gt;</translation>
 <translation id="9068849894565669697">색상 선택</translation>
@@ -5775,7 +5776,7 @@
 <translation id="93766956588638423">확장 프로그램 복구</translation>
 <translation id="938339467127511841">Linux(베타) 저장용량</translation>
 <translation id="938470336146445890">사용자 인증서를 설치하세요.</translation>
-<translation id="939252827960237676">캡처화면을 저장하지 못했습니다.</translation>
+<translation id="939252827960237676">스크린샷을 저장할 수 없습니다.</translation>
 <translation id="939519157834106403">SSID</translation>
 <translation id="939598580284253335">암호 입력</translation>
 <translation id="939736085109172342">새 폴더</translation>
diff --git a/chrome/app/resources/generated_resources_ky.xtb b/chrome/app/resources/generated_resources_ky.xtb
index 7c01e91a..f713336a 100644
--- a/chrome/app/resources/generated_resources_ky.xtb
+++ b/chrome/app/resources/generated_resources_ky.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Тармактар жок</translation>
 <translation id="1056898198331236512">Эскертүү</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store колдонмолору</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> файлында купуя маалымат камтылгандыктан, ал бөгөттөлдү.</translation>
 <translation id="1061904396131502319">Тыныгууга убакыт келип калды</translation>
 <translation id="1067048845568873861">Түзүлгөн</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Бул барак которулду</translation>
 <translation id="3177909033752230686">Баракчанын тили:</translation>
 <translation id="3179982752812949580">Тексттин ариби</translation>
+<translation id="3181825792072797598">Шайкештирүүнү күйгүзүү</translation>
 <translation id="3181954750937456830">Коопсуз серептөө (сизди жана түзмөгүңүздү кооптуу сайттардан коргойт)</translation>
 <translation id="3182749001423093222">Орфографиялык текшерүү</translation>
 <translation id="3183139917765991655">Профиль импорттогуч</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Колдонмолорду түзүп, сыноо үчүн Android Debug Bridge (ADB) куралын иштетиңиз. Бул аракет Google тарабынан текшерилбеген Android колдонмолорун орнотууга уруксат берет. Аларды өчүрүү үчүн түзмөктү баштапкы абалга кайтаруу керек болот.</translation>
 <translation id="7685049629764448582">JavaScript эстутуму</translation>
 <translation id="7685087414635069102">PIN код талап кылынат</translation>
+<translation id="768549422429443215">Тилдерди кошуңуз же тизмени иреттеңиз.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Жаңы сырсөздү ырастаңыз</translation>
 <translation id="7690378713476594306">Тизмеден тандаңыз</translation>
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb
index 3280595..2e639b34 100644
--- a/chrome/app/resources/generated_resources_lo.xtb
+++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ບໍ່ມີເຄືອຂ່າຍ</translation>
 <translation id="1056898198331236512">ຄໍາເຕືອນ</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">ແອັບ Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> ປະກອບມີເນື້ອຫາທີ່ອ່ອນໄຫວ ແລະ ໄດ້ຖືກບລັອກໄວ້ແລ້ວ.</translation>
 <translation id="1061904396131502319">ໃກ້ຮອດເວລາພັກແລ້ວ</translation>
 <translation id="1067048845568873861">ສ້າງຂຶ້ນແລ້ວ</translation>
@@ -1567,6 +1566,7 @@
 <translation id="3172808215939929606">ໄດ້ແປໜ້ານີ້ແລ້ວ</translation>
 <translation id="3177909033752230686">ພາ​ສາຂອງໜ້າເວັບ:</translation>
 <translation id="3179982752812949580">ຟອນຂໍ້ຄວາມ</translation>
+<translation id="3181825792072797598">ເປີດ Sync</translation>
 <translation id="3181954750937456830">Safe Browsing (ປົກປ້ອງທ່ານ ແລະ ອຸປະກອນຂອງທ່ານຈາກເວັບໄຊອັນຕະລາຍ)</translation>
 <translation id="3182749001423093222">ກວດການສະກົດຄຳ</translation>
 <translation id="3183139917765991655">ຕົວ​ນຳ​ເຂົ້າ​ໂປ​ຣ​ໄຟ​ລ໌</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">ເພື່ອສ້າງ ແລະ ທົດສອບແອັບຂອງທ່ານ, ກະລຸນາເປີດນຳໃຊ້ຂົວຕໍ່ແກ້ໄຂບັນຫາ Android (ADB). ກະລຸນາຮັບຊາບວ່າການດຳເນີນການນີ້ອະນຸຍາດການຕິດຕັ້ງແອັບ Android ທີ່ບໍ່ໄດ້ຜ່ານການກວດຢັ້ງຢືນຈາກ Google ແລະ ຈຳເປັນຕ້ອງຣີເຊັດເປັນຄ່າໂຮງງານເພື່ອປິດນຳໃຊ້.</translation>
 <translation id="7685049629764448582">ຄວາມ​ຈໍາ JavaScript</translation>
 <translation id="7685087414635069102">ຈໍາເປັນຕ້ອງມີ PIN</translation>
+<translation id="768549422429443215">ເພີ່ມພາສາ ຫຼື ຈັດລຳດັບລາຍການໃໝ່.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ຢືນຢັນລະຫັດຜ່ານໃໝ່</translation>
 <translation id="7690378713476594306">ເລືອກຈາກລາຍການ</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index 1b1c275..da47551 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nėra tinklų</translation>
 <translation id="1056898198331236512">Įspėjimas</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">„Play“ parduotuvės programos</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> yra neskelbtino turinio ir failas buvo užblokuotas.</translation>
 <translation id="1061904396131502319">Beveik atėjo laikas padaryti pertrauką</translation>
 <translation id="1067048845568873861">Sukurtas</translation>
@@ -244,7 +243,7 @@
 <translation id="1329584516321524826">Ką tik atnaujinta</translation>
 <translation id="1330145147221172764">Įgalinti ekrano klaviatūrą</translation>
 <translation id="1331977651797684645">Tai buvau aš.</translation>
-<translation id="1333489022424033687">Kai kurios svetainės <ph name="ORIGIN" /> funkcijos gali neveikti, kol neišvalysite duomenų, kuriuos kitos svetainės išsaugojo jūsų įrenginyje</translation>
+<translation id="1333489022424033687">Kai kurios svetainės <ph name="ORIGIN" /> funkcijos gali neveikti, iki kol išvalysite duomenis, kuriuos kitos svetainės išsaugojo jūsų įrenginyje</translation>
 <translation id="133535873114485416">Pageidaujama įvestis</translation>
 <translation id="1335929031622236846">Įrenginio registracija</translation>
 <translation id="1338802252451106843"><ph name="ORIGIN" /> nori atidaryti šią programą.</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Šis puslapis išverstas</translation>
 <translation id="3177909033752230686">Puslapio kalba:</translation>
 <translation id="3179982752812949580">Teksto šriftas</translation>
+<translation id="3181825792072797598">Įjungti sinchronizavimą</translation>
 <translation id="3181954750937456830">Saugus naršymas (apsaugo jus ir jūsų įrenginį nuo pavojingų svetainių)</translation>
 <translation id="3182749001423093222">Rašybos tikrinimas</translation>
 <translation id="3183139917765991655">Profilio importavimo priemonė</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Kad galėtumėte kurti ir testuoti programas, įgalinkite „Android“ derinimo tiltą (ADB). Atminkite, kad atlikus šį veiksmą bus leidžiama įdiegti „Android“ programas, kurios nebuvo patvirtintos „Google“, o norint išjungti ADB, reikės atkurti gamyklinius nustatymus.</translation>
 <translation id="7685049629764448582">„JavaScript“ atmintis</translation>
 <translation id="7685087414635069102">Reikia PIN kodo</translation>
+<translation id="768549422429443215">Pridėkite kalbų arba pertvarkykite sąrašą.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Patvirtinkite naują slaptažodį</translation>
 <translation id="7690378713476594306">Pasirinkti iš sąrašo</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb
index 4d0d01e..84724fa 100644
--- a/chrome/app/resources/generated_resources_lv.xtb
+++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nav tīklu</translation>
 <translation id="1056898198331236512">Brīdinājums</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play veikala lietotnes</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> ietver sensitīvu saturu un tika bloķēts.</translation>
 <translation id="1061904396131502319">Tūlīt būs pārtraukums</translation>
 <translation id="1067048845568873861">Izveidots</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Šī lapa ir pārtulkota</translation>
 <translation id="3177909033752230686">Lapas valoda:</translation>
 <translation id="3179982752812949580">Teksta fonts</translation>
+<translation id="3181825792072797598">Ieslēgt sinhronizāciju</translation>
 <translation id="3181954750937456830">Droša pārlūkošana (aizsargā jūs un ierīci pret bīstamām vietnēm)</translation>
 <translation id="3182749001423093222">Pareizrakstības pārbaude</translation>
 <translation id="3183139917765991655">Profilu importētājs</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Lai veidotu un testētu lietotnes, iespējojiet Android atkļūdošanas tiltu (ADB). Ņemiet vērā, ka šī darbība ļauj instalēt Android lietotnes, ko uzņēmums Google nav verificējis, un rīka atspējošanai ir nepieciešams atjaunot rūpnīcas iestatījumus.</translation>
 <translation id="7685049629764448582">JavaScript atmiņa</translation>
 <translation id="7685087414635069102">Jāievada PIN</translation>
+<translation id="768549422429443215">Pievienojiet valodas vai pārkārtojiet sarakstu.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Apstipriniet jauno paroli</translation>
 <translation id="7690378713476594306">Izvēlēties no saraksta</translation>
diff --git a/chrome/app/resources/generated_resources_mk.xtb b/chrome/app/resources/generated_resources_mk.xtb
index dad4e49..02128c77 100644
--- a/chrome/app/resources/generated_resources_mk.xtb
+++ b/chrome/app/resources/generated_resources_mk.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Нема мрежи</translation>
 <translation id="1056898198331236512">Предупредување</translation>
 <translation id="1058262162121953039">Личен код за деблокирање (PUK)</translation>
-<translation id="1060881073479695738">Апликации од Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> содржи чувствителни содржини и е блокирана.</translation>
 <translation id="1061904396131502319">Речиси е време за пауза</translation>
 <translation id="1067048845568873861">Создадено</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Страницава е преведена</translation>
 <translation id="3177909033752230686">Јазик на страницата:</translation>
 <translation id="3179982752812949580">Фонт на текстот</translation>
+<translation id="3181825792072797598">Вклучи синхронизација</translation>
 <translation id="3181954750937456830">Безбедно прелистување (ве заштитува вас и вашиот уред од опасни сајтови)</translation>
 <translation id="3182749001423093222">Проверка на правопис</translation>
 <translation id="3183139917765991655">Увозник на профил</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">За создавање и тестирање на вашите апликации, овозможете ја Android Debug Bridge (ADB). Имајте предвид дека дејствово овозможува инсталирање апликации за Android што не се потврдени од Google, а за оневозможувањето е потребно фабричко ресетирање.</translation>
 <translation id="7685049629764448582">Меморија на JavaScript</translation>
 <translation id="7685087414635069102">Потребен е PIN</translation>
+<translation id="768549422429443215">Додајте јазици или прередете го списокот.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Потврдете ја новата лозинка</translation>
 <translation id="7690378713476594306">Изберете од списокот</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index 4db447c..8479ef5a 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">നെറ്റ്‌വർക്കുകളൊന്നും ഇല്ല</translation>
 <translation id="1056898198331236512">മുന്നറിയിപ്പ്</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play സ്‌റ്റോർ ആപ്പുകൾ</translation>
 <translation id="1061745542578250838">സൂക്ഷ്മമായി കൈകാര്യം ചെയ്യേണ്ട ഉള്ളടക്കം <ph name="FILE_NAME" /> എന്നതിൽ അടങ്ങിയിരിക്കുന്നതിനാൽ അത് ബ്ലോക്ക് ചെയ്തു.</translation>
 <translation id="1061904396131502319">ഇടവേളയ്ക്കുള്ള സമയം ആകാറായിരിക്കുന്നു</translation>
 <translation id="1067048845568873861">സൃഷ്‌ടിച്ചു</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">ഈ പേജ് വിവർത്തനം ചെയ്‌തിരിക്കുന്നു</translation>
 <translation id="3177909033752230686">പേജ് ഭാഷ:</translation>
 <translation id="3179982752812949580">ടെക്‌സ്‌റ്റ് ഫോണ്ട്</translation>
+<translation id="3181825792072797598">സമന്വയിപ്പിക്കൽ ഓണാക്കുക</translation>
 <translation id="3181954750937456830">സുരക്ഷിത ബ്രൗസിംഗ് (അപകടകരമായ സൈറ്റുകളിൽ നിന്ന് നിങ്ങളെയും ഉപകരണത്തെയും പരിരക്ഷിക്കുന്നു)</translation>
 <translation id="3182749001423093222">അക്ഷരത്തെറ്റ് പരിശോധന</translation>
 <translation id="3183139917765991655">പ്രൊഫൈൽ ഇംപോർട്ടർ</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">ആപ്പുകൾ സൃഷ്ടിക്കാനും പരിശോധിക്കാനും, Android ഡീബഗ് ബ്രിഡ്ജ് (ADB) പ്രവർത്തനക്ഷമമാക്കുക. Google പരിശോധിച്ചുറപ്പിച്ചിട്ടില്ലാത്ത Android ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ ഈ പ്രവൃത്തി അനുവദിക്കുമെന്നതും ഇത് പ്രവർത്തനരഹിതമാക്കാൻ ഫാക്ടറി റീസെറ്റ് ചെയ്യേണ്ടി വരുമെന്നതും ശ്രദ്ധിക്കുക.</translation>
 <translation id="7685049629764448582">JavaScript മെമ്മറി</translation>
 <translation id="7685087414635069102">പിൻ ആവശ്യമാണ്</translation>
+<translation id="768549422429443215">ഭാഷകളോ പുനഃക്രമീകരണ ലിസ്‌റ്റോ ചേർക്കുക.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">പുതിയ പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക</translation>
 <translation id="7690378713476594306">ലിസ്റ്റിൽ നിന്ന് തിരഞ്ഞെടുക്കുക</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb
index 505bd898..acdc10a 100644
--- a/chrome/app/resources/generated_resources_mn.xtb
+++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Сүлжээ алга</translation>
 <translation id="1056898198331236512">Анхааруулга</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store-н апп</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> нь мэдрэг контент агуулж байгаа бөгөөд түүнийг хориглосон байна.</translation>
 <translation id="1061904396131502319">Завсарлах цаг ойртож байна</translation>
 <translation id="1067048845568873861">Үүсгэсэн</translation>
@@ -1564,6 +1563,7 @@
 <translation id="3172808215939929606">Энэ хуудсыг орчуулсан байна</translation>
 <translation id="3177909033752230686">Хуудасны хэл:</translation>
 <translation id="3179982752812949580">Текстийн фонт</translation>
+<translation id="3181825792072797598">Синкийг асаах</translation>
 <translation id="3181954750937456830">Аюулгүй хөтөч (таныг болон таны төхөөрөмжийг аюултай сайтаас хамгаалдаг)</translation>
 <translation id="3182749001423093222">Зөв бичгийн алдаа шалгах</translation>
 <translation id="3183139917765991655">Профайл импортлогч</translation>
@@ -4647,6 +4647,7 @@
 <translation id="7684718995427157417">Апликейшн үүсгэж, шалгахын тулд Android Debug Bridge (ADB)-г идэвхжүүлнэ үү. Энэ үйлдэл нь Google-н баталгаажуулаагүй Андройд аппыг суулгахыг зөвшөөрөх бөгөөд идэвхгүй болгоход үйлдвэрийн тохиргоонд шинэчлэх шаардлагатай.</translation>
 <translation id="7685049629764448582">JavaScript санах ой</translation>
 <translation id="7685087414635069102">ПИН шаардлагатай</translation>
+<translation id="768549422429443215">Хэл нэмэх эсвэл жагсаалтыг дахин эрэмбэлнэ үү.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Шинэ нууц үг баталгаажуулна уу</translation>
 <translation id="7690378713476594306">Жагсаалтаас сонгох</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 6fcc9b4..10c4bb1 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">कोणतीही नेटवर्क नाहीत</translation>
 <translation id="1056898198331236512">चेतावणी</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play स्टोअर ॲप</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> मध्ये संवेदनशील आशयाचा समावेश आहे आणि ती ब्लॉक केली गेली आहे.</translation>
 <translation id="1061904396131502319">विश्रांतीची वेळ झाली आहे</translation>
 <translation id="1067048845568873861">तयार केले</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">या पेजचे भाषांतर केले गेले आहे</translation>
 <translation id="3177909033752230686">पृष्ठ भाषा:</translation>
 <translation id="3179982752812949580">मजकुराचा फाँट</translation>
+<translation id="3181825792072797598">सिंक चालू करा</translation>
 <translation id="3181954750937456830">सुरक्षित ब्राउझिंग (तुम्हाला आणि तुमच्या डिव्हाइसना धोकादायक साइटपासून सुरक्षित ठेवते)</translation>
 <translation id="3182749001423093222">स्पेल चेक</translation>
 <translation id="3183139917765991655">प्रोफाईल आयातकर्ता</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">तुमची ॲप्स तयार करण्यासाठी आणि त्यांची चाचणी करण्यासाठी, Android डीबग ब्रिज (ADB) सुरू करा. लक्षात ठेवा की, ही क्रिया Google ने पडताळणी न केलेली Android ॲप्स इंस्टॉल करण्याची अनुमती देते आणि यासाठी फॅक्टरी रीसेट बंद करण्याची आवश्यकता आहे.</translation>
 <translation id="7685049629764448582">JavaScript मेमरी</translation>
 <translation id="7685087414635069102">पिन आवश्यक</translation>
+<translation id="768549422429443215">भाषा जोडा किंवा सूचीचा क्रम पुन्हा लावा.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">नवीन पासवर्ड कन्फर्म करा</translation>
 <translation id="7690378713476594306">सूचीतून निवडा</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index 04964f8..c93dcca 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Tiada rangkaian</translation>
 <translation id="1056898198331236512">Amaran</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Apl Gedung Play</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> mengandungi kandungan sensitif, dan telah disekat.</translation>
 <translation id="1061904396131502319">Masa rehat hampir tiba</translation>
 <translation id="1067048845568873861">Dibuat</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Halaman ini telah diterjemahkan</translation>
 <translation id="3177909033752230686">Bahasa Halaman:</translation>
 <translation id="3179982752812949580">Fon teks</translation>
+<translation id="3181825792072797598">Hidupkan Penyegerakan</translation>
 <translation id="3181954750937456830">Penyemakan Imbas Selamat (melindungi anda dan peranti anda daripada tapak yang berbahaya)</translation>
 <translation id="3182749001423093222">Semakan ejaan</translation>
 <translation id="3183139917765991655">Pengimport Profil</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Untuk membuat dan menguji apl anda, dayakan Titi Nyahpepijat Android (ADB). Harap maklum bahawa tindakan ini membolehkan pemasangan apl Android yang belum disahkan oleh Google dan memerlukan tetapan semula kilang untuk melumpuhkannya.</translation>
 <translation id="7685049629764448582">Memori JavaScript</translation>
 <translation id="7685087414635069102">PIN diperlukan</translation>
+<translation id="768549422429443215">Tambah bahasa dan susun semula senarai.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Sahkan kata laluan baharu</translation>
 <translation id="7690378713476594306">Pilih daripada senarai</translation>
diff --git a/chrome/app/resources/generated_resources_my.xtb b/chrome/app/resources/generated_resources_my.xtb
index 2c967a1..68f11a5 100644
--- a/chrome/app/resources/generated_resources_my.xtb
+++ b/chrome/app/resources/generated_resources_my.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ကွန်ရက်ချိတ်ဆက်မှု မရှိပါ</translation>
 <translation id="1056898198331236512">သတိပေးချက်</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">'Play စတိုး' အက်ပ်များ</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> တွင် အလွန်အရေးကြီးသော အကြောင်းအရာများ ပါဝင်သည့်အတွက် ပိတ်ထားသည်။</translation>
 <translation id="1061904396131502319">ခေတ္တနားချိန် ရောက်တော့မည်</translation>
 <translation id="1067048845568873861">ပြုလုပ်ပြီးပါပြီ</translation>
@@ -1570,6 +1569,7 @@
 <translation id="3172808215939929606">ဤစာမျက်နှာကို ဘာသာပြန်ပြီးပါပြီ။</translation>
 <translation id="3177909033752230686">စာမျက်နှာ ဘာသာစကား −</translation>
 <translation id="3179982752812949580">စာသားဖောင့်</translation>
+<translation id="3181825792072797598">စင့်ခ်လုပ်ခြင်းကို ဖွင့်ပါ</translation>
 <translation id="3181954750937456830">အင်တာနက်ကို လုံခြုံစွာအသုံးပြုရေးစနစ် (သင်နှင့် သင့်စက်ကို အန္တရာယ်ရှိသည့် ဝဘ်ဆိုက်များမှ ကာကွယ်သည်)</translation>
 <translation id="3182749001423093222">စာလုံးပေါင်းသတ်ပုံစစ်ခြင်း</translation>
 <translation id="3183139917765991655">Profile Importer</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">သင်၏အက်ပ်များကို ပြုလုပ်ပြီး စမ်းသပ်ရန် 'Android အမှားပြင်ဆင်မှုတံတား' (ADB) ဖွင့်ပါ။ ယခုလုပ်ဆောင်ချက်သည် Google က အတည်မပြုရသေးသော Android အက်ပ်များကို ထည့်သွင်းရန်ခွင့်ပြုပြီး ပိတ်ရန်အတွက် စက်ရုံထုတ်ဆက်တင် ပြင်ဆင်သတ်မှတ်ရန် လိုအပ်ကြောင်း သတိပြုပါ။</translation>
 <translation id="7685049629764448582">JavaScript မှတ်ဉာဏ်</translation>
 <translation id="7685087414635069102">ပင်နံပါတ် လိုအပ်သည်</translation>
+<translation id="768549422429443215">ဘာသာစကားများ ထည့်ပါ သို့မဟုတ် စာရင်းကို ပြန်စီပါ။</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">စကားဝှက်အသစ်ကို အတည်ပြုပါ</translation>
 <translation id="7690378713476594306">စာရင်းထဲမှ ရွေးရန်</translation>
diff --git a/chrome/app/resources/generated_resources_ne.xtb b/chrome/app/resources/generated_resources_ne.xtb
index 496c3078..2fd049b1 100644
--- a/chrome/app/resources/generated_resources_ne.xtb
+++ b/chrome/app/resources/generated_resources_ne.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">कुनै पनि नेटवर्क छैन</translation>
 <translation id="1056898198331236512">चेतावनी</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store का अनुप्रयोगहरू</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> मा संवेदनशील सामग्री समावेश भएकाले यसलाई रोक लगाइएको छ।</translation>
 <translation id="1061904396131502319">विश्राम लिने समय हुनै लाग्यो</translation>
 <translation id="1067048845568873861">सिर्जना गरियो</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">यस पृष्ठलाई अनुवाद गरिएको छ</translation>
 <translation id="3177909033752230686">पृष्ठको भाषा:</translation>
 <translation id="3179982752812949580">पाठको फन्ट</translation>
+<translation id="3181825792072797598">सिंकलाई सक्रिय गर्नुहोस्</translation>
 <translation id="3181954750937456830">सुरक्षित ब्राउजिङ (तपाईं र तपाईंको यन्त्रलाई खतरनाक साइटहरूबाट सुरक्षित राख्छ)</translation>
 <translation id="3182749001423093222">हिज्जे जाँच</translation>
 <translation id="3183139917765991655">प्रोफाइल आयातकर्ता</translation>
@@ -4648,6 +4648,7 @@
 <translation id="7684718995427157417">आफ्ना अनुप्रयोगहरू बनाउन तथा परीक्षण गर्न Android Debug Bridge (ADB) सक्षम पार्नुहोस्। यस कारबाहीले Google ले प्रमाणीकरण नगरेका Android अनुप्रयोगहरू स्थापना गर्ने अनुमति दिन्छ र यसलाई असक्षम पार्न फ्याक्ट्री रिसेट गर्नु पर्ने हुन्छ भन्ने कुरामा ध्यान दिनुहोस्।</translation>
 <translation id="7685049629764448582">जाभास्क्रिप्ट स्मृ</translation>
 <translation id="7685087414635069102">पिन चाहिन्छ</translation>
+<translation id="768549422429443215">भाषाहरू थप्नुहोस् वा सूचीको क्रम मिलाउनुहोस्।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">नयाँ पासवर्ड पुष्टि गर्नुहोस्</translation>
 <translation id="7690378713476594306">सूचीबाट छान्नुहोस्</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index 5cda882..13edc2d 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Geen netwerken</translation>
 <translation id="1056898198331236512">Waarschuwing</translation>
 <translation id="1058262162121953039">Pukcode</translation>
-<translation id="1060881073479695738">Play Store-apps</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> bevat gevoelige content en is geblokkeerd.</translation>
 <translation id="1061904396131502319">Bijna tijd voor pauze</translation>
 <translation id="1067048845568873861">Gemaakt</translation>
@@ -439,7 +438,7 @@
 <translation id="1604432177629086300">Kan niet afdrukken. Controleer de printer en probeer het opnieuw.</translation>
 <translation id="1605544918554600534"><ph name="PROFILE_NAME" />: wachtwoordsynchronisatie werkt niet</translation>
 <translation id="1607139524282324606">Item wissen</translation>
-<translation id="1608626060424371292">Deze gebruiker verwijderen</translation>
+<translation id="1608626060424371292">Gebruiker verwijderen</translation>
 <translation id="1608668830839595724">Meer acties voor geselecteerde items</translation>
 <translation id="1609170755653088773">Dit wachtwoord synchroniseren met je iPhone</translation>
 <translation id="161042844686301425">Cyaan</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Deze pagina is vertaald</translation>
 <translation id="3177909033752230686">Brontaal:</translation>
 <translation id="3179982752812949580">Lettertype</translation>
+<translation id="3181825792072797598">Synchronisatie inschakelen</translation>
 <translation id="3181954750937456830">Safe Browsing (hiermee worden jij en je apparaat beschermd tegen gevaarlijke sites)</translation>
 <translation id="3182749001423093222">Spellingcontrole</translation>
 <translation id="3183139917765991655">Profile Importer</translation>
@@ -1755,7 +1755,7 @@
 <translation id="3464012987031883895">Een site heeft toegang tot audio-invoer</translation>
 <translation id="346431825526753">Dit is een account voor kinderen dat wordt beheerd door <ph name="CUSTODIAN_EMAIL" />.</translation>
 <translation id="3468999815377931311">Android-telefoon</translation>
-<translation id="3470442499439619530">Deze gebruiker verwijderen</translation>
+<translation id="3470442499439619530">Gebruiker verwijderen</translation>
 <translation id="3471876058939596279">HDMI- en USB Type-C-poorten kunnen niet tegelijkertijd worden gebruikt voor video. Gebruik een andere videopoort.</translation>
 <translation id="3473479545200714844">Vergrootglas</translation>
 <translation id="3475843873335999118">Je vingerafdruk wordt nog steeds niet herkend. Geef je wachtwoord op.</translation>
@@ -1849,7 +1849,7 @@
 <translation id="3599863153486145794">Hiermee wordt de geschiedenis van alle ingelogde apparaten gewist. Er kunnen andere vormen van browsegeschiedenis zijn opgeslagen voor je Google-account op <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
 <translation id="3600051066689725006">Informatie over webverzoek</translation>
 <translation id="3600792891314830896">Sites dempen die geluid afspelen</translation>
-<translation id="360180734785106144">Nieuwe functies aanbieden zodra deze beschikbaar komen</translation>
+<translation id="360180734785106144">je nieuwe functies aan te bieden zodra deze beschikbaar komen</translation>
 <translation id="3602290021589620013">Voorbeeld</translation>
 <translation id="3603177256297531067">Deze pagina kan niet worden vertaald</translation>
 <translation id="3603622770190368340">Netwerkcertificaat verkrijgen</translation>
@@ -4250,7 +4250,7 @@
 <translation id="7088674813905715446">Dit apparaat is uit bedrijf genomen door de beheerder. Vraag je beheerder om het apparaat op 'in behandeling' in te stellen, zodat het kan worden aangemeld.</translation>
 <translation id="7092474863625458670">Met Voice Match krijg je rechtstreeks met je stem toegang tot de Assistent.
     <ph name="BR" />
-    <ph name="BEGIN_BOLD" />Houd rekening met het volgende:<ph name="END_BOLD" /> Een vergelijkbare stem of opname kan mogelijk ook toegang krijgen tot deze je Assistent. Je kunt je toestemming voor Voice Match intrekken door de functie uit te schakelen in de Instellingen voor de Assistent.</translation>
+    <ph name="BEGIN_BOLD" />Houd rekening met het volgende:<ph name="END_BOLD" /> Een vergelijkbare stem of opname kan mogelijk ook toegang krijgen tot je Assistent. Je kunt je toestemming voor Voice Match intrekken door de functie uit te schakelen in de Instellingen voor de Assistent.</translation>
 <translation id="7093434536568905704">GTK+</translation>
 <translation id="7093866338626856921">Gegevens uitwisselen met de apparaten met de naam: <ph name="HOSTNAMES" /></translation>
 <translation id="7098389117866926363">USB-C-apparaat (poort links aan de achterkant)</translation>
@@ -4495,7 +4495,7 @@
 <translation id="744341768939279100">Een nieuw profiel maken</translation>
 <translation id="7443806024147773267">Toegang tot je wachtwoorden telkens wanneer je bent ingelogd op je Google-account</translation>
 <translation id="7444983668544353857"><ph name="NETWORKDEVICE" /> uitschakelen</translation>
-<translation id="7448430327655618736">Apps automatisch installeren</translation>
+<translation id="7448430327655618736">apps automatisch te installeren</translation>
 <translation id="7450761244949417357">Wordt nu geopend in <ph name="ALTERNATIVE_BROWSER_NAME" /></translation>
 <translation id="7453008956351770337">Door het selecteren van deze printer geef je de volgende extensie toegang tot je printer:</translation>
 <translation id="7456142309650173560">dev</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Schakel Android Debug Bridge (ADB) in om je apps te maken en te testen. Let op: Met deze actie sta je toe dat Android-apps worden geïnstalleerd die niet door Google zijn geverifieerd. Als je deze functie wilt uitschakelen, moet je apparaat worden teruggezet op de fabrieksinstellingen.</translation>
 <translation id="7685049629764448582">JavaScript-geheugen</translation>
 <translation id="7685087414635069102">Pincode vereist</translation>
+<translation id="768549422429443215">Voeg talen toe of sorteer de lijst opnieuw.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Nieuw wachtwoord bevestigen</translation>
 <translation id="7690378713476594306">Selecteer een optie in de lijst</translation>
@@ -5047,7 +5048,7 @@
 <translation id="8199300056570174101">Eigenschappen van netwerk (service) en apparaat</translation>
 <translation id="8200772114523450471">Doorgaan</translation>
 <translation id="8202160505685531999">Geef je wachtwoord opnieuw op om je <ph name="DEVICE_TYPE" />-profiel te updaten.</translation>
-<translation id="8203732864715032075">Je meldingen sturen en deze computer standaard onthouden voor Berichten. <ph name="LINK_BEGIN" />Meer informatie<ph name="LINK_END" /></translation>
+<translation id="8203732864715032075">je meldingen te sturen en deze computer standaard te gebruiken voor Berichten. <ph name="LINK_BEGIN" />Meer informatie<ph name="LINK_END" /></translation>
 <translation id="820568752112382238">Meest bezochte sites</translation>
 <translation id="8206354486702514201">Deze instelling wordt door je beheerder afgedwongen.</translation>
 <translation id="8206581664590136590">Verzend gebruiks- en diagnostische gegevens. Verbeter de Android-functionaliteit voor je kind door automatisch diagnostische, apparaat- en app-gebruiksgegevens naar Google te verzenden. Deze gegevens worden niet gebruikt om je kind te identificeren en kunnen helpen om de systeem- en app-stabiliteit te verbeteren en andere optimalisaties mogelijk te maken. Daarnaast zijn bepaalde verzamelde gegevens nuttig voor Google-apps en -partners, zoals Android-ontwikkelaars. Als je de instelling voor aanvullende Web- en app-activiteit hebt ingeschakeld voor je kind, kunnen deze gegevens worden opgeslagen in het Google-account van je kind. <ph name="BEGIN_LINK1" />Meer informatie<ph name="END_LINK1" /></translation>
@@ -5386,7 +5387,7 @@
 <translation id="8680251145628383637">Log in om je bladwijzers, geschiedenis, wachtwoorden en andere instellingen op te halen op al je apparaten. Je wordt ook automatisch ingelogd bij je Google-services.</translation>
 <translation id="8682730193597992579"><ph name="PRINTER_NAME" /> is verbonden en gereed</translation>
 <translation id="8688579245973331962">Staat je naam er niet bij?</translation>
-<translation id="8688591111840995413">Slecht wachtwoord</translation>
+<translation id="8688591111840995413">Ongeldig wachtwoord</translation>
 <translation id="8688672835843460752">Beschikbaar</translation>
 <translation id="8695825812785969222">&amp;Locatie openen...</translation>
 <translation id="869884720829132584">Menu 'Applicaties'</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index cf65742b3..07103ab 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Ingen nettverk</translation>
 <translation id="1056898198331236512">Advarsel</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Butikk-apper</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> inneholder sensitivt innhold og er blokkert.</translation>
 <translation id="1061904396131502319">Snart tid for en pause</translation>
 <translation id="1067048845568873861">Opprettet</translation>
@@ -1560,6 +1559,7 @@
 <translation id="3172808215939929606">Siden er oversatt</translation>
 <translation id="3177909033752230686">Språket siden er på:</translation>
 <translation id="3179982752812949580">Skrifttype</translation>
+<translation id="3181825792072797598">Slå på synkronisering</translation>
 <translation id="3181954750937456830">Safe Browsing (beskytter deg og enheten din mot farlige nettsteder)</translation>
 <translation id="3182749001423093222">Stavekontroll</translation>
 <translation id="3183139917765991655">Profile Importer</translation>
@@ -4638,6 +4638,7 @@
 <translation id="7684718995427157417">For å lage og teste apper, slå på Android Debug Bridge (ADB). Merk at dette gjør det mulig å installere Android-apper som ikke er verifisert av Google, og enheten må tilbakestilles til fabrikkinnstillingene hvis du vil slå av ADB igjen.</translation>
 <translation id="7685049629764448582">JavaScript-minne</translation>
 <translation id="7685087414635069102">PIN-kode kreves</translation>
+<translation id="768549422429443215">Legg til språk eller endre rekkefølgen på listen.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bekreft det nye passordet</translation>
 <translation id="7690378713476594306">Velg fra listen</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb
index 801980b4..68c3d34 100644
--- a/chrome/app/resources/generated_resources_or.xtb
+++ b/chrome/app/resources/generated_resources_or.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">କୌଣସି ନେଟ୍‌ୱର୍କ ନାହିଁ</translation>
 <translation id="1056898198331236512">ଚେତାବନୀ</translation>
 <translation id="1058262162121953039">ବ୍ୟକ୍ତିଗତ ଅନ୍‌ଲକ୍ କୀ'</translation>
-<translation id="1060881073479695738">Play Store ଆପ୍‌ଗୁଡ଼ିକ</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" />ରେ ସମ୍ବେଦନଶୀଳ ବିଷୟବସ୍ତୁ ରହିଛି ଏବଂ ଏହାକୁ ବ୍ଲକ୍ କରାଯାଇଛି।</translation>
 <translation id="1061904396131502319">ବିରତି ପାଇଁ ପ୍ରାୟ ସମୟ ହୋଇଗଲାଣି</translation>
 <translation id="1067048845568873861">ସୃଷ୍ଟିହେଲା:</translation>
@@ -4649,6 +4648,7 @@
 <translation id="7684718995427157417">ଆପଣଙ୍କର ଆପ୍‍ଗୁଡ଼ିକ ତିଆରି କରିବା ଏବଂ ପରୀକ୍ଷା କରିବା ପାଇଁ Android Debug Bridge (ADB) ସକ୍ଷମ କରନ୍ତୁ। ଧ୍ୟାନ ଦିଅନ୍ତୁ ଯେ ଏହି କାର୍ଯ୍ୟ Google ଦ୍ୱାରା ଯାଞ୍ଚ କରାଯାଇନଥିବା Android ଆପ୍ସର ଇନ୍‍ଷ୍ଟଲେସନ୍‍କୁ ଅନୁମତି ଦିଏ ଏବଂ ଅକ୍ଷମ କରିବା ପାଇଁ ଏକ ଫ୍ୟାକ୍ଟୋରୀ ରିସେଟ୍ ଆବଶ୍ୟକ କରେ।</translation>
 <translation id="7685049629764448582">JavaScript ମେମୋରି</translation>
 <translation id="7685087414635069102">ପିନ୍ ଆବଶ୍ୟକ ଅଟେ</translation>
+<translation id="768549422429443215">ଭାଷାଗୁଡ଼ିକୁ ଯୋଗ କରନ୍ତୁ କିମ୍ବା ତାଲିକାକୁ ପୁନଃକ୍ରମରେ ରଖନ୍ତୁ।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ନୂଆ ପାସ୍‌ୱାର୍ଡ ସୁନିଶ୍ଚିତ କରନ୍ତୁ</translation>
 <translation id="7690378713476594306">ତାଲିକାରୁ ବାଛନ୍ତୁ</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb
index 9e0aee3..de3b6340 100644
--- a/chrome/app/resources/generated_resources_pa.xtb
+++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ਕੋਈ ਨੈੱਟਵਰਕ ਨਹੀਂ ਮਿਲੇ</translation>
 <translation id="1056898198331236512">ਚਿਤਾਵਨੀ</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play ਸਟੋਰ ਐਪਾਂ</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> ਵਿੱਚ ਸੰਵੇਦਨਸ਼ੀਲ ਸਮੱਗਰੀ ਹੈ, ਅਤੇ ਇਸਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
 <translation id="1061904396131502319">ਥੋੜ੍ਹੀ ਦੇਰ ਆਰਾਮ ਕਰਨ ਦਾ ਸਮਾਂ ਹੋਣ ਵਾਲਾ ਹੈ</translation>
 <translation id="1067048845568873861">ਬਣਾਇਆ</translation>
@@ -1567,6 +1566,7 @@
 <translation id="3172808215939929606">ਇਸ ਪੰਨੇ ਦਾ ਅਨੁਵਾਦ ਕੀਤਾ ਜਾ ਚੁੱਕਾ ਹੈ</translation>
 <translation id="3177909033752230686">ਪੰਨਾ ਭਾਸ਼ਾ:</translation>
 <translation id="3179982752812949580">ਲਿਖਤ ਦਾ ਫੌਂਟ</translation>
+<translation id="3181825792072797598">ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਕਰੋ</translation>
 <translation id="3181954750937456830">ਸੁਰੱਖਿਅਤ ਬ੍ਰਾਊਜ਼ਿੰਗ (ਖਤਰਨਾਕ ਸਾਈਟਾਂ ਤੋਂ ਤੁਹਾਡੀ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਸੁਰੱਖਿਆ ਕਰਦੀ ਹੈ)</translation>
 <translation id="3182749001423093222">ਸ਼ਬਦ-ਜੋੜ ਜਾਂਚ</translation>
 <translation id="3183139917765991655">ਪ੍ਰੋਫਾਈਲ ਆਯਾਤ ਕਰੋ</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">ਆਪਣੀਆਂ ਐਪਾਂ ਬਣਾਉਣ ਜਾਂ ਜਾਂਚਣ ਲਈ, Android ਡੀਬੱਗ ਬਰਿੱਜ (ADB) ਨੂੰ ਚਾਲੂ ਕਰੋ। ਨੋਟ ਕਰੋ ਕਿ ਇਸ ਕਾਰਵਾਈ ਨਾਲ ਉਹ Android ਐਪਾਂ ਸਥਾਪਤ ਹੋ ਸਕਦੀਆਂ ਹਨ, ਜਿਨ੍ਹਾਂ ਦੀ ਪੁਸ਼ਟੀ Google ਨੇ ਨਹੀਂ ਕੀਤੀ ਹੈ, ਅਤੇ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਨੂੰ ਬੰਦ ਕਰਨ ਦੀ ਲੋੜ ਪੈਂਦੀ ਹੈ।</translation>
 <translation id="7685049629764448582">JavaScript ਮੈਮਰੀ</translation>
 <translation id="7685087414635069102">ਪਿੰਨ ਲੋੜੀਂਦਾ ਹੈ</translation>
+<translation id="768549422429443215">ਭਾਸ਼ਾਵਾਂ ਸ਼ਾਮਲ ਕਰੋ ਜਾਂ ਸੂਚੀ ਨੂੰ ਮੁੜ-ਕ੍ਰਮਬੱਧ ਕਰੋ।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ਨਵੇਂ ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</translation>
 <translation id="7690378713476594306">ਸੂਚੀ ਵਿੱਚੋਂ ਚੁਣੋ</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index 715b02e6..952ec650 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Brak sieci</translation>
 <translation id="1056898198331236512">Ostrzeżenie</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikacje ze Sklepu Play</translation>
 <translation id="1061745542578250838">Plik <ph name="FILE_NAME" /> zawiera treści o charakterze kontrowersyjnym, więc został zablokowany.</translation>
 <translation id="1061904396131502319">Wielkimi krokami nadchodzi przerwa</translation>
 <translation id="1067048845568873861">Utworzono</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Ta strona została przetłumaczona</translation>
 <translation id="3177909033752230686">Język strony:</translation>
 <translation id="3179982752812949580">Czcionka tekstu</translation>
+<translation id="3181825792072797598">Włącz synchronizację</translation>
 <translation id="3181954750937456830">Bezpieczne przeglądanie (chroni Ciebie i Twoje urządzenie przed niebezpiecznymi witrynami)</translation>
 <translation id="3182749001423093222">Sprawdzanie pisowni</translation>
 <translation id="3183139917765991655">Importer profilów</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Aby utworzyć i przetestować swoje aplikacje, włącz Android Debug Bridge (ADB). Pamiętaj, że to działanie wiąże się z zezwoleniem na instalowanie aplikacji na Androida, które nie zostały zweryfikowane przez Google, a do wyłączenia tej funkcji konieczne jest przywrócenie ustawień fabrycznych.</translation>
 <translation id="7685049629764448582">Pamięć JavaScript</translation>
 <translation id="7685087414635069102">Wymagany kod PIN</translation>
+<translation id="768549422429443215">Dodaj języki lub zmień kolejność na liście.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potwierdź nowe hasło</translation>
 <translation id="7690378713476594306">Wybierz z listy</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index d541e41..dfb24c64 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nenhuma rede encontrada</translation>
 <translation id="1056898198331236512">Aviso</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Apps da Play Store</translation>
 <translation id="1061745542578250838">O arquivo <ph name="FILE_NAME" /> apresenta conteúdo sensível e foi bloqueado.</translation>
 <translation id="1061904396131502319">Está quase na hora de fazer uma pausa</translation>
 <translation id="1067048845568873861">Criado em</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Esta página foi traduzida</translation>
 <translation id="3177909033752230686">Idioma da página:</translation>
 <translation id="3179982752812949580">Fonte do texto</translation>
+<translation id="3181825792072797598">Ativar a Sincronização</translation>
 <translation id="3181954750937456830">Navegação segura: protege você e seu dispositivo de sites perigosos</translation>
 <translation id="3182749001423093222">Verificação ortográfica</translation>
 <translation id="3183139917765991655">Importador de perfil</translation>
@@ -4655,6 +4655,7 @@
 <translation id="7684718995427157417">Para criar e testar seus apps, ative o Android Debug Bridge (ADB). Essa ação permite a instalação de apps para Android que não foram verificados pelo Google. Para desativá-lo, será necessária uma redefinição para a configuração original.</translation>
 <translation id="7685049629764448582">Memória JavaScript</translation>
 <translation id="7685087414635069102">PIN necessário</translation>
+<translation id="768549422429443215">Adicionar idiomas ou reordenar lista.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar nova senha</translation>
 <translation id="7690378713476594306">Escolher na lista</translation>
@@ -5521,7 +5522,7 @@
 <translation id="8847988622838149491">USB</translation>
 <translation id="8850251000316748990">Ver mais…</translation>
 <translation id="885246833287407341">Argumentos de função da API</translation>
-<translation id="8853586775156634952">O card será salvo apenas neste dispositivo</translation>
+<translation id="8853586775156634952">O cartão será salvo apenas neste dispositivo</translation>
 <translation id="8855501062415172277">O arquivo <ph name="FILE_NAME" /> apresenta conteúdo sensível.</translation>
 <translation id="8855977033756560989">Esse dispositivo Chromebook Enterprise vem com o Upgrade do Chrome Enterprise Para aproveitar ao máximo os recursos corporativos, inscreva esse dispositivo com uma conta de administrador do Google.</translation>
 <translation id="885701979325669005">Armazenamento</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index 81c3b77..319c79f 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nenhuma rede</translation>
 <translation id="1056898198331236512">Aviso</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplicações da Play Store</translation>
 <translation id="1061745542578250838">O ficheiro <ph name="FILE_NAME" /> tem conteúdo sensível e foi bloqueado.</translation>
 <translation id="1061904396131502319">Está quase na altura de fazer uma pausa</translation>
 <translation id="1067048845568873861">Data da criação</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Esta página foi traduzida</translation>
 <translation id="3177909033752230686">Idioma da página:</translation>
 <translation id="3179982752812949580">Tipo de letra do texto</translation>
+<translation id="3181825792072797598">Ativar Sincronização</translation>
 <translation id="3181954750937456830">Navegação segura (protege o utilizador e o seu dispositivo contra sites perigosos)</translation>
 <translation id="3182749001423093222">Verificação ortográfica</translation>
 <translation id="3183139917765991655">Importador de perfis</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Para criar e testar aplicações, ative o Bridge de depuração do Android (adb). Tenha em atenção que esta ação permite a instalação de aplicações para Android que não foram validadas pela Google. Além disso, se pretender desativar o adb, terá de efetuar uma reposição de dados de fábrica.</translation>
 <translation id="7685049629764448582">Memória JavaScript</translation>
 <translation id="7685087414635069102">PIN necessário</translation>
+<translation id="768549422429443215">Adicione idiomas ou reordene a lista.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar a nova palavra-passe</translation>
 <translation id="7690378713476594306">Escolher na lista</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb
index 238923c..07955b5 100644
--- a/chrome/app/resources/generated_resources_ro.xtb
+++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nu s-au găsit rețele</translation>
 <translation id="1056898198331236512">Avertisment</translation>
 <translation id="1058262162121953039">Codul PUK</translation>
-<translation id="1060881073479695738">Aplicații din Magazinul Play</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> include conținut sensibil și a fost blocat.</translation>
 <translation id="1061904396131502319">Se apropie timpul pentru o pauză</translation>
 <translation id="1067048845568873861">Creat</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Pagina a fost tradusă</translation>
 <translation id="3177909033752230686">Limba paginii:</translation>
 <translation id="3179982752812949580">Fontul textului</translation>
+<translation id="3181825792072797598">Activează sincronizarea</translation>
 <translation id="3181954750937456830">Navigare sigură (protecție împotriva site-urilor periculoase)</translation>
 <translation id="3182749001423093222">Verificarea ortografiei</translation>
 <translation id="3183139917765991655">Instrument de import al profilurilor</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Pentru a crea și testa aplicații, activează Android Debug Bridge (ADB). Reține că această acțiune permite instalarea aplicațiilor Android care nu au fost verificate de Google și pentru dezactivarea instrumentului este necesară revenirea la setările din fabrică.</translation>
 <translation id="7685049629764448582">Memorie JavaScript</translation>
 <translation id="7685087414635069102">PIN necesar</translation>
+<translation id="768549422429443215">Adaugă limbi sau reordonează lista.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmă noua parolă</translation>
 <translation id="7690378713476594306">Alege din listă</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index d085b2e..4035c86 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Нет сетей</translation>
 <translation id="1056898198331236512">Внимание</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Приложения из Play Маркета</translation>
 <translation id="1061745542578250838">Файл "<ph name="FILE_NAME" />" заблокирован, так как содержит конфиденциальную информацию.</translation>
 <translation id="1061904396131502319">Скоро перерыв</translation>
 <translation id="1067048845568873861">Создано</translation>
@@ -1567,6 +1566,7 @@
 <translation id="3172808215939929606">Страница переведена</translation>
 <translation id="3177909033752230686">Язык страницы:</translation>
 <translation id="3179982752812949580">Шрифт текста</translation>
+<translation id="3181825792072797598">Включить</translation>
 <translation id="3181954750937456830">Безопасный просмотр (защищает вас и ваше устройство от опасных сайтов)</translation>
 <translation id="3182749001423093222">Проверка правописания</translation>
 <translation id="3183139917765991655">Импорт профилей</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">Чтобы создавать и тестировать приложения, включите Android Debug Bridge (ADB). Обратите внимание, что это позволит устанавливать приложения для Android, которые не были проверены системами Google. Для отключения инструмента потребуется сбросить настройки устройства до заводских.</translation>
 <translation id="7685049629764448582">Память JavaScript</translation>
 <translation id="7685087414635069102">Требуется PIN-код</translation>
+<translation id="768549422429443215">Добавьте языки или измените порядок их расположения.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Введите новый пароль ещё раз</translation>
 <translation id="7690378713476594306">Выбрать из списка</translation>
diff --git a/chrome/app/resources/generated_resources_si.xtb b/chrome/app/resources/generated_resources_si.xtb
index 3e8b9ee..9ccef00 100644
--- a/chrome/app/resources/generated_resources_si.xtb
+++ b/chrome/app/resources/generated_resources_si.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ජාල නැත</translation>
 <translation id="1056898198331236512">අවවාදයයි</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store යෙදුම්</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> හට සංවේදී අන්තර්ගතය අඩංගුයි, එය අවහිර කර ඇත.</translation>
 <translation id="1061904396131502319">විවේකයක් සඳහා වේලාවයි</translation>
 <translation id="1067048845568873861">සාදන ලදි</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">මෙම පිටුව පරිවර්තනය කර ඇත</translation>
 <translation id="3177909033752230686">පිටුවේ භාෂාව:</translation>
 <translation id="3179982752812949580">පාඨ අකුරු වර්ගය</translation>
+<translation id="3181825792072797598">සමමුහුර්තය ක්‍රියාත්මක කරන්න</translation>
 <translation id="3181954750937456830">ආරක්‍ෂිත බ්‍රවුස් කිරීම (අනතුරුදායක වෙබ් අඩවිවලින් ඔබ හා ඔබේ උපාංගය භාවිත කරයි)</translation>
 <translation id="3182749001423093222">අක්ෂර වින්‍යාස පරීක්ෂාව</translation>
 <translation id="3183139917765991655">පැතිකඩ ආනයනකරු</translation>
@@ -4650,6 +4650,7 @@
 <translation id="7684718995427157417">ඔබේ යෙදුම් සෑදීමට සහ පරීක්‍ෂා කිරීමට, Android Debug Bridge (ADB) සබල කරන්න. මෙම ක්‍රියාව Google විසින් සත්‍යාපිත නොවන Android යෙදුම් ස්ථාපන කිරීමට ඉඩ දෙන අතර, අබල කිරීමට කර්මාන්තශාලා යළි සැකසුමක් අවශ්‍ය වන බව සලකන්න.</translation>
 <translation id="7685049629764448582">JavaScript මතකය</translation>
 <translation id="7685087414635069102">රහස් අංකය අවශ්‍යයි</translation>
+<translation id="768549422429443215">භාෂා එක් කරන්න හෝ ලැයිස්තුව යළි පෙළගස්වන්න.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> <ph name="DEVICE_PATH" /></translation>
 <translation id="7690294790491645610">නව මුරපදය තහවුරු කරන්න</translation>
 <translation id="7690378713476594306">ලැයිස්තුවෙන් තෝරා ගන්න</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 51de37f..f81b42d 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Žiadne siete</translation>
 <translation id="1056898198331236512">Upozornenie</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikácie Obchodu Play</translation>
 <translation id="1061745542578250838">Súbor <ph name="FILE_NAME" /> zahŕňa citlivý obsah a bol zablokovaný.</translation>
 <translation id="1061904396131502319">Už je takmer čas na prestávku</translation>
 <translation id="1067048845568873861">Vytvorené</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">Táto stránka bola preložená</translation>
 <translation id="3177909033752230686">Jazyk stránky:</translation>
 <translation id="3179982752812949580">Písmo textu</translation>
+<translation id="3181825792072797598">Zapnúť synchronizáciu</translation>
 <translation id="3181954750937456830">Bezpečné prehliadanie (chráni vás aj zariadenie pred nebezpečnými webmi)</translation>
 <translation id="3182749001423093222">Kontrola pravopisu</translation>
 <translation id="3183139917765991655">Profile Importer</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">Ak chcete vytvárať a testovať aplikácie, aktivujte Android Debug Bridge (ADB). Upozorňujeme, že touto akciou umožníte inštalácie aplikácií pre Android, ktoré Google neoveril, a deaktivácia vyžaduje obnovenie výrobných nastavení.</translation>
 <translation id="7685049629764448582">Pamäť jazyka JavaScript</translation>
 <translation id="7685087414635069102">Vyžaduje sa kód PIN</translation>
+<translation id="768549422429443215">Pridajte jazyky alebo upravte poradie zoznamu.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrďte nové heslo</translation>
 <translation id="7690378713476594306">Vybrať v zozname</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index e641599..f719b1ea 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Ni omrežij</translation>
 <translation id="1056898198331236512">Opozorilo</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikacije Trgovine Play</translation>
 <translation id="1061745542578250838">Datoteka <ph name="FILE_NAME" /> vsebuje občutljivo vsebino in je blokirana.</translation>
 <translation id="1061904396131502319">Skoraj je že čas za odmor</translation>
 <translation id="1067048845568873861">Ustvarjeno</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Ta stran je prevedena</translation>
 <translation id="3177909033752230686">Jezik strani:</translation>
 <translation id="3179982752812949580">Pisava besedila</translation>
+<translation id="3181825792072797598">Vklopi sinhronizacijo</translation>
 <translation id="3181954750937456830">Varno brskanje (ščiti vas in napravo pred nevarnimi spletnimi mesti)</translation>
 <translation id="3182749001423093222">Preverjanje črkovanja</translation>
 <translation id="3183139917765991655">Uvoznik profilov</translation>
@@ -4655,6 +4655,7 @@
 <translation id="7684718995427157417">Če želite ustvarjati in preizkušati aplikacije, omogočite most za odpravljanje težav s sistemom Android (ADB). Upoštevajte, da to dejanje omogoča namestitev aplikacij za Android, ki jih ni preveril Google, če želite orodje onemogočiti, pa je potrebna tovarniško ponastavitev.</translation>
 <translation id="7685049629764448582">Pomnilnik za JavaScript</translation>
 <translation id="7685087414635069102">Zahtevana je koda PIN</translation>
+<translation id="768549422429443215">Dodajte jezike ali preuredite seznam.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potrdite novo geslo</translation>
 <translation id="7690378713476594306">Izbira s seznama</translation>
diff --git a/chrome/app/resources/generated_resources_sq.xtb b/chrome/app/resources/generated_resources_sq.xtb
index fe1ab65..6f6b7d8b 100644
--- a/chrome/app/resources/generated_resources_sq.xtb
+++ b/chrome/app/resources/generated_resources_sq.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Nuk ka asnjë rrjet</translation>
 <translation id="1056898198331236512">Paralajmërim</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Aplikacionet e "Dyqanit të Play"</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> përfshin përmbajtje delikate dhe është bllokuar.</translation>
 <translation id="1061904396131502319">Pothuajse koha për një pushim</translation>
 <translation id="1067048845568873861">U krijua</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">Kjo faqe është përkthyer</translation>
 <translation id="3177909033752230686">Gjuha e faqes:</translation>
 <translation id="3179982752812949580">Lloji i fontit</translation>
+<translation id="3181825792072797598">Aktivizo "Sinkronizimin"</translation>
 <translation id="3181954750937456830">"Shfletimi i sigurt" (të mbron ty dhe pajisjen tënde nga sajtet e rrezikshme)</translation>
 <translation id="3182749001423093222">Kontrolli drejtshkrimor</translation>
 <translation id="3183139917765991655">Importuesi i profilit</translation>
@@ -4650,6 +4650,7 @@
 <translation id="7684718995427157417">Për të krijuar dhe testuar aplikacionet e tua, aktivizo "Urën e korrigjimit të Android" (ADB). Ki parasysh se ky veprim lejon instalimin e aplikacioneve të Android që nuk janë verifikuar nga Google dhe për çaktivizimin kërkohet rivendosja e cilësimeve të fabrikës.</translation>
 <translation id="7685049629764448582">Memoria e JavaScript</translation>
 <translation id="7685087414635069102">Kërkohet kodi PIN</translation>
+<translation id="768549422429443215">Shto gjuhën ose rendit përsëri listën.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Konfirmo fjalëkalimin e ri</translation>
 <translation id="7690378713476594306">Zgjidh nga lista</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index ecb3e58..acd7263 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Нема мрежа</translation>
 <translation id="1056898198331236512">Упозорење</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">апликације из Play продавнице</translation>
 <translation id="1061745542578250838">Датотека <ph name="FILE_NAME" /> садржи осетљив садржај и блокирана је.</translation>
 <translation id="1061904396131502319">Скоро је време за паузу</translation>
 <translation id="1067048845568873861">Направљено</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">Ова страница је преведена</translation>
 <translation id="3177909033752230686">Језик странице:</translation>
 <translation id="3179982752812949580">Фонт текста</translation>
+<translation id="3181825792072797598">Укључи синхронизацију</translation>
 <translation id="3181954750937456830">Безбедно прегледање (штити вас и уређај од опасних сајтова)</translation>
 <translation id="3182749001423093222">Провера правописа</translation>
 <translation id="3183139917765991655">Увоз профила</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">Да бисте правили и тестирали апликације, омогућите Android Debug Bridge (ADB). Имајте на уму да ова радња омогућава инсталирање Android апликација које Google није верификовао и захтева ресетовање на фабричка подешавања да би се онемогућила.</translation>
 <translation id="7685049629764448582">JavaScript меморија</translation>
 <translation id="7685087414635069102">PIN је обавезан</translation>
+<translation id="768549422429443215">Додајте језике или промените редослед ставки на листи.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Потврдите нову лозинку</translation>
 <translation id="7690378713476594306">Одаберите са листе</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index a463a6c..5c2e041e 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Inga nätverk</translation>
 <translation id="1056898198331236512">Varning</translation>
 <translation id="1058262162121953039">PUK-kod</translation>
-<translation id="1060881073479695738">Appar från Play Butik</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> har känsligt innehåll och har blockerats.</translation>
 <translation id="1061904396131502319">Snart dags för en paus</translation>
 <translation id="1067048845568873861">Skapad</translation>
@@ -132,7 +131,7 @@
 <translation id="117445914942805388"><ph name="BEGIN_LINK" />Besök inställningarna för synkronisering<ph name="END_LINK" /> om du vill rensa webbinformation från alla synkroniserade enheter och ditt Google-konto.</translation>
 <translation id="1175364870820465910">Skriv &amp;ut...</translation>
 <translation id="1177138678118607465">Google kan använda webbhistoriken för att anpassa Sök och andra tjänster från Google. Du kan ändra detta på myaccount.google.com/activitycontrols/search</translation>
-<translation id="1177863135347784049">Anpassad</translation>
+<translation id="1177863135347784049">Anpassat</translation>
 <translation id="1178581264944972037">Paus</translation>
 <translation id="117916940443676133">Säkerhetsnyckeln skyddas inte av en pinkod. Skapa en pinkod först innan du hanterar inloggningsuppgifter.</translation>
 <translation id="1181037720776840403">Ta bort</translation>
@@ -208,7 +207,7 @@
 <translation id="1282420830958964167">Du har nått den gräns som din förälder har angett för <ph name="APP_NAME" />. Du kan använda den i <ph name="TIME_LIMIT" /> i morgon.</translation>
 <translation id="1285320974508926690">Översätt aldrig den här webbplatsen</translation>
 <translation id="1285484354230578868">Spara data i Google Drive-kontot</translation>
-<translation id="1288037062697528143">Nattljuset tänds automatiskt vid solnedgången</translation>
+<translation id="1288037062697528143">Nattljuset aktiveras automatiskt vid solnedgången</translation>
 <translation id="1288300545283011870">Talegenskaper</translation>
 <translation id="1293264513303784526">USB-C-enhet (vänster port)</translation>
 <translation id="1293556467332435079">Filer</translation>
@@ -439,7 +438,7 @@
 <translation id="1604432177629086300">Utskriften misslyckades. Kontrollera skrivaren och försök igen.</translation>
 <translation id="1605544918554600534"><ph name="PROFILE_NAME" />: Det går inte att synkronisera lösenord</translation>
 <translation id="1607139524282324606">Rensa post</translation>
-<translation id="1608626060424371292">Ta bort den här användaren</translation>
+<translation id="1608626060424371292">Ta bort denna användare</translation>
 <translation id="1608668830839595724">Fler åtgärder för valda objekt</translation>
 <translation id="1609170755653088773">Synkronisera det här lösenordet med iPhone</translation>
 <translation id="161042844686301425">Cyanblå</translation>
@@ -480,7 +479,7 @@
 <translation id="1660204651932907780">Tillåt att ljud spelas upp på webbplatser (rekommenderas)</translation>
 <translation id="1660763353352708040">Ett fel har uppstått med nätadaptern</translation>
 <translation id="1661156625580498328">Tillämpa AES-kryptering (rekommenderas).</translation>
-<translation id="1661867754829461514">PIN saknas</translation>
+<translation id="1661867754829461514">Pinkod saknas</translation>
 <translation id="16620462294541761">Det gick inte att verifiera lösenordet. Försök igen.</translation>
 <translation id="166278006618318542">Mottagarens publika nyckelalgoritm</translation>
 <translation id="166439687370499867">Du får inte ändra delade nätverkskonfigurationer</translation>
@@ -697,7 +696,7 @@
 <translation id="1956050014111002555">Filen innehöll flera certifikat men inga certifikat importerades:</translation>
 <translation id="1956390763342388273">Alla filer från <ph name="FOLDER_PATH" /> laddas upp. Gör bara detta om du litar på webbplatsen.</translation>
 <translation id="1962233722219655970">Denna sida använder en Native Client-app som inte fungerar på din dator.</translation>
-<translation id="1963227389609234879">Ta bort &amp;alla</translation>
+<translation id="1963227389609234879">Ta bort alla</translation>
 <translation id="1965624977906726414">Har inga speciella behörigheter.</translation>
 <translation id="1969654639948595766">WebRTC-textloggar (<ph name="WEBRTC_TEXT_LOG_COUNT" />)</translation>
 <translation id="1970368523891847084">Videoläget har aktiverats</translation>
@@ -870,7 +869,7 @@
 <translation id="2203682048752833055">Sökmotorn som används i <ph name="BEGIN_LINK" />adressfältet<ph name="END_LINK" /></translation>
 <translation id="2204034823255629767">Läsa och ändra allt som du skriver</translation>
 <translation id="220792432208469595">Skicka diagnostik- och användningsdata. Den här enheten skickar för närvarande diagnostikdata, enhetsdata och data om appanvändning till Google automatiskt. Denna data används till att förbättra systemets och apparnas stabilitet med mera. Viss samlad data används även till att förbättra appar från Google och partner, till exempel Android-utvecklare. Ägaren har gjort denna inställning obligatorisk. Om ytterligare webb- och appaktivitet har aktiverats kan denna data sparas i Google-kontot. <ph name="BEGIN_LINK1" />Läs mer<ph name="END_LINK1" /></translation>
-<translation id="220858061631308971">Ange den här PIN-koden på <ph name="DEVICE_NAME" />:</translation>
+<translation id="220858061631308971">Ange den här pinkoden på <ph name="DEVICE_NAME" />:</translation>
 <translation id="2213140827792212876">Ta bort delning</translation>
 <translation id="2214018885812055163">Delade mappar</translation>
 <translation id="2214884991347062907">Fel lösenord. Försök igen.</translation>
@@ -1058,7 +1057,7 @@
 <translation id="2470702053775288986">Tillägg som inte stöds har inaktiverats</translation>
 <translation id="2473195200299095979">Översätt den här sidan</translation>
 <translation id="2475982808118771221">Det uppstod ett fel</translation>
-<translation id="2476578072172137802">Inställningar för webbplatsen</translation>
+<translation id="2476578072172137802">Webbplatsinställningar</translation>
 <translation id="2478176599153288112">Mediefilsbehörigheter för <ph name="EXTENSION" /></translation>
 <translation id="247949520305900375">Dela ljud</translation>
 <translation id="2480868415629598489">Ändra data som du kopierar och klistrar in</translation>
@@ -1234,7 +1233,7 @@
 <translation id="270921614578699633">Medelvärde för</translation>
 <translation id="2709516037105925701">Autofyll</translation>
 <translation id="271033894570825754">Ny</translation>
-<translation id="2712173769900027643">Begär behörighet</translation>
+<translation id="2712173769900027643">Be om tillstånd</translation>
 <translation id="2713444072780614174">Vit</translation>
 <translation id="2714393097308983682">Google Play Butik</translation>
 <translation id="2715751256863167692">Med den här uppgraderingen återställs Chromebook och nuvarande användardata tas bort.</translation>
@@ -1480,7 +1479,7 @@
 <translation id="3036546437875325427">Aktivera blixt</translation>
 <translation id="3037754279345160234">Det gick inte att analysera konfigurationen för domänanslutning. Kontakta administratören.</translation>
 <translation id="3038612606416062604">Lägg till en skrivare manuellt</translation>
-<translation id="3038675903128704560">Tillåt inte några webbplatser att använda en plugin för få åtkomst till datorn</translation>
+<translation id="3038675903128704560">Tillåt inte några webbplatser att använda en plugin för att få åtkomst till datorn</translation>
 <translation id="3039491566278747710">Det gick inte att installera offlinepolicyn på enheten.</translation>
 <translation id="3043581297103810752">Från <ph name="ORIGIN" /></translation>
 <translation id="3045447014237878114">Den här webbplatsen laddade ned flera filer automatiskt</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Sidan har översatts</translation>
 <translation id="3177909033752230686">Sidans språk:</translation>
 <translation id="3179982752812949580">Textens teckensnitt</translation>
+<translation id="3181825792072797598">Aktivera synkronisering</translation>
 <translation id="3181954750937456830">Säker webbsökning (skyddar dig och enheten från skadliga webbplatser)</translation>
 <translation id="3182749001423093222">Stavningskontroll</translation>
 <translation id="3183139917765991655">Profilimportör</translation>
@@ -1621,7 +1621,7 @@
 <translation id="3269612321104318480">Ljust blågrön och vit</translation>
 <translation id="326999365752735949">Laddar ned skillnaden</translation>
 <translation id="3270965368676314374">Läsa, ändra och ta bort foton, musik och andra media från datorn</translation>
-<translation id="327147043223061465">Visa alla cookies och webbplatsuppgifter</translation>
+<translation id="327147043223061465">Visa alla cookies och all webbplatsdata</translation>
 <translation id="3271648667212143903"><ph name="ORIGIN" /> vill ansluta</translation>
 <translation id="3274763671541996799">Du har aktiverat helskärmsläget.</translation>
 <translation id="3275778809241512831">Den interna säkerhetsnyckeln är i nuläget osäker. Ta bort den från alla tjänster där du har använt den. Återställ säkerhetsnyckeln för att lösa problemet.</translation>
@@ -1755,7 +1755,7 @@
 <translation id="3464012987031883895">En webbplats tar emot ljudindata</translation>
 <translation id="346431825526753">Det här är ett konto för barn som hanteras av <ph name="CUSTODIAN_EMAIL" />.</translation>
 <translation id="3468999815377931311">Android-mobil</translation>
-<translation id="3470442499439619530">Ta bort den här användaren</translation>
+<translation id="3470442499439619530">Ta bort denna användare</translation>
 <translation id="3471876058939596279">HDMI- och USB Type-C-portar kan inte användas till video och dockningsstation samtidigt. Använd en annan videoport.</translation>
 <translation id="3473479545200714844">Skärmförstorare</translation>
 <translation id="3475843873335999118">Fingeravtrycket känns fortfarande inte igen. Ange ditt lösenord.</translation>
@@ -1965,7 +1965,7 @@
 <translation id="3737536731758327622">Det du laddar ned visas här</translation>
 <translation id="3738924763801731196"><ph name="OID" />:</translation>
 <translation id="3739254215541673094">Vill du öppna <ph name="APPLICATION" />?</translation>
-<translation id="3742055079367172538">Skärmbilden har tagits</translation>
+<translation id="3742055079367172538">Skärmdumpen har tagits</translation>
 <translation id="3742666961763734085">Ingen organisationsenhet med det namnet hittades. Försök igen.</translation>
 <translation id="3744111561329211289">Synkronisera i bakgrunden</translation>
 <translation id="3748026146096797577">Ej ansluten</translation>
@@ -2066,7 +2066,7 @@
 <translation id="3867944738977021751">Certifikatfält</translation>
 <translation id="3869917919960562512">Fel index.</translation>
 <translation id="3870931306085184145">Det finns inga sparade lösenord för <ph name="DOMAIN" /></translation>
-<translation id="3871092408932389764">Lägsta</translation>
+<translation id="3871092408932389764">Lägst</translation>
 <translation id="3871350334636688135">Efter 24 timmar genomför administratören en engångsuppdatering som raderar din lokala data när du startar om enheten. Spara den lokala data du behöver i molnet inom 24 timmar.</translation>
 <translation id="3872220884670338524">Fler åtgärder, sparat konto för <ph name="USERNAME" /> på <ph name="DOMAIN" /></translation>
 <translation id="3872991219937722530">Frigör diskutrymme för att enheten ska fortsätta svara.</translation>
@@ -2344,7 +2344,7 @@
 <translation id="4275663329226226506">Media</translation>
 <translation id="4275830172053184480">Starta om enheten</translation>
 <translation id="4278101229438943600">Assistenten är redo</translation>
-<translation id="4278390842282768270">Tillåtet</translation>
+<translation id="4278390842282768270">Tillåts</translation>
 <translation id="4281844954008187215">Användarvillkor</translation>
 <translation id="4282196459431406533">Smart Lock är aktiverat</translation>
 <translation id="4285418559658561636">Uppdatera lösenordet</translation>
@@ -2815,7 +2815,7 @@
 <translation id="4996978546172906250">Dela via</translation>
 <translation id="4997086284911172121">Ingen internetanslutning</translation>
 <translation id="4998873842614926205">Bekräfta ändringar</translation>
-<translation id="5000922062037820727">Blockerad (rekommenderas)</translation>
+<translation id="5000922062037820727">Blockeras (rekommenderas)</translation>
 <translation id="5008936837313706385">Aktivitetsnamn</translation>
 <translation id="5010043101506446253">Certifikatutfärdare</translation>
 <translation id="5015344424288992913">Tolkar proxy...</translation>
@@ -2861,7 +2861,7 @@
 <translation id="5075131525758602494">Ange SIM-kortets pinkod</translation>
 <translation id="5075910247684008552">Osäkert innehåll blockeras som standard på säkra webbplatser</translation>
 <translation id="5078638979202084724">Skapa bokmärken för alla flikar</translation>
-<translation id="5078796286268621944">Fel PIN</translation>
+<translation id="5078796286268621944">Fel pinkod</translation>
 <translation id="5079950360618752063">Använd det föreslagna lösenordet</translation>
 <translation id="508059534790499809">Uppdatera en Kerberos-biljett</translation>
 <translation id="5084230410268011727">Tillåt att webbplatser använder rörelse- och ljussensorer</translation>
@@ -3014,7 +3014,7 @@
 <translation id="5302932258331363306">Visa ersättningar</translation>
 <translation id="5305688511332277257">Ingen installerad</translation>
 <translation id="5307030433605830021">Källan stöds inte</translation>
-<translation id="5308380583665731573">Ansluta</translation>
+<translation id="5308380583665731573">Anslut</translation>
 <translation id="5310281978693206542">Skicka länken till dina enheter</translation>
 <translation id="5311304534597152726">Loggar in som</translation>
 <translation id="53116743016968120"><ph name="ERROR_MESSAGE" /> Försök igen.</translation>
@@ -3057,7 +3057,7 @@
 <translation id="5372579129492968947">Lossa tillägg</translation>
 <translation id="5376169624176189338">Klicka för att återvända, håll ned för att se historik</translation>
 <translation id="5376931455988532197">Filen är för stor</translation>
-<translation id="537813040452600081">Sidor du visar i det här fönstret syns inte i webbläsarhistoriken och de lämnar inga andra spår efter sig (till exempel cookies) på datorn när du har loggat ut till. Filer som du laddar ned och bokmärken du skapar sparas inte.</translation>
+<translation id="537813040452600081">Sidor du visar i det här fönstret syns inte i webbläsarhistoriken och de lämnar inga andra spår efter sig (till exempel cookies) på datorn när du har loggat ut. Filer som du laddar ned och bokmärken du skapar sparas inte.</translation>
 <translation id="5379140238605961210">Fortsätt att blockera mikrofonåtkomsten</translation>
 <translation id="5382591305415226340">Hantera länkar som stöds</translation>
 <translation id="5383377866517186886">Kamera har inaktiverats i systeminställningarna för Mac.</translation>
@@ -3221,7 +3221,7 @@
 <translation id="5595485650161345191">Redigera adress</translation>
 <translation id="5596627076506792578">Fler alternativ</translation>
 <translation id="5600706100022181951">Nedladdningen av uppdateringen förbrukar <ph name="UPDATE_SIZE_MB" /> MB mobildata. Vill du fortsätta?</translation>
-<translation id="5601503069213153581">PIN-kod</translation>
+<translation id="5601503069213153581">Pinkod</translation>
 <translation id="5602765853043467355">Rensa bokmärken, historik , lösenord med mera från den här enheten</translation>
 <translation id="5605623530403479164">Andra sökmotorer</translation>
 <translation id="5605758115928394442">En avisering har skickats till din mobil för att bekräfta att det är du.</translation>
@@ -3427,14 +3427,14 @@
 <translation id="5886009770935151472">Finger 1</translation>
 <translation id="5889282057229379085">Maximalt antal mellanliggande CU: <ph name="NUM_INTERMEDIATE_CA" /></translation>
 <translation id="5895138241574237353">Starta om</translation>
-<translation id="5895187275912066135">Utfärdat den</translation>
+<translation id="5895187275912066135">Utfärdat</translation>
 <translation id="5900302528761731119">Profilbild i Google Profiler</translation>
 <translation id="5900358982890952556">Uppgradera Linux (beta)</translation>
 <translation id="5901494423252125310">Skrivarens lucka är öppen</translation>
 <translation id="5901630391730855834">Gul</translation>
 <translation id="5906655207909574370">Uppdateringen är nästan klar! Slutför den genom att starta om enheten.</translation>
 <translation id="5906732635754427568">Data kopplad till den här appen tas bort från enheten.</translation>
-<translation id="5908769186679515905">Förhindra att webbplatser kör Flash</translation>
+<translation id="5908769186679515905">Blockera webbplatser från att köra Flash</translation>
 <translation id="5910363049092958439">S&amp;para bild som...</translation>
 <translation id="5911533659001334206">Kortkommandovisare</translation>
 <translation id="5912378097832178659">&amp;Redigera sökmotorer...</translation>
@@ -3645,7 +3645,7 @@
 <translation id="6196640612572343990">Blockera cookies från tredje part</translation>
 <translation id="6196854373336333322">Tillägget <ph name="EXTENSION_NAME" /> har tagit kontroll över dina proxyinställningar, vilket innebär att det kan ändra, knäcka eller tjuvlyssna på allt du gör på webben. Om du inte vet varför den här ändringen inträffade är den troligen inte önskvärd.</translation>
 <translation id="6198102561359457428">Logga ut och sedan in igen ...</translation>
-<translation id="6198252989419008588">Byt PIN</translation>
+<translation id="6198252989419008588">Byt pinkod</translation>
 <translation id="6202304368170870640">Du kan logga in på eller låsa upp enheten med pinkoden.</translation>
 <translation id="6206311232642889873">Kopiera &amp;bild</translation>
 <translation id="6207200176136643843">Återställ standardzoomnivån</translation>
@@ -3720,7 +3720,7 @@
 <translation id="6295158916970320988">Alla webbplatser</translation>
 <translation id="6295855836753816081">Sparar ...</translation>
 <translation id="629730747756840877">Konto</translation>
-<translation id="6298962879096096191">Avinstallera appar med hjälp av Google Play</translation>
+<translation id="6298962879096096191">Installera appar med hjälp av Google Play</translation>
 <translation id="630065524203833229">&amp;Avsluta</translation>
 <translation id="6300718114348072351">Det gick inte att konfigurera <ph name="PRINTER_NAME" /> automatiskt. Ange avancerade utskriftsalternativ. <ph name="LINK_BEGIN" />Läs mer<ph name="LINK_END" /></translation>
 <translation id="6305607932814307878">Global policy:</translation>
@@ -3775,7 +3775,7 @@
 <translation id="6385543213911723544">Webbplatser får spara och läsa uppgifter i cookies</translation>
 <translation id="6386099547750337629">Kontakta supporten om du inte väntade dig detta.</translation>
 <translation id="6387674443318562538">Dela lodrätt</translation>
-<translation id="6388429472088318283">Sök på språk</translation>
+<translation id="6388429472088318283">Sök efter språk</translation>
 <translation id="6390020764191254941">Flytta fliken till ett nytt fönster</translation>
 <translation id="6390799748543157332">Sidorna du visar i den här fliken visas inte i webbläsarhistoriken och lämnar inga andra spår, till exempel cookies, på datorn när du har stängt alla öppna gästfönster. Filer som du laddar ned kommer dock att sparas.</translation>
 <translation id="6393156038355142111">Föreslå ett starkt lösenord</translation>
@@ -4250,7 +4250,7 @@
 <translation id="7088674813905715446">Den här enheten har avaktualiserats av administratören. Du måste be administratören sätta enheten som väntande innan du kan registrera den.</translation>
 <translation id="7092474863625458670">Med Voice Match får du åtkomst till assistenten direkt genom att använda rösten.
     <ph name="BR" />
-    <ph name="BEGIN_BOLD" />Tänk på detta:<ph name="END_BOLD" /> En liknande röst eller en inspelning kan kanske också använda Assistenten. Du kan ta bort behörigheten för Voice Match senare genom att inaktivera dem i inställningarna för Google Assistent.</translation>
+    <ph name="BEGIN_BOLD" />Tänk på detta:<ph name="END_BOLD" /> Det kan hända att en liknande röst eller en inspelning också kan använda Assistenten. Du kan ta bort behörigheten för Voice Match senare genom att inaktivera den i inställningarna för Google Assistent.</translation>
 <translation id="7093434536568905704">GTK+</translation>
 <translation id="7093866338626856921">Utväxla data med enheterna <ph name="HOSTNAMES" /></translation>
 <translation id="7098389117866926363">USB-C-enhet (vänstra porten på baksidan)</translation>
@@ -4303,7 +4303,7 @@
 <translation id="7167486101654761064">Öppna &amp;alltid filer av denna typ</translation>
 <translation id="716810439572026343">Laddar ned <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Minsta teckenstorlek</translation>
-<translation id="7170041865419449892">Utanför intervallet</translation>
+<translation id="7170041865419449892">Utanför räckvidden</translation>
 <translation id="7171259390164035663">Registrera dig inte</translation>
 <translation id="7171559745792467651">Installera appar från dina andra enheter</translation>
 <translation id="7174199383876220879">Nyhet! Styr uppspelningen av musik, videor med mera.</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Aktivera Androids felsökningsbrygga (ADB) om du vill skapa och testa appar. Observera att den här åtgärden tillåter att Android-appar som inte har verifierats av Google installeras. Du måste återställa enheten till standardinställningarna för att inaktivera detta.</translation>
 <translation id="7685049629764448582">JavaScript-minne</translation>
 <translation id="7685087414635069102">Pinkod krävs</translation>
+<translation id="768549422429443215">Lägg till språk eller ändra ordning på listan.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bekräfta det nya lösenordet</translation>
 <translation id="7690378713476594306">Välj i lista</translation>
@@ -4923,7 +4924,7 @@
 <translation id="8017679124341497925">Genvägen har ändrats</translation>
 <translation id="8018313076035239964">Styr vilken information som webbplatser kan ta del av och vilket innehåll de kan visa</translation>
 <translation id="8023801379949507775">Uppdatera tillägg nu</translation>
-<translation id="8024483450737722621">Appar som du har laddat ned på Google Play tas bort från Chromebook.
+<translation id="8024483450737722621">Appar som du har laddat ned från Google Play tas bort från Chromebook.
       <ph name="LINE_BREAKS1" />
       Innehåll du har köpt, t.ex. filmer, TV-program, musik, böcker eller andra köp i appar, kan också tas bort.
       <ph name="LINE_BREAKS2" />
@@ -4942,7 +4943,7 @@
 <translation id="8041089156583427627">Skicka feedback</translation>
 <translation id="8042142357103597104">Textgenomskinlighet</translation>
 <translation id="8044262338717486897"><ph name="LINUX_APP_NAME" /> svarar inte.</translation>
-<translation id="8044899503464538266">Långsamt</translation>
+<translation id="8044899503464538266">Långsam</translation>
 <translation id="8045253504249021590">Synkronisering har stoppats via Google Översikt.</translation>
 <translation id="8045923671629973368">Ange program-id eller adress i webbutik</translation>
 <translation id="804786196054284061">Licensavtal för slutanvändare</translation>
@@ -5644,7 +5645,7 @@
 <translation id="9023015617655685412">Bokmärk den här fliken …</translation>
 <translation id="9024127637873500333">&amp;Öppna i ny flik</translation>
 <translation id="9024158959543687197">Det gick inte att montera den delade resursen. Kontrollera filresursens webbadress och försök igen.</translation>
-<translation id="9026731007018893674">ladda ned</translation>
+<translation id="9026731007018893674">nedladdning</translation>
 <translation id="9026852570893462412">Detta kan ta några minuter. Den virtuella maskinen laddas ned.</translation>
 <translation id="9027459031423301635">Öppna länk i ny &amp;flik</translation>
 <translation id="9030515284705930323">Organisationen har inte aktiverat Google Play Butik för ditt konto. Kontakta administratören om du vill veta mer.</translation>
@@ -5659,7 +5660,7 @@
 <translation id="904451693890288097">Ange lösenordet för <ph name="DEVICE_NAME" />:</translation>
 <translation id="9044646465488564462">Det gick inte att ansluta till nätverket: <ph name="DETAILS" /></translation>
 <translation id="9045430190527754450">Skickar webbadresserna till sidor som du försöker nå till Google</translation>
-<translation id="9046895021617826162">Kunde inte ansluta</translation>
+<translation id="9046895021617826162">Anslutningen misslyckades</translation>
 <translation id="9050666287014529139">Lösenfras</translation>
 <translation id="9052208328806230490">Du har registrerat dina skrivare med <ph name="CLOUD_PRINT_NAME" /> och du använde kontot <ph name="EMAIL" /></translation>
 <translation id="9052404922357793350">Fortsätt blockera</translation>
@@ -5706,7 +5707,7 @@
 <translation id="9112987648460918699">Sök...</translation>
 <translation id="9114663181201435112">Logga in enkelt</translation>
 <translation id="9115675100829699941">&amp;Bokmärken</translation>
-<translation id="9116465289595958864">Senast ändrat</translation>
+<translation id="9116465289595958864">Senast ändrad</translation>
 <translation id="9116799625073598554">App för anteckningar</translation>
 <translation id="9117030152748022724">Hantera dina appar</translation>
 <translation id="9121814364785106365">Öppna som en fast flik</translation>
diff --git a/chrome/app/resources/generated_resources_sw.xtb b/chrome/app/resources/generated_resources_sw.xtb
index bf4c387..82b6832 100644
--- a/chrome/app/resources/generated_resources_sw.xtb
+++ b/chrome/app/resources/generated_resources_sw.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Hakuna mitandao</translation>
 <translation id="1056898198331236512">Ilani</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Programu za Duka la Google Play</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> ina maudhui nyeti na imezuiwa.</translation>
 <translation id="1061904396131502319">Muda wa kupumzika umekaribia</translation>
 <translation id="1067048845568873861">Kiliundwa</translation>
@@ -1566,6 +1565,7 @@
 <translation id="3172808215939929606">Ukurasa huu umetafsiriwa</translation>
 <translation id="3177909033752230686">Lugha ya Ukurasa:</translation>
 <translation id="3179982752812949580">Fonti ya maandishi</translation>
+<translation id="3181825792072797598">Washa kipengele cha Kusawazisha</translation>
 <translation id="3181954750937456830">Kuvinjari Salama (hukulinda wewe na kifaa chako dhidi ya tovuti hatari)</translation>
 <translation id="3182749001423093222">Kikagua maendelezo</translation>
 <translation id="3183139917765991655">Kiletaji cha Wasifu</translation>
@@ -4648,6 +4648,7 @@
 <translation id="7684718995427157417">Ili kutengeneza na kujaribu programu zako, washa Zana ya Android Debug Bridge (ADB). Kumbuka kwamba hatua hii inaruhusu usakinishaji wa programu za Android ambazo hazijathibitishwa na Google na zinahitaji urejeshe mipangilio ya kiwandani ya kifaa ili kuzizima.</translation>
 <translation id="7685049629764448582">Kumbukumbu ya JavaScript</translation>
 <translation id="7685087414635069102">PIN inahitajika</translation>
+<translation id="768549422429443215">Ongeza lugha au panga orodha upya.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Thibitisha nenosiri jipya</translation>
 <translation id="7690378713476594306">Chagua kutoka kwenye orodha</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index 1b88f65c..b6bd4d28 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -48,7 +48,6 @@
 <translation id="1056775291175587022">நெட்வொர்க்குகள் இல்லை</translation>
 <translation id="1056898198331236512">எச்சரிக்கை</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play ஸ்டோர் ஆப்ஸ்</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> பாதுகாக்க வேண்டிய உள்ளடக்கத்தைக் கொண்டுள்ளது, எனவே இது முடக்கப்பட்டுள்ளது.</translation>
 <translation id="1061904396131502319">சாதனம் பூட்டப்பட உள்ளது</translation>
 <translation id="1067048845568873861">உருவாக்கப்பட்டது</translation>
@@ -1564,6 +1563,7 @@
 <translation id="3172808215939929606">இந்தப் பக்கம் மொழிபெயர்க்கப்பட்டது</translation>
 <translation id="3177909033752230686">பக்கத்தின் மொழி:</translation>
 <translation id="3179982752812949580">உரையின் எழுத்துரு</translation>
+<translation id="3181825792072797598">ஒத்திசைவை இயக்கு</translation>
 <translation id="3181954750937456830">பாதுகாப்பு உலாவல் (ஆபத்தான தளங்களிலிருந்து உங்களையும் சாதனத்தையும் பாதுகாக்கும்)</translation>
 <translation id="3182749001423093222">எழுத்துப் பிழை சரிபார்ப்பான்</translation>
 <translation id="3183139917765991655">புரோஃபைல் இம்போர்ட்டர்</translation>
@@ -1573,7 +1573,7 @@
 <translation id="3192947282887913208">ஆடியோ கோப்புகள்</translation>
 <translation id="3194737229810486521">உங்கள் சாதனத்தில், தரவை நிரந்தரமாகச் சேமிக்க <ph name="URL" /> விரும்புகிறது</translation>
 <translation id="3199127022143353223">சேவைகங்கள்</translation>
-<translation id="3201306578844503970">நெட்வொர்க் பிழையால் விர்ச்சுவல் மெஷினை நிறுவ முடியவில்லை. மீண்டும் முயலவும் அல்லது உங்கள் நிறுவனத்தின் சாதன நிர்வாகியைத் தொடர்பு கொள்ளவும். பிழைக் குறியீடு: <ph name="ERROR_CODE" />.</translation>
+<translation id="3201306578844503970">நெட்வொர்க் பிழை காரணமாக விர்ச்சுவல் மெஷினை நிறுவ முடியவில்லை. மீண்டும் முயலவும் அல்லது உங்கள் நிறுவனத்தின் சாதன நிர்வாகியைத் தொடர்பு கொள்ளவும். பிழைக் குறியீடு: <ph name="ERROR_CODE" />.</translation>
 <translation id="3201422919974259695">கிடைக்கக்கூடிய USB சாதனங்கள் இங்குத் தோன்றும்.</translation>
 <translation id="3202131003361292969">தடம்</translation>
 <translation id="3202173864863109533">இந்தத் தாவலின் ஆடியோ முடக்கப்படுகிறது.</translation>
@@ -2208,7 +2208,7 @@
 <translation id="407520071244661467">அளவு</translation>
 <translation id="4075639477629295004"><ph name="FILE_NAME" />ஐ அலைபரப்ப முடியவில்லை.</translation>
 <translation id="4077917118009885966">இந்தத் தளத்தில் விளம்பரங்கள் தடுக்கப்பட்டன</translation>
-<translation id="4077919383365622693"><ph name="SITE" /> தளத்தால் சேமிக்கப்பட்ட தரவும் குக்கீகளும்.</translation>
+<translation id="4077919383365622693"><ph name="SITE" /> தளத்தால் சேமிக்கப்பட்ட எல்லா தரவும் குக்கீகளும் அழிக்கப்படும்.</translation>
 <translation id="4079140982534148664">'மேம்பட்ட எழுத்துப் பிழை சரிபார்க்கும்' அம்சத்தைப் பயன்படுத்து</translation>
 <translation id="4081242589061676262">கோப்பை அலைபரப்ப முடியவில்லை.</translation>
 <translation id="4084682180776658562">புக்மார்க்</translation>
@@ -4634,6 +4634,7 @@
 <translation id="7684718995427157417">ஆப்ஸை உருவாக்கவும் பரிசோதிக்கவும் Android டீபக் பிரிட்ஜை (ADB) இயக்கவும். கவனத்திற்கு: இது Googleளால் சரிபார்க்கப்படாத Android ஆப்ஸ் நிறுவப்படுவதை அனுமதிக்கும், இதை முடக்க ஆரம்பநிலை அமைப்புகளுக்கு சாதனத்தை மீட்டமைக்க வேண்டும்.</translation>
 <translation id="7685049629764448582">JavaScript நினைவகம்</translation>
 <translation id="7685087414635069102">பின் தேவை</translation>
+<translation id="768549422429443215">மொழிகளைச் சேர்க்கவும் அல்லது பட்டியலை மாற்றியமைக்கவும்.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">புதிய கடவுச்சொல்லை உறுதிப்படுத்துக</translation>
 <translation id="7690378713476594306">பட்டியலில் இருந்து தேர்வு செய்யவும்</translation>
@@ -5769,7 +5770,7 @@
 <translation id="960719561871045870">ஆபரேட்டர் குறியீடு</translation>
 <translation id="960987915827980018">1 மணிநேரம் உள்ளது</translation>
 <translation id="962802172452141067">புத்தகக்குறி கோப்புறை ட்ரீ</translation>
-<translation id="964057662886721376">சில நீட்டிப்புகள் வேகத்தைக் குறைக்கக்கூடும். முக்கியமாக, நீங்கள் அறியாமல் நிறுவியவை இப்படி இருக்கும்.</translation>
+<translation id="964057662886721376">சில நீட்டிப்புகள் வேகத்தைக் குறைக்கக்கூடும். முக்கியமாக, நீங்கள் அறியாமல் நிறுவியவை இப்படி செய்யக்கூடும்.</translation>
 <translation id="964286338916298286">உங்கள் சாதனத்திற்கான Chrome சலுகைகளை உங்கள் IT நிர்வாகி முடக்கியுள்ளார்.</translation>
 <translation id="964439421054175458">{NUM_APLLICATIONS,plural, =1{இணங்காத பயன்பாடு}other{இணங்காத ஆப்ஸ்}}</translation>
 <translation id="965211523698323809"><ph name="DEVICE_TYPE" /> சாதனத்திலிருந்து மெசேஜ்களை அனுப்பலாம் / பெறலாம். <ph name="LINK_BEGIN" />மேலும் அறிக<ph name="LINK_END" /></translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index 797a76e..f8ce6774 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">నెట్‌వర్క్‌లు లేవు</translation>
 <translation id="1056898198331236512">హెచ్చరిక</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play స్టోర్ యాప్‌లు</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> గోప్యమైన కంటెంట్‌ను కలిగి ఉన్నందున బ్లాక్ చేయబడింది.</translation>
 <translation id="1061904396131502319">దాదాపు విరామ సమయం</translation>
 <translation id="1067048845568873861">సృష్టించబడింది</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">ఈ పేజీ అనువదించబడింది</translation>
 <translation id="3177909033752230686">పేజీ భాష:</translation>
 <translation id="3179982752812949580">వచన ఫాంట్</translation>
+<translation id="3181825792072797598">సమకాలీకరణను ఆన్ చేయి</translation>
 <translation id="3181954750937456830">సురక్షిత బ్రౌజింగ్ (ప్రమాదకరమైన సైట్‌ల నుండి మిమ్మల్ని, మీ పరికరాన్ని రక్షిస్తుంది)</translation>
 <translation id="3182749001423093222">స్పెల్ చెక్</translation>
 <translation id="3183139917765991655">ప్రొఫైల్ ఇంపోర్టర్</translation>
@@ -4652,6 +4652,7 @@
 <translation id="7684718995427157417">మీ యాప్‌లను సృష్టించి, పరీక్షించడానికి Android డీబగ్ బ్రిడ్జ్ (ADB)ను ప్రారంభించండి. ఈ చర్య వలన Google ద్వారా ధృవీకరించబడని Android యాప్‌ల ఇన్‌స్టాలేషన్ అనుమతించబడుతుందని, దీనిని నిలిపివేయడానికి ఫ్యాక్టరీ రీసెట్ చేయాల్సి ఉంటుందని గుర్తుంచుకోండి.</translation>
 <translation id="7685049629764448582">JavaScript మెమరీ</translation>
 <translation id="7685087414635069102">పిన్ అవసరం</translation>
+<translation id="768549422429443215">భాషలను జోడించండి లేదా జాబితా క్రమాన్ని మళ్లీ మార్చండి.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">కొత్త పాస్‌వర్డ్‌ను నిర్ధారించండి</translation>
 <translation id="7690378713476594306">జాబితా నుండి ఎంచుకోండి</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb
index 1f473e4..2bd01d1 100644
--- a/chrome/app/resources/generated_resources_th.xtb
+++ b/chrome/app/resources/generated_resources_th.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">ไม่พบเครือข่าย</translation>
 <translation id="1056898198331236512">คำเตือน</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">แอป Play Store</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> มีเนื้อหาที่ละเอียดอ่อนและถูกบล็อกแล้ว</translation>
 <translation id="1061904396131502319">เกือบถึงเวลาพักแล้ว</translation>
 <translation id="1067048845568873861">สร้างแล้ว</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">แปลหน้านี้แล้ว</translation>
 <translation id="3177909033752230686">ภาษาหน้าเว็บ:</translation>
 <translation id="3179982752812949580">แบบอักษรของข้อความ</translation>
+<translation id="3181825792072797598">เปิดการซิงค์</translation>
 <translation id="3181954750937456830">Google Safe Browsing (ปกป้องคุณและอุปกรณ์จากเว็บไซต์ที่เป็นอันตราย)</translation>
 <translation id="3182749001423093222">ตรวจตัวสะกด</translation>
 <translation id="3183139917765991655">ตัวนำเข้าโปรไฟล์</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">หากต้องการสร้างและทดสอบแอป ให้เปิดใช้ Android Debug Bridge (ADB) โปรดทราบว่าการดำเนินการนี้จะอนุญาตให้ติดตั้งแอป Android ที่ยังไม่ได้รับการยืนยันจาก Google และต้องรีเซ็ตเป็นค่าเริ่มต้นเพื่อปิดใช้</translation>
 <translation id="7685049629764448582">หน่วยความจำ JavaScript</translation>
 <translation id="7685087414635069102">ต้องระบุ PIN</translation>
+<translation id="768549422429443215">เพิ่มภาษาหรือจัดเรียงรายการใหม่</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ยืนยันรหัสผ่านใหม่</translation>
 <translation id="7690378713476594306">เลือกจากรายการ</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb
index fa71044..a711637 100644
--- a/chrome/app/resources/generated_resources_tr.xtb
+++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Hücresel ağ yok</translation>
 <translation id="1056898198331236512">Uyarı</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Store uygulamaları</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> hassas içerik barındırdığından engellendi.</translation>
 <translation id="1061904396131502319">Mola verme zamanı yaklaştı</translation>
 <translation id="1067048845568873861">Oluşturulduğu tarih</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Bu sayfa çevrildi</translation>
 <translation id="3177909033752230686">Sayfanın Dili:</translation>
 <translation id="3179982752812949580">Metin yazı tipi</translation>
+<translation id="3181825792072797598">Senkronizasyonu aç</translation>
 <translation id="3181954750937456830">Gizli Göz Atma (sizi ve cihazınızı tehlikelerden korur)</translation>
 <translation id="3182749001423093222">Yazım denetimi</translation>
 <translation id="3183139917765991655">Profil İçe Aktarıcısı</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">Uygulama oluşturup test etmek için Android Debug Bridge'i (ADB) etkinleştirin. Bu işlemin Google tarafından doğrulanmamış Android uygulamasının yüklenmesine izin verdiğini ve devre dışı bırakmak için fabrika ayarlarına sıfırlama işlemi yapılması gerektirdiğini unutmayın.</translation>
 <translation id="7685049629764448582">JavaScript belleği</translation>
 <translation id="7685087414635069102">PIN gerekli</translation>
+<translation id="768549422429443215">Dil ekleyin veya listeyi yeniden sıralayın</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Yeni şifreyi doğrula</translation>
 <translation id="7690378713476594306">Listeden seç</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index 72fe4a0..ad4b2dde 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Немає мереж</translation>
 <translation id="1056898198331236512">Застереження</translation>
 <translation id="1058262162121953039">PUK-код</translation>
-<translation id="1060881073479695738">Додатки з Play Маркету</translation>
 <translation id="1061745542578250838">Файл <ph name="FILE_NAME" /> було заблоковано, оскільки він містить конфіденційний контент.</translation>
 <translation id="1061904396131502319">Невдовзі час зробити перерву</translation>
 <translation id="1067048845568873861">Створено</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Цю сторінку перекладено</translation>
 <translation id="3177909033752230686">Мова сторінки:</translation>
 <translation id="3179982752812949580">Шрифт тексту</translation>
+<translation id="3181825792072797598">Увімкнути синхронізацію</translation>
 <translation id="3181954750937456830">Безпечний перегляд (захищає вас і ваш пристрій від небезпечних сайтів)</translation>
 <translation id="3182749001423093222">Перевірка правопису</translation>
 <translation id="3183139917765991655">Засіб імпортування профілів</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Щоб створювати й перевіряти додатки, увімкніть Android Debug Bridge (ADB). Зауважте, що цією дією ви дозволяєте встановлювати додатки для Android, які не були перевірені Google. Щоб вимкнути інструмент, доведеться відновити заводські налаштування.</translation>
 <translation id="7685049629764448582">Пам'ять JavaScript</translation>
 <translation id="7685087414635069102">Потрібен PIN-код</translation>
+<translation id="768549422429443215">Додайте мови або змініть порядок у списку.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Підтвердьте новий пароль</translation>
 <translation id="7690378713476594306">Вибрати зі списку</translation>
diff --git a/chrome/app/resources/generated_resources_ur.xtb b/chrome/app/resources/generated_resources_ur.xtb
index 7e41d2f2..395287b 100644
--- a/chrome/app/resources/generated_resources_ur.xtb
+++ b/chrome/app/resources/generated_resources_ur.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">کوئی نیٹ ورک نہیں ہے</translation>
 <translation id="1056898198331236512">وارننگ</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">‏Play اسٹور ایپس</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> حساس مواد پر مشتمل ہے، اور مسدود کر دیا گیا ہے۔</translation>
 <translation id="1061904396131502319">وقفے کا وقت تقریباً ہو گیا ہے</translation>
 <translation id="1067048845568873861">بنائی گئی</translation>
@@ -245,7 +244,7 @@
 <translation id="1329584516321524826">ابھی اپ ڈیٹ ہوا ہے</translation>
 <translation id="1330145147221172764">آن اسکرین کی بورڈ فعال کریں</translation>
 <translation id="1331977651797684645">یہ میں تھا۔</translation>
-<translation id="1333489022424033687">ہو سکتا ہے <ph name="ORIGIN" /> پر کچھ خصوصیات اس وقت تک کام نہ کرے جب تک آپ اپنے آلے پر دیگر سائٹس کے ذریعے اسٹور کردہ ڈیٹا کو صاف نہیں کرتے ہیں</translation>
+<translation id="1333489022424033687">ہو سکتا ہے <ph name="ORIGIN" /> پر کچھ خصوصیات اس وقت تک کام نہ کریں جب تک آپ اپنے آلے پر دیگر سائٹس کے ذریعے اسٹور کردہ ڈیٹا کو صاف نہیں کرتے ہیں</translation>
 <translation id="133535873114485416">ترجیحی ان پٹ</translation>
 <translation id="1335929031622236846">اپنے آلہ کا اندراج کرائيں</translation>
 <translation id="1338802252451106843"><ph name="ORIGIN" /> یہ ایپلیکیشن کھولنا چاہتا ہے۔</translation>
@@ -1570,6 +1569,7 @@
 <translation id="3172808215939929606">اس صفحہ کا ترجمہ کر دیا گیا ہے</translation>
 <translation id="3177909033752230686">صفحہ کی زبان:</translation>
 <translation id="3179982752812949580">متن کا فونٹ</translation>
+<translation id="3181825792072797598">مطابقت پذیری آن کریں</translation>
 <translation id="3181954750937456830">محفوظ براؤزنگ (آپ اور آپ کے آلہ کی خطرناک سائٹس سے حفاظت کرتی ہے)</translation>
 <translation id="3182749001423093222">املا کی جانچ</translation>
 <translation id="3183139917765991655">پروفائل درآمد کنندہ</translation>
@@ -4654,6 +4654,7 @@
 <translation id="7684718995427157417">‏اپنی ایپس کو تخلیق کرنے اور ٹیسٹ کرنے کے لیے، Android ڈیبگ برِج (ADB) کو فعال کریں۔ نوٹ کریں کہ یہ کارروائی ان Android ایپس کو انسٹال کرنے کی اجازت دیتی ہے جن کی تصدیق Google کے ذریعے نہیں کی گئی ہے، اور غیر فعال کرنے کے لیے فیکٹری ری سیٹ کی ضرورت ہوتی ہے۔</translation>
 <translation id="7685049629764448582">‏JavaScript میموری</translation>
 <translation id="7685087414635069102">‏PIN درکار ہے</translation>
+<translation id="768549422429443215">زبانیں شامل کریں یا فہرست دوبارہ ترتیب دیں۔</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">نئے پاس ورڈ کی توثیق کریں</translation>
 <translation id="7690378713476594306">فہرست سے منتخب کریں</translation>
diff --git a/chrome/app/resources/generated_resources_uz.xtb b/chrome/app/resources/generated_resources_uz.xtb
index 55395ca..1bbf29b9 100644
--- a/chrome/app/resources/generated_resources_uz.xtb
+++ b/chrome/app/resources/generated_resources_uz.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Hech qanday tarmoq yo‘q</translation>
 <translation id="1056898198331236512">Ogohlantirish</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play Market ilovalari</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> fayli ichida virusli kontent mavjudligi ehtimoli tufayli bloklandi.</translation>
 <translation id="1061904396131502319">Tanaffus qilish vaqti keldi</translation>
 <translation id="1067048845568873861">Yaratilgan sanasi</translation>
@@ -1567,6 +1566,7 @@
 <translation id="3172808215939929606">Bu sahifa tarjima qilindi</translation>
 <translation id="3177909033752230686">Sahifa tili:</translation>
 <translation id="3179982752812949580">Matn shrifti</translation>
+<translation id="3181825792072797598">Sinxronizatsiyani yoqish</translation>
 <translation id="3181954750937456830">Saytlarni xavfsiz kezish (sizni va qurilmangizni xavfli saytlardan himoya qiladi)</translation>
 <translation id="3182749001423093222">Imlo tekshiruvi</translation>
 <translation id="3183139917765991655">Profillar importi</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">Ilovalar ishlab chiqish va ularni sinash uchun Android Debug Bridge (ADB) vositasini faollashtiring. Eslatma: bunda Google tomonidan tekshirilmagan Android ilovalar ham oʻrnatilishi mumkin va zavod sozlamalariga tiklash yoqilmasligi kerak.</translation>
 <translation id="7685049629764448582">JavaScript xotira</translation>
 <translation id="7685087414635069102">PIN kodni kiritish zarur</translation>
+<translation id="768549422429443215">Tillar kiritish yoki roʻyxatni qayta tartiblash.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Yangi parolni tasdiqlang.</translation>
 <translation id="7690378713476594306">Ro‘yxatdan tanlash</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index 884bc20b..3940d62 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Không có mạng</translation>
 <translation id="1056898198331236512">Cảnh báo</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Ứng dụng Cửa hàng Play</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> chứa nội dung nhạy cảm và đã bị chặn.</translation>
 <translation id="1061904396131502319">Sắp đến giờ nghỉ giải lao</translation>
 <translation id="1067048845568873861">Đã tạo</translation>
@@ -1569,6 +1568,7 @@
 <translation id="3172808215939929606">Trang này đã được dịch</translation>
 <translation id="3177909033752230686">Ngôn ngữ trang:</translation>
 <translation id="3179982752812949580">Phông chữ</translation>
+<translation id="3181825792072797598">Bật Đồng bộ hóa</translation>
 <translation id="3181954750937456830">Duyệt web an toàn (bảo vệ bạn cũng như thiết bị của bạn khỏi các trang web nguy hiểm)</translation>
 <translation id="3182749001423093222">Kiểm tra chính tả</translation>
 <translation id="3183139917765991655">Trình nhập hồ sơ</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Để tạo và thử nghiệm ứng dụng của bạn, hãy bật Cầu gỡ lỗi Android (Android Debug Bridge – ADB). Xin lưu ý rằng thao tác này sẽ cho phép cài đặt các ứng dụng Android mà Google chưa xác minh. Để tắt ADB, bạn cần phải đặt lại thiết bị về trạng thái ban đầu.</translation>
 <translation id="7685049629764448582">Bộ nhớ cho JavaScript</translation>
 <translation id="7685087414635069102">Cần có mã PIN</translation>
+<translation id="768549422429443215">Thêm ngôn ngữ hoặc sắp xếp lại danh sách.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Xác nhận mật khẩu mới</translation>
 <translation id="7690378713476594306">Chọn từ danh sách</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index 504f077a..68f13539 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">找不到任何网络</translation>
 <translation id="1056898198331236512">警告</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play 商店应用</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> 包含敏感内容,因此已被拦截。</translation>
 <translation id="1061904396131502319">快到休息时间了</translation>
 <translation id="1067048845568873861">创建时间</translation>
@@ -244,7 +243,7 @@
 <translation id="1329584516321524826">上次更新时间:刚才</translation>
 <translation id="1330145147221172764">启用屏幕键盘</translation>
 <translation id="1331977651797684645">是我本人。</translation>
-<translation id="1333489022424033687"><ph name="ORIGIN" /> 上的某些功能可能无法正常发挥作用,除非您清除其他网站在您设备上存储的数据</translation>
+<translation id="1333489022424033687">请清除您设备上存储的其他网站的数据,否则 <ph name="ORIGIN" /> 上的某些功能可能无法正常运行</translation>
 <translation id="133535873114485416">首选输入模式</translation>
 <translation id="1335929031622236846">注册您的设备</translation>
 <translation id="1338802252451106843"><ph name="ORIGIN" /> 想打开此应用。</translation>
@@ -1565,6 +1564,7 @@
 <translation id="3172808215939929606">此网页已翻译完毕</translation>
 <translation id="3177909033752230686">网页语言:</translation>
 <translation id="3179982752812949580">文本字体</translation>
+<translation id="3181825792072797598">开启同步功能</translation>
 <translation id="3181954750937456830">安全浏览(保护您和您的设备不受危险网站的侵害)</translation>
 <translation id="3182749001423093222">拼写检查</translation>
 <translation id="3183139917765991655">个人资料导入应用</translation>
@@ -4103,7 +4103,7 @@
 <translation id="6892812721183419409">以 <ph name="USER" /> 身份打开链接</translation>
 <translation id="6895032998810961280">向 Google 报告在此次清理期间在您计算机中发现的有害软件、系统设置和进程的相关详情</translation>
 <translation id="6896758677409633944">复制</translation>
-<translation id="6897363604023044284">选择网站以清除数据</translation>
+<translation id="6897363604023044284">选择需要清除数据的网站</translation>
 <translation id="6898440773573063262">自助服务终端应用现在可配置为在此设备上自动启动。</translation>
 <translation id="6898699227549475383">组织 (O)</translation>
 <translation id="6900284862687837908">后台应用:<ph name="BACKGROUND_APP_URL" /></translation>
@@ -4648,6 +4648,7 @@
 <translation id="7684718995427157417">要创建和测试您的应用,请启用 Android 调试桥 (ADB)。请注意,此操作会允许安装未经 Google 验证的 Android 应用,而且您会需要将设备恢复出厂设置才能停用 ADB。</translation>
 <translation id="7685049629764448582">JavaScript 使用的内存</translation>
 <translation id="7685087414635069102">必须输入 PIN 码</translation>
+<translation id="768549422429443215">添加语言或将列表中的语言重新排列。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">再次输入新密码</translation>
 <translation id="7690378713476594306">从列表中选择</translation>
diff --git a/chrome/app/resources/generated_resources_zh-HK.xtb b/chrome/app/resources/generated_resources_zh-HK.xtb
index 93941f6..aa710773 100644
--- a/chrome/app/resources/generated_resources_zh-HK.xtb
+++ b/chrome/app/resources/generated_resources_zh-HK.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">沒有網絡</translation>
 <translation id="1056898198331236512">警告</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">「Play 商店」應用程式</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> 包含敏感內容,因此已被封鎖。</translation>
 <translation id="1061904396131502319">快到休息時間了</translation>
 <translation id="1067048845568873861">已建立</translation>
@@ -1567,6 +1566,7 @@
 <translation id="3172808215939929606">已翻譯此網頁的內容</translation>
 <translation id="3177909033752230686">網頁語言:</translation>
 <translation id="3179982752812949580">文字字型</translation>
+<translation id="3181825792072797598">開啟同步處理功能</translation>
 <translation id="3181954750937456830">安全瀏覽 (保護您和裝置免受危險網站攻擊)</translation>
 <translation id="3182749001423093222">拼字檢查</translation>
 <translation id="3183139917765991655">個人檔案匯入工具</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">如要建立並測試您的應用程式,請啟用「Android 偵錯橋接器」(ADB)。請注意,此操作允許安裝未經 Google 驗證的 Android 應用程式,並且需要恢復原廠設定才能停用。</translation>
 <translation id="7685049629764448582">JavaScript 記憶體使用量</translation>
 <translation id="7685087414635069102">必須提供 PIN</translation>
+<translation id="768549422429443215">新增語言或重新排列清單。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">確認新密碼</translation>
 <translation id="7690378713476594306">從清單中選擇</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index af413e4..b007211 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">沒有網路</translation>
 <translation id="1056898198331236512">警告</translation>
 <translation id="1058262162121953039">PUK</translation>
-<translation id="1060881073479695738">Play 商店應用程式</translation>
 <translation id="1061745542578250838"><ph name="FILE_NAME" /> 包含敏感內容,因此已遭到封鎖。</translation>
 <translation id="1061904396131502319">快到休息時間了</translation>
 <translation id="1067048845568873861">建立時間</translation>
@@ -197,7 +196,7 @@
 <translation id="1260451001046713751">一律允許 <ph name="HOST" /> 的彈出式視窗和重新導向</translation>
 <translation id="126156426083987769">示範模式的裝置授權發生問題。</translation>
 <translation id="126710816202626562">翻譯語言:</translation>
-<translation id="126768002343224824">16x</translation>
+<translation id="126768002343224824">16 倍</translation>
 <translation id="1272079795634619415">停止</translation>
 <translation id="1272293450992660632">PIN 碼值不相符。</translation>
 <translation id="1272978324304772054">裝置註冊的網域中沒有這個使用者帳戶。如果你要使用其他網域進行註冊,必須先完成裝置修復作業。</translation>
@@ -832,7 +831,7 @@
 <translation id="2157474325782140681">如要取得其他功能,請使用這部 Chromebook 的專用座架。</translation>
 <translation id="215753907730220065">結束全螢幕</translation>
 <translation id="2157875535253991059">這個頁面已顯示為全螢幕。</translation>
-<translation id="216169395504480358">新增 WiFi...</translation>
+<translation id="216169395504480358">新增 Wi-Fi...</translation>
 <translation id="2162155940152307086">同步功能會在你退出同步功能設定後立即啟動</translation>
 <translation id="2163470535490402084">請連線至網際網路,以登入您的 <ph name="DEVICE_TYPE" />。</translation>
 <translation id="2165421703844373933">只要說出「Ok Google」就能存取 Google 助理。如要節省電力,請選擇「啟用 (建議設定)」。這樣一來,你的 Google 助理就只會在裝置插上電源或充電時回應你的指令。</translation>
@@ -1015,7 +1014,7 @@
 <translation id="241727068219398187">系統已採用你在 <ph name="TIME" />設定的 Google 密碼針對資料進行加密處理。加密的資料不包括 Google Pay 的付款方式和地址。</translation>
 <translation id="2419706071571366386">為了安全起見,當你未使用電腦時請登出帳戶。</translation>
 <translation id="2422125132043002186">已取消 Linux 還原作業</translation>
-<translation id="2423578206845792524">另存圖檔(&amp;V)...</translation>
+<translation id="2423578206845792524">另存圖片(&amp;V)...</translation>
 <translation id="2428510569851653187">說明分頁當掉時你正在執行的動作</translation>
 <translation id="2431027948063157455">無法載入 Google 助理,請檢查網路連線狀態並重試。</translation>
 <translation id="2432753757290432042">必須更新 Linux (測試版)</translation>
@@ -1037,7 +1036,7 @@
 <translation id="2448312741937722512">類型</translation>
 <translation id="2450223707519584812">找不到 Google API 金鑰,因此您無法新增使用者。詳情請參閱 <ph name="DETAILS_URL" />。</translation>
 <translation id="2450849356604136918">沒有運作中的檢視畫面</translation>
-<translation id="2451298179137331965">2x</translation>
+<translation id="2451298179137331965">2 倍</translation>
 <translation id="2453860139492968684">結束</translation>
 <translation id="2454247629720664989">關鍵字</translation>
 <translation id="245650153866130664">如果要自動重新整理票證,請勾選「記住密碼」。你的密碼只會儲存在你的裝置上。</translation>
@@ -1090,7 +1089,7 @@
 <translation id="2507397597949272797">「<ph name="NAME" />」已暫停</translation>
 <translation id="2508428939232952663">Google Play 商店帳戶</translation>
 <translation id="2509495747794740764">縮放比例必須為介於 10 和 200 之間的數字。</translation>
-<translation id="2509566264613697683">8x</translation>
+<translation id="2509566264613697683">8 倍</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2517472476991765520">掃描</translation>
 <translation id="2518024842978892609">使用您的用戶端憑證</translation>
@@ -1165,7 +1164,7 @@
 <translation id="2619761439309613843">每日變換新桌布</translation>
 <translation id="2620436844016719705">系統</translation>
 <translation id="2621713457727696555">已受到安全保護</translation>
-<translation id="26224892172169984">不允許任何網站處理通訊協定</translation>
+<translation id="26224892172169984">禁止任何網站處理通訊協定</translation>
 <translation id="2624142942574147739">這個網頁正在存取你的攝影機和麥克風。</translation>
 <translation id="2626799779920242286">請稍後再試。</translation>
 <translation id="2628770867680720336">如要啟用 ADB 偵錯,必須將這部 Chromebook 恢復原廠設定。<ph name="BEGIN_LINK_LEARN_MORE" />瞭解詳情<ph name="END_LINK_LEARN_MORE" /></translation>
@@ -1479,7 +1478,7 @@
 <translation id="3036546437875325427">啟用 Flash</translation>
 <translation id="3037754279345160234">無法對加入網域的設定進行剖析,請與你的管理員聯絡。</translation>
 <translation id="3038612606416062604">手動新增印表機</translation>
-<translation id="3038675903128704560">不允許任何網站使用外掛程式存取你的電腦</translation>
+<translation id="3038675903128704560">禁止任何網站使用外掛程式存取你的電腦</translation>
 <translation id="3039491566278747710">無法在裝置上安裝離線政策。</translation>
 <translation id="3043581297103810752">來自 <ph name="ORIGIN" /></translation>
 <translation id="3045447014237878114">這個網站已自動下載多個檔案</translation>
@@ -1525,7 +1524,7 @@
 <translation id="3122496702278727796">無法建立資料目錄</translation>
 <translation id="3124111068741548686">USER 控制代碼</translation>
 <translation id="3126026824346185272">Ctrl</translation>
-<translation id="3127156390846601284">這會將顯示的所有網站儲存在你裝置上的資料全部刪除。你要繼續操作嗎?</translation>
+<translation id="3127156390846601284">這將會刪除所有顯示的網站儲存在你裝置上的全部資料。你要繼續操作嗎?</translation>
 <translation id="3127860049873093642">為避免發生充電和效能問題,請使用相容的 Dell 或 USB Type-C 電源變壓器。</translation>
 <translation id="3129173833825111527">左邊界</translation>
 <translation id="3130528281680948470">你的裝置將會進行重設,且所有使用者帳戶和本機資料都會遭到移除。這項操作無法復原。</translation>
@@ -1568,6 +1567,7 @@
 <translation id="3172808215939929606">這個網頁的內容已經過翻譯</translation>
 <translation id="3177909033752230686">網頁語言:</translation>
 <translation id="3179982752812949580">文字字型</translation>
+<translation id="3181825792072797598">開啟同步處理功能</translation>
 <translation id="3181954750937456830">安全瀏覽 (保護你和你的裝置不受危險網站攻擊)</translation>
 <translation id="3182749001423093222">拼字檢查</translation>
 <translation id="3183139917765991655">設定檔匯入工具</translation>
@@ -2285,7 +2285,7 @@
 <translation id="4175737294868205930">永久儲存空間</translation>
 <translation id="4176463684765177261">已停用</translation>
 <translation id="4180788401304023883">刪除憑證授權單位(CA) 的「<ph name="CERTIFICATE_NAME" />」憑證?</translation>
-<translation id="4181602000363099176">20x</translation>
+<translation id="4181602000363099176">20 倍</translation>
 <translation id="4181841719683918333">語言</translation>
 <translation id="4184885522552335684">拖曳即可移動顯示畫面</translation>
 <translation id="4194570336751258953">啟用點按功能</translation>
@@ -2731,7 +2731,7 @@
 <translation id="4882831918239250449">控制 Google 使用瀏覽記錄提供個人化搜尋服務、廣告和其他內容的方式</translation>
 <translation id="4883436287898674711">所有 <ph name="WEBSITE_1" /> 網站</translation>
 <translation id="48838266408104654">工作管理員(&amp;T)</translation>
-<translation id="4884987973312178454">6x</translation>
+<translation id="4884987973312178454">6 倍</translation>
 <translation id="4885705234041587624">MSCHAPv2</translation>
 <translation id="4887424188275796356">使用 System Viewer 開啟</translation>
 <translation id="488785315393301722">顯示詳細資料</translation>
@@ -2761,7 +2761,7 @@
 <translation id="4920887663447894854">下列網站已遭封鎖,無法在你瀏覽此網頁時追蹤你的位置:</translation>
 <translation id="492299503953721473">移除 Android 應用程式</translation>
 <translation id="4923279099980110923">是,我願意協助</translation>
-<translation id="4924352752174756392">12x</translation>
+<translation id="4924352752174756392">12 倍</translation>
 <translation id="4925542575807923399">這個帳戶的管理員要求此帳戶必需是多重登入工作階段中第一個登入的帳戶。</translation>
 <translation id="4927753642311223124">這裡沒有任何通知訊息,以後再來看看吧!</translation>
 <translation id="4929386379796360314">列印目的地</translation>
@@ -2850,7 +2850,7 @@
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5067399438976153555">一律啟用</translation>
 <translation id="5067867186035333991">當 <ph name="HOST" /> 要求存取麥克風時詢問我。</translation>
-<translation id="5068918910148307423">禁止最近關閉的網站完成資料的傳送及接收</translation>
+<translation id="5068918910148307423">禁止最近關閉的網站完成資料收發作業</translation>
 <translation id="5068919226082848014">披薩</translation>
 <translation id="5072052264945641674">調整游標大小</translation>
 <translation id="5072836811783999860">顯示受管理書籤</translation>
@@ -3100,7 +3100,7 @@
 <translation id="544083962418256601">建立捷徑...</translation>
 <translation id="5442228125690314719">建立磁碟映像檔時發生錯誤,請再試一次。</translation>
 <translation id="5442550868130618860">開啟自動更新功能</translation>
-<translation id="5445400788035474247">10x</translation>
+<translation id="5445400788035474247">10 倍</translation>
 <translation id="5446983216438178612">顯示機構憑證</translation>
 <translation id="5448293924669608770">糟糕,登入帳戶時發生錯誤</translation>
 <translation id="5449551289610225147">密碼無效</translation>
@@ -3202,7 +3202,7 @@
 <translation id="5578059481725149024">自動登入</translation>
 <translation id="558170650521898289">Microsoft Windows 硬體驅動程式驗證</translation>
 <translation id="5582839680698949063">主選單</translation>
-<translation id="5583640892426849032">Backspace 鍵</translation>
+<translation id="5583640892426849032">Backspace</translation>
 <translation id="5584088138253955452">要儲存使用者名稱嗎?</translation>
 <translation id="5584915726528712820"><ph name="BEGIN_PARAGRAPH1" />這會提供裝置和裝置使用情況的一般資訊 (例如電池電量、系統和應用程式活動,以及錯誤資訊)。這些資料會用於改善 Android 使用體驗,而部分匯總資訊還能協助 Google 應用程式和合作夥伴 (例如 Android 開發人員) 提高應用程式和產品的品質。<ph name="END_PARAGRAPH1" />
     <ph name="BEGIN_PARAGRAPH2" />即使關閉這項功能,你的裝置仍然可以傳送基本服務 (例如系統更新與安全服務) 所需的資訊。<ph name="END_PARAGRAPH2" />
@@ -4220,7 +4220,7 @@
 <translation id="7056526158851679338">檢查裝置 (&amp;I)</translation>
 <translation id="7059858479264779982">設為自動啟動</translation>
 <translation id="7059893117020417984">如果想要進行私密瀏覽,請按一下三個圓點圖示的選單,然後開啟無痕式視窗</translation>
-<translation id="7062222374113411376">允許最近關閉的網站完成資料的傳送及接收 (建議)</translation>
+<translation id="7062222374113411376">允許最近關閉的網站完成資料收發作業 (建議)</translation>
 <translation id="7063129466199351735">正在處理捷徑...</translation>
 <translation id="7063311912041006059">以 <ph name="SPECIAL_SYMBOL" /> 取代查詢的網址</translation>
 <translation id="7063957500469387217">使用 Google 雲端列印設定或管理印表機。</translation>
@@ -4472,7 +4472,7 @@
 <translation id="7410344089573941623">當 <ph name="HOST" /> 要求存取攝影機和麥克風時詢問我。</translation>
 <translation id="741204030948306876">是,我要啟用</translation>
 <translation id="7412226954991670867">GPU 記憶體</translation>
-<translation id="7414464185801331860">18x</translation>
+<translation id="7414464185801331860">18 倍</translation>
 <translation id="7415454883318062233">設定完成</translation>
 <translation id="7416362041876611053">不明的網路錯誤。</translation>
 <translation id="741906494724992817">這個應用程式不需要任何特殊權限。</translation>
@@ -4611,7 +4611,7 @@
 <translation id="7631887513477658702">一律開啟這類檔案(&amp;A)</translation>
 <translation id="7632948528260659758">下列 Kiosk 應用程式更新失敗:</translation>
 <translation id="7634566076839829401">發生錯誤,請再試一次。</translation>
-<translation id="763632859238619983">不允許任何網站安裝付款處理常式</translation>
+<translation id="763632859238619983">禁止任何網站安裝付款處理常式</translation>
 <translation id="7636919061354591437">安裝到這部裝置</translation>
 <translation id="7638605456503525968">序列埠</translation>
 <translation id="764017888128728"><ph name="PASSWORD_MANAGER_BRAND" /> 會使用您儲存的密碼,讓您自動登入符合資格的網站。</translation>
@@ -4651,6 +4651,7 @@
 <translation id="7684718995427157417">如要建立並測試你的應用程式,請啟用 Android Debug Bridge (ADB)。請注意,這項操作會允許你安裝未經 Google 驗證的 Android 應用程式,而且需要將裝置恢復原廠設定才能停用。</translation>
 <translation id="7685049629764448582">JavaScript 記憶體使用量</translation>
 <translation id="7685087414635069102">請輸入 PIN 碼</translation>
+<translation id="768549422429443215">新增語言或重新排列清單。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">確認新密碼</translation>
 <translation id="7690378713476594306">從清單中選擇</translation>
@@ -5634,7 +5635,7 @@
 <translation id="9018218886431812662">安裝完成</translation>
 <translation id="901834265349196618">電子郵件</translation>
 <translation id="9019062154811256702">讀取及變更自動填入設定</translation>
-<translation id="9020362265352758658">4x</translation>
+<translation id="9020362265352758658">4 倍</translation>
 <translation id="9021662811137657072">系統偵測到病毒</translation>
 <translation id="9022847679183471841"><ph name="AVATAR_NAME" />目前已在這部電腦上使用這個帳戶。</translation>
 <translation id="9023009238991294202">這個裝置的其他使用者可以使用這個網路。</translation>
@@ -5667,7 +5668,7 @@
 <translation id="9056810968620647706">找不到相符項目。</translation>
 <translation id="9057354806206861646">更新時間表</translation>
 <translation id="9062065967472365419">隨機</translation>
-<translation id="9062468308252555888">14x</translation>
+<translation id="9062468308252555888">14 倍</translation>
 <translation id="9063208415146866933">第 <ph name="ERROR_LINE_START" /> 至第 <ph name="ERROR_LINE_END" /> 行有錯誤</translation>
 <translation id="9064142312330104323">Google 個人資料相片 (載入中)</translation>
 <translation id="9064275926664971810">啟用自動填入功能,輕鬆一按即可填妥表單</translation>
diff --git a/chrome/app/resources/generated_resources_zu.xtb b/chrome/app/resources/generated_resources_zu.xtb
index a26aaef..fb8e8ad 100644
--- a/chrome/app/resources/generated_resources_zu.xtb
+++ b/chrome/app/resources/generated_resources_zu.xtb
@@ -49,7 +49,6 @@
 <translation id="1056775291175587022">Awekho amanethiwekhi</translation>
 <translation id="1056898198331236512">Isexwayiso</translation>
 <translation id="1058262162121953039">I-PUK</translation>
-<translation id="1060881073479695738">Izinhlelo zokusebenza ze-Google Play Isitolo</translation>
 <translation id="1061745542578250838">I-<ph name="FILE_NAME" /> iqukethe ulwazi oluzwelayo, futhi ivinjiwe.</translation>
 <translation id="1061904396131502319">Kucishe isikhathi sekhefu</translation>
 <translation id="1067048845568873861">Idaliwe</translation>
@@ -1567,6 +1566,7 @@
 <translation id="3172808215939929606">Leli khasi lihunyushiwe</translation>
 <translation id="3177909033752230686">Ulimi lwekhasi:</translation>
 <translation id="3179982752812949580">Ifonti yombhalo</translation>
+<translation id="3181825792072797598">Vula ukuvumelanisa</translation>
 <translation id="3181954750937456830">I-Safe Browsing (ivikela wena nedivayisi yakho kumasayithi ayingozi)</translation>
 <translation id="3182749001423093222">Ukuhlola ukupela</translation>
 <translation id="3183139917765991655">Isingenisi sephrofayela</translation>
@@ -4653,6 +4653,7 @@
 <translation id="7684718995427157417">Ukuze udale uphinde uhlole izinhlelo zakho zokusebenza, nika amandla i-Android Debug Bridge (ADB). Qaphela ukuthi lesi senzo sivumela ukufakwa kwezinhlelo zokusebenza ze-Android ezingazange ziqinisekiswe i-Google, futhi sidinga ukusethwa kabusha kwasekuqaleni ukuze usikhubaze.</translation>
 <translation id="7685049629764448582">Imemori ye-JavaScript</translation>
 <translation id="7685087414635069102">I-PIN iyadingeka</translation>
+<translation id="768549422429443215">Engeza izilimi noma oda kabusha uhlu.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Qinisekisa iphasiwedi entsha</translation>
 <translation id="7690378713476594306">Khetha kusuka kuhlu</translation>
diff --git a/chrome/app/resources/google_chrome_strings_ar.xtb b/chrome/app/resources/google_chrome_strings_ar.xtb
index 6a19026..c0ffd52 100644
--- a/chrome/app/resources/google_chrome_strings_ar.xtb
+++ b/chrome/app/resources/google_chrome_strings_ar.xtb
@@ -50,7 +50,7 @@
 <translation id="2290014774651636340">‏مفاتيح واجهة برمجة تطبيقات Google مفقودة. وسيترتب على ذلك توقف بعض وظائف Google Chrome عن العمل.</translation>
 <translation id="2290095356545025170">‏هل تريد فعلًا إزالة Google Chrome؟</translation>
 <translation id="2309047409763057870">‏هذا تثبيت ثانوي من Google Chrome، ولا يمكن جعله متصفحك التلقائي.</translation>
-<translation id="2341767445688917208">‏تعذّر على نظام تشغيل Chrome مزامنة كلمات المرور. إصلاح المشكلة الآن.</translation>
+<translation id="2341767445688917208">‏تعذّر على نظام التشغيل Chrome مزامنة كلمات المرور. إصلاح المشكلة الآن</translation>
 <translation id="2348335408836342058">‏يحتاج Chrome إلى إذن للوصول إلى الكاميرا والميكروفون من أجل موقع الويب هذا.</translation>
 <translation id="2429317896000329049">‏تعذر على Google Chrome مزامنة البيانات نظرًا لأن المزامنة غير متاحة في نطاقك.</translation>
 <translation id="2467438592969358367">‏يرغب Google Chrome في تصدير كلمات مرورك، لذا يُرجى كتابة كلمة مرور Windows للسماح بذلك.</translation>
@@ -210,7 +210,7 @@
 <translation id="7855730255114109580">‏Google Chrome محدّث</translation>
 <translation id="7890208801193284374">‏إذا كنت تشارك الكمبيوتر مع أصدقائك وعائلتك، فبإمكانهم التصفح على حدة وإعداد Chrome على النحو الذي يريدونه.</translation>
 <translation id="7896673875602241923">‏سجّل شخص ما الدخول من قبل إلى Chrome على جهاز الكمبيوتر هذا باسم <ph name="ACCOUNT_EMAIL_LAST" />. يُرجى إنشاء حساب مستخدم جديد في Chrome للإبقاء على معلوماتك بشكلٍ منفصل.</translation>
-<translation id="7916016681687251387">‏تعذّر على نظام التشغيل Chrome مزامنة بياناتك. إصلاح المشكلة الآن.</translation>
+<translation id="7916016681687251387">‏تعذّر على نظام التشغيل Chrome مزامنة بياناتك. إصلاح المشكلة الآن</translation>
 <translation id="7962410387636238736">‏لن يستلم جهاز الكمبيوتر هذا تحديثات Google Chrome لأن Windows XP وWindows Vista أصبحا غير مدعومين.</translation>
 <translation id="8008534537613507642">‏إعادة تثبيت Chrome</translation>
 <translation id="8013993649590906847">‏في حال لم تتضمن صورة ما وصفًا مفيدًا، سيحاول Chrome توفير وصف لك. لإنشاء الأوصاف، سيتم إرسال الصور إلى Google.</translation>
diff --git a/chrome/app/resources/google_chrome_strings_sv.xtb b/chrome/app/resources/google_chrome_strings_sv.xtb
index dfc87eb6..3bfe16a9 100644
--- a/chrome/app/resources/google_chrome_strings_sv.xtb
+++ b/chrome/app/resources/google_chrome_strings_sv.xtb
@@ -171,7 +171,7 @@
 <translation id="6291549208091401781">Google Chrome har redan installerats för alla användare på datorn.</translation>
 <translation id="6338556085225130112">Uppdaterar Google Chrome
 </translation>
-<translation id="6368958679917195344">Chrome OS fungerar tack vare <ph name="BEGIN_LINK_CROS_OSS" />öppen källkod<ph name="END_LINK_CROS_OSS" />.</translation>
+<translation id="6368958679917195344">Chrome OS fungerar tack vare <ph name="BEGIN_LINK_CROS_OSS" />ytterligare program med öppen källkod<ph name="END_LINK_CROS_OSS" />.</translation>
 <translation id="6515495397637126556"><ph name="PAGE_TITLE" /> – Google Chrome Dev</translation>
 <translation id="6566149418543181476">Google Chrome uppdateras (<ph name="PROGRESS_PERCENT" />)</translation>
 <translation id="6676384891291319759">Gå ut på Internet</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 171ac82..cc453704 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3760,8 +3760,6 @@
       "metrics/perf/collection_params.h",
       "metrics/perf/cpu_identity.cc",
       "metrics/perf/cpu_identity.h",
-      "metrics/perf/heap_collector.cc",
-      "metrics/perf/heap_collector.h",
       "metrics/perf/metric_collector.cc",
       "metrics/perf/metric_collector.h",
       "metrics/perf/metric_provider.cc",
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc
index a487cef..d6b5fef 100644
--- a/chrome/browser/captive_portal/captive_portal_browsertest.cc
+++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -71,6 +71,7 @@
 #include "content/public/test/url_loader_interceptor.h"
 #include "net/base/net_errors.h"
 #include "net/cert/x509_certificate.h"
+#include "net/dns/mock_host_resolver.h"
 #include "net/http/transport_security_state.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -910,6 +911,9 @@
       std::make_unique<content::URLLoaderInterceptor>(base::Bind(
           &CaptivePortalBrowserTest::OnIntercept, base::Unretained(this)));
 
+  // Do not introduce DNS errors.
+  host_resolver()->AddRule("*", "127.0.0.1");
+
   // Double-check that the captive portal service isn't enabled by default for
   // browser tests.
   EXPECT_EQ(CaptivePortalService::DISABLED_FOR_TESTING,
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 7926632..f53b622 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4368,9 +4368,10 @@
               network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
       return;
     }
-    content::CreateFileURLLoader(request, std::move(loader), std::move(client),
-                                 /*observer=*/nullptr,
-                                 /* allow_directory_listing */ true);
+    content::CreateFileURLLoaderBypassingSecurityChecks(
+        request, std::move(loader), std::move(client),
+        /*observer=*/nullptr,
+        /* allow_directory_listing */ true);
   }
 
   void Clone(
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 3d4de44..4950abb 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -76,6 +76,7 @@
     "//chrome/browser/resource_coordinator:tab_metrics_event_proto",
     "//chrome/browser/ssl:proto",
     "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings",
+    "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings",
     "//chrome/browser/web_applications",
     "//chrome/browser/web_applications:web_applications_on_extensions",
     "//chrome/browser/web_applications/components",
diff --git a/chrome/browser/chromeos/crostini/crostini_installer.h b/chrome/browser/chromeos/crostini/crostini_installer.h
index a2e6174..922e97c 100644
--- a/chrome/browser/chromeos/crostini/crostini_installer.h
+++ b/chrome/browser/chromeos/crostini/crostini_installer.h
@@ -29,6 +29,7 @@
  public:
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused.
+  // When you add entries to this enum don't forget to update enums.xml
   enum class SetupResult {
     kNotStarted = 0,
     // kUserCancelled = 1,
diff --git a/chrome/browser/chromeos/crostini/crostini_upgrader.cc b/chrome/browser/chromeos/crostini/crostini_upgrader.cc
index abd33881..6f990b53 100644
--- a/chrome/browser/chromeos/crostini/crostini_upgrader.cc
+++ b/chrome/browser/chromeos/crostini/crostini_upgrader.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/crostini/crostini_upgrader.h"
 
+#include "base/barrier_closure.h"
+#include "base/system/sys_info.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager_factory.h"
@@ -17,6 +19,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/network_service_instance.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
 
 namespace crostini {
 
@@ -58,7 +61,7 @@
 }
 
 CrostiniUpgrader::CrostiniUpgrader(Profile* profile)
-    : profile_(profile), container_id_("", "") {
+    : profile_(profile), container_id_("", ""), pmc_observer_(this) {
   CrostiniManager::GetForProfile(profile_)->AddUpgradeContainerProgressObserver(
       this);
 }
@@ -100,6 +103,72 @@
   }
 }
 
+void CrostiniUpgrader::StartPrechecks() {
+  auto* pmc = chromeos::PowerManagerClient::Get();
+  if (pmc_observer_.IsObserving(pmc)) {
+    // This could happen if two StartPrechecks were run at the same time. If it
+    // does, drop the second call.
+    return;
+  }
+
+  prechecks_callback_ =
+      base::BarrierClosure(2, /* Number of asynchronous prechecks to wait for */
+                           base::BindOnce(&CrostiniUpgrader::DoPrechecks,
+                                          weak_ptr_factory_.GetWeakPtr()));
+
+  pmc_observer_.Add(pmc);
+  pmc->RequestStatusUpdate();
+
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+      base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
+                     base::FilePath(crostini::kHomeDirectory)),
+      base::BindOnce(&CrostiniUpgrader::OnAvailableDiskSpace,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CrostiniUpgrader::PowerChanged(
+    const power_manager::PowerSupplyProperties& proto) {
+  // A battery can be FULL, CHARGING, DISCHARGING, or NOT_PRESENT. If we're on a
+  // system with no battery, we can assume stable power from the fact that we
+  // are running at all. Otherwise we want the battery to be full or charging. A
+  // less conservative check is possible, but we can expect users to have access
+  // to a charger.
+  power_status_good_ = proto.battery_state() !=
+                       power_manager::PowerSupplyProperties::DISCHARGING;
+
+  auto* pmc = chromeos::PowerManagerClient::Get();
+  pmc_observer_.Remove(pmc);
+
+  prechecks_callback_.Run();
+}
+
+void CrostiniUpgrader::OnAvailableDiskSpace(int64_t bytes) {
+  free_disk_space_ = bytes;
+
+  prechecks_callback_.Run();
+}
+
+void CrostiniUpgrader::DoPrechecks() {
+  chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus status;
+  if (free_disk_space_ < kDiskRequired) {
+    status = chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::
+        INSUFFICIENT_SPACE;
+  } else if (content::GetNetworkConnectionTracker()->IsOffline()) {
+    status = chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::
+        NETWORK_FAILURE;
+  } else if (!power_status_good_) {
+    status =
+        chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::LOW_POWER;
+  } else {
+    status = chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus::OK;
+  }
+
+  for (auto& observer : upgrader_observers_) {
+    observer.PrecheckStatus(status);
+  }
+}
+
 void CrostiniUpgrader::Upgrade(const ContainerId& container_id) {
   container_id_ = container_id;
   CrostiniManager::GetForProfile(profile_)->UpgradeContainer(
diff --git a/chrome/browser/chromeos/crostini/crostini_upgrader.h b/chrome/browser/chromeos/crostini/crostini_upgrader.h
index 6f16eb4c..d573216 100644
--- a/chrome/browser/chromeos/crostini/crostini_upgrader.h
+++ b/chrome/browser/chromeos/crostini/crostini_upgrader.h
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_UPGRADER_H_
 
 #include "base/callback_forward.h"
+#include "base/scoped_observer.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/crostini/crostini_upgrader_ui_delegate.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 class Profile;
@@ -16,6 +18,7 @@
 
 class CrostiniUpgrader : public KeyedService,
                          public UpgradeContainerProgressObserver,
+                         public chromeos::PowerManagerClient::Observer,
                          public CrostiniUpgraderUIDelegate {
  public:
   static CrostiniUpgrader* GetForProfile(Profile* profile);
@@ -33,6 +36,7 @@
   void AddObserver(CrostiniUpgraderUIObserver* observer) override;
   void RemoveObserver(CrostiniUpgraderUIObserver* observer) override;
   void Backup() override;
+  void StartPrechecks() override;
   void Upgrade(const ContainerId& container_id) override;
   void Cancel() override;
   void CancelBeforeStart() override;
@@ -43,18 +47,36 @@
       UpgradeContainerProgressStatus status,
       const std::vector<std::string>& messages) override;
 
+  // chromeos::PowerManagerClient::Observer:
+  void PowerChanged(const power_manager::PowerSupplyProperties& proto) override;
+
   // Return true if internal state allows starting upgrade.
   bool CanUpgrade();
 
+  // Require at least 1 GiB of free space. Experiments on an unmodified
+  // container suggest this is a bare minimum, anyone with a substantial amount
+  // of programs installed will likely require more.
+  static constexpr int64_t kDiskRequired = 1 << 30;
+
  private:
   void OnCancel(CrostiniResult result);
   void OnBackup(CrostiniResult result);
   void OnUpgrade(CrostiniResult result);
+  void OnAvailableDiskSpace(int64_t bytes);
+  void DoPrechecks();
 
   Profile* profile_;
   ContainerId container_id_;
   base::ObserverList<CrostiniUpgraderUIObserver>::Unchecked upgrader_observers_;
 
+  base::RepeatingClosure prechecks_callback_;
+  bool power_status_good_ = false;
+  int64_t free_disk_space_ = -1;
+
+  ScopedObserver<chromeos::PowerManagerClient,
+                 chromeos::PowerManagerClient::Observer>
+      pmc_observer_;
+
   base::WeakPtrFactory<CrostiniUpgrader> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/chromeos/crostini/crostini_upgrader_ui_delegate.h b/chrome/browser/chromeos/crostini/crostini_upgrader_ui_delegate.h
index c035b34..20766a6c 100644
--- a/chrome/browser/chromeos/crostini/crostini_upgrader_ui_delegate.h
+++ b/chrome/browser/chromeos/crostini/crostini_upgrader_ui_delegate.h
@@ -7,6 +7,7 @@
 
 #include "base/callback_forward.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom.h"
 
 namespace crostini {
 
@@ -17,6 +18,8 @@
   virtual void OnBackupProgress(int percent) = 0;
   virtual void OnBackupSucceeded() = 0;
   virtual void OnBackupFailed() = 0;
+  virtual void PrecheckStatus(
+      chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus status) = 0;
   virtual void OnUpgradeProgress(const std::vector<std::string>& messages) = 0;
   virtual void OnUpgradeSucceeded() = 0;
   virtual void OnUpgradeFailed() = 0;
@@ -33,6 +36,8 @@
   // Back up the current container before upgrading
   virtual void Backup() = 0;
 
+  virtual void StartPrechecks() = 0;
+
   // Start the upgrade.
   virtual void Upgrade(const ContainerId& container_id) = 0;
 
diff --git a/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.cc b/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.cc
index 44704d38..172cf0a 100644
--- a/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.cc
+++ b/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.cc
@@ -35,7 +35,7 @@
 
 void ChromeCryptohomeAuthenticator::CheckSafeModeOwnership(
     const UserContext& context,
-    const IsOwnerCallback& callback) {
+    IsOwnerCallback callback) {
   // |IsOwnerForSafeModeAsync| expects logged in state to be
   // LOGGED_IN_SAFE_MODE.
   if (LoginState::IsInitialized()) {
@@ -46,7 +46,7 @@
   OwnerSettingsServiceChromeOS::IsOwnerForSafeModeAsync(
       context.GetUserIDHash(),
       OwnerSettingsServiceChromeOSFactory::GetInstance()->GetOwnerKeyUtil(),
-      callback);
+      std::move(callback));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h b/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h
index 4f49744..a0d79f63 100644
--- a/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h
+++ b/chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h
@@ -22,7 +22,7 @@
   bool IsKnownUser(const UserContext& context) override;
   bool IsSafeMode() override;
   void CheckSafeModeOwnership(const UserContext& context,
-                              const IsOwnerCallback& callback) override;
+                              IsOwnerCallback callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ChromeCryptohomeAuthenticator);
diff --git a/chrome/browser/chromeos/login/auth/chrome_login_performer.cc b/chrome/browser/chromeos/login/auth/chrome_login_performer.cc
index df417025..588e9bd 100644
--- a/chrome/browser/chromeos/login/auth/chrome_login_performer.cc
+++ b/chrome/browser/chromeos/login/auth/chrome_login_performer.cc
@@ -33,13 +33,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ChromeLoginPerformer, public:
 
-bool ChromeLoginPerformer::RunTrustedCheck(const base::Closure& callback) {
+bool ChromeLoginPerformer::RunTrustedCheck(base::OnceClosure callback) {
   CrosSettings* cros_settings = CrosSettings::Get();
 
   CrosSettingsProvider::TrustedStatus status =
       cros_settings->PrepareTrustedValues(
-          base::Bind(&ChromeLoginPerformer::DidRunTrustedCheck,
-                     weak_factory_.GetWeakPtr(), callback));
+          base::BindOnce(&ChromeLoginPerformer::DidRunTrustedCheck,
+                         weak_factory_.GetWeakPtr(), &callback));
   // Must not proceed without signature verification.
   if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
     if (delegate_)
@@ -54,18 +54,18 @@
   } else {
     DCHECK(status == CrosSettingsProvider::TRUSTED);
     // CrosSettingsProvider::TRUSTED
-    callback.Run();
+    std::move(callback).Run();
     return true;  // Some callback was called.
   }
 }
 
-void ChromeLoginPerformer::DidRunTrustedCheck(const base::Closure& callback) {
+void ChromeLoginPerformer::DidRunTrustedCheck(base::OnceClosure* callback) {
   CrosSettings* cros_settings = CrosSettings::Get();
 
   CrosSettingsProvider::TrustedStatus status =
       cros_settings->PrepareTrustedValues(
-          base::Bind(&ChromeLoginPerformer::DidRunTrustedCheck,
-                     weak_factory_.GetWeakPtr(), callback));
+          base::BindOnce(&ChromeLoginPerformer::DidRunTrustedCheck,
+                         weak_factory_.GetWeakPtr(), callback));
   // Must not proceed without signature verification.
   if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
     if (delegate_)
@@ -78,7 +78,7 @@
     return;
   } else {
     DCHECK(status == CrosSettingsProvider::TRUSTED);
-    callback.Run();
+    std::move(*callback).Run();
   }
 }
 
@@ -92,8 +92,8 @@
     const AccountId& account_id,
     bool wildcard_match,
     const std::string& refresh_token,
-    const base::Closure& success_callback,
-    const base::Closure& failure_callback) {
+    base::OnceClosure success_callback,
+    base::OnceClosure failure_callback) {
   // On cloud managed devices, reconfirm login permission with the server.
   policy::BrowserPolicyConnectorChromeOS* connector =
       g_browser_process->platform_part()->browser_policy_connector_chromeos();
@@ -103,17 +103,18 @@
     if (refresh_token.empty()) {
       NOTREACHED() << "Refresh token must be present.";
       OnlineWildcardLoginCheckCompleted(
-          success_callback, failure_callback,
+          std::move(success_callback), std::move(failure_callback),
           policy::WildcardLoginChecker::RESULT_FAILED);
     } else {
       wildcard_login_checker_->StartWithRefreshToken(
           refresh_token,
-          base::Bind(&ChromeLoginPerformer::OnlineWildcardLoginCheckCompleted,
-                     weak_factory_.GetWeakPtr(), success_callback,
-                     failure_callback));
+          base::BindOnce(
+              &ChromeLoginPerformer::OnlineWildcardLoginCheckCompleted,
+              weak_factory_.GetWeakPtr(), std::move(success_callback),
+              std::move(failure_callback)));
     }
   } else {
-    success_callback.Run();
+    std::move(success_callback).Run();
   }
 }
 
@@ -176,13 +177,13 @@
 }
 
 void ChromeLoginPerformer::OnlineWildcardLoginCheckCompleted(
-    const base::Closure& success_callback,
-    const base::Closure& failure_callback,
+    base::OnceClosure success_callback,
+    base::OnceClosure failure_callback,
     policy::WildcardLoginChecker::Result result) {
   if (result == policy::WildcardLoginChecker::RESULT_ALLOWED) {
-    success_callback.Run();
+    std::move(success_callback).Run();
   } else {
-    failure_callback.Run();
+    std::move(failure_callback).Run();
   }
 }
 
diff --git a/chrome/browser/chromeos/login/auth/chrome_login_performer.h b/chrome/browser/chromeos/login/auth/chrome_login_performer.h
index 428e322..7b1bfee5 100644
--- a/chrome/browser/chromeos/login/auth/chrome_login_performer.h
+++ b/chrome/browser/chromeos/login/auth/chrome_login_performer.h
@@ -39,14 +39,17 @@
                          bool* wildcard_match) override;
 
  protected:
-  bool RunTrustedCheck(const base::Closure& callback) override;
-  void DidRunTrustedCheck(const base::Closure& callback);
+  bool RunTrustedCheck(base::OnceClosure callback) override;
+  // Runs |callback| unconditionally, but DidRunTrustedCheck() will only be run
+  // itself sometimes, so ownership of |callback| should not be held in the
+  // Callback pointing to DidRunTrustedCheck.
+  void DidRunTrustedCheck(base::OnceClosure* callback);
 
   void RunOnlineWhitelistCheck(const AccountId& account_id,
                                bool wildcard_match,
                                const std::string& refresh_token,
-                               const base::Closure& success_callback,
-                               const base::Closure& failure_callback) override;
+                               base::OnceClosure success_callback,
+                               base::OnceClosure failure_callback) override;
   bool AreSupervisedUsersAllowed() override;
 
   bool UseExtendedAuthenticatorForSupervisedUser(
@@ -66,8 +69,8 @@
 
  private:
   void OnlineWildcardLoginCheckCompleted(
-      const base::Closure& success_callback,
-      const base::Closure& failure_callback,
+      base::OnceClosure success_callback,
+      base::OnceClosure failure_callback,
       policy::WildcardLoginChecker::Result result);
 
   // Used to verify logins that matched wildcard on the login whitelist.
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
index d370a90a..6e54370e 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -157,19 +157,18 @@
 // not. Responds via |callback|.
 void DoesPrivateKeyExistAsync(
     const scoped_refptr<OwnerKeyUtil>& owner_key_util,
-    const OwnerSettingsServiceChromeOS::IsOwnerCallback& callback) {
+    OwnerSettingsServiceChromeOS::IsOwnerCallback callback) {
   if (!owner_key_util.get()) {
-    callback.Run(false);
+    std::move(callback).Run(false);
     return;
   }
   scoped_refptr<base::TaskRunner> task_runner = base::CreateTaskRunner(
       {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
   base::PostTaskAndReplyWithResult(
-      task_runner.get(),
-      FROM_HERE,
-      base::Bind(&DoesPrivateKeyExistAsyncHelper, owner_key_util),
-      callback);
+      task_runner.get(), FROM_HERE,
+      base::BindOnce(&DoesPrivateKeyExistAsyncHelper, owner_key_util),
+      std::move(callback));
 }
 
 }  // namespace
@@ -269,14 +268,13 @@
   return OwnerSettingsService::IsOwner();
 }
 
-void OwnerSettingsServiceChromeOS::IsOwnerAsync(
-    const IsOwnerCallback& callback) {
+void OwnerSettingsServiceChromeOS::IsOwnerAsync(IsOwnerCallback callback) {
   if (InstallAttributes::Get()->IsEnterpriseManaged()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(callback, false));
+        FROM_HERE, base::BindOnce(std::move(callback), false));
     return;
   }
-  OwnerSettingsService::IsOwnerAsync(callback);
+  OwnerSettingsService::IsOwnerAsync(std::move(callback));
 }
 
 bool OwnerSettingsServiceChromeOS::HandlesSetting(const std::string& setting) {
@@ -383,17 +381,18 @@
 void OwnerSettingsServiceChromeOS::IsOwnerForSafeModeAsync(
     const std::string& user_hash,
     const scoped_refptr<OwnerKeyUtil>& owner_key_util,
-    const IsOwnerCallback& callback) {
+    IsOwnerCallback callback) {
   CHECK(chromeos::LoginState::Get()->IsInSafeMode());
 
   // Make sure NSS is initialized and NSS DB is loaded for the user before
   // searching for the owner key.
   base::PostTaskAndReply(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
-                 user_hash,
-                 ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
-      base::Bind(&DoesPrivateKeyExistAsync, owner_key_util, callback));
+      base::BindOnce(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
+                     user_hash,
+                     ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
+      base::BindOnce(&DoesPrivateKeyExistAsync, owner_key_util,
+                     std::move(callback)));
 }
 
 // static
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
index aa54cb9..7abe77be 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
@@ -67,7 +67,7 @@
 
   // ownership::OwnerSettingsService implementation:
   bool IsOwner() override;
-  void IsOwnerAsync(const IsOwnerCallback& callback) override;
+  void IsOwnerAsync(IsOwnerCallback callback) override;
   bool HandlesSetting(const std::string& setting) override;
   bool Set(const std::string& setting, const base::Value& value) override;
   bool AppendToList(const std::string& setting,
@@ -93,7 +93,7 @@
   static void IsOwnerForSafeModeAsync(
       const std::string& user_hash,
       const scoped_refptr<ownership::OwnerKeyUtil>& owner_key_util,
-      const IsOwnerCallback& callback);
+      IsOwnerCallback callback);
 
   // Assembles PolicyData based on |settings|, |policy_data|, |user_id| and
   // |pending_management_settings|. Applies local-owner policy fixups if needed.
diff --git a/chrome/browser/chromeos/settings/cros_settings.cc b/chrome/browser/chromeos/settings/cros_settings.cc
index 2027bce..ac14dee 100644
--- a/chrome/browser/chromeos/settings/cros_settings.cc
+++ b/chrome/browser/chromeos/settings/cros_settings.cc
@@ -127,11 +127,11 @@
 }
 
 CrosSettingsProvider::TrustedStatus CrosSettings::PrepareTrustedValues(
-    const base::Closure& callback) const {
+    base::OnceClosure callback) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (size_t i = 0; i < providers_.size(); ++i) {
     CrosSettingsProvider::TrustedStatus status =
-        providers_[i]->PrepareTrustedValues(callback);
+        providers_[i]->PrepareTrustedValues(&callback);
     if (status != CrosSettingsProvider::TRUSTED)
       return status;
   }
diff --git a/chrome/browser/chromeos/settings/cros_settings.h b/chrome/browser/chromeos/settings/cros_settings.h
index 1d093690..e1641c7 100644
--- a/chrome/browser/chromeos/settings/cros_settings.h
+++ b/chrome/browser/chromeos/settings/cros_settings.h
@@ -81,7 +81,7 @@
   //   PrepareTrustedValues() should be called again at that point to determine
   //   whether all providers are serving trusted values now.
   virtual CrosSettingsProvider::TrustedStatus PrepareTrustedValues(
-      const base::Closure& callback) const;
+      base::OnceClosure callback) const;
 
   // These are convenience forms of Get().  The value will be retrieved
   // and the return value will be true if the |path| is valid and the value at
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index 43e49052..3a5d45f 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -1152,10 +1152,10 @@
 }
 
 DeviceSettingsProvider::TrustedStatus
-DeviceSettingsProvider::PrepareTrustedValues(base::OnceClosure callback) {
+DeviceSettingsProvider::PrepareTrustedValues(base::OnceClosure* callback) {
   TrustedStatus status = RequestTrustedEntity();
-  if (status == TEMPORARILY_UNTRUSTED && !callback.is_null())
-    callbacks_.push_back(std::move(callback));
+  if (status == TEMPORARILY_UNTRUSTED && *callback)
+    callbacks_.push_back(std::move(*callback));
   return status;
 }
 
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.h b/chrome/browser/chromeos/settings/device_settings_provider.h
index df8343e..b165373 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.h
+++ b/chrome/browser/chromeos/settings/device_settings_provider.h
@@ -55,7 +55,7 @@
 
   // CrosSettingsProvider implementation.
   const base::Value* Get(const std::string& path) const override;
-  TrustedStatus PrepareTrustedValues(base::OnceClosure callback) override;
+  TrustedStatus PrepareTrustedValues(base::OnceClosure* callback) override;
   bool HandlesSetting(const std::string& path) const override;
 
   // Helper function that decodes policies from provided proto into the pref
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
index 98c9ab5..d3f43856 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -358,8 +358,10 @@
 
   // Verify that the policy blob has been correctly parsed and trusted.
   // The trusted flag should be set before the call to PrepareTrustedValues.
+  base::OnceClosure closure = base::DoNothing();
   EXPECT_EQ(CrosSettingsProvider::TRUSTED,
-            provider_->PrepareTrustedValues(base::Closure()));
+            provider_->PrepareTrustedValues(&closure));
+  EXPECT_TRUE(closure);  // Ownership of |closure| was not taken.
   const base::Value* value = provider_->Get(kStatsReportingPref);
   ASSERT_TRUE(value);
   bool bool_value;
@@ -373,8 +375,10 @@
   ReloadDeviceSettings();
 
   // The trusted flag should be set before the call to PrepareTrustedValues.
+  base::OnceClosure closure = base::DoNothing();
   EXPECT_EQ(CrosSettingsProvider::TRUSTED,
-            provider_->PrepareTrustedValues(base::Closure()));
+            provider_->PrepareTrustedValues(&closure));
+  EXPECT_TRUE(closure);  // Ownership of |closure| was not taken.
   const base::Value* value = provider_->Get(kReleaseChannel);
   ASSERT_TRUE(value);
   std::string string_value;
@@ -507,8 +511,10 @@
   // Verify that the cached settings blob is not "trusted".
   EXPECT_EQ(DeviceSettingsService::STORE_VALIDATION_ERROR,
             device_settings_service_->status());
+  base::OnceClosure closure = base::DoNothing();
   EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
-            provider_->PrepareTrustedValues(base::Closure()));
+            provider_->PrepareTrustedValues(&closure));
+  EXPECT_TRUE(closure);  // Ownership of |closure| was not taken.
 }
 
 TEST_F(DeviceSettingsProviderTest, PolicyRetrievalNoPolicy) {
@@ -519,33 +525,40 @@
   // Verify that the cached settings blob is not "trusted".
   EXPECT_EQ(DeviceSettingsService::STORE_NO_POLICY,
             device_settings_service_->status());
+  base::OnceClosure closure = base::DoNothing();
   EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
-            provider_->PrepareTrustedValues(base::Closure()));
+            provider_->PrepareTrustedValues(&closure));
+  EXPECT_TRUE(closure);  // Ownership of |closure| was not taken.
 }
 
 TEST_F(DeviceSettingsProviderTest, PolicyFailedPermanentlyNotification) {
   session_manager_client_.set_device_policy(std::string());
 
+  base::OnceClosure closure = base::BindOnce(
+      &DeviceSettingsProviderTest::GetTrustedCallback, base::Unretained(this));
+
   EXPECT_CALL(*this, GetTrustedCallback());
   EXPECT_EQ(CrosSettingsProvider::TEMPORARILY_UNTRUSTED,
-            provider_->PrepareTrustedValues(
-                base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
-                           base::Unretained(this))));
+            provider_->PrepareTrustedValues(&closure));
+  EXPECT_FALSE(closure);  // Ownership of |closure| was taken.
 
   ReloadDeviceSettings();
   Mock::VerifyAndClearExpectations(this);
 
+  closure = base::DoNothing::Once();
   EXPECT_EQ(CrosSettingsProvider::PERMANENTLY_UNTRUSTED,
-            provider_->PrepareTrustedValues(base::Closure()));
+            provider_->PrepareTrustedValues(&closure));
+  EXPECT_TRUE(closure);  // Ownership of |closure| was not taken.
 }
 
 TEST_F(DeviceSettingsProviderTest, PolicyLoadNotification) {
   EXPECT_CALL(*this, GetTrustedCallback());
 
+  base::OnceClosure closure = base::BindOnce(
+      &DeviceSettingsProviderTest::GetTrustedCallback, base::Unretained(this));
   EXPECT_EQ(CrosSettingsProvider::TEMPORARILY_UNTRUSTED,
-            provider_->PrepareTrustedValues(
-                base::Bind(&DeviceSettingsProviderTest::GetTrustedCallback,
-                           base::Unretained(this))));
+            provider_->PrepareTrustedValues(&closure));
+  EXPECT_FALSE(closure);  // Ownership of |closure| was taken.
 
   ReloadDeviceSettings();
   Mock::VerifyAndClearExpectations(this);
diff --git a/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc b/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc
index a54d33b5..d9ee3fd 100644
--- a/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/stub_cros_settings_provider.cc
@@ -37,9 +37,9 @@
 }
 
 CrosSettingsProvider::TrustedStatus
-StubCrosSettingsProvider::PrepareTrustedValues(base::OnceClosure callback) {
+StubCrosSettingsProvider::PrepareTrustedValues(base::OnceClosure* callback) {
   if (trusted_status_ == TEMPORARILY_UNTRUSTED)
-    callbacks_.push_back(std::move(callback));
+    callbacks_.push_back(std::move(*callback));
   return trusted_status_;
 }
 
diff --git a/chrome/browser/chromeos/settings/stub_cros_settings_provider.h b/chrome/browser/chromeos/settings/stub_cros_settings_provider.h
index 0ffea22..cb0fd231 100644
--- a/chrome/browser/chromeos/settings/stub_cros_settings_provider.h
+++ b/chrome/browser/chromeos/settings/stub_cros_settings_provider.h
@@ -24,7 +24,7 @@
 
   // CrosSettingsProvider implementation.
   const base::Value* Get(const std::string& path) const override;
-  TrustedStatus PrepareTrustedValues(base::OnceClosure callback) override;
+  TrustedStatus PrepareTrustedValues(base::OnceClosure* callback) override;
   bool HandlesSetting(const std::string& path) const override;
 
   void SetTrustedStatus(TrustedStatus status);
diff --git a/chrome/browser/chromeos/settings/stub_cros_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/stub_cros_settings_provider_unittest.cc
index 829dbe9..b122be7 100644
--- a/chrome/browser/chromeos/settings/stub_cros_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/stub_cros_settings_provider_unittest.cc
@@ -8,21 +8,13 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/values.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
 
-namespace {
-
-void Fail() {
-  // Should never be called.
-  FAIL();
-}
-
-}  // namespace
-
 class StubCrosSettingsProviderTest : public testing::Test {
  protected:
   StubCrosSettingsProviderTest()
@@ -90,9 +82,11 @@
 
 TEST_F(StubCrosSettingsProviderTest, PrepareTrustedValues) {
   // Should return immediately without invoking the callback.
+  base::OnceClosure closure = base::BindOnce([]() { FAIL(); });
   CrosSettingsProvider::TrustedStatus trusted =
-      provider_->PrepareTrustedValues(base::Bind(&Fail));
+      provider_->PrepareTrustedValues(&closure);
   EXPECT_EQ(CrosSettingsProvider::TRUSTED, trusted);
+  EXPECT_TRUE(closure);  // The |closure| was not taken or run.
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.cc b/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.cc
index 60213cf..d04c0a2 100644
--- a/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.cc
@@ -36,7 +36,7 @@
 
 CrosSettingsProvider::TrustedStatus
 SupervisedUserCrosSettingsProvider::PrepareTrustedValues(
-    base::OnceClosure callback) {
+    base::OnceClosure* callback) {
   return TrustedStatus::TRUSTED;
 }
 
diff --git a/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.h b/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.h
index a6397a2..a3526440 100644
--- a/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.h
+++ b/chrome/browser/chromeos/settings/supervised_user_cros_settings_provider.h
@@ -25,7 +25,7 @@
 
   // CrosSettingsProvider:
   const base::Value* Get(const std::string& path) const override;
-  TrustedStatus PrepareTrustedValues(base::OnceClosure callback) override;
+  TrustedStatus PrepareTrustedValues(base::OnceClosure* callback) override;
   bool HandlesSetting(const std::string& path) const override;
 
  private:
diff --git a/chrome/browser/devtools/global_confirm_info_bar.cc b/chrome/browser/devtools/global_confirm_info_bar.cc
index 106733e..f26872e 100644
--- a/chrome/browser/devtools/global_confirm_info_bar.cc
+++ b/chrome/browser/devtools/global_confirm_info_bar.cc
@@ -28,18 +28,18 @@
 
   // ConfirmInfoBarDelegate overrides
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+  base::string16 GetLinkText() const override;
+  GURL GetLinkURL() const override;
+  bool LinkClicked(WindowOpenDisposition disposition) override;
+  void InfoBarDismissed() override;
   base::string16 GetMessageText() const override;
   gfx::ElideBehavior GetMessageElideBehavior() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
   bool Cancel() override;
-  base::string16 GetLinkText() const override;
-  GURL GetLinkURL() const override;
-  bool LinkClicked(WindowOpenDisposition disposition) override;
-  void InfoBarDismissed() override;
 
-  infobars::InfoBar* info_bar_;
+  infobars::InfoBar* info_bar_ = nullptr;
   base::WeakPtr<GlobalConfirmInfoBar> global_info_bar_;
 
   DISALLOW_COPY_AND_ASSIGN(DelegateProxy);
@@ -47,12 +47,9 @@
 
 GlobalConfirmInfoBar::DelegateProxy::DelegateProxy(
     base::WeakPtr<GlobalConfirmInfoBar> global_info_bar)
-    : info_bar_(nullptr),
-      global_info_bar_(global_info_bar) {
-}
+    : global_info_bar_(global_info_bar) {}
 
-GlobalConfirmInfoBar::DelegateProxy::~DelegateProxy() {
-}
+GlobalConfirmInfoBar::DelegateProxy::~DelegateProxy() = default;
 
 infobars::InfoBarDelegate::InfoBarIdentifier
 GlobalConfirmInfoBar::DelegateProxy::GetIdentifier() const {
@@ -60,6 +57,33 @@
                           : INVALID;
 }
 
+base::string16 GlobalConfirmInfoBar::DelegateProxy::GetLinkText() const {
+  return global_info_bar_ ? global_info_bar_->delegate_->GetLinkText()
+                          : base::string16();
+}
+
+GURL GlobalConfirmInfoBar::DelegateProxy::GetLinkURL() const {
+  return global_info_bar_ ? global_info_bar_->delegate_->GetLinkURL() : GURL();
+}
+
+bool GlobalConfirmInfoBar::DelegateProxy::LinkClicked(
+    WindowOpenDisposition disposition) {
+  return global_info_bar_ &&
+         global_info_bar_->delegate_->LinkClicked(disposition);
+}
+
+void GlobalConfirmInfoBar::DelegateProxy::InfoBarDismissed() {
+  base::WeakPtr<GlobalConfirmInfoBar> info_bar = global_info_bar_;
+  // See comments in GlobalConfirmInfoBar::DelegateProxy::Accept().
+  if (info_bar) {
+    info_bar->OnInfoBarRemoved(info_bar_, false);
+    info_bar->delegate_->InfoBarDismissed();
+  }
+  // Could be destroyed after this point.
+  if (info_bar)
+    info_bar->Close();
+}
+
 base::string16 GlobalConfirmInfoBar::DelegateProxy::GetMessageText() const {
   return global_info_bar_ ? global_info_bar_->delegate_->GetMessageText()
                           : base::string16();
@@ -74,7 +98,7 @@
 
 int GlobalConfirmInfoBar::DelegateProxy::GetButtons() const {
   return global_info_bar_ ? global_info_bar_->delegate_->GetButtons()
-                          : 0;
+                          : BUTTON_NONE;
 }
 
 base::string16 GlobalConfirmInfoBar::DelegateProxy::GetButtonLabel(
@@ -113,34 +137,6 @@
   return true;
 }
 
-base::string16 GlobalConfirmInfoBar::DelegateProxy::GetLinkText() const {
-  return global_info_bar_ ? global_info_bar_->delegate_->GetLinkText()
-                          : base::string16();
-}
-
-GURL GlobalConfirmInfoBar::DelegateProxy::GetLinkURL() const {
-  return global_info_bar_ ? global_info_bar_->delegate_->GetLinkURL()
-                          : GURL();
-}
-
-bool GlobalConfirmInfoBar::DelegateProxy::LinkClicked(
-    WindowOpenDisposition disposition) {
-  return global_info_bar_ ?
-      global_info_bar_->delegate_->LinkClicked(disposition) : false;
-}
-
-void GlobalConfirmInfoBar::DelegateProxy::InfoBarDismissed() {
-  base::WeakPtr<GlobalConfirmInfoBar> info_bar = global_info_bar_;
-  // See comments in GlobalConfirmInfoBar::DelegateProxy::Accept().
-  if (info_bar) {
-    info_bar->OnInfoBarRemoved(info_bar_, false);
-    info_bar->delegate_->InfoBarDismissed();
-  }
-  // Could be destroyed after this point.
-  if (info_bar)
-      info_bar->Close();
-}
-
 void GlobalConfirmInfoBar::DelegateProxy::Detach() {
   global_info_bar_.reset();
 }
@@ -150,9 +146,9 @@
 // static
 base::WeakPtr<GlobalConfirmInfoBar> GlobalConfirmInfoBar::Show(
     std::unique_ptr<ConfirmInfoBarDelegate> delegate) {
-  GlobalConfirmInfoBar* info_bar =
-      new GlobalConfirmInfoBar(std::move(delegate));
-  return info_bar->weak_factory_.GetWeakPtr();
+  // Owns itself, deleted by Close().
+  auto* infobar = new GlobalConfirmInfoBar(std::move(delegate));
+  return infobar->weak_factory_.GetWeakPtr();
 }
 
 void GlobalConfirmInfoBar::Close() {
@@ -161,9 +157,7 @@
 
 GlobalConfirmInfoBar::GlobalConfirmInfoBar(
     std::unique_ptr<ConfirmInfoBarDelegate> delegate)
-    : delegate_(std::move(delegate)),
-      browser_tab_strip_tracker_(this, nullptr, nullptr),
-      is_closing_(false) {
+    : delegate_(std::move(delegate)) {
   browser_tab_strip_tracker_.Init();
 }
 
@@ -196,7 +190,7 @@
 void GlobalConfirmInfoBar::OnInfoBarRemoved(infobars::InfoBar* info_bar,
                                             bool animate) {
   // Do not process alien infobars.
-  for (auto it : proxies_) {
+  for (const auto& it : proxies_) {
     if (it.second->info_bar_ == info_bar) {
       OnManagerShuttingDown(info_bar->owner());
       break;
@@ -218,8 +212,8 @@
   if (base::Contains(proxies_, infobar_service))
     return;
 
-  std::unique_ptr<GlobalConfirmInfoBar::DelegateProxy> proxy(
-      new GlobalConfirmInfoBar::DelegateProxy(weak_factory_.GetWeakPtr()));
+  auto proxy = std::make_unique<GlobalConfirmInfoBar::DelegateProxy>(
+      weak_factory_.GetWeakPtr());
   GlobalConfirmInfoBar::DelegateProxy* proxy_ptr = proxy.get();
   infobars::InfoBar* added_bar = infobar_service->AddInfoBar(
       infobar_service->CreateConfirmInfoBar(std::move(proxy)));
diff --git a/chrome/browser/devtools/global_confirm_info_bar.h b/chrome/browser/devtools/global_confirm_info_bar.h
index 82afbd7..367c515 100644
--- a/chrome/browser/devtools/global_confirm_info_bar.h
+++ b/chrome/browser/devtools/global_confirm_info_bar.h
@@ -56,11 +56,11 @@
 
   std::unique_ptr<ConfirmInfoBarDelegate> delegate_;
   std::map<infobars::InfoBarManager*, DelegateProxy*> proxies_;
-  BrowserTabStripTracker browser_tab_strip_tracker_;
+  BrowserTabStripTracker browser_tab_strip_tracker_{this, nullptr, nullptr};
 
   // Indicates if the global infobar is currently in the process of shutting
   // down.
-  bool is_closing_;
+  bool is_closing_ = false;
 
   base::WeakPtrFactory<GlobalConfirmInfoBar> weak_factory_{this};
 
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 4487370..5dce9e7e9 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -305,7 +305,7 @@
   download::DownloadItem* item_;
   bool waiting_ = false;
   bool error_ = false;
-  int prev_percent_ = 0;
+  int prev_percent_ = -1;
 
   DISALLOW_COPY_AND_ASSIGN(PercentWaiter);
 };
@@ -418,15 +418,36 @@
     base::RunLoop run_loop;
     completion_closure_ = run_loop.QuitClosure();
     run_loop.Run();
-    return;
   }
 
+  // Wait for a particular number of download to be created.
+  void WaitForDownloadCreation(int num_download_created) {
+    if (num_download_created_ >= num_download_created)
+      return;
+    num_download_to_wait_ = num_download_created;
+    base::RunLoop run_loop;
+    download_creation_closure_ = run_loop.QuitClosure();
+    run_loop.Run();
+  }
+
+  int num_download_created() const { return num_download_created_; }
+
+  void reset_num_download_created() { num_download_created_ = 0; }
+
  private:
   void OnDownloadsInitialized(bool active_downloads_only) override {
     if (completion_closure_)
       std::move(completion_closure_).Run();
   }
 
+  void OnDownloadCreated(download::DownloadItem* item) override {
+    num_download_created_++;
+    if (download_creation_closure_ &&
+        num_download_created_ >= num_download_to_wait_) {
+      std::move(download_creation_closure_).Run();
+    }
+  }
+
   void OnManagerGoingDown(
       download::SimpleDownloadManagerCoordinator* coordinator) override {
     DCHECK_EQ(coordinator_, coordinator);
@@ -436,6 +457,9 @@
 
   download::SimpleDownloadManagerCoordinator* coordinator_;
   base::OnceClosure completion_closure_;
+  base::OnceClosure download_creation_closure_;
+  int num_download_created_ = 0;
+  int num_download_to_wait_ = 0;
 };
 
 void CreateCompletedDownload(content::DownloadManager* download_manager,
@@ -4288,6 +4312,63 @@
   CHECK_EQ(download, history_download);
 }
 
+// Check that InProgressDownloadManager can handle transient downloads with the
+// same GUID.
+IN_PROC_BROWSER_TEST_F(InProgressDownloadTest,
+                       DownloadURLWithInProgressManager) {
+  embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url = embedded_test_server()->GetURL("/downloads/a_zip_file.zip");
+  base::FilePath origin(OriginFile(
+      base::FilePath(FILE_PATH_LITERAL("downloads/a_zip_file.zip"))));
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  ASSERT_TRUE(base::PathExists(origin));
+  std::string guid = base::GenerateGUID();
+
+  // Wait for in-progress download manager to initialize.
+  download::InProgressDownloadManager* in_progress_manager =
+      DownloadManagerUtils::GetInProgressDownloadManager(
+          browser()->profile()->GetProfileKey());
+  download::SimpleDownloadManagerCoordinator* coordinator =
+      SimpleDownloadManagerCoordinatorFactory::GetForKey(
+          browser()->profile()->GetProfileKey());
+  SimpleDownloadManagerCoordinatorWaiter coordinator_waiter(coordinator);
+  coordinator_waiter.WaitForInitialization();
+
+  base::FilePath target_path;
+  ASSERT_TRUE(
+      base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &target_path));
+  target_path =
+      target_path.Append(base::FilePath(FILE_PATH_LITERAL("a_zip_file.zip")));
+  std::vector<GURL> url_chain;
+  url_chain.emplace_back(url);
+  // Kick off 2 download with the same GUID
+  auto params = std::make_unique<DownloadUrlParameters>(
+      url, TRAFFIC_ANNOTATION_FOR_TESTS, net::NetworkIsolationKey());
+  params->set_guid(guid);
+  params->set_file_path(target_path);
+  params->set_transient(true);
+  params->set_require_safety_checks(false);
+  in_progress_manager->DownloadUrl(std::move(params));
+  auto params2 = std::make_unique<DownloadUrlParameters>(
+      url, TRAFFIC_ANNOTATION_FOR_TESTS, net::NetworkIsolationKey());
+  params2->set_guid(guid);
+  params2->set_file_path(target_path);
+  params2->set_transient(true);
+  params2->set_require_safety_checks(false);
+  in_progress_manager->DownloadUrl(std::move(params2));
+  coordinator_waiter.WaitForDownloadCreation(1);
+  download::DownloadItem* download = coordinator->GetDownloadByGuid(guid);
+  ASSERT_TRUE(download);
+
+  PercentWaiter waiter(download);
+  // Download should continue and complete.
+  ASSERT_TRUE(waiter.WaitForFinished());
+
+  // Only 1 download is created above, no more new downloads are created.
+  ASSERT_EQ(coordinator_waiter.num_download_created(), 1);
+}
+
 #if BUILDFLAG(FULL_SAFE_BROWSING)
 
 namespace {
diff --git a/chrome/browser/engagement/site_engagement_metrics.cc b/chrome/browser/engagement/site_engagement_metrics.cc
index e3222aa..f26f15a 100644
--- a/chrome/browser/engagement/site_engagement_metrics.cc
+++ b/chrome/browser/engagement/site_engagement_metrics.cc
@@ -36,18 +36,12 @@
 const char SiteEngagementMetrics::kEngagementScoreHistogram[] =
     "SiteEngagementService.EngagementScore";
 
-const char SiteEngagementMetrics::kEngagementScoreHistogramIsZero[] =
-    "SiteEngagementService.EngagementScore.IsZero";
-
 const char SiteEngagementMetrics::kOriginsWithMaxEngagementHistogram[] =
     "SiteEngagementService.OriginsWithMaxEngagement";
 
 const char SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram[] =
     "SiteEngagementService.OriginsWithMaxDailyEngagement";
 
-const char SiteEngagementMetrics::kPercentOriginsWithMaxEngagementHistogram[] =
-    "SiteEngagementService.PercentOriginsWithMaxEngagement";
-
 const char SiteEngagementMetrics::kEngagementTypeHistogram[] =
     "SiteEngagementService.EngagementType";
 
@@ -57,12 +51,6 @@
 const char SiteEngagementMetrics::kDaysSinceLastShortcutLaunchHistogram[] =
     "SiteEngagementService.DaysSinceLastShortcutLaunch";
 
-const char SiteEngagementMetrics::kScoreDecayedFromHistogram[] =
-    "SiteEngagementService.ScoreDecayedFrom";
-
-const char SiteEngagementMetrics::kScoreDecayedToHistogram[] =
-    "SiteEngagementService.ScoreDecayedTo";
-
 void SiteEngagementMetrics::RecordTotalSiteEngagement(double total_engagement) {
   UMA_HISTOGRAM_COUNTS_10000(kTotalEngagementHistogram, total_engagement);
 }
@@ -88,11 +76,9 @@
   for (size_t i = 0; i < base::size(kEngagementBucketHistogramBuckets); ++i)
     score_buckets[kEngagementBucketHistogramBuckets[i]] = 0;
 
-  const double threshold_0 = std::numeric_limits<double>::epsilon();;
   for (const auto& detail : details) {
     double score = detail.total_score;
     UMA_HISTOGRAM_COUNTS_100(kEngagementScoreHistogram, score);
-    UMA_HISTOGRAM_BOOLEAN(kEngagementScoreHistogramIsZero, score < threshold_0);
 
     auto bucket = score_buckets.lower_bound(score);
     if (bucket == score_buckets.end())
@@ -122,12 +108,6 @@
                            total_origins);
 }
 
-void SiteEngagementMetrics::RecordPercentOriginsWithMaxEngagement(
-    double percentage) {
-  UMA_HISTOGRAM_COUNTS_100(kPercentOriginsWithMaxEngagementHistogram,
-                           percentage);
-}
-
 void SiteEngagementMetrics::RecordEngagement(
     SiteEngagementService::EngagementType type) {
   UMA_HISTOGRAM_ENUMERATION(kEngagementTypeHistogram, type,
@@ -138,14 +118,6 @@
   UMA_HISTOGRAM_COUNTS_100(kDaysSinceLastShortcutLaunchHistogram, days);
 }
 
-void SiteEngagementMetrics::RecordScoreDecayedFrom(double score) {
-  UMA_HISTOGRAM_COUNTS_100(kScoreDecayedFromHistogram, score);
-}
-
-void SiteEngagementMetrics::RecordScoreDecayedTo(double score) {
-  UMA_HISTOGRAM_COUNTS_100(kScoreDecayedToHistogram, score);
-}
-
 // static
 std::vector<std::string>
 SiteEngagementMetrics::GetEngagementBucketHistogramNames() {
diff --git a/chrome/browser/engagement/site_engagement_metrics.h b/chrome/browser/engagement/site_engagement_metrics.h
index 650d6d92..076297bb 100644
--- a/chrome/browser/engagement/site_engagement_metrics.h
+++ b/chrome/browser/engagement/site_engagement_metrics.h
@@ -26,18 +26,14 @@
       const std::vector<mojom::SiteEngagementDetails>& details);
   static void RecordOriginsWithMaxEngagement(int total_origins);
   static void RecordOriginsWithMaxDailyEngagement(int total_origins);
-  static void RecordPercentOriginsWithMaxEngagement(double percentage);
   static void RecordEngagement(SiteEngagementService::EngagementType type);
   static void RecordDaysSinceLastShortcutLaunch(int days);
-  static void RecordScoreDecayedFrom(double score);
-  static void RecordScoreDecayedTo(double score);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, CheckHistograms);
   FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest,
                            GetTotalNotificationPoints);
   FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, LastShortcutLaunch);
-  FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, ScoreDecayHistograms);
   FRIEND_TEST_ALL_PREFIXES(SiteEngagementHelperTest,
                            MixedInputEngagementAccumulation);
   static const char kTotalEngagementHistogram[];
@@ -45,15 +41,11 @@
   static const char kMeanEngagementHistogram[];
   static const char kMedianEngagementHistogram[];
   static const char kEngagementScoreHistogram[];
-  static const char kEngagementScoreHistogramIsZero[];
   static const char kOriginsWithMaxEngagementHistogram[];
   static const char kOriginsWithMaxDailyEngagementHistogram[];
-  static const char kPercentOriginsWithMaxEngagementHistogram[];
   static const char kEngagementTypeHistogram[];
   static const char kEngagementBucketHistogramBase[];
   static const char kDaysSinceLastShortcutLaunchHistogram[];
-  static const char kScoreDecayedFromHistogram[];
-  static const char kScoreDecayedToHistogram[];
 
   static std::vector<std::string> GetEngagementBucketHistogramNames();
 };
diff --git a/chrome/browser/engagement/site_engagement_score.cc b/chrome/browser/engagement/site_engagement_score.cc
index dcf7af79a..d88ef95 100644
--- a/chrome/browser/engagement/site_engagement_score.cc
+++ b/chrome/browser/engagement/site_engagement_score.cc
@@ -227,17 +227,10 @@
 
 void SiteEngagementScore::AddPoints(double points) {
   DCHECK_NE(0, points);
-  double decayed_score = DecayedScore();
-
-  // Record the original and decayed scores after a decay event.
-  if (decayed_score < raw_score_) {
-    SiteEngagementMetrics::RecordScoreDecayedFrom(raw_score_);
-    SiteEngagementMetrics::RecordScoreDecayedTo(decayed_score);
-  }
 
   // As the score is about to be updated, commit any decay that has happened
   // since the last update.
-  raw_score_ = decayed_score;
+  raw_score_ = DecayedScore();
 
   base::Time now = clock_->Now();
   if (!last_engagement_time_.is_null() &&
diff --git a/chrome/browser/engagement/site_engagement_service.cc b/chrome/browser/engagement/site_engagement_service.cc
index 22934735..cef3bc4 100644
--- a/chrome/browser/engagement/site_engagement_service.cc
+++ b/chrome/browser/engagement/site_engagement_service.cc
@@ -534,10 +534,6 @@
     total_engagement += detail.total_score;
   }
 
-  int percent_origins_with_max_engagement =
-      (total_origins == 0
-           ? 0
-           : (origins_with_max_engagement * 100) / total_origins);
   double mean_engagement =
       (total_origins == 0 ? 0 : total_engagement / total_origins);
 
@@ -552,8 +548,6 @@
       OriginsWithMaxDailyEngagement());
   SiteEngagementMetrics::RecordOriginsWithMaxEngagement(
       origins_with_max_engagement);
-  SiteEngagementMetrics::RecordPercentOriginsWithMaxEngagement(
-      percent_origins_with_max_engagement);
 }
 
 bool SiteEngagementService::ShouldRecordEngagement(const GURL& url) const {
diff --git a/chrome/browser/engagement/site_engagement_service_unittest.cc b/chrome/browser/engagement/site_engagement_service_unittest.cc
index 682aa80f..bedfb059 100644
--- a/chrome/browser/engagement/site_engagement_service_unittest.cc
+++ b/chrome/browser/engagement/site_engagement_service_unittest.cc
@@ -54,9 +54,6 @@
 
 base::FilePath g_temp_history_dir;
 
-const int kMoreAccumulationsThanNeededToMaxDailyEngagement = 40;
-const int kMoreDaysThanNeededToMaxTotalEngagement = 40;
-const int kMorePeriodsThanNeededToDecayMaxScore = 40;
 const double kMaxRoundingDeviation = 0.0001;
 
 // Waits until a change is observed in site engagement content settings.
@@ -575,8 +572,6 @@
       SiteEngagementMetrics::kOriginsWithMaxEngagementHistogram, 0);
   histograms.ExpectTotalCount(
       SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram, 0);
-  histograms.ExpectTotalCount(
-      SiteEngagementMetrics::kPercentOriginsWithMaxEngagementHistogram, 0);
   histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram,
                               0);
 
@@ -595,8 +590,6 @@
       SiteEngagementMetrics::kMedianEngagementHistogram, 0, 1);
   histograms.ExpectUniqueSample(
       SiteEngagementMetrics::kOriginsWithMaxEngagementHistogram, 0, 1);
-  histograms.ExpectUniqueSample(
-      SiteEngagementMetrics::kPercentOriginsWithMaxEngagementHistogram, 0, 1);
   histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram,
                               0);
 
@@ -643,8 +636,6 @@
       SiteEngagementMetrics::kOriginsWithMaxEngagementHistogram, 0, 2);
   histograms.ExpectUniqueSample(
       SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram, 0, 2);
-  histograms.ExpectUniqueSample(
-      SiteEngagementMetrics::kPercentOriginsWithMaxEngagementHistogram, 0, 2);
   histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram,
                               6);
   histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram,
@@ -714,8 +705,6 @@
       SiteEngagementMetrics::kOriginsWithMaxEngagementHistogram, 0, 3);
   histograms.ExpectUniqueSample(
       SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram, 0, 3);
-  histograms.ExpectUniqueSample(
-      SiteEngagementMetrics::kPercentOriginsWithMaxEngagementHistogram, 0, 3);
   histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram,
                               12);
   histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram,
@@ -799,8 +788,6 @@
       SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram, 0, 3);
   histograms.ExpectBucketCount(
       SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram, 1, 1);
-  histograms.ExpectUniqueSample(
-      SiteEngagementMetrics::kPercentOriginsWithMaxEngagementHistogram, 0, 4);
   histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram,
                               24);
   histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram,
@@ -1468,101 +1455,6 @@
   }
 }
 
-TEST_F(SiteEngagementServiceTest, ScoreDecayHistograms) {
-  base::Time current_day = GetReferenceTime();
-  clock_.SetNow(current_day);
-  base::HistogramTester histograms;
-  GURL origin1("http://www.google.com/");
-  GURL origin2("http://drive.google.com/");
-
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram,
-                              0);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                              0);
-
-  service_->AddPoints(origin2, SiteEngagementScore::GetNavigationPoints());
-
-  // Max the score for origin1.
-  for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) {
-    current_day += base::TimeDelta::FromDays(1);
-    clock_.SetNow(current_day);
-
-    for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j)
-      service_->AddPoints(origin1, SiteEngagementScore::GetNavigationPoints());
-  }
-
-  EXPECT_EQ(SiteEngagementScore::kMaxPoints, service_->GetScore(origin1));
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram,
-                              0);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                              0);
-
-  // Check histograms after one decay period.
-  clock_.SetNow(
-      current_day +
-      base::TimeDelta::FromHours(SiteEngagementScore::GetDecayPeriodInHours()));
-
-  // Trigger decay and histogram hit.
-  service_->AddPoints(origin1, 0.01);
-  histograms.ExpectUniqueSample(
-      SiteEngagementMetrics::kScoreDecayedFromHistogram,
-      SiteEngagementScore::kMaxPoints, 1);
-  histograms.ExpectUniqueSample(
-      SiteEngagementMetrics::kScoreDecayedToHistogram,
-      SiteEngagementScore::kMaxPoints - SiteEngagementScore::GetDecayPoints(),
-      1);
-
-  // Check histograms after another decay period.
-  clock_.SetNow(current_day +
-                base::TimeDelta::FromHours(
-                    2 * SiteEngagementScore::GetDecayPeriodInHours()));
-  // Trigger decay and histogram hit.
-  service_->AddPoints(origin1, 0.01);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram,
-                              2);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                              2);
-
-  // Check decay to zero. Start at the 3rd decay period (we have had two
-  // already). This will be 40 decays in total.
-  for (int i = 3; i <= kMorePeriodsThanNeededToDecayMaxScore; ++i) {
-    clock_.SetNow(current_day +
-                  base::TimeDelta::FromHours(
-                      i * SiteEngagementScore::GetDecayPeriodInHours()));
-    // Trigger decay and histogram hit.
-    service_->AddPoints(origin1, 0.01);
-  }
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram,
-                              kMorePeriodsThanNeededToDecayMaxScore);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                              kMorePeriodsThanNeededToDecayMaxScore);
-  // It should have taken (20 - 3) = 17 of the 38 decays to get to zero, since
-  // we started from 95. Expect the remaining 21 decays to be to bucket 0 (and
-  // hence 20 from bucket 0).
-  histograms.ExpectBucketCount(
-      SiteEngagementMetrics::kScoreDecayedFromHistogram, 0, 20);
-  histograms.ExpectBucketCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                               0, 21);
-  // Trigger decay and histogram hit for origin2, checking an independent decay.
-  service_->AddPoints(origin2, 0.01);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram,
-                              kMorePeriodsThanNeededToDecayMaxScore + 1);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                              kMorePeriodsThanNeededToDecayMaxScore + 1);
-  histograms.ExpectBucketCount(
-      SiteEngagementMetrics::kScoreDecayedFromHistogram, 0, 21);
-  histograms.ExpectBucketCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                               0, 22);
-
-  // Add more points and ensure no more samples are present.
-  service_->AddPoints(origin1, 0.01);
-  service_->AddPoints(origin2, 0.01);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram,
-                              kMorePeriodsThanNeededToDecayMaxScore + 1);
-  histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram,
-                              kMorePeriodsThanNeededToDecayMaxScore + 1);
-}
-
 TEST_F(SiteEngagementServiceTest, LastEngagementTime) {
   // The last engagement time should start off null in prefs and in the service.
   base::Time last_engagement_time = base::Time::FromInternalValue(
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index 01134e7..bfece9b 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -963,6 +963,7 @@
     rule.id = id++;
     rule.condition->url_filter = base::StringPrintf("num=%d|", i);
     rule.condition->resource_types = std::vector<std::string>({"main_frame"});
+    rule.priority = 1;
     rules.push_back(rule);
   }
 
@@ -973,6 +974,7 @@
     rule.condition->url_filter = base::StringPrintf("num=%d|", i);
     rule.condition->resource_types = std::vector<std::string>({"main_frame"});
     rule.action->type = std::string("allow");
+    rule.priority = 2;
     rules.push_back(rule);
   }
 
@@ -1009,20 +1011,21 @@
   struct {
     std::string url_filter;
     int id;
+    int priority;
     std::string action_type;
     base::Optional<std::string> redirect_url;
   } rules_data[] = {
-      {"google.com", 1, "redirect", static_redirect_url.spec()},
-      {"num=1|", 2, "allow", base::nullopt},
-      {"1|", 3, "redirect", dynamic_redirect_url.spec()},
-      {"num=21|", 4, "allow", base::nullopt},
+      {"google.com", 1, 1, "redirect", static_redirect_url.spec()},
+      {"num=1|", 2, 2, "allow", base::nullopt},
+      {"1|", 3, 1, "redirect", dynamic_redirect_url.spec()},
+      {"num=21|", 4, 2, "allow", base::nullopt},
   };
 
   std::vector<TestRule> rules;
   for (const auto& rule_data : rules_data) {
     TestRule rule = CreateGenericRule();
     rule.id = rule_data.id;
-    rule.priority = kMinValidPriority;
+    rule.priority = rule_data.priority;
     rule.condition->url_filter = rule_data.url_filter;
     rule.condition->resource_types = std::vector<std::string>({"main_frame"});
     rule.action->type = rule_data.action_type;
@@ -1275,15 +1278,16 @@
   struct {
     std::string url_filter;
     int id;
+    int priority;
     std::string action_type;
     base::Optional<std::string> redirect_url;
   } rules_data[] = {
-      {"example.com", 1, "redirect", get_url_for_host("yahoo.com")},
-      {"yahoo.com", 2, "redirect", get_url_for_host("google.com")},
-      {"abc.com", 3, "redirect", get_url_for_host("def.com")},
-      {"def.com", 4, "block", base::nullopt},
-      {"def.com", 5, "redirect", get_url_for_host("xyz.com")},
-      {"ghi*", 6, "redirect", get_url_for_host("ghijk.com")},
+      {"example.com", 1, 1, "redirect", get_url_for_host("yahoo.com")},
+      {"yahoo.com", 2, 1, "redirect", get_url_for_host("google.com")},
+      {"abc.com", 3, 1, "redirect", get_url_for_host("def.com")},
+      {"def.com", 4, 2, "block", base::nullopt},
+      {"def.com", 5, 1, "redirect", get_url_for_host("xyz.com")},
+      {"ghi*", 6, 1, "redirect", get_url_for_host("ghijk.com")},
   };
 
   // Load the extension.
@@ -1292,7 +1296,7 @@
     TestRule rule = CreateGenericRule();
     rule.condition->url_filter = rule_data.url_filter;
     rule.id = rule_data.id;
-    rule.priority = kMinValidPriority;
+    rule.priority = rule_data.priority;
     rule.condition->resource_types = std::vector<std::string>({"main_frame"});
     rule.action->type = rule_data.action_type;
     rule.action->redirect.emplace();
@@ -1441,7 +1445,7 @@
       // TODO(crbug.com/985104): Add a https test server to display https pages
       // so this redirect rule can be removed.
       {"|https*", 3, 6, "redirect", google_url.spec()},
-      {"exact.com", 4, 1, "block", base::nullopt},
+      {"exact.com", 4, 5, "block", base::nullopt},
   };
 
   // Load the extension.
diff --git a/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
index 4169d05..679e3dd0 100644
--- a/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
@@ -193,10 +193,10 @@
   rule.action->type = std::string("redirect");
   rule.action->redirect.emplace();
   rule.action->redirect->url = std::string("https://google.com");
+  rule.priority.reset();
   AddRule(rule);
-  LoadAndExpectError(
-      ParseInfo(ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY, *rule.id)
-          .GetErrorDescription());
+  LoadAndExpectError(ParseInfo(ParseResult::ERROR_EMPTY_RULE_PRIORITY, *rule.id)
+                         .GetErrorDescription());
 }
 
 TEST_P(RuleIndexingTest, EmptyRedirectRuleUrl) {
@@ -229,7 +229,7 @@
   rule.priority = kMinValidPriority - 1;
   AddRule(rule);
   LoadAndExpectError(
-      ParseInfo(ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY, *rule.id)
+      ParseInfo(ParseResult::ERROR_INVALID_RULE_PRIORITY, *rule.id)
           .GetErrorDescription());
 }
 
@@ -400,22 +400,26 @@
     [
       {
         "id" : 1,
+        "priority": 1,
         "condition" : [],
         "action" : {"type" : "block" }
       },
       {
         "id" : 2,
+        "priority": 1,
         "condition" : {"urlFilter" : "abc"},
         "action" : {"type" : "block" }
       },
       {
         "id" : 3,
+        "priority": 1,
         "invalidKey" : "invalidKeyValue",
         "condition" : {"urlFilter" : "example"},
         "action" : {"type" : "block" }
       },
       {
         "id" : "6",
+        "priority": 1,
         "condition" : {"urlFilter" : "google"},
         "action" : {"type" : "block" }
       }
diff --git a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
index c9c00eb..25f6daf8 100644
--- a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
@@ -92,8 +92,7 @@
                   RulesetSource::CreateStatic(*last_loaded_extension_),
                   expected_checksum, &matchers[0]));
 
-    *matcher = std::make_unique<CompositeMatcher>(std::move(matchers),
-                                                  nullptr /* action_tracker */);
+    *matcher = std::make_unique<CompositeMatcher>(std::move(matchers));
   }
 
   void SetIncognitoEnabled(const Extension* extension, bool incognito_enabled) {
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 40b059d..fc197ea0 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -37,6 +37,7 @@
 #include "extensions/browser/process_manager.h"
 #include "extensions/browser/process_manager_observer.h"
 #include "extensions/browser/warning_service.h"
+#include "extensions/common/extension_id.h"
 #include "storage/browser/file_system/file_system_context.h"
 #include "storage/browser/file_system/file_system_operation.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index c480246..b8a8d6de 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -50,6 +50,7 @@
 #include "extensions/browser/test_extension_registry_observer.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/permissions/permission_set.h"
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index 408e6e0..e5950030 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -29,6 +29,7 @@
 #include "extensions/browser/install_flag.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_info.h"
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 467868d9..0b23f32 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -41,6 +41,7 @@
 #include "extensions/browser/uninstall_reason.h"
 #include "extensions/buildflags/buildflags.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest.h"
 
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc
index fc7866e..60781c4 100644
--- a/chrome/browser/extensions/extension_system_impl.cc
+++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -460,7 +460,7 @@
 
 void ExtensionSystemImpl::RegisterExtensionWithRequestContexts(
     const Extension* extension,
-    const base::Closure& callback) {
+    base::OnceClosure callback) {
   base::Time install_time;
   if (extension->location() != Manifest::COMPONENT) {
     install_time = ExtensionPrefs::Get(profile_)->
@@ -482,7 +482,7 @@
       base::BindOnce(&InfoMap::AddExtension, info_map(),
                      base::RetainedRef(extension), install_time,
                      incognito_enabled, notifications_disabled),
-      callback);
+      std::move(callback));
 }
 
 void ExtensionSystemImpl::UnregisterExtensionWithRequestContexts(
diff --git a/chrome/browser/extensions/extension_system_impl.h b/chrome/browser/extensions/extension_system_impl.h
index 476c9cc..a6e8925 100644
--- a/chrome/browser/extensions/extension_system_impl.h
+++ b/chrome/browser/extensions/extension_system_impl.h
@@ -62,7 +62,7 @@
 
   void RegisterExtensionWithRequestContexts(
       const Extension* extension,
-      const base::Closure& callback) override;
+      base::OnceClosure callback) override;
 
   void UnregisterExtensionWithRequestContexts(
       const std::string& extension_id,
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc
index 2e165d23..6d284cd6 100644
--- a/chrome/browser/extensions/install_signer.cc
+++ b/chrome/browser/extensions/install_signer.cc
@@ -29,6 +29,7 @@
 #include "crypto/secure_hash.h"
 #include "crypto/sha2.h"
 #include "crypto/signature_verifier.h"
+#include "extensions/common/extension.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "rlz/buildflags/buildflags.h"
 #include "services/network/public/cpp/resource_request.h"
diff --git a/chrome/browser/extensions/install_signer.h b/chrome/browser/extensions/install_signer.h
index 88e3b74..2da3dc3e 100644
--- a/chrome/browser/extensions/install_signer.h
+++ b/chrome/browser/extensions/install_signer.h
@@ -12,7 +12,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 
 namespace base {
 class DictionaryValue;
diff --git a/chrome/browser/extensions/install_verifier.h b/chrome/browser/extensions/install_verifier.h
index 727a74b..9065dd1 100644
--- a/chrome/browser/extensions/install_verifier.h
+++ b/chrome/browser/extensions/install_verifier.h
@@ -15,6 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "extensions/browser/management_policy.h"
+#include "extensions/common/extension_id.h"
 
 namespace content {
 class BrowserContext;
diff --git a/chrome/browser/extensions/warning_badge_service.h b/chrome/browser/extensions/warning_badge_service.h
index 61d39c8b..728baaff 100644
--- a/chrome/browser/extensions/warning_badge_service.h
+++ b/chrome/browser/extensions/warning_badge_service.h
@@ -10,6 +10,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "extensions/browser/warning_service.h"
 #include "extensions/browser/warning_set.h"
+#include "extensions/common/extension_id.h"
 
 class Profile;
 
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win.cc b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
index 17ad8cb..cdd314b 100644
--- a/chrome/browser/metrics/antivirus_metrics_provider_win.cc
+++ b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
@@ -43,7 +43,7 @@
   }
 }
 
-void AntiVirusMetricsProvider::AsyncInit(const base::Closure& done_callback) {
+void AntiVirusMetricsProvider::AsyncInit(base::OnceClosure done_callback) {
   if (!remote_util_win_) {
     remote_util_win_ = LaunchUtilWinServiceInstance();
     remote_util_win_.reset_on_idle_timeout(base::TimeDelta::FromSeconds(5));
@@ -56,14 +56,14 @@
   remote_util_win_->GetAntiVirusProducts(
       ShouldReportFullNames(),
       base::BindOnce(&AntiVirusMetricsProvider::GotAntiVirusProducts,
-                     base::Unretained(this), done_callback));
+                     base::Unretained(this), std::move(done_callback)));
 }
 
 void AntiVirusMetricsProvider::GotAntiVirusProducts(
-    const base::Closure& done_callback,
+    base::OnceClosure done_callback,
     const std::vector<metrics::SystemProfileProto::AntiVirusProduct>& result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   remote_util_win_.reset();
   av_products_ = result;
-  done_callback.Run();
+  std::move(done_callback).Run();
 }
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win.h b/chrome/browser/metrics/antivirus_metrics_provider_win.h
index e5641eda..fbf3012c 100644
--- a/chrome/browser/metrics/antivirus_metrics_provider_win.h
+++ b/chrome/browser/metrics/antivirus_metrics_provider_win.h
@@ -28,7 +28,7 @@
   ~AntiVirusMetricsProvider() override;
 
   // metrics::MetricsDataProvider:
-  void AsyncInit(const base::Closure& done_callback) override;
+  void AsyncInit(base::OnceClosure done_callback) override;
   void ProvideSystemProfileMetrics(
       metrics::SystemProfileProto* system_profile_proto) override;
 
@@ -42,7 +42,7 @@
   // |done_callback| is the callback that should be called once all metrics are
   // gathered.
   void GotAntiVirusProducts(
-      const base::Closure& done_callback,
+      base::OnceClosure done_callback,
       const std::vector<metrics::SystemProfileProto::AntiVirusProduct>& result);
 
   mojo::Remote<chrome::mojom::UtilWin> remote_util_win_;
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc
index e0d007b..151868ad 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -184,8 +184,9 @@
     profile_provider_->Init();
 }
 
-void ChromeOSMetricsProvider::AsyncInit(const base::Closure& done_callback) {
-  base::RepeatingClosure barrier = base::BarrierClosure(3, done_callback);
+void ChromeOSMetricsProvider::AsyncInit(base::OnceClosure done_callback) {
+  base::RepeatingClosure barrier =
+      base::BarrierClosure(3, std::move(done_callback));
   InitTaskGetFullHardwareClass(barrier);
   InitTaskGetBluetoothAdapter(barrier);
   InitTaskGetArcFeatures(barrier);
@@ -201,7 +202,7 @@
 }
 
 void ChromeOSMetricsProvider::InitTaskGetFullHardwareClass(
-    const base::Closure& callback) {
+    base::OnceClosure callback) {
   // Run the (potentially expensive) task in the background to avoid blocking
   // the UI thread.
   base::PostTaskAndReplyWithResult(
@@ -211,21 +212,21 @@
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&GetFullHardwareClassOnBackgroundThread),
       base::BindOnce(&ChromeOSMetricsProvider::SetFullHardwareClass,
-                     weak_ptr_factory_.GetWeakPtr(), callback));
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void ChromeOSMetricsProvider::InitTaskGetBluetoothAdapter(
-    const base::Closure& callback) {
+    base::OnceClosure callback) {
   device::BluetoothAdapterFactory::GetAdapter(
       base::BindOnce(&ChromeOSMetricsProvider::SetBluetoothAdapter,
-                     weak_ptr_factory_.GetWeakPtr(), callback));
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void ChromeOSMetricsProvider::InitTaskGetArcFeatures(
-    const base::RepeatingClosure& callback) {
+    base::OnceClosure callback) {
   arc::ArcFeaturesParser::GetArcFeatures(
       base::BindOnce(&ChromeOSMetricsProvider::OnArcFeaturesParsed,
-                     weak_ptr_factory_.GetWeakPtr(), callback));
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void ChromeOSMetricsProvider::ProvideSystemProfileMetrics(
@@ -419,27 +420,27 @@
 }
 
 void ChromeOSMetricsProvider::SetBluetoothAdapter(
-    base::Closure callback,
+    base::OnceClosure callback,
     scoped_refptr<device::BluetoothAdapter> adapter) {
   adapter_ = adapter;
-  callback.Run();
+  std::move(callback).Run();
 }
 
 void ChromeOSMetricsProvider::SetFullHardwareClass(
-    base::Closure callback,
+    base::OnceClosure callback,
     std::string full_hardware_class) {
   if (!base::FeatureList::IsEnabled(features::kUmaShortHWClass)) {
     DCHECK(hardware_class_.empty());
     hardware_class_ = full_hardware_class;
   }
   full_hardware_class_ = full_hardware_class;
-  callback.Run();
+  std::move(callback).Run();
 }
 
 void ChromeOSMetricsProvider::OnArcFeaturesParsed(
-    base::RepeatingClosure callback,
+    base::OnceClosure callback,
     base::Optional<arc::ArcFeatures> features) {
-  base::ScopedClosureRunner runner(callback);
+  base::ScopedClosureRunner runner(std::move(callback));
   if (!features) {
     LOG(WARNING) << "ArcFeatures not available on this build";
     return;
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.h b/chrome/browser/metrics/chromeos_metrics_provider.h
index e7aa36f..a733fec68 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider.h
+++ b/chrome/browser/metrics/chromeos_metrics_provider.h
@@ -60,19 +60,19 @@
 
   // Loads hardware class information. When this task is complete, |callback|
   // is run.
-  void InitTaskGetFullHardwareClass(const base::Closure& callback);
+  void InitTaskGetFullHardwareClass(base::OnceClosure callback);
 
   // Creates the Bluetooth adapter. When this task is complete, |callback| is
   // run.
-  void InitTaskGetBluetoothAdapter(const base::Closure& callback);
+  void InitTaskGetBluetoothAdapter(base::OnceClosure callback);
 
   // Retrieves ARC features using ArcFeaturesParser. When this task is complete,
   // |callback| is run.
-  void InitTaskGetArcFeatures(const base::RepeatingClosure& callback);
+  void InitTaskGetArcFeatures(base::OnceClosure callback);
 
   // metrics::MetricsProvider:
   void Init() override;
-  void AsyncInit(const base::Closure& done_callback) override;
+  void AsyncInit(base::OnceClosure done_callback) override;
   void OnDidCreateMetricsLog() override;
   void ProvideSystemProfileMetrics(
       metrics::SystemProfileProto* system_profile_proto) override;
@@ -92,15 +92,15 @@
 
   // Sets the Bluetooth Adapter instance used for the WriteBluetoothProto()
   // call and calls callback.
-  void SetBluetoothAdapter(base::Closure callback,
+  void SetBluetoothAdapter(base::OnceClosure callback,
                            scoped_refptr<device::BluetoothAdapter> adapter);
 
   // Sets the full hardware class, then calls the callback.
-  void SetFullHardwareClass(base::Closure callback,
+  void SetFullHardwareClass(base::OnceClosure callback,
                             std::string full_hardware_class);
 
   // Updates ARC-related system profile fields, then calls the callback.
-  void OnArcFeaturesParsed(base::RepeatingClosure callback,
+  void OnArcFeaturesParsed(base::OnceClosure callback,
                            base::Optional<arc::ArcFeatures> features);
 
   // Writes info about paired Bluetooth devices on this system.
diff --git a/chrome/browser/metrics/google_update_metrics_provider_win.cc b/chrome/browser/metrics/google_update_metrics_provider_win.cc
index 7776c80..8c7d68b 100644
--- a/chrome/browser/metrics/google_update_metrics_provider_win.cc
+++ b/chrome/browser/metrics/google_update_metrics_provider_win.cc
@@ -51,9 +51,10 @@
 }
 
 void GoogleUpdateMetricsProviderWin::AsyncInit(
-    const base::Closure& done_callback) {
+    base::OnceClosure done_callback) {
   if (!IsGoogleChromeBuild()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, done_callback);
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  std::move(done_callback));
     return;
   }
 
@@ -62,9 +63,10 @@
   base::PostTaskAndReplyWithResult(
       FROM_HERE,
       {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-      base::Bind(&GoogleUpdateMetricsProviderWin::GetGoogleUpdateDataBlocking),
-      base::Bind(&GoogleUpdateMetricsProviderWin::ReceiveGoogleUpdateData,
-                 weak_ptr_factory_.GetWeakPtr(), done_callback));
+      base::BindOnce(
+          &GoogleUpdateMetricsProviderWin::GetGoogleUpdateDataBlocking),
+      base::BindOnce(&GoogleUpdateMetricsProviderWin::ReceiveGoogleUpdateData,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(done_callback)));
 }
 
 void GoogleUpdateMetricsProviderWin::ProvideSystemProfileMetrics(
@@ -134,8 +136,8 @@
 }
 
 void GoogleUpdateMetricsProviderWin::ReceiveGoogleUpdateData(
-    const base::Closure& done_callback,
+    base::OnceClosure done_callback,
     const GoogleUpdateMetrics& google_update_metrics) {
   google_update_metrics_ = google_update_metrics;
-  done_callback.Run();
+  std::move(done_callback).Run();
 }
diff --git a/chrome/browser/metrics/google_update_metrics_provider_win.h b/chrome/browser/metrics/google_update_metrics_provider_win.h
index 08e1e6b..e1226bf5 100644
--- a/chrome/browser/metrics/google_update_metrics_provider_win.h
+++ b/chrome/browser/metrics/google_update_metrics_provider_win.h
@@ -19,7 +19,7 @@
   ~GoogleUpdateMetricsProviderWin() override;
 
   // metrics::MetricsProvider
-  void AsyncInit(const base::Closure& done_callback) override;
+  void AsyncInit(base::OnceClosure done_callback) override;
   void ProvideSystemProfileMetrics(
       metrics::SystemProfileProto* system_profile_proto) override;
 
@@ -52,7 +52,7 @@
   // Receives |google_update_metrics| from a blocking pool thread and runs
   // |done_callback|.
   void ReceiveGoogleUpdateData(
-      const base::Closure& done_callback,
+      base::OnceClosure done_callback,
       const GoogleUpdateMetrics& google_update_metrics);
 
   // Google Update metrics that were fetched via GetGoogleUpdateData(). Will be
diff --git a/chrome/browser/metrics/perf/heap_collector.cc b/chrome/browser/metrics/perf/heap_collector.cc
deleted file mode 100644
index 435323f..0000000
--- a/chrome/browser/metrics/perf/heap_collector.cc
+++ /dev/null
@@ -1,451 +0,0 @@
-// Copyright 2019 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/metrics/perf/heap_collector.h"
-
-#include <inttypes.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/allocator/allocator_extension.h"
-#include "base/command_line.h"
-#include "base/debug/proc_maps_linux.h"
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/process/launch.h"
-#include "base/process/process_handle.h"
-#include "base/rand_util.h"
-#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
-#include "base/strings/strcat.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
-#include "base/system/sys_info.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
-#include "components/services/heap_profiling/public/cpp/settings.h"
-#include "third_party/metrics_proto/sampled_profile.pb.h"
-
-namespace metrics {
-
-namespace {
-
-// Supported collection mode values.
-const char kCollectionModeTcmalloc[] = "cwp-tcmalloc";
-const char kCollectionModeShimLayer[] = "cwp-shim-layer";
-
-// Name of the heap collector. It is appended to the UMA metric names for
-// reporting collection and upload status.
-const char kHeapCollectorName[] = "Heap";
-
-// The approximate gap in bytes between sampling actions. Heap allocations are
-// sampled using a geometric distribution with the specified mean.
-const size_t kHeapSamplingIntervalBytes = 1 * 1024 * 1024;
-
-// Feature parameters that control the behavior of the heap collector.
-constexpr base::FeatureParam<int> kSamplingIntervalBytes{
-    &heap_profiling::kOOPHeapProfilingFeature, "SamplingIntervalBytes",
-    kHeapSamplingIntervalBytes};
-
-constexpr base::FeatureParam<int> kPeriodicCollectionIntervalMs{
-    &heap_profiling::kOOPHeapProfilingFeature, "PeriodicCollectionIntervalMs",
-    3 * 3600 * 1000};  // 3h
-
-constexpr base::FeatureParam<int> kResumeFromSuspendSamplingFactor{
-    &heap_profiling::kOOPHeapProfilingFeature,
-    "ResumeFromSuspend::SamplingFactor", 10};
-
-constexpr base::FeatureParam<int> kResumeFromSuspendMaxDelaySec{
-    &heap_profiling::kOOPHeapProfilingFeature, "ResumeFromSuspend::MaxDelaySec",
-    5};
-
-constexpr base::FeatureParam<int> kRestoreSessionSamplingFactor{
-    &heap_profiling::kOOPHeapProfilingFeature, "RestoreSession::SamplingFactor",
-    10};
-
-constexpr base::FeatureParam<int> kRestoreSessionMaxDelaySec{
-    &heap_profiling::kOOPHeapProfilingFeature, "RestoreSession::MaxDelaySec",
-    10};
-
-// Limit the total size of protobufs that can be cached, so they don't take up
-// too much memory. If the size of cached protobufs exceeds this value, stop
-// collecting further perf data. The current value is 2 MB.
-const size_t kCachedHeapDataProtobufSizeThreshold = 2 * 1024 * 1024;
-
-// Location of quipper on ChromeOS.
-const char kQuipperLocation[] = "/usr/bin/quipper";
-
-// Quipper arguments for passing in a profile and the process PID.
-const char kQuipperHeapProfile[] = "input_heap_profile";
-const char kQuipperProcessPid[] = "pid";
-
-void DeleteFileAsync(const base::FilePath& path) {
-  base::PostTask(
-      FROM_HERE,
-      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-       base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
-      base::BindOnce(base::IgnoreResult(&base::DeleteFile), std::move(path),
-                     false));
-}
-
-// Deletes the temp file when the object goes out of scope.
-class FileDeleter {
- public:
-  explicit FileDeleter(const base::FilePath& path) : path_(path) {}
-  ~FileDeleter() { DeleteFileAsync(path_); }
-
- private:
-  const base::FilePath path_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileDeleter);
-};
-
-void SetHeapSamplingPeriod(size_t sampling_period, HeapCollectionMode mode) {
-  switch (mode) {
-    case HeapCollectionMode::kNone:
-      break;
-    case HeapCollectionMode::kTcmalloc: {
-      bool res = base::allocator::SetNumericProperty(
-          "tcmalloc.sampling_period_bytes", sampling_period);
-      DCHECK(res);
-      break;
-    }
-    case HeapCollectionMode::kShimLayer: {
-      base::SamplingHeapProfiler::Get()->SetSamplingInterval(sampling_period);
-      break;
-    }
-  }
-}
-
-std::string CountAndSizeToString(uintptr_t count, uintptr_t size) {
-  return base::StringPrintf("%" PRIuPTR ": %" PRIuPTR " [%" PRIuPTR
-                            ": %" PRIuPTR "] @",
-                            count, size, count, size);
-}
-
-void WriteProfileHeader(
-    base::File* out,
-    base::StringPiece label,
-    const std::vector<base::SamplingHeapProfiler::Sample>& samples) {
-  // Compute the total count and total size
-  uintptr_t total_count = samples.size();
-  uintptr_t total_size = 0;
-  for (const auto& sample : samples) {
-    total_size += sample.total;
-  }
-
-  std::string header = base::StrCat(
-      {"heap profile: ", CountAndSizeToString(total_count, total_size), " ",
-       label, "\n"});
-  int res = out->WriteAtCurrentPos(header.c_str(), header.length());
-  DCHECK_EQ(res, static_cast<int>(header.length()));
-}
-
-// Prints the process runtime mappings. Returns if the operation was a success.
-bool PrintProcSelfMaps(base::File* out, const std::string& proc_maps) {
-  std::vector<base::debug::MappedMemoryRegion> regions;
-  if (!base::debug::ParseProcMaps(proc_maps, &regions))
-    return false;
-
-  int res = out->WriteAtCurrentPos("\nMAPPED_LIBRARIES:\n", 19);
-  DCHECK_EQ(res, 19);
-
-  for (const auto& region : regions) {
-    // We assume 'flags' looks like 'rwxp' or 'rwx'.
-    char r = (region.permissions & base::debug::MappedMemoryRegion::READ) ? 'r'
-                                                                          : '-';
-    char w = (region.permissions & base::debug::MappedMemoryRegion::WRITE)
-                 ? 'w'
-                 : '-';
-    char x = (region.permissions & base::debug::MappedMemoryRegion::EXECUTE)
-                 ? 'x'
-                 : '-';
-    char p = (region.permissions & base::debug::MappedMemoryRegion::PRIVATE)
-                 ? 'p'
-                 : '-';
-
-    // The devices major / minor values and the inode are not filled by
-    // ParseProcMaps, so write them as zero values. They are not relevant for
-    // symbolization.
-    std::string row = base::StringPrintf("%08" PRIxPTR "-%08" PRIxPTR
-                                         " %c%c%c%c %08llx 00:00 0 %s\n",
-                                         region.start, region.end, r, w, x, p,
-                                         region.offset, region.path.c_str());
-
-    int res = out->WriteAtCurrentPos(row.c_str(), row.length());
-    DCHECK_EQ(res, static_cast<int>(row.length()));
-  }
-  return true;
-}
-
-// Fetches profile from shim layer sampler and attempts to write it to the given
-// output file in the format used by the tcmalloc based heap sampler, with a
-// header line, followed by a row for each sample, and a section with the
-// process runtime mappings.
-bool FetchShimProfileAndSaveToFile(base::File* out) {
-  std::vector<base::SamplingHeapProfiler::Sample> samples =
-      base::SamplingHeapProfiler::Get()->GetSamples(0);
-  std::string proc_maps;
-  if (!base::debug::ReadProcMaps(&proc_maps))
-    return false;
-
-  return internal::WriteHeapProfileToFile(out, samples, proc_maps);
-}
-
-bool FetchProfileAndSaveToFile(base::File* out, HeapCollectionMode mode) {
-  switch (mode) {
-    case HeapCollectionMode::kNone:
-      DCHECK(false) << "Collection attempted for collection mode NONE";
-      return true;
-    case HeapCollectionMode::kTcmalloc: {
-      std::string writer;
-      base::allocator::GetHeapSample(&writer);
-      int res = out->WriteAtCurrentPos(writer.c_str(), writer.length());
-      DCHECK_EQ(res, static_cast<int>(writer.length()));
-      return true;
-    }
-    case HeapCollectionMode::kShimLayer:
-      return FetchShimProfileAndSaveToFile(out);
-  }
-}
-
-}  // namespace
-
-namespace internal {
-
-bool WriteHeapProfileToFile(
-    base::File* out,
-    const std::vector<base::SamplingHeapProfiler::Sample>& samples,
-    const std::string& proc_maps) {
-  WriteProfileHeader(out, "heap_v2/1", samples);
-  for (const auto& sample : samples) {
-    std::string row = CountAndSizeToString(1, sample.total);
-    for (const void* frame : sample.stack) {
-      base::StringAppendF(&row, " %p", frame);
-    }
-    row.append("\n", 1);
-    int res = out->WriteAtCurrentPos(row.c_str(), row.length());
-    DCHECK_EQ(res, static_cast<int>(row.length()));
-  }
-  return PrintProcSelfMaps(out, proc_maps);
-}
-
-}  // namespace internal
-
-// static
-HeapCollectionMode HeapCollector::CollectionModeFromString(std::string mode) {
-  if (mode == kCollectionModeTcmalloc)
-    return HeapCollectionMode::kTcmalloc;
-  if (mode == kCollectionModeShimLayer)
-    return HeapCollectionMode::kShimLayer;
-  return HeapCollectionMode::kNone;
-}
-
-HeapCollector::HeapCollector(HeapCollectionMode mode)
-    : internal::MetricCollector(kHeapCollectorName, CollectionParams()),
-      mode_(mode),
-      is_enabled_(false),
-      sampling_period_bytes_(kHeapSamplingIntervalBytes) {
-  if (mode_ == HeapCollectionMode::kShimLayer) {
-    base::SamplingHeapProfiler::Init();
-  }
-}
-
-const char* HeapCollector::ToolName() const {
-  return kHeapCollectorName;
-}
-
-HeapCollector::~HeapCollector() {
-  // Disable heap sampling when the collector exits.
-  DisableSampling();
-}
-
-void HeapCollector::EnableSampling() {
-  if (is_enabled_)
-    return;
-  switch (mode_) {
-    case HeapCollectionMode::kNone:
-      break;
-    case HeapCollectionMode::kTcmalloc:
-      SetHeapSamplingPeriod(sampling_period_bytes_, mode_);
-      break;
-    case HeapCollectionMode::kShimLayer:
-      base::SamplingHeapProfiler::Get()->Start();
-      break;
-  }
-  is_enabled_ = true;
-}
-
-void HeapCollector::DisableSampling() {
-  if (!is_enabled_)
-    return;
-  switch (mode_) {
-    case HeapCollectionMode::kNone:
-      break;
-    case HeapCollectionMode::kTcmalloc:
-      SetHeapSamplingPeriod(0, mode_);
-      break;
-    case HeapCollectionMode::kShimLayer:
-      base::SamplingHeapProfiler::Get()->Stop();
-      break;
-  }
-  is_enabled_ = false;
-}
-
-void HeapCollector::SetUp() {
-  if (base::FeatureList::IsEnabled(heap_profiling::kOOPHeapProfilingFeature)) {
-    sampling_period_bytes_ = kSamplingIntervalBytes.Get();
-    SetCollectionParamsFromFeatureParams();
-  }
-
-  // For the tcmalloc collector, we set the sampling period every time we enable
-  // it. The shim layer sampler has a separate API for starting and stopping, so
-  // we must set its sampling period once explicitly.
-  if (mode_ == HeapCollectionMode::kShimLayer) {
-    SetHeapSamplingPeriod(sampling_period_bytes_, mode_);
-  }
-  EnableSampling();
-}
-
-void HeapCollector::SetCollectionParamsFromFeatureParams() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CollectionParams& params = collection_params();
-  params.periodic_interval =
-      base::TimeDelta::FromMilliseconds(kPeriodicCollectionIntervalMs.Get());
-  params.resume_from_suspend.sampling_factor =
-      kResumeFromSuspendSamplingFactor.Get();
-  params.resume_from_suspend.max_collection_delay =
-      base::TimeDelta::FromSeconds(kResumeFromSuspendMaxDelaySec.Get());
-  params.restore_session.sampling_factor = kRestoreSessionSamplingFactor.Get();
-  params.restore_session.max_collection_delay =
-      base::TimeDelta::FromSeconds(kRestoreSessionMaxDelaySec.Get());
-}
-
-base::WeakPtr<internal::MetricCollector> HeapCollector::GetWeakPtr() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return weak_factory_.GetWeakPtr();
-}
-
-bool HeapCollector::ShouldCollect() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // Do not collect further data if we've already collected a substantial amount
-  // of data, as indicated by |kCachedHeapDataProtobufSizeThreshold|.
-  if (cached_data_size_ >= kCachedHeapDataProtobufSizeThreshold) {
-    AddToUmaHistogram(CollectionAttemptStatus::NOT_READY_TO_COLLECT);
-    return false;
-  }
-  return true;
-}
-
-void HeapCollector::CollectProfile(
-    std::unique_ptr<SampledProfile> sampled_profile) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  if (mode_ == HeapCollectionMode::kNone)
-    return;
-
-  auto incognito_observer = WindowedIncognitoMonitor::CreateObserver();
-  // For privacy reasons, Chrome should only collect heap profiles if there is
-  // no incognito session active (or gets spawned while the profile is saved).
-  if (incognito_observer->IncognitoActive()) {
-    AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_ACTIVE);
-    return;
-  }
-
-  base::Optional<base::FilePath> temp_file =
-      DumpProfileToTempFile(std::move(incognito_observer));
-  if (!temp_file)
-    return;
-
-  auto quipper = MakeQuipperCommand(temp_file.value());
-  ParseAndSaveProfile(std::move(quipper), std::move(temp_file.value()),
-                      std::move(sampled_profile));
-}
-
-base::Optional<base::FilePath> HeapCollector::DumpProfileToTempFile(
-    std::unique_ptr<WindowedIncognitoObserver> incognito_observer) {
-  base::FilePath temp_path;
-  if (!base::CreateTemporaryFile(&temp_path)) {
-    AddToUmaHistogram(CollectionAttemptStatus::UNABLE_TO_COLLECT);
-    return base::nullopt;
-  }
-  base::File temp(temp_path, base::File::FLAG_CREATE_ALWAYS |
-                                 base::File::FLAG_READ |
-                                 base::File::FLAG_WRITE);
-  DCHECK(temp.created());
-  DCHECK(temp.IsValid());
-
-  bool success = FetchProfileAndSaveToFile(&temp, mode_);
-  temp.Close();
-
-  if (!success) {
-    AddToUmaHistogram(CollectionAttemptStatus::DATA_COLLECTION_FAILED);
-    DeleteFileAsync(temp_path);
-    return base::nullopt;
-  }
-  if (incognito_observer->IncognitoLaunched()) {
-    AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_LAUNCHED);
-    DeleteFileAsync(temp_path);
-    return base::nullopt;
-  }
-  return base::make_optional<base::FilePath>(temp_path);
-}
-
-// static
-std::unique_ptr<base::CommandLine> HeapCollector::MakeQuipperCommand(
-    const base::FilePath& profile_path) {
-  auto quipper =
-      std::make_unique<base::CommandLine>(base::FilePath(kQuipperLocation));
-  quipper->AppendSwitchPath(kQuipperHeapProfile, profile_path);
-  quipper->AppendSwitchASCII(kQuipperProcessPid,
-                             base::NumberToString(base::GetCurrentProcId()));
-  return quipper;
-}
-
-void HeapCollector::ParseAndSaveProfile(
-    std::unique_ptr<base::CommandLine> parser,
-    base::FilePath profile_path,
-    std::unique_ptr<SampledProfile> sampled_profile) {
-  // Parsing processor information may be expensive. Compute asynchronously
-  // in a separate thread.
-  auto task_runner = base::SequencedTaskRunnerHandle::Get();
-  base::PostTask(
-      FROM_HERE,
-      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-      base::BindOnce(&HeapCollector::ParseProfileOnThreadPool, task_runner,
-                     weak_factory_.GetWeakPtr(), std::move(parser),
-                     std::move(profile_path), std::move(sampled_profile)));
-}
-
-// static
-void HeapCollector::ParseProfileOnThreadPool(
-    scoped_refptr<base::SequencedTaskRunner> task_runner,
-    base::WeakPtr<HeapCollector> heap_collector,
-    std::unique_ptr<base::CommandLine> parser,
-    base::FilePath profile_path,
-    std::unique_ptr<SampledProfile> sampled_profile) {
-  // We may exit due to parsing errors, so use a FileDeleter to remove the
-  // temporary profile data on all paths.
-  FileDeleter file_deleter(profile_path);
-
-  // Run the parser command on the profile file.
-  std::string output;
-  if (!base::GetAppOutput(*parser, &output)) {
-    heap_collector->AddToUmaHistogram(
-        CollectionAttemptStatus::ILLEGAL_DATA_RETURNED);
-    return;
-  }
-  task_runner->PostTask(
-      FROM_HERE,
-      base::BindOnce(&HeapCollector::SaveSerializedPerfProto, heap_collector,
-                     std::move(sampled_profile), std::move(output)));
-}
-
-}  // namespace metrics
diff --git a/chrome/browser/metrics/perf/heap_collector.h b/chrome/browser/metrics/perf/heap_collector.h
deleted file mode 100644
index cc330016..0000000
--- a/chrome/browser/metrics/perf/heap_collector.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2019 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_METRICS_PERF_HEAP_COLLECTOR_H_
-#define CHROME_BROWSER_METRICS_PERF_HEAP_COLLECTOR_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/feature_list.h"
-#include "base/optional.h"
-#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
-#include "chrome/browser/metrics/perf/metric_collector.h"
-
-namespace base {
-class CommandLine;
-class File;
-class FilePath;
-}  // namespace base
-
-namespace metrics {
-
-// Collection mode type.
-enum class HeapCollectionMode {
-  // No heap collection.
-  kNone = 0,
-  // Use allocation sampling inside tcmalloc.
-  kTcmalloc = 1,
-  // Use allocation sampling at the shim layer.
-  kShimLayer = 2,
-};
-
-class WindowedIncognitoObserver;
-
-// Enables collection of heap profiles using the tcmalloc heap sampling
-// profiler.
-class HeapCollector : public internal::MetricCollector {
- public:
-  explicit HeapCollector(HeapCollectionMode mode);
-
-  static HeapCollectionMode CollectionModeFromString(std::string mode);
-
-  // MetricCollector:
-  ~HeapCollector() override;
-  const char* ToolName() const override;
-
- protected:
-  // MetricCollector:
-  void SetUp() override;
-  base::WeakPtr<internal::MetricCollector> GetWeakPtr() override;
-  bool ShouldCollect() const override;
-  void CollectProfile(std::unique_ptr<SampledProfile> sampled_profile) override;
-
-  // Fetches a heap profile from tcmalloc, dumps it to a temp file, and returns
-  // the path.
-  base::Optional<base::FilePath> DumpProfileToTempFile(
-      std::unique_ptr<WindowedIncognitoObserver> incognito_observer);
-
-  // Generates a quipper command to parse the given profile file.
-  static std::unique_ptr<base::CommandLine> MakeQuipperCommand(
-      const base::FilePath& profile_path);
-
-  // Executes the given command line to parse a profile stored at the given
-  // path by posting an asynchronous task to the thread pool, since the parsing
-  // may be blocking.
-  void ParseAndSaveProfile(std::unique_ptr<base::CommandLine> parser,
-                           base::FilePath profile_path,
-                           std::unique_ptr<SampledProfile> sampled_profile);
-
-  // Executes on the thread pool the given command line to parse a profile
-  // stored at the given path and saves it in the given sampled profile. The
-  // given temporary profile path is removed after parsing. The updated sampled
-  // profile is passed to SaveSerializedPerfProto on the given task runner.
-  static void ParseProfileOnThreadPool(
-      scoped_refptr<base::SequencedTaskRunner> task_runner,
-      base::WeakPtr<HeapCollector> heap_collector,
-      std::unique_ptr<base::CommandLine> parser,
-      base::FilePath profile_path,
-      std::unique_ptr<SampledProfile> sampled_profile);
-
-  // Start and stop the collection.
-  void EnableSampling();
-  void DisableSampling();
-  HeapCollectionMode Mode() const { return mode_; }
-  bool IsEnabled() const { return is_enabled_; }
-
- private:
-  // Change the values in |collection_params_| based on the values of field
-  // trial parameters.
-  void SetCollectionParamsFromFeatureParams();
-
-  // Heap collection mode. Thread safe.
-  const HeapCollectionMode mode_;
-
-  bool is_enabled_;
-
-  // Heap sampling period.
-  size_t sampling_period_bytes_;
-
-  base::WeakPtrFactory<HeapCollector> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(HeapCollector);
-};
-
-// Exposed for unit testing.
-namespace internal {
-
-// Writes the given heap samples and runtime mappings to the given output file
-// in the same format as the one produced by the tcmalloc sampler.
-bool WriteHeapProfileToFile(
-    base::File* out,
-    const std::vector<base::SamplingHeapProfiler::Sample>& samples,
-    const std::string& proc_maps);
-
-}  // namespace internal
-
-}  // namespace metrics
-
-#endif  // CHROME_BROWSER_METRICS_PERF_HEAP_COLLECTOR_H_
diff --git a/chrome/browser/metrics/perf/heap_collector_unittest.cc b/chrome/browser/metrics/perf/heap_collector_unittest.cc
deleted file mode 100644
index 9b67b55..0000000
--- a/chrome/browser/metrics/perf/heap_collector_unittest.cc
+++ /dev/null
@@ -1,736 +0,0 @@
-// Copyright 2019 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/metrics/perf/heap_collector.h"
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "base/allocator/allocator_extension.h"
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/sampling_heap_profiler/poisson_allocation_sampler.h"
-#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/scoped_feature_list.h"
-#include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
-#include "components/services/heap_profiling/public/cpp/settings.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/test/browser_task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/metrics_proto/sampled_profile.pb.h"
-
-namespace metrics {
-
-namespace {
-
-// Returns a sample PerfDataProto for a heap profile.
-PerfDataProto GetSampleHeapPerfDataProto() {
-  PerfDataProto proto;
-
-  // Add file attributes.
-  PerfDataProto_PerfFileAttr* file_attr = proto.add_file_attrs();
-  PerfDataProto_PerfEventAttr* event_attr = file_attr->mutable_attr();
-  event_attr->set_type(1);    // PERF_TYPE_SOFTWARE
-  event_attr->set_size(96);   // PERF_ATTR_SIZE_VER3
-  event_attr->set_config(9);  // PERF_COUNT_SW_DUMMY
-  event_attr->set_sample_id_all(true);
-  event_attr->set_sample_period(111222);
-  event_attr->set_sample_type(1 /*PERF_SAMPLE_IP*/ | 2 /*PERF_SAMPLE_TID*/ |
-                              32 /*PERF_SAMPLE_CALLCHAIN*/ |
-                              64 /*PERF_SAMPLE_ID*/ |
-                              256 /*PERF_SAMPLE_PERIOD*/);
-  event_attr->set_mmap(true);
-  file_attr->add_ids(0);
-
-  PerfDataProto_PerfEventType* event_type = proto.add_event_types();
-  event_type->set_id(9);  // PERF_COUNT_SW_DUMMY
-
-  file_attr = proto.add_file_attrs();
-  event_attr = file_attr->mutable_attr();
-  event_attr->set_type(1);    // PERF_TYPE_SOFTWARE
-  event_attr->set_size(96);   // PERF_ATTR_SIZE_VER3
-  event_attr->set_config(9);  // PERF_COUNT_SW_DUMMY
-  event_attr->set_sample_id_all(true);
-  event_attr->set_sample_period(111222);
-  event_attr->set_sample_type(1 /*PERF_SAMPLE_IP*/ | 2 /*PERF_SAMPLE_TID*/ |
-                              32 /*PERF_SAMPLE_CALLCHAIN*/ |
-                              64 /*PERF_SAMPLE_ID*/ |
-                              256 /*PERF_SAMPLE_PERIOD*/);
-  file_attr->add_ids(1);
-
-  event_type = proto.add_event_types();
-  event_type->set_id(9);  // PERF_COUNT_SW_DUMMY
-
-  // Add MMAP event.
-  PerfDataProto_PerfEvent* event = proto.add_events();
-  PerfDataProto_EventHeader* header = event->mutable_header();
-  header->set_type(1);  // PERF_RECORD_MMAP
-  header->set_misc(0);
-  header->set_size(0);
-
-  PerfDataProto_MMapEvent* mmap = event->mutable_mmap_event();
-  mmap->set_pid(3456);
-  mmap->set_tid(3456);
-  mmap->set_start(0x617aa770f000);
-  mmap->set_len(0x617ab0689000 - 0x617aa770f000);
-  mmap->set_pgoff(16);
-
-  PerfDataProto_SampleInfo* sample_info = mmap->mutable_sample_info();
-  sample_info->set_pid(3456);
-  sample_info->set_tid(3456);
-  sample_info->set_id(0);
-
-  // Add Sample events.
-  event = proto.add_events();
-  header = event->mutable_header();
-  header->set_type(9);  // PERF_RECORD_SAMPLE
-  header->set_misc(2);  // PERF_RECORD_MISC_USER
-  header->set_size(0);
-
-  double scale = 1 / (1 - exp(-(1024.00 / 2.00) / 111222.00));
-
-  PerfDataProto_SampleEvent* sample = event->mutable_sample_event();
-  sample->set_ip(0x617aae951c31);
-  sample->set_pid(3456);
-  sample->set_tid(3456);
-  sample->set_id(0);
-  sample->set_period(2 * scale);
-  sample->add_callchain(static_cast<uint64_t>(-512));  // PERF_CONTEXT_USER
-  sample->add_callchain(0x617aae951c31);
-  sample->add_callchain(0x617aae95062e);
-
-  event = proto.add_events();
-  header = event->mutable_header();
-  header->set_type(9);  // PERF_RECORD_SAMPLE
-  header->set_misc(2);  // PERF_RECORD_MISC_USER
-  header->set_size(0);
-
-  sample = event->mutable_sample_event();
-  sample->set_ip(0x617aae951c31);
-  sample->set_pid(3456);
-  sample->set_tid(3456);
-  sample->set_id(1);
-  sample->set_period(1024 * scale);
-  sample->add_callchain(static_cast<uint64_t>(-512));  // PERF_CONTEXT_USER
-  sample->add_callchain(0x617aae951c31);
-  sample->add_callchain(0x617aae95062e);
-
-  return proto;
-}
-
-// Allows testing of HeapCollector behavior when an incognito window is opened.
-class TestIncognitoObserver : public WindowedIncognitoObserver {
- public:
-  // Factory function to create a TestIncognitoObserver object contained in a
-  // std::unique_ptr<WindowedIncognitoObserver> object. |incognito_launched|
-  // simulates the presence of an open incognito window, or the lack thereof.
-  // Used for passing observers to ParseOutputProtoIfValid().
-  static std::unique_ptr<WindowedIncognitoObserver> CreateWithIncognitoLaunched(
-      bool incognito_launched) {
-    return base::WrapUnique(new TestIncognitoObserver(incognito_launched));
-  }
-
-  bool IncognitoLaunched() const override { return incognito_launched_; }
-
- private:
-  explicit TestIncognitoObserver(bool incognito_launched)
-      : WindowedIncognitoObserver(nullptr, 0),
-        incognito_launched_(incognito_launched) {}
-
-  bool incognito_launched_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestIncognitoObserver);
-};
-
-// Allows access to some private methods for testing.
-class TestHeapCollector : public HeapCollector {
- public:
-  TestHeapCollector() : HeapCollector(HeapCollectionMode::kTcmalloc) {}
-  explicit TestHeapCollector(HeapCollectionMode mode) : HeapCollector(mode) {}
-
-  using HeapCollector::AddCachedDataDelta;
-  using HeapCollector::collection_params;
-  using HeapCollector::DumpProfileToTempFile;
-  using HeapCollector::Init;
-  using HeapCollector::IsEnabled;
-  using HeapCollector::IsRunning;
-  using HeapCollector::MakeQuipperCommand;
-  using HeapCollector::Mode;
-  using HeapCollector::ParseAndSaveProfile;
-  using HeapCollector::RecordUserLogin;
-  using HeapCollector::set_profile_done_callback;
-
-  DISALLOW_COPY_AND_ASSIGN(TestHeapCollector);
-};
-
-const base::TimeDelta kPeriodicCollectionInterval =
-    base::TimeDelta::FromHours(1);
-
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-size_t HeapSamplingPeriod(const TestHeapCollector& collector) {
-  CHECK_EQ(collector.Mode(), HeapCollectionMode::kTcmalloc)
-      << "Reading heap sampling period works only with tcmalloc sampling";
-  size_t sampling_period;
-  CHECK(base::allocator::GetNumericProperty("tcmalloc.sampling_period_bytes",
-                                            &sampling_period))
-      << "Failed to read heap sampling period";
-  return sampling_period;
-}
-#endif
-
-}  // namespace
-
-class HeapCollectorTest : public testing::Test {
- public:
-  HeapCollectorTest()
-      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
-
-  void SaveProfile(std::unique_ptr<SampledProfile> sampled_profile) {
-    cached_profile_data_.resize(cached_profile_data_.size() + 1);
-    cached_profile_data_.back().Swap(sampled_profile.get());
-  }
-
-  void MakeHeapCollector(HeapCollectionMode mode) {
-    heap_collector_ = std::make_unique<TestHeapCollector>(mode);
-    // Set the periodic collection delay to a well known quantity, so we can
-    // fast forward the time.
-    heap_collector_->collection_params().periodic_interval =
-        kPeriodicCollectionInterval;
-    heap_collector_->set_profile_done_callback(base::BindRepeating(
-        &HeapCollectorTest::SaveProfile, base::Unretained(this)));
-
-    heap_collector_->Init();
-    // HeapCollector requires the user to be logged in.
-    heap_collector_->RecordUserLogin(base::TimeTicks::Now());
-  }
-
-  void TearDown() override {
-    heap_collector_.reset();
-    cached_profile_data_.clear();
-  }
-
- protected:
-  content::BrowserTaskEnvironment task_environment_;
-
-  std::vector<SampledProfile> cached_profile_data_;
-
-  std::unique_ptr<TestHeapCollector> heap_collector_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeapCollectorTest);
-};
-
-TEST_F(HeapCollectorTest, CheckTestIncognitoObserver) {
-  EXPECT_FALSE(TestIncognitoObserver::CreateWithIncognitoLaunched(false)
-                   ->IncognitoLaunched());
-  EXPECT_TRUE(TestIncognitoObserver::CreateWithIncognitoLaunched(true)
-                  ->IncognitoLaunched());
-}
-
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-TEST_F(HeapCollectorTest, CheckSetup_Tcmalloc) {
-  MakeHeapCollector(HeapCollectionMode::kTcmalloc);
-
-  // No profiles are cached on start.
-  EXPECT_TRUE(cached_profile_data_.empty());
-
-  // Heap sampling is enabled.
-  size_t sampling_period = HeapSamplingPeriod(*heap_collector_);
-  EXPECT_GT(sampling_period, 0u);
-}
-
-TEST_F(HeapCollectorTest, NoCollectionWhenProfileCacheFull_Tcmalloc) {
-  MakeHeapCollector(HeapCollectionMode::kTcmalloc);
-  // Timer is active after login and a periodic collection is scheduled.
-  EXPECT_TRUE(heap_collector_->IsRunning());
-  // Pretend the cache is full.
-  heap_collector_->AddCachedDataDelta(4 * 1024 * 1024);
-
-  // Advance the clock by a periodic collection interval. We shouldn't find a
-  // profile because the cache is full.
-  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
-
-  EXPECT_TRUE(cached_profile_data_.empty());
-}
-
-TEST_F(HeapCollectorTest, DumpProfileToTempFile_NoIncognito_Tcmalloc) {
-  MakeHeapCollector(HeapCollectionMode::kTcmalloc);
-
-  auto incognito_observer =
-      TestIncognitoObserver::CreateWithIncognitoLaunched(false);
-  base::Optional<base::FilePath> got_path =
-      heap_collector_->DumpProfileToTempFile(std::move(incognito_observer));
-  // Check that we got a path.
-  ASSERT_TRUE(got_path);
-  // Check that the file is readable and not empty.
-  base::File temp(got_path.value(),
-                  base::File::FLAG_OPEN | base::File::FLAG_READ);
-  ASSERT_TRUE(temp.IsValid());
-  EXPECT_GT(temp.GetLength(), 0);
-  temp.Close();
-  // We must be able to remove the temp file.
-  ASSERT_TRUE(base::DeleteFile(got_path.value(), false));
-}
-
-TEST_F(HeapCollectorTest, DumpProfileToTempFile_IncognitoOpened_Tcmalloc) {
-  MakeHeapCollector(HeapCollectionMode::kTcmalloc);
-
-  auto incognito_observer =
-      TestIncognitoObserver::CreateWithIncognitoLaunched(true);
-  base::Optional<base::FilePath> got_path =
-      heap_collector_->DumpProfileToTempFile(std::move(incognito_observer));
-  // Check that we got a path.
-  ASSERT_FALSE(got_path);
-}
-
-TEST_F(HeapCollectorTest, ParseAndSaveProfile_Tcmalloc) {
-  MakeHeapCollector(HeapCollectionMode::kTcmalloc);
-
-  // Write a sample perf data proto to a temp file.
-  const base::FilePath kTempProfile(
-      FILE_PATH_LITERAL("/tmp/ParseAndSaveProfile.test"));
-  PerfDataProto heap_proto = GetSampleHeapPerfDataProto();
-  std::string serialized_proto = heap_proto.SerializeAsString();
-
-  base::File temp(kTempProfile, base::File::FLAG_CREATE_ALWAYS |
-                                    base::File::FLAG_READ |
-                                    base::File::FLAG_WRITE);
-  EXPECT_TRUE(temp.created());
-  EXPECT_TRUE(temp.IsValid());
-  int res = temp.WriteAtCurrentPos(serialized_proto.c_str(),
-                                   serialized_proto.length());
-  EXPECT_EQ(res, static_cast<int>(serialized_proto.length()));
-  temp.Close();
-
-  // Create a command line that copies the input file to the output.
-  base::CommandLine::StringVector argv;
-  argv.push_back("cat");
-  argv.push_back(kTempProfile.value());
-  auto cat = std::make_unique<base::CommandLine>(argv);
-
-  // Run the command.
-  auto sampled_profile = std::make_unique<SampledProfile>();
-  sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
-  heap_collector_->ParseAndSaveProfile(std::move(cat), kTempProfile,
-                                       std::move(sampled_profile));
-  task_environment_.RunUntilIdle();
-
-  // Check that the profile was cached.
-  ASSERT_EQ(1U, cached_profile_data_.size());
-
-  const SampledProfile& profile = cached_profile_data_[0];
-  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
-  EXPECT_TRUE(profile.has_ms_after_boot());
-  EXPECT_TRUE(profile.has_ms_after_login());
-
-  ASSERT_TRUE(profile.has_perf_data());
-  EXPECT_EQ(serialized_proto, profile.perf_data().SerializeAsString());
-
-  // Check that the temp profile file is removed after pending tasks complete.
-  temp =
-      base::File(kTempProfile, base::File::FLAG_OPEN | base::File::FLAG_READ);
-  ASSERT_FALSE(temp.IsValid());
-}
-#endif
-
-TEST_F(HeapCollectorTest, CheckSetup_ShimLayer) {
-  MakeHeapCollector(HeapCollectionMode::kShimLayer);
-
-  // No profiles are cached on start.
-  EXPECT_TRUE(cached_profile_data_.empty());
-
-  // Heap sampling is enabled.
-  EXPECT_TRUE(heap_collector_->IsEnabled());
-}
-
-TEST_F(HeapCollectorTest, NoCollectionWhenProfileCacheFull_ShimLayer) {
-  MakeHeapCollector(HeapCollectionMode::kShimLayer);
-  // Timer is active after login and a periodic collection is scheduled.
-  EXPECT_TRUE(heap_collector_->IsRunning());
-  // Pretend the cache is full.
-  heap_collector_->AddCachedDataDelta(4 * 1024 * 1024);
-
-  // Advance the clock by a periodic collection interval. We shouldn't find a
-  // profile because the cache is full.
-  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
-
-  EXPECT_TRUE(cached_profile_data_.empty());
-}
-
-TEST_F(HeapCollectorTest, DumpProfileToTempFile_NoIncognito_ShimLayer) {
-  MakeHeapCollector(HeapCollectionMode::kShimLayer);
-
-  auto incognito_observer =
-      TestIncognitoObserver::CreateWithIncognitoLaunched(false);
-  base::Optional<base::FilePath> got_path =
-      heap_collector_->DumpProfileToTempFile(std::move(incognito_observer));
-  // Check that we got a path.
-  ASSERT_TRUE(got_path);
-  // Check that the file is readable and not empty.
-  base::File temp(got_path.value(),
-                  base::File::FLAG_OPEN | base::File::FLAG_READ);
-  ASSERT_TRUE(temp.IsValid());
-  EXPECT_GT(temp.GetLength(), 0);
-  temp.Close();
-  // We must be able to remove the temp file.
-  ASSERT_TRUE(base::DeleteFile(got_path.value(), false));
-}
-
-TEST_F(HeapCollectorTest, DumpProfileToTempFile_IncognitoOpened_ShimLayer) {
-  MakeHeapCollector(HeapCollectionMode::kShimLayer);
-
-  auto incognito_observer =
-      TestIncognitoObserver::CreateWithIncognitoLaunched(true);
-  base::Optional<base::FilePath> got_path =
-      heap_collector_->DumpProfileToTempFile(std::move(incognito_observer));
-  // Check that we got a path.
-  ASSERT_FALSE(got_path);
-}
-
-TEST_F(HeapCollectorTest, MakeQuipperCommand) {
-  const base::FilePath kTempProfile(
-      FILE_PATH_LITERAL("/tmp/MakeQuipperCommand.test"));
-  std::unique_ptr<base::CommandLine> got =
-      TestHeapCollector::MakeQuipperCommand(kTempProfile);
-  ASSERT_TRUE(got);
-
-  // Check that we got the correct two switch names.
-  ASSERT_EQ(got->GetSwitches().size(), 2u);
-  EXPECT_TRUE(got->HasSwitch("input_heap_profile"));
-  EXPECT_TRUE(got->HasSwitch("pid"));
-
-  // Check that we got the correct program name and switch values.
-  EXPECT_EQ(got->GetProgram().value(), "/usr/bin/quipper");
-  EXPECT_EQ(got->GetSwitchValuePath("input_heap_profile"), kTempProfile);
-  EXPECT_EQ(got->GetSwitchValueASCII("pid"),
-            base::NumberToString(base::GetCurrentProcId()));
-}
-
-TEST_F(HeapCollectorTest, ParseAndSaveProfile_ShimLayer) {
-  MakeHeapCollector(HeapCollectionMode::kShimLayer);
-
-  // Write a sample perf data proto to a temp file.
-  const base::FilePath kTempProfile(
-      FILE_PATH_LITERAL("/tmp/ParseAndSaveProfile.test"));
-  PerfDataProto heap_proto = GetSampleHeapPerfDataProto();
-  std::string serialized_proto = heap_proto.SerializeAsString();
-
-  base::File temp(kTempProfile, base::File::FLAG_CREATE_ALWAYS |
-                                    base::File::FLAG_READ |
-                                    base::File::FLAG_WRITE);
-  EXPECT_TRUE(temp.created());
-  EXPECT_TRUE(temp.IsValid());
-  int res = temp.WriteAtCurrentPos(serialized_proto.c_str(),
-                                   serialized_proto.length());
-  EXPECT_EQ(res, static_cast<int>(serialized_proto.length()));
-  temp.Close();
-
-  // Create a command line that copies the input file to the output.
-  base::CommandLine::StringVector argv;
-  argv.push_back("cat");
-  argv.push_back(kTempProfile.value());
-  auto cat = std::make_unique<base::CommandLine>(argv);
-
-  // Run the command.
-  auto sampled_profile = std::make_unique<SampledProfile>();
-  sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
-  heap_collector_->ParseAndSaveProfile(std::move(cat), kTempProfile,
-                                       std::move(sampled_profile));
-  task_environment_.RunUntilIdle();
-
-  // Check that the profile was cached.
-  ASSERT_EQ(1U, cached_profile_data_.size());
-
-  const SampledProfile& profile = cached_profile_data_[0];
-  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
-  EXPECT_TRUE(profile.has_ms_after_boot());
-  EXPECT_TRUE(profile.has_ms_after_login());
-
-  ASSERT_TRUE(profile.has_perf_data());
-  EXPECT_EQ(serialized_proto, profile.perf_data().SerializeAsString());
-
-  // Check that the temp profile file is removed after pending tasks complete.
-  temp =
-      base::File(kTempProfile, base::File::FLAG_OPEN | base::File::FLAG_READ);
-  ASSERT_FALSE(temp.IsValid());
-}
-
-class HeapCollectorCollectionParamsTest : public testing::Test {
- public:
-  HeapCollectorCollectionParamsTest() = default;
-
- protected:
-  content::BrowserTaskEnvironment task_environment_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeapCollectorCollectionParamsTest);
-};
-
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-TEST_F(HeapCollectorCollectionParamsTest, ParametersOverride_Tcmalloc) {
-  std::map<std::string, std::string> params;
-  params.insert(std::make_pair("SamplingIntervalBytes", "800000"));
-  params.insert(std::make_pair("PeriodicCollectionIntervalMs", "3600000"));
-  params.insert(std::make_pair("ResumeFromSuspend::SamplingFactor", "1"));
-  params.insert(std::make_pair("ResumeFromSuspend::MaxDelaySec", "10"));
-  params.insert(std::make_pair("RestoreSession::SamplingFactor", "2"));
-  params.insert(std::make_pair("RestoreSession::MaxDelaySec", "20"));
-
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      heap_profiling::kOOPHeapProfilingFeature, params);
-
-  auto heap_collector =
-      std::make_unique<TestHeapCollector>(HeapCollectionMode::kTcmalloc);
-  const auto& parsed_params = heap_collector->collection_params();
-
-  // Not initialized yet:
-  size_t sampling_period = HeapSamplingPeriod(*heap_collector);
-  EXPECT_NE(800000u, sampling_period);
-  EXPECT_NE(base::TimeDelta::FromHours(1), parsed_params.periodic_interval);
-  EXPECT_NE(1, parsed_params.resume_from_suspend.sampling_factor);
-  EXPECT_NE(base::TimeDelta::FromSeconds(10),
-            parsed_params.resume_from_suspend.max_collection_delay);
-  EXPECT_NE(2, parsed_params.restore_session.sampling_factor);
-  EXPECT_NE(base::TimeDelta::FromSeconds(20),
-            parsed_params.restore_session.max_collection_delay);
-
-  heap_collector->Init();
-
-  sampling_period = HeapSamplingPeriod(*heap_collector);
-  EXPECT_EQ(800000u, sampling_period);
-  EXPECT_EQ(base::TimeDelta::FromHours(1), parsed_params.periodic_interval);
-  EXPECT_EQ(1, parsed_params.resume_from_suspend.sampling_factor);
-  EXPECT_EQ(base::TimeDelta::FromSeconds(10),
-            parsed_params.resume_from_suspend.max_collection_delay);
-  EXPECT_EQ(2, parsed_params.restore_session.sampling_factor);
-  EXPECT_EQ(base::TimeDelta::FromSeconds(20),
-            parsed_params.restore_session.max_collection_delay);
-}
-#endif
-
-TEST_F(HeapCollectorCollectionParamsTest, ParametersOverride_ShimLayer) {
-  std::map<std::string, std::string> params;
-  params.insert(std::make_pair("SamplingIntervalBytes", "800000"));
-  params.insert(std::make_pair("PeriodicCollectionIntervalMs", "3600000"));
-  params.insert(std::make_pair("ResumeFromSuspend::SamplingFactor", "1"));
-  params.insert(std::make_pair("ResumeFromSuspend::MaxDelaySec", "10"));
-  params.insert(std::make_pair("RestoreSession::SamplingFactor", "2"));
-  params.insert(std::make_pair("RestoreSession::MaxDelaySec", "20"));
-
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      heap_profiling::kOOPHeapProfilingFeature, params);
-
-  auto heap_collector =
-      std::make_unique<TestHeapCollector>(HeapCollectionMode::kShimLayer);
-  const auto& parsed_params = heap_collector->collection_params();
-
-  // Not initialized yet:
-  EXPECT_NE(base::TimeDelta::FromHours(1), parsed_params.periodic_interval);
-  EXPECT_NE(1, parsed_params.resume_from_suspend.sampling_factor);
-  EXPECT_NE(base::TimeDelta::FromSeconds(10),
-            parsed_params.resume_from_suspend.max_collection_delay);
-  EXPECT_NE(2, parsed_params.restore_session.sampling_factor);
-  EXPECT_NE(base::TimeDelta::FromSeconds(20),
-            parsed_params.restore_session.max_collection_delay);
-
-  heap_collector->Init();
-
-  EXPECT_EQ(base::TimeDelta::FromHours(1), parsed_params.periodic_interval);
-  EXPECT_EQ(1, parsed_params.resume_from_suspend.sampling_factor);
-  EXPECT_EQ(base::TimeDelta::FromSeconds(10),
-            parsed_params.resume_from_suspend.max_collection_delay);
-  EXPECT_EQ(2, parsed_params.restore_session.sampling_factor);
-  EXPECT_EQ(base::TimeDelta::FromSeconds(20),
-            parsed_params.restore_session.max_collection_delay);
-}
-
-namespace {
-
-std::vector<base::SamplingHeapProfiler::Sample> SamplingHeapProfilerSamples() {
-  // Generate a sample using the SamplingHeapProfiler collector. Then, duplicate
-  // and customize their values.
-  base::SamplingHeapProfiler::Init();
-  auto* collector = base::SamplingHeapProfiler::Get();
-  collector->Start();
-
-  auto* sampler = base::PoissonAllocationSampler::Get();
-  sampler->SuppressRandomnessForTest(true);
-  sampler->SetSamplingInterval(1000000);
-  // Generate and remove a dummy sample, because the first sample is potentially
-  // ignored by the SHP profiler.
-  sampler->RecordAlloc(reinterpret_cast<void*>(1), 1000000,
-                       base::PoissonAllocationSampler::AllocatorType::kMalloc,
-                       nullptr);
-  sampler->RecordFree(reinterpret_cast<void*>(1));
-  // Generate a second sample that we are going to retrieve.
-  sampler->RecordAlloc(reinterpret_cast<void*>(2), 1000000,
-                       base::PoissonAllocationSampler::AllocatorType::kMalloc,
-                       nullptr);
-
-  auto samples = collector->GetSamples(0);
-  EXPECT_EQ(1lu, samples.size());
-  sampler->RecordFree(reinterpret_cast<void*>(2));
-  collector->Stop();
-
-  // Customize the sample.
-  auto& sample1 = samples[0];
-  sample1.size = 100;
-  sample1.total = 1000;
-  sample1.stack = {reinterpret_cast<void*>(0x10000),
-                   reinterpret_cast<void*>(0x10100),
-                   reinterpret_cast<void*>(0x10200)};
-
-  samples.emplace_back(samples.back());
-  EXPECT_EQ(2lu, samples.size());
-  auto& sample2 = samples[1];
-  sample2.size = 200;
-  sample2.total = 2000;
-  sample2.stack = {
-      reinterpret_cast<void*>(0x20000), reinterpret_cast<void*>(0x20100),
-      reinterpret_cast<void*>(0x20200), reinterpret_cast<void*>(0x20300)};
-
-  samples.emplace_back(samples.back());
-  EXPECT_EQ(3lu, samples.size());
-  auto& sample3 = samples[2];
-  sample3.size = 300;
-  sample3.total = 3000;
-  sample3.stack = {reinterpret_cast<void*>(0x30000),
-                   reinterpret_cast<void*>(0x30100),
-                   reinterpret_cast<void*>(0x30200)};
-
-  return samples;
-}
-
-std::string GetProcMaps() {
-  return R"text(304acba71000-304acba72000 ---p 00000000 00:00 0
-304acba72000-304acd86a000 rw-p 00000000 00:00 0
-304acd86a000-304acd86b000 ---p 00000000 00:00 0
-304acd86b000-304acd88a000 rw-p 00000000 00:00 0
-304acd88a000-304acd88b000 ---p 00000000 00:00 0
-304acd88b000-304acd8aa000 rw-p 00000000 00:00 0
-5ffa92db8000-5ffa93d15000 r--p 00000000 b3:03 71780                      /opt/google/chrome/chrome
-5ffa93d15000-5ffa93d16000 r--p 00f5d000 b3:03 71780                      /opt/google/chrome/chrome
-5ffa93d16000-5ffa93d17000 r--p 00f5e000 b3:03 71780                      /opt/google/chrome/chrome
-5ffa93d17000-5ffa9d176000 r-xp 00f5f000 b3:03 71780                      /opt/google/chrome/chrome
-5ffa9d176000-5ffa9d1ca000 rw-p 0a3be000 b3:03 71780                      /opt/google/chrome/chrome
-5ffa9d1ca000-5ffa9d8ff000 r--p 0a412000 b3:03 71780                      /opt/google/chrome/chrome
-5ffa9d8ff000-5ffa9db6c000 rw-p 00000000 00:00 0
-7f9c9e11c000-7f9c9e11d000 ---p 00000000 00:00 0
-7f9c9e11d000-7f9c9e91d000 rw-p 00000000 00:00 0                          [stack:1843]
-7f9c9e91d000-7f9c9e91e000 ---p 00000000 00:00 0
-7f9c9e91e000-7f9c9f11e000 rw-p 00000000 00:00 0
-7f9ca0d47000-7f9ca0d4c000 r-xp 00000000 b3:03 46090                      /lib64/libnss_dns-2.27.so
-7f9ca0d4c000-7f9ca0f4b000 ---p 00005000 b3:03 46090                      /lib64/libnss_dns-2.27.so
-7f9ca0f4b000-7f9ca0f4c000 r--p 00004000 b3:03 46090                      /lib64/libnss_dns-2.27.so
-7f9ca0f4c000-7f9ca0f4d000 rw-p 00005000 b3:03 46090                      /lib64/libnss_dns-2.27.so
-7f9ca0f4d000-7f9ca114d000 rw-s 00000000 00:13 16382                      /dev/shm/.com.google.Chrome.nohIdv (deleted)
-7f9ca26a0000-7f9ca26a1000 ---p 00000000 00:00 0
-7f9ca26a1000-7f9ca2ea1000 rw-p 00000000 00:00 0                          [stack:1796]
-7f9ca2ea1000-7f9ca2f31000 r-xp 00000000 b3:03 46120                      /lib64/libpcre.so.1.2.9
-7f9ca2f31000-7f9ca2f32000 r--p 0008f000 b3:03 46120                      /lib64/libpcre.so.1.2.9
-7f9ca2f32000-7f9ca2f33000 rw-p 00090000 b3:03 46120                      /lib64/libpcre.so.1.2.9
-7f9ca2f33000-7f9ca302d000 r-xp 00000000 b3:03 40207                      /usr/lib64/libglib-2.0.so.0.5200.3
-7f9ca302e000-7f9ca302f000 r--p 000fa000 b3:03 40207                      /usr/lib64/libglib-2.0.so.0.5200.3
-7f9ca4687000-7f9ca4887000 rw-s 00000000 00:13 12699                      /dev/shm/.com.google.Chrome.KWz8dN (deleted)
-7f9ca4887000-7f9ca4888000 ---p 00000000 00:00 0
-7f9ca4888000-7f9ca5088000 rw-p 00000000 00:00 0                          [stack:1423]
-7f9ca52c8000-7f9ca52c9000 ---p 00000000 00:00 0
-7f9ca52c9000-7f9ca5ac9000 rw-p 00000000 00:00 0                          [stack:1411]
-7f9ca5aec000-7f9ca5b66000 r--p 00000000 b3:03 39083                      /usr/share/fonts/roboto/Roboto-Light.ttf
-7f9ca5b66000-7f9ca5d66000 rw-s 00000000 00:13 10081                      /dev/shm/.com.google.Chrome.MLuvgs (deleted)
-)text";
-}
-
-}  // namespace
-
-TEST(HeapCollectorShimLayerTest, WriteHeapProfileToFile_InvalidProcMaps) {
-  base::FilePath temp_path;
-  ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
-  base::File temp(temp_path, base::File::FLAG_CREATE_ALWAYS |
-                                 base::File::FLAG_READ |
-                                 base::File::FLAG_WRITE);
-  ASSERT_TRUE(temp.created());
-  ASSERT_TRUE(temp.IsValid());
-
-  auto samples = SamplingHeapProfilerSamples();
-  std::string proc_maps = "Bogus proc maps\n";
-  EXPECT_FALSE(internal::WriteHeapProfileToFile(&temp, samples, proc_maps));
-  temp.Close();
-  base::DeleteFile(temp_path, false);
-}
-
-TEST(HeapCollectorShimLayerTest, WriteHeapProfileToFile) {
-  base::FilePath temp_path;
-  ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
-  base::File temp(temp_path, base::File::FLAG_CREATE_ALWAYS |
-                                 base::File::FLAG_READ |
-                                 base::File::FLAG_WRITE);
-  ASSERT_TRUE(temp.created());
-  ASSERT_TRUE(temp.IsValid());
-
-  auto samples = SamplingHeapProfilerSamples();
-  auto proc_maps = GetProcMaps();
-  EXPECT_TRUE(internal::WriteHeapProfileToFile(&temp, samples, proc_maps));
-  temp.Close();
-
-  std::string got;
-  EXPECT_TRUE(base::ReadFileToString(temp_path, &got));
-
-  std::string want = R"text(heap profile: 3: 6000 [3: 6000] @ heap_v2/1
-1: 1000 [1: 1000] @ 0x10000 0x10100 0x10200
-1: 2000 [1: 2000] @ 0x20000 0x20100 0x20200 0x20300
-1: 3000 [1: 3000] @ 0x30000 0x30100 0x30200
-
-MAPPED_LIBRARIES:
-304acba71000-304acba72000 ---p 00000000 00:00 0 
-304acba72000-304acd86a000 rw-p 00000000 00:00 0 
-304acd86a000-304acd86b000 ---p 00000000 00:00 0 
-304acd86b000-304acd88a000 rw-p 00000000 00:00 0 
-304acd88a000-304acd88b000 ---p 00000000 00:00 0 
-304acd88b000-304acd8aa000 rw-p 00000000 00:00 0 
-5ffa92db8000-5ffa93d15000 r--p 00000000 00:00 0 /opt/google/chrome/chrome
-5ffa93d15000-5ffa93d16000 r--p 00f5d000 00:00 0 /opt/google/chrome/chrome
-5ffa93d16000-5ffa93d17000 r--p 00f5e000 00:00 0 /opt/google/chrome/chrome
-5ffa93d17000-5ffa9d176000 r-xp 00f5f000 00:00 0 /opt/google/chrome/chrome
-5ffa9d176000-5ffa9d1ca000 rw-p 0a3be000 00:00 0 /opt/google/chrome/chrome
-5ffa9d1ca000-5ffa9d8ff000 r--p 0a412000 00:00 0 /opt/google/chrome/chrome
-5ffa9d8ff000-5ffa9db6c000 rw-p 00000000 00:00 0 
-7f9c9e11c000-7f9c9e11d000 ---p 00000000 00:00 0 
-7f9c9e11d000-7f9c9e91d000 rw-p 00000000 00:00 0 [stack:1843]
-7f9c9e91d000-7f9c9e91e000 ---p 00000000 00:00 0 
-7f9c9e91e000-7f9c9f11e000 rw-p 00000000 00:00 0 
-7f9ca0d47000-7f9ca0d4c000 r-xp 00000000 00:00 0 /lib64/libnss_dns-2.27.so
-7f9ca0d4c000-7f9ca0f4b000 ---p 00005000 00:00 0 /lib64/libnss_dns-2.27.so
-7f9ca0f4b000-7f9ca0f4c000 r--p 00004000 00:00 0 /lib64/libnss_dns-2.27.so
-7f9ca0f4c000-7f9ca0f4d000 rw-p 00005000 00:00 0 /lib64/libnss_dns-2.27.so
-7f9ca0f4d000-7f9ca114d000 rw-- 00000000 00:00 0 /dev/shm/.com.google.Chrome.nohIdv (deleted)
-7f9ca26a0000-7f9ca26a1000 ---p 00000000 00:00 0 
-7f9ca26a1000-7f9ca2ea1000 rw-p 00000000 00:00 0 [stack:1796]
-7f9ca2ea1000-7f9ca2f31000 r-xp 00000000 00:00 0 /lib64/libpcre.so.1.2.9
-7f9ca2f31000-7f9ca2f32000 r--p 0008f000 00:00 0 /lib64/libpcre.so.1.2.9
-7f9ca2f32000-7f9ca2f33000 rw-p 00090000 00:00 0 /lib64/libpcre.so.1.2.9
-7f9ca2f33000-7f9ca302d000 r-xp 00000000 00:00 0 /usr/lib64/libglib-2.0.so.0.5200.3
-7f9ca302e000-7f9ca302f000 r--p 000fa000 00:00 0 /usr/lib64/libglib-2.0.so.0.5200.3
-7f9ca4687000-7f9ca4887000 rw-- 00000000 00:00 0 /dev/shm/.com.google.Chrome.KWz8dN (deleted)
-7f9ca4887000-7f9ca4888000 ---p 00000000 00:00 0 
-7f9ca4888000-7f9ca5088000 rw-p 00000000 00:00 0 [stack:1423]
-7f9ca52c8000-7f9ca52c9000 ---p 00000000 00:00 0 
-7f9ca52c9000-7f9ca5ac9000 rw-p 00000000 00:00 0 [stack:1411]
-7f9ca5aec000-7f9ca5b66000 r--p 00000000 00:00 0 /usr/share/fonts/roboto/Roboto-Light.ttf
-7f9ca5b66000-7f9ca5d66000 rw-- 00000000 00:00 0 /dev/shm/.com.google.Chrome.MLuvgs (deleted)
-)text";
-
-  EXPECT_EQ(want, got);
-  base::DeleteFile(temp_path, false);
-}
-
-}  // namespace metrics
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos.cc b/chrome/browser/metrics/perf/profile_provider_chromeos.cc
index b77ba86a..7e4c85a0 100644
--- a/chrome/browser/metrics/perf/profile_provider_chromeos.cc
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos.cc
@@ -9,8 +9,6 @@
 #include "base/feature_list.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
-#include "chrome/browser/metrics/perf/heap_collector.h"
 #include "chrome/browser/metrics/perf/metric_provider.h"
 #include "chrome/browser/metrics/perf/perf_events_collector.h"
 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
@@ -74,19 +72,6 @@
 }
 
 void ProfileProvider::Init() {
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-  if (base::FeatureList::IsEnabled(heap_profiling::kOOPHeapProfilingFeature)) {
-    HeapCollectionMode mode = HeapCollector::CollectionModeFromString(
-        base::GetFieldTrialParamValueByFeature(
-            heap_profiling::kOOPHeapProfilingFeature,
-            heap_profiling::kOOPHeapProfilingFeatureMode));
-    if (mode != HeapCollectionMode::kNone) {
-      collectors_.push_back(std::make_unique<MetricProvider>(
-          std::make_unique<HeapCollector>(mode)));
-    }
-  }
-#endif
-
   for (auto& collector : collectors_) {
     collector->Init();
   }
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
index 7ab0245..ad59e09 100644
--- a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
@@ -17,12 +17,10 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chrome/browser/metrics/perf/heap_collector.h"
 #include "chrome/browser/metrics/perf/metric_collector.h"
 #include "chrome/browser/metrics/perf/metric_provider.h"
 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
 #include "chromeos/login/login_state/login_state.h"
-#include "components/services/heap_profiling/public/cpp/settings.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_task_environment.h"
@@ -485,21 +483,21 @@
 
 namespace {
 
-class TestParamsProfileProvider : public ProfileProvider {
+class TestStockProfileProvider : public ProfileProvider {
  public:
-  TestParamsProfileProvider() = default;
+  TestStockProfileProvider() = default;
 
   using ProfileProvider::collectors_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(TestParamsProfileProvider);
+  DISALLOW_COPY_AND_ASSIGN(TestStockProfileProvider);
 };
 
 }  // namespace
 
-class ProfileProviderFeatureParamsTest : public testing::Test {
+class ProfileProviderStockTest : public testing::Test {
  public:
-  ProfileProviderFeatureParamsTest() = default;
+  ProfileProviderStockTest() = default;
 
   void SetUp() override {
     // ProfileProvider requires chromeos::LoginState and
@@ -517,60 +515,17 @@
   content::BrowserTaskEnvironment task_environment_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ProfileProviderFeatureParamsTest);
+  DISALLOW_COPY_AND_ASSIGN(ProfileProviderStockTest);
 };
 
-TEST_F(ProfileProviderFeatureParamsTest, HeapCollectorDisabled) {
-  std::map<std::string, std::string> params;
-  params.insert(
-      std::make_pair(heap_profiling::kOOPHeapProfilingFeatureMode, "non-cwp"));
-
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      heap_profiling::kOOPHeapProfilingFeature, params);
-
-  TestParamsProfileProvider profile_provider;
+TEST_F(ProfileProviderStockTest, CheckSetup) {
+  TestStockProfileProvider profile_provider;
   // We should have one collector registered.
   EXPECT_EQ(1u, profile_provider.collectors_.size());
 
-  // After initialization, we should still have a single collector, because the
-  // sampling factor param is set to 0.
+  // After initialization, we should still have a single collector.
   profile_provider.Init();
   EXPECT_EQ(1u, profile_provider.collectors_.size());
-
-  // Before destroying ScopedFeatureList, we need to finish SetUp() of each
-  // registered collector, which accesses field trial params on its own
-  // dedicated sequence.
-  task_environment_.RunUntilIdle();
-}
-
-TEST_F(ProfileProviderFeatureParamsTest, HeapCollectorEnabled) {
-  std::map<std::string, std::string> params;
-  params.insert(std::make_pair(heap_profiling::kOOPHeapProfilingFeatureMode,
-                               "cwp-tcmalloc"));
-
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      heap_profiling::kOOPHeapProfilingFeature, params);
-
-  TestParamsProfileProvider profile_provider;
-  // We should have one collector registered.
-  EXPECT_EQ(1u, profile_provider.collectors_.size());
-
-  // After initialization, if the new tcmalloc is enabled, we should have two
-  // collectors, because the sampling factor param is set to 1. Otherwise, we
-  // must still have one collector only.
-  profile_provider.Init();
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-  EXPECT_EQ(2u, profile_provider.collectors_.size());
-#else
-  EXPECT_EQ(1u, profile_provider.collectors_.size());
-#endif
-
-  // Before destroying ScopedFeatureList, we need to finish SetUp() of each
-  // registered collector, which accesses field trial params on its own
-  // dedicated sequence.
-  task_environment_.RunUntilIdle();
 }
 
 }  // namespace metrics
diff --git a/chrome/browser/metrics/plugin_metrics_provider.cc b/chrome/browser/metrics/plugin_metrics_provider.cc
index ca2058c..f1398a2 100644
--- a/chrome/browser/metrics/plugin_metrics_provider.cc
+++ b/chrome/browser/metrics/plugin_metrics_provider.cc
@@ -116,11 +116,10 @@
   BrowserChildProcessObserver::Remove(this);
 }
 
-void PluginMetricsProvider::AsyncInit(const base::Closure& done_callback) {
+void PluginMetricsProvider::AsyncInit(base::OnceClosure done_callback) {
   content::PluginService::GetInstance()->GetPlugins(
-      base::Bind(&PluginMetricsProvider::OnGotPlugins,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 done_callback));
+      base::BindOnce(&PluginMetricsProvider::OnGotPlugins,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(done_callback)));
 }
 
 void PluginMetricsProvider::ProvideSystemProfileMetrics(
@@ -323,10 +322,10 @@
 }
 
 void PluginMetricsProvider::OnGotPlugins(
-    const base::Closure& done_callback,
+    base::OnceClosure done_callback,
     const std::vector<content::WebPluginInfo>& plugins) {
   plugins_ = plugins;
-  done_callback.Run();
+  std::move(done_callback).Run();
 }
 
 PluginMetricsProvider::ChildProcessStats&
diff --git a/chrome/browser/metrics/plugin_metrics_provider.h b/chrome/browser/metrics/plugin_metrics_provider.h
index dcf0fad..0a3aa1c9 100644
--- a/chrome/browser/metrics/plugin_metrics_provider.h
+++ b/chrome/browser/metrics/plugin_metrics_provider.h
@@ -37,7 +37,7 @@
   ~PluginMetricsProvider() override;
 
   // metrics::MetricsDataProvider:
-  void AsyncInit(const base::Closure& done_callback) override;
+  void AsyncInit(base::OnceClosure done_callback) override;
   void ProvideSystemProfileMetrics(
       metrics::SystemProfileProto* system_profile_proto) override;
   void ProvideStabilityMetrics(
@@ -67,7 +67,7 @@
   struct ChildProcessStats;
 
   // Receives the plugin list from the PluginService and calls |done_callback|.
-  void OnGotPlugins(const base::Closure& done_callback,
+  void OnGotPlugins(base::OnceClosure done_callback,
                     const std::vector<content::WebPluginInfo>& plugins);
 
   // Returns reference to ChildProcessStats corresponding to |data|.
diff --git a/chrome/browser/nacl_host/nacl_infobar_delegate.cc b/chrome/browser/nacl_host/nacl_infobar_delegate.cc
index 69da54d..023c21d9 100644
--- a/chrome/browser/nacl_host/nacl_infobar_delegate.cc
+++ b/chrome/browser/nacl_host/nacl_infobar_delegate.cc
@@ -18,25 +18,15 @@
       std::unique_ptr<ConfirmInfoBarDelegate>(new NaClInfoBarDelegate())));
 }
 
-NaClInfoBarDelegate::NaClInfoBarDelegate() : ConfirmInfoBarDelegate() {
-}
+NaClInfoBarDelegate::NaClInfoBarDelegate() = default;
 
-NaClInfoBarDelegate::~NaClInfoBarDelegate() {
-}
+NaClInfoBarDelegate::~NaClInfoBarDelegate() = default;
 
 infobars::InfoBarDelegate::InfoBarIdentifier
 NaClInfoBarDelegate::GetIdentifier() const {
   return NACL_INFOBAR_DELEGATE;
 }
 
-base::string16 NaClInfoBarDelegate::GetMessageText() const {
-  return l10n_util::GetStringUTF16(IDS_NACL_APP_MISSING_ARCH_MESSAGE);
-}
-
-int NaClInfoBarDelegate::GetButtons() const {
-  return BUTTON_NONE;
-}
-
 base::string16 NaClInfoBarDelegate::GetLinkText() const {
   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
 }
@@ -44,3 +34,11 @@
 GURL NaClInfoBarDelegate::GetLinkURL() const {
   return GURL("https://support.google.com/chrome/?p=ib_nacl");
 }
+
+base::string16 NaClInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_NACL_APP_MISSING_ARCH_MESSAGE);
+}
+
+int NaClInfoBarDelegate::GetButtons() const {
+  return BUTTON_NONE;
+}
diff --git a/chrome/browser/nacl_host/nacl_infobar_delegate.h b/chrome/browser/nacl_host/nacl_infobar_delegate.h
index e47e2b4..85f29c4 100644
--- a/chrome/browser/nacl_host/nacl_infobar_delegate.h
+++ b/chrome/browser/nacl_host/nacl_infobar_delegate.h
@@ -20,10 +20,10 @@
   ~NaClInfoBarDelegate() override;
 
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  base::string16 GetMessageText() const override;
-  int GetButtons() const override;
   base::string16 GetLinkText() const override;
   GURL GetLinkURL() const override;
+  base::string16 GetMessageText() const override;
+  int GetButtons() const override;
 
   DISALLOW_COPY_AND_ASSIGN(NaClInfoBarDelegate);
 };
diff --git a/chrome/browser/notifications/chime/android/features.cc b/chrome/browser/notifications/chime/android/features.cc
index 1e275620..91a0e86 100644
--- a/chrome/browser/notifications/chime/android/features.cc
+++ b/chrome/browser/notifications/chime/android/features.cc
@@ -7,14 +7,14 @@
 
 jboolean JNI_ChimeSession_IsEnabled(JNIEnv* env) {
   return base::FeatureList::IsEnabled(
-      notifications::features::kChimeNotificationPlatform);
+      notifications::features::kUseChimeAndroidSdk);
 }
 
 namespace notifications {
 namespace features {
 
-const base::Feature kChimeNotificationPlatform{
-    "ChimeNotificationPlatform", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kUseChimeAndroidSdk{"UseChimeAndroidSdk",
+                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
 }  // namespace features
 }  // namespace notifications
diff --git a/chrome/browser/notifications/chime/android/features.h b/chrome/browser/notifications/chime/android/features.h
index e6759de..a3c61bb 100644
--- a/chrome/browser/notifications/chime/android/features.h
+++ b/chrome/browser/notifications/chime/android/features.h
@@ -10,8 +10,8 @@
 namespace notifications {
 namespace features {
 
-// The feature flag to determine whether to use Chime notification platform.
-extern const base::Feature kChimeNotificationPlatform;
+// The feature flag to determine whether to use Chime Android SDK.
+extern const base::Feature kUseChimeAndroidSdk;
 
 }  // namespace features
 }  // namespace notifications
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
index 4f82dee..deb569d 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/page_load_metrics/observers/previews_ukm_observer.h"
 
-#include "base/base64.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
@@ -18,7 +17,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
 #include "components/offline_pages/buildflags/buildflags.h"
-#include "components/optimization_guide/proto/hints.pb.h"
 #include "components/page_load_metrics/browser/page_load_metrics_observer.h"
 #include "components/page_load_metrics/browser/page_load_metrics_util.h"
 #include "components/page_load_metrics/common/page_load_timing.h"
@@ -144,9 +142,6 @@
   offline_eligibility_reason_ = previews_user_data->EligibilityReasonForPreview(
       previews::PreviewsType::OFFLINE);
 
-  serialized_hint_version_string_ =
-      previews_user_data->serialized_hint_version_string();
-
   return CONTINUE_OBSERVING;
 }
 
@@ -174,7 +169,7 @@
 PreviewsUKMObserver::FlushMetricsOnAppEnterBackground(
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  RecordMetrics();
+  RecordPreviewsTypes();
   return STOP_OBSERVING;
 }
 
@@ -182,19 +177,14 @@
 PreviewsUKMObserver::OnHidden(
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  RecordMetrics();
+  RecordPreviewsTypes();
   return STOP_OBSERVING;
 }
 
 void PreviewsUKMObserver::OnComplete(
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  RecordMetrics();
-}
-
-void PreviewsUKMObserver::RecordMetrics() {
   RecordPreviewsTypes();
-  RecordOptimizationGuideInfo();
 }
 
 void PreviewsUKMObserver::RecordPreviewsTypes() {
@@ -281,35 +271,6 @@
   builder.Record(ukm::UkmRecorder::Get());
 }
 
-void PreviewsUKMObserver::RecordOptimizationGuideInfo() {
-  if (!serialized_hint_version_string_.has_value()) {
-    return;
-  }
-
-  // Deserialize the serialized version string into its protobuffer.
-  std::string binary_version_pb;
-  if (!base::Base64Decode(serialized_hint_version_string_.value(),
-                          &binary_version_pb))
-    return;
-
-  optimization_guide::proto::Version hint_version;
-  if (!hint_version.ParseFromString(binary_version_pb))
-    return;
-
-  ukm::builders::OptimizationGuide builder(GetDelegate().GetSourceId());
-  if (hint_version.has_generation_timestamp() &&
-      hint_version.generation_timestamp().seconds() > 0) {
-    builder.SetHintGenerationTimestamp(
-        hint_version.generation_timestamp().seconds());
-  }
-  if (hint_version.has_hint_source() &&
-      hint_version.hint_source() !=
-          optimization_guide::proto::HINT_SOURCE_UNKNOWN) {
-    builder.SetHintSource(static_cast<int>(hint_version.hint_source()));
-  }
-  builder.Record(ukm::UkmRecorder::Get());
-}
-
 void PreviewsUKMObserver::OnEventOccurred(const void* const event_key) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (event_key == PreviewsUITabHelper::OptOutEventKey())
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h
index d8c985c1..f06ae57 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h
@@ -55,9 +55,7 @@
   virtual bool IsOfflinePreview(content::WebContents* web_contents) const;
 
  private:
-  void RecordMetrics();
   void RecordPreviewsTypes();
-  void RecordOptimizationGuideInfo();
 
   // The preview type that was actually committed and seen by the user.
   PreviewsType committed_preview_;
@@ -85,7 +83,6 @@
   base::Optional<previews::PreviewsEligibilityReason>
       offline_eligibility_reason_;
   base::Optional<base::TimeDelta> navigation_restart_penalty_;
-  base::Optional<std::string> serialized_hint_version_string_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
index 76b32b4..daac776 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
@@ -50,15 +50,13 @@
       bool save_data_enabled,
       std::unordered_map<PreviewsType, PreviewsEligibilityReason>
           eligibility_reasons,
-      base::Optional<base::TimeDelta> navigation_restart_penalty,
-      base::Optional<std::string> hint_version_string)
+      base::Optional<base::TimeDelta> navigation_restart_penalty)
       : committed_state_(committed_state),
         allowed_state_(allowed_state),
         origin_opt_out_received_(origin_opt_out_received),
         save_data_enabled_(save_data_enabled),
         eligibility_reasons_(eligibility_reasons),
-        navigation_restart_penalty_(navigation_restart_penalty),
-        hint_version_string_(hint_version_string) {}
+        navigation_restart_penalty_(navigation_restart_penalty) {}
 
   ~TestPreviewsUKMObserver() override {}
 
@@ -93,11 +91,6 @@
       user_data->SetEligibilityReasonForPreview(iter->first, iter->second);
     }
 
-    if (hint_version_string_.has_value()) {
-      user_data->set_serialized_hint_version_string(
-          hint_version_string_.value());
-    }
-
     return PreviewsUKMObserver::OnCommit(navigation_handle, source_id);
   }
 
@@ -118,7 +111,6 @@
   std::unordered_map<PreviewsType, PreviewsEligibilityReason>
       eligibility_reasons_;
   base::Optional<base::TimeDelta> navigation_restart_penalty_;
-  base::Optional<std::string> hint_version_string_;
 
   DISALLOW_COPY_AND_ASSIGN(TestPreviewsUKMObserver);
 };
@@ -135,15 +127,13 @@
                bool save_data_enabled,
                std::unordered_map<PreviewsType, PreviewsEligibilityReason>
                    eligibility_reasons,
-               base::Optional<base::TimeDelta> navigation_restart_penalty,
-               base::Optional<std::string> hint_version_string) {
+               base::Optional<base::TimeDelta> navigation_restart_penalty) {
     committed_state_ = committed_state;
     allowed_state_ = allowed_state;
     origin_opt_out_ = origin_opt_out;
     save_data_enabled_ = save_data_enabled;
     eligibility_reasons_ = eligibility_reasons;
     navigation_restart_penalty_ = navigation_restart_penalty;
-    hint_version_string_ = hint_version_string;
     auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
         GURL(kDefaultTestUrl), web_contents());
     if (committed_state == content::OFFLINE_PAGE_ON)
@@ -152,44 +142,6 @@
     navigation->Commit();
   }
 
-  void ValidateUKM(content::PreviewsState expected_recorded_previews,
-                   int opt_out_value,
-                   bool origin_opt_out_expected,
-                   bool save_data_enabled_expected,
-                   bool previews_likely_expected,
-                   std::unordered_map<PreviewsType, PreviewsEligibilityReason>
-                       eligibility_reasons,
-                   base::Optional<base::TimeDelta> navigation_restart_penalty,
-                   base::Optional<int64_t> hint_generation_timestamp,
-                   base::Optional<int> hint_source) {
-    ValidatePreviewsUKM(expected_recorded_previews, opt_out_value,
-                        origin_opt_out_expected, save_data_enabled_expected,
-                        previews_likely_expected, eligibility_reasons,
-                        navigation_restart_penalty);
-    ValidateOptimizationGuideUKM(hint_generation_timestamp, hint_source);
-  }
-
-  void SetUp() override {
-    page_load_metrics::PageLoadMetricsObserverTestHarness::SetUp();
-    PreviewsUITabHelper::CreateForWebContents(web_contents());
-  }
-
- protected:
-  void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
-    tracker->AddObserver(std::make_unique<TestPreviewsUKMObserver>(
-        committed_state_, allowed_state_, origin_opt_out_, save_data_enabled_,
-        eligibility_reasons_, navigation_restart_penalty_,
-        hint_version_string_));
-    // Data is only added to the first navigation after RunTest().
-    committed_state_ = content::PREVIEWS_OFF;
-    allowed_state_ = content::PREVIEWS_OFF;
-    origin_opt_out_ = false;
-    eligibility_reasons_.clear();
-    navigation_restart_penalty_ = base::nullopt;
-    hint_version_string_ = base::nullopt;
-  }
-
- private:
   void ValidatePreviewsUKM(
       content::PreviewsState expected_recorded_previews,
       int opt_out_value,
@@ -315,39 +267,25 @@
     }
   }
 
-  void ValidateOptimizationGuideUKM(
-      base::Optional<int64_t> hint_generation_timestamp,
-      base::Optional<int> hint_source) {
-    using UkmEntry = ukm::builders::OptimizationGuide;
-    auto entries =
-        tester()->test_ukm_recorder().GetEntriesByName(UkmEntry::kEntryName);
-    if (!hint_generation_timestamp.has_value() && !hint_source.has_value()) {
-      EXPECT_EQ(0u, entries.size());
-      return;
-    }
-
-    EXPECT_EQ(1u, entries.size());
-    for (const auto* const entry : entries) {
-      tester()->test_ukm_recorder().ExpectEntrySourceHasUrl(
-          entry, GURL(kDefaultTestUrl));
-      if (hint_generation_timestamp.has_value()) {
-        tester()->test_ukm_recorder().ExpectEntryMetric(
-            entry, UkmEntry::kHintGenerationTimestampName,
-            hint_generation_timestamp.value());
-      } else {
-        EXPECT_FALSE(tester()->test_ukm_recorder().EntryHasMetric(
-            entry, UkmEntry::kHintGenerationTimestampName));
-      }
-      if (hint_source.has_value()) {
-        tester()->test_ukm_recorder().ExpectEntryMetric(
-            entry, UkmEntry::kHintSourceName, hint_source.value());
-      } else {
-        EXPECT_FALSE(tester()->test_ukm_recorder().EntryHasMetric(
-            entry, UkmEntry::kHintSourceName));
-      }
-    }
+  void SetUp() override {
+    page_load_metrics::PageLoadMetricsObserverTestHarness::SetUp();
+    PreviewsUITabHelper::CreateForWebContents(web_contents());
   }
 
+ protected:
+  void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
+    tracker->AddObserver(std::make_unique<TestPreviewsUKMObserver>(
+        committed_state_, allowed_state_, origin_opt_out_, save_data_enabled_,
+        eligibility_reasons_, navigation_restart_penalty_));
+    // Data is only added to the first navigation after RunTest().
+    committed_state_ = content::PREVIEWS_OFF;
+    allowed_state_ = content::PREVIEWS_OFF;
+    origin_opt_out_ = false;
+    eligibility_reasons_.clear();
+    navigation_restart_penalty_ = base::nullopt;
+  }
+
+ private:
   content::PreviewsState committed_state_ = content::PREVIEWS_OFF;
   content::PreviewsState allowed_state_ = content::PREVIEWS_OFF;
   bool origin_opt_out_ = false;
@@ -355,7 +293,6 @@
   std::unordered_map<PreviewsType, PreviewsEligibilityReason>
       eligibility_reasons_ = {};
   base::Optional<base::TimeDelta> navigation_restart_penalty_ = base::nullopt;
-  base::Optional<std::string> hint_version_string_ = base::nullopt;
 
   DISALLOW_COPY_AND_ASSIGN(PreviewsUKMObserverTest);
 };
@@ -365,17 +302,14 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, UntrackedPreviewTypeOptOut) {
@@ -383,20 +317,17 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
   tester()->metrics_web_contents_observer()->BroadcastEventToObservers(
       PreviewsUITabHelper::OptOutEventKey());
   tester()->NavigateToUntrackedUrl();
 
   // Opt out should not be added since we don't track this type.
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, LitePageSeen) {
@@ -405,18 +336,15 @@
               content::DEFER_ALL_SCRIPT_ON /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::SERVER_LITE_PAGE_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::SERVER_LITE_PAGE_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, LitePageOptOutChip) {
@@ -424,20 +352,17 @@
           content::SERVER_LITE_PAGE_ON /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->metrics_web_contents_observer()->BroadcastEventToObservers(
       PreviewsUITabHelper::OptOutEventKey());
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::SERVER_LITE_PAGE_ON, 2 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::SERVER_LITE_PAGE_ON, 2 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, LitePageRedirectSeen) {
@@ -446,18 +371,15 @@
               content::OFFLINE_PAGE_ON /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::LITE_PAGE_REDIRECT_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::LITE_PAGE_REDIRECT_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, LitePageRedirectOptOutChip) {
@@ -465,37 +387,17 @@
           content::LITE_PAGE_REDIRECT_ON /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->metrics_web_contents_observer()->BroadcastEventToObservers(
       PreviewsUITabHelper::OptOutEventKey());
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::LITE_PAGE_REDIRECT_ON, 2 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
-}
-
-TEST_F(PreviewsUKMObserverTest, NoScriptSeenWithBadVersionString) {
-  RunTest(content::NOSCRIPT_ON /* committed_state */,
-          content::NOSCRIPT_ON /* allowed_state */, false /* origin_opt_out */,
-          false /* save_data_enabled */, {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */, "badversion");
-
-  tester()->NavigateToUntrackedUrl();
-
-  ValidateUKM(content::NOSCRIPT_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::LITE_PAGE_REDIRECT_ON, 2 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, NoScriptOptOutChip) {
@@ -503,20 +405,17 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->metrics_web_contents_observer()->BroadcastEventToObservers(
       PreviewsUITabHelper::OptOutEventKey());
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::NOSCRIPT_ON, 2 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::NOSCRIPT_ON, 2 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, OfflinePreviewsSeen) {
@@ -524,18 +423,15 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsSeen) {
@@ -543,18 +439,15 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::RESOURCE_LOADING_HINTS_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::RESOURCE_LOADING_HINTS_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsOptOutChip) {
@@ -562,20 +455,17 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->metrics_web_contents_observer()->BroadcastEventToObservers(
       PreviewsUITabHelper::OptOutEventKey());
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::RESOURCE_LOADING_HINTS_ON, 2 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::RESOURCE_LOADING_HINTS_ON, 2 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, DeferAllScriptSeen) {
@@ -583,18 +473,15 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::DEFER_ALL_SCRIPT_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::DEFER_ALL_SCRIPT_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, DeferAllScriptOptOutChip) {
@@ -602,20 +489,17 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->metrics_web_contents_observer()->BroadcastEventToObservers(
       PreviewsUITabHelper::OptOutEventKey());
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::DEFER_ALL_SCRIPT_ON, 2 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              true /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::DEFER_ALL_SCRIPT_ON, 2 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, OriginOptOut) {
@@ -623,18 +507,15 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           true /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              true /* origin_opt_out_expected */,
-              false /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      true /* origin_opt_out_expected */,
+                      false /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, DataSaverEnabled) {
@@ -642,18 +523,15 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, true /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 // Navigation restart penalty can occur independently of a preview being
@@ -664,19 +542,16 @@
       content::PREVIEWS_UNSPECIFIED /* allowed_state */,
       false /* origin_opt_out */, false /* save_data_enabled */,
       {} /* eligibility_reasons */,
-      base::TimeDelta::FromMilliseconds(1337) /* navigation_restart_penalty */,
-      base::nullopt /* hint_version_string */);
+      base::TimeDelta::FromMilliseconds(1337) /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(
+  ValidatePreviewsUKM(
       content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
       false /* origin_opt_out_expected */,
       false /* save_data_enabled_expected */, false /* previews_likely */,
       {} /* eligibility_reasons */,
-      base::TimeDelta::FromMilliseconds(1337) /* navigation_restart_penalty */,
-      base::nullopt /* hint_generation_timestamp */,
-      base::nullopt /* hint_source */);
+      base::TimeDelta::FromMilliseconds(1337) /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, PreviewsLikelySet_PreCommitDecision) {
@@ -684,54 +559,45 @@
           content::OFFLINE_PAGE_ON | content::NOSCRIPT_ON /* allowed_state */,
           false /* origin_opt_out */, true /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */, true /* previews_likely */,
-              {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, PreviewsLikelyNotSet_PostCommitDecision) {
   RunTest(content::PREVIEWS_OFF /* committed_state */,
           content::NOSCRIPT_ON /* allowed_state */, false /* origin_opt_out */,
           true /* save_data_enabled */, {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, PreviewsLikelyNotSet_PreviewsOff) {
   RunTest(content::PREVIEWS_OFF /* committed_state */,
           content::PREVIEWS_OFF /* allowed_state */, false /* origin_opt_out */,
           true /* save_data_enabled */, {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, CoinFlipResult_Holdback) {
@@ -739,18 +605,15 @@
           content::OFFLINE_PAGE_ON /* allowed_state */,
           false /* origin_opt_out */, true /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */, true /* previews_likely */,
-              {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, CoinFlipResult_Allowed) {
@@ -758,18 +621,15 @@
           content::OFFLINE_PAGE_ON /* allowed_state */,
           false /* origin_opt_out */, true /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */, true /* previews_likely */,
-              {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::OFFLINE_PAGE_ON, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      true /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, LogPreviewsEligibilityReason_WithAllowed) {
@@ -786,25 +646,22 @@
            // ALLOWED is equal to zero and should not be recorded.
            {PreviewsType::LITE_PAGE_REDIRECT,
             PreviewsEligibilityReason::ALLOWED}} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */,
-              {{PreviewsType::OFFLINE,
-                PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
-               {PreviewsType::LITE_PAGE,
-                PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
-               {PreviewsType::NOSCRIPT,
-                PreviewsEligibilityReason::
-                    BLACKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(
+      content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+      false /* origin_opt_out_expected */,
+      true /* save_data_enabled_expected */, false /* previews_likely */,
+      {{PreviewsType::OFFLINE,
+        PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+       {PreviewsType::LITE_PAGE,
+        PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+       {PreviewsType::NOSCRIPT,
+        PreviewsEligibilityReason::
+            BLACKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */,
+      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, LogPreviewsEligibilityReason_NoneAllowed) {
@@ -821,94 +678,24 @@
            {PreviewsType::LITE_PAGE_REDIRECT,
             PreviewsEligibilityReason::
                 BLACKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->NavigateToUntrackedUrl();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */,
-              {{PreviewsType::OFFLINE,
-                PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
-               {PreviewsType::LITE_PAGE,
-                PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
-               {PreviewsType::NOSCRIPT,
-                PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED},
-               {PreviewsType::LITE_PAGE_REDIRECT,
-                PreviewsEligibilityReason::
-                    BLACKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
-}
-
-TEST_F(PreviewsUKMObserverTest, LogOptimizationGuideHintVersion_NoHintSource) {
-  optimization_guide::proto::Version hint_version;
-  hint_version.mutable_generation_timestamp()->set_seconds(123);
-  std::string hint_version_string;
-  hint_version.SerializeToString(&hint_version_string);
-  base::Base64Encode(hint_version_string, &hint_version_string);
-  RunTest(content::PREVIEWS_OFF /* committed_state */,
-          content::PREVIEWS_UNSPECIFIED /* allowed_state */,
-          false /* origin_opt_out */, true /* save_data_enabled */,
-          {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */, hint_version_string);
-
-  tester()->NavigateToUntrackedUrl();
-
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              123 /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
-}
-
-TEST_F(PreviewsUKMObserverTest,
-       LogOptimizationGuideHintVersion_NoHintGenerationTimestamp) {
-  optimization_guide::proto::Version hint_version;
-  hint_version.set_hint_source(
-      optimization_guide::proto::HINT_SOURCE_OPTIMIZATION_HINTS_COMPONENT);
-  std::string hint_version_string;
-  hint_version.SerializeToString(&hint_version_string);
-  base::Base64Encode(hint_version_string, &hint_version_string);
-  RunTest(content::PREVIEWS_OFF /* committed_state */,
-          content::PREVIEWS_UNSPECIFIED /* allowed_state */,
-          false /* origin_opt_out */, true /* save_data_enabled */,
-          {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */, hint_version_string);
-
-  tester()->NavigateToUntrackedUrl();
-
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              1 /* hint_source */);
-}
-
-TEST_F(PreviewsUKMObserverTest,
-       LogOptimizationGuideHintVersion_NotActuallyAVersionProto) {
-  RunTest(content::PREVIEWS_OFF /* committed_state */,
-          content::PREVIEWS_UNSPECIFIED /* allowed_state */,
-          false /* origin_opt_out */, true /* save_data_enabled */,
-          {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */, "notahintversion");
-
-  tester()->NavigateToUntrackedUrl();
-
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(
+      content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+      false /* origin_opt_out_expected */,
+      true /* save_data_enabled_expected */, false /* previews_likely */,
+      {{PreviewsType::OFFLINE,
+        PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+       {PreviewsType::LITE_PAGE,
+        PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+       {PreviewsType::NOSCRIPT,
+        PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED},
+       {PreviewsType::LITE_PAGE_REDIRECT,
+        PreviewsEligibilityReason::
+            BLACKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */,
+      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, CheckReportingForHidden) {
@@ -916,18 +703,15 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, true /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   web_contents()->WasHidden();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, CheckReportingForFlushMetrics) {
@@ -935,18 +719,15 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, true /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
 
   tester()->SimulateAppEnterBackground();
 
-  ValidateUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
-              false /* origin_opt_out_expected */,
-              true /* save_data_enabled_expected */,
-              false /* previews_likely */, {} /* eligibility_reasons */,
-              base::nullopt /* navigation_restart_penalty */,
-              base::nullopt /* hint_generation_timestamp */,
-              base::nullopt /* hint_source */);
+  ValidatePreviewsUKM(content::PREVIEWS_UNSPECIFIED, 0 /* opt_out_value */,
+                      false /* origin_opt_out_expected */,
+                      true /* save_data_enabled_expected */,
+                      false /* previews_likely */, {} /* eligibility_reasons */,
+                      base::nullopt /* navigation_restart_penalty */);
 }
 
 TEST_F(PreviewsUKMObserverTest, TestPageEndReasonUMA) {
@@ -957,8 +738,7 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
   tester()->NavigateToUntrackedUrl();
   histogram_tester.ExpectUniqueSample(
       "Previews.PageEndReason.None",
@@ -971,8 +751,7 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
   tester()->NavigateToUntrackedUrl();
   histogram_tester.ExpectUniqueSample(
       "Previews.PageEndReason.LitePageRedirect",
@@ -986,8 +765,7 @@
           content::PREVIEWS_UNSPECIFIED /* allowed_state */,
           false /* origin_opt_out */, false /* save_data_enabled */,
           {} /* eligibility_reasons */,
-          base::nullopt /* navigation_restart_penalty */,
-          base::nullopt /* hint_version_string */);
+          base::nullopt /* navigation_restart_penalty */);
   tester()->NavigateToUntrackedUrl();
   histogram_tester.ExpectUniqueSample(
       "Previews.PageEndReason.DeferAllScript",
diff --git a/chrome/browser/paint_preview/DEPS b/chrome/browser/paint_preview/DEPS
index 82134df..910f5dd 100644
--- a/chrome/browser/paint_preview/DEPS
+++ b/chrome/browser/paint_preview/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/paint_preview/browser",
   "+components/paint_preview/common",
+  "+components/paint_preview/public",
   "+components/services/paint_preview_compositor/public/mojom",
 ]
diff --git a/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc b/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc
index 8c22c7c..9dfd55f1 100644
--- a/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc
+++ b/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc
@@ -2,13 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
 #include <utility>
 #include <vector>
 
 #include "base/bind.h"
 #include "base/run_loop.h"
+#include "base/test/gtest_util.h"
 #include "base/unguessable_token.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/paint_preview/browser/compositor_utils.h"
+#include "components/paint_preview/browser/paint_preview_base_service_test_factory.h"
+#include "components/paint_preview/browser/paint_preview_compositor_client_impl.h"
+#include "components/paint_preview/browser/paint_preview_compositor_service_impl.h"
+#include "components/paint_preview/public/paint_preview_compositor_client.h"
+#include "components/paint_preview/public/paint_preview_compositor_service.h"
 #include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
 #include "content/public/browser/service_process_host.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -16,27 +26,60 @@
 
 namespace paint_preview {
 
-class PaintPreviewCompositorCollectionBrowserTest
-    : public InProcessBrowserTest {
+namespace {
+
+// These functions cast the public API for the CompositorService and
+// CompositorClient to the *Impl versions. This exposes some internal test-only
+// methods to validate internal state.
+
+std::unique_ptr<PaintPreviewCompositorServiceImpl> ToCompositorServiceImpl(
+    std::unique_ptr<PaintPreviewCompositorService> service) {
+  return std::unique_ptr<PaintPreviewCompositorServiceImpl>(
+      reinterpret_cast<PaintPreviewCompositorServiceImpl*>(service.release()));
+}
+
+std::unique_ptr<PaintPreviewCompositorClientImpl> ToCompositorClientImpl(
+    std::unique_ptr<PaintPreviewCompositorClient> client) {
+  return std::unique_ptr<PaintPreviewCompositorClientImpl>(
+      reinterpret_cast<PaintPreviewCompositorClientImpl*>(client.release()));
+}
+
+}  // namespace
+
+class PaintPreviewCompositorBrowserTest : public InProcessBrowserTest {
  public:
-  PaintPreviewCompositorCollectionBrowserTest() = default;
-  ~PaintPreviewCompositorCollectionBrowserTest() override = default;
+  PaintPreviewCompositorBrowserTest() = default;
+  ~PaintPreviewCompositorBrowserTest() override = default;
+
+  PaintPreviewCompositorBrowserTest(const PaintPreviewCompositorBrowserTest&) =
+      delete;
+  PaintPreviewCompositorBrowserTest& operator=(
+      const PaintPreviewCompositorBrowserTest&) = delete;
 
  protected:
-  mojo::Remote<mojom::PaintPreviewCompositorCollection> StartUtilityProcess() {
-    return content::ServiceProcessHost::Launch<
-        mojom::PaintPreviewCompositorCollection>(
-        content::ServiceProcessHost::Options()
-            .WithSandboxType(service_manager::SandboxType::kPdfCompositor)
-            .Pass());
+  void CreateServiceInstance() {
+    key_ = std::make_unique<SimpleFactoryKey>(
+        browser()->profile()->GetPath(),
+        browser()->profile()->IsOffTheRecord());
+    PaintPreviewBaseServiceTestFactory::GetInstance()->SetTestingFactory(
+        key_.get(),
+        base::BindRepeating(&PaintPreviewBaseServiceTestFactory::Build));
   }
+
+  PaintPreviewBaseService* GetBaseService() {
+    return PaintPreviewBaseServiceTestFactory::GetForKey(key_.get());
+  }
+
+ private:
+  std::unique_ptr<SimpleFactoryKey> key_ = nullptr;
 };
 
-IN_PROC_BROWSER_TEST_F(PaintPreviewCompositorCollectionBrowserTest,
+// Test that a "true" initialization works and doesn't crash.
+IN_PROC_BROWSER_TEST_F(PaintPreviewCompositorBrowserTest,
                        TestInitializationSuccess) {
   base::RunLoop loop;
   mojo::Remote<mojom::PaintPreviewCompositorCollection> compositor_collection =
-      StartUtilityProcess();
+      CreateCompositorCollection();
   EXPECT_TRUE(compositor_collection.is_bound());
   EXPECT_TRUE(compositor_collection.is_connected());
 
@@ -50,6 +93,94 @@
       },
       loop.QuitClosure()));
   loop.Run();
+  compositor_collection.reset();
+}
+
+IN_PROC_BROWSER_TEST_F(PaintPreviewCompositorBrowserTest, CompositorCreate) {
+  CreateServiceInstance();
+  auto* base_service = GetBaseService();
+  auto compositor_service = ToCompositorServiceImpl(
+      base_service->StartCompositorService(base::DoNothing()));
+
+  base::RunLoop loop;
+  auto compositor = ToCompositorClientImpl(
+      compositor_service->CreateCompositor(loop.QuitClosure()));
+  loop.Run();
+  EXPECT_TRUE(compositor_service->HasActiveClients());
+  EXPECT_TRUE(base::Contains(compositor_service->ActiveClientsForTesting(),
+                             compositor->Token()));
+  EXPECT_TRUE(compositor->IsBoundAndConnected());
+  compositor.reset();
+
+  EXPECT_FALSE(compositor_service->HasActiveClients());
+}
+
+IN_PROC_BROWSER_TEST_F(PaintPreviewCompositorBrowserTest,
+                       MultipleCompositorCreate) {
+  CreateServiceInstance();
+  auto* base_service = GetBaseService();
+  auto compositor_service = ToCompositorServiceImpl(
+      base_service->StartCompositorService(base::DoNothing()));
+  EXPECT_EQ(0U, compositor_service->ActiveClientsForTesting().size());
+  EXPECT_FALSE(compositor_service->HasActiveClients());
+
+  base::RunLoop loop_0;
+  auto compositor_0 = ToCompositorClientImpl(
+      compositor_service->CreateCompositor(loop_0.QuitClosure()));
+  loop_0.Run();
+  EXPECT_TRUE(compositor_service->HasActiveClients());
+  EXPECT_EQ(1U, compositor_service->ActiveClientsForTesting().size());
+  EXPECT_TRUE(base::Contains(compositor_service->ActiveClientsForTesting(),
+                             compositor_0->Token()));
+  EXPECT_TRUE(compositor_0->IsBoundAndConnected());
+
+  base::RunLoop loop_1;
+  auto compositor_1 = ToCompositorClientImpl(
+      compositor_service->CreateCompositor(loop_1.QuitClosure()));
+  loop_1.Run();
+  EXPECT_TRUE(compositor_service->HasActiveClients());
+  EXPECT_EQ(2U, compositor_service->ActiveClientsForTesting().size());
+  EXPECT_TRUE(base::Contains(compositor_service->ActiveClientsForTesting(),
+                             compositor_1->Token()));
+  EXPECT_TRUE(compositor_1->IsBoundAndConnected());
+  EXPECT_NE(compositor_0->Token(), compositor_1->Token());
+
+  compositor_0.reset();
+  EXPECT_TRUE(compositor_service->HasActiveClients());
+  EXPECT_EQ(1U, compositor_service->ActiveClientsForTesting().size());
+  EXPECT_TRUE(base::Contains(compositor_service->ActiveClientsForTesting(),
+                             compositor_1->Token()));
+
+  compositor_1.reset();
+  EXPECT_FALSE(compositor_service->HasActiveClients());
+}
+
+IN_PROC_BROWSER_TEST_F(PaintPreviewCompositorBrowserTest,
+                       KillWithActiveCompositors) {
+  CreateServiceInstance();
+  auto* base_service = GetBaseService();
+  // NOTE: the disconnect handler for the service as a whole only triggers if
+  // the service is killed unexpectedly. Here the |compositor_service| object
+  // is deleted (performing a graceful shutdown) so the handler won't run.
+  auto compositor_service = ToCompositorServiceImpl(
+      base_service->StartCompositorService(base::DoNothing()));
+
+  base::RunLoop loop;
+  auto compositor = ToCompositorClientImpl(
+      compositor_service->CreateCompositor(loop.QuitClosure()));
+  loop.Run();
+  EXPECT_TRUE(compositor_service->HasActiveClients());
+  EXPECT_TRUE(base::Contains(compositor_service->ActiveClientsForTesting(),
+                             compositor->Token()));
+  EXPECT_TRUE(compositor->IsBoundAndConnected());
+
+  base::RunLoop disconnect_loop;
+  compositor->SetDisconnectHandler(disconnect_loop.QuitClosure());
+
+  // Kill before releasing active compositors.
+  compositor_service.reset();
+  disconnect_loop.Run();
+  EXPECT_FALSE(compositor->IsBoundAndConnected());
 }
 
 }  // namespace paint_preview
diff --git a/chrome/browser/password_manager/password_manager_infobar_delegate_android.cc b/chrome/browser/password_manager/password_manager_infobar_delegate_android.cc
index d5ccfaa..9ca596ce 100644
--- a/chrome/browser/password_manager/password_manager_infobar_delegate_android.cc
+++ b/chrome/browser/password_manager/password_manager_infobar_delegate_android.cc
@@ -12,11 +12,7 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 
-PasswordManagerInfoBarDelegate::~PasswordManagerInfoBarDelegate() {}
-
-PasswordManagerInfoBarDelegate::PasswordManagerInfoBarDelegate()
-    : ConfirmInfoBarDelegate(),
-      details_message_(base::string16()) {}
+PasswordManagerInfoBarDelegate::~PasswordManagerInfoBarDelegate() = default;
 
 base::string16 PasswordManagerInfoBarDelegate::GetDetailsMessageText() const {
   return details_message_;
@@ -31,25 +27,27 @@
   return IDR_ANDROID_INFOBAR_SAVE_PASSWORD;
 }
 
+GURL PasswordManagerInfoBarDelegate::GetLinkURL() const {
+  return GURL(password_manager::kPasswordManagerHelpCenterSmartLock);
+}
+
 bool PasswordManagerInfoBarDelegate::ShouldExpire(
     const NavigationDetails& details) const {
   return !details.is_redirect && ConfirmInfoBarDelegate::ShouldExpire(details);
 }
 
-base::string16 PasswordManagerInfoBarDelegate::GetMessageText() const {
-  return message_;
-}
-
-GURL PasswordManagerInfoBarDelegate::GetLinkURL() const {
-  return GURL(password_manager::kPasswordManagerHelpCenterSmartLock);
-}
-
 bool PasswordManagerInfoBarDelegate::LinkClicked(
     WindowOpenDisposition disposition) {
   ConfirmInfoBarDelegate::LinkClicked(disposition);
   return true;
 }
 
+base::string16 PasswordManagerInfoBarDelegate::GetMessageText() const {
+  return message_;
+}
+
+PasswordManagerInfoBarDelegate::PasswordManagerInfoBarDelegate() = default;
+
 void PasswordManagerInfoBarDelegate::SetMessage(const base::string16& message) {
   message_ = message;
 }
diff --git a/chrome/browser/password_manager/password_manager_infobar_delegate_android.h b/chrome/browser/password_manager/password_manager_infobar_delegate_android.h
index 981714f..094ca7d7 100644
--- a/chrome/browser/password_manager/password_manager_infobar_delegate_android.h
+++ b/chrome/browser/password_manager/password_manager_infobar_delegate_android.h
@@ -21,10 +21,10 @@
   // ConfirmInfoBarDelegate:
   InfoBarAutomationType GetInfoBarAutomationType() const override;
   int GetIconId() const override;
-  bool ShouldExpire(const NavigationDetails& details) const override;
-  base::string16 GetMessageText() const override;
   GURL GetLinkURL() const override;
+  bool ShouldExpire(const NavigationDetails& details) const override;
   bool LinkClicked(WindowOpenDisposition disposition) override;
+  base::string16 GetMessageText() const override;
 
  protected:
   PasswordManagerInfoBarDelegate();
diff --git a/chrome/browser/pepper_broker_infobar_delegate.cc b/chrome/browser/pepper_broker_infobar_delegate.cc
index bf2b80d..fee04be 100644
--- a/chrome/browser/pepper_broker_infobar_delegate.cc
+++ b/chrome/browser/pepper_broker_infobar_delegate.cc
@@ -40,8 +40,7 @@
     HostContentSettingsMap* content_settings,
     TabSpecificContentSettings* tab_content_settings,
     base::OnceCallback<void(bool)> callback)
-    : ConfirmInfoBarDelegate(),
-      url_(url),
+    : url_(url),
       plugin_name_(plugin_name),
       content_settings_(content_settings),
       tab_content_settings_(tab_content_settings),
@@ -61,6 +60,14 @@
   return kExtensionIcon;
 }
 
+base::string16 PepperBrokerInfoBarDelegate::GetLinkText() const {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+GURL PepperBrokerInfoBarDelegate::GetLinkURL() const {
+  return GURL("https://support.google.com/chrome/?p=ib_pepper_broker");
+}
+
 base::string16 PepperBrokerInfoBarDelegate::GetMessageText() const {
   return l10n_util::GetStringFUTF16(
       IDS_PEPPER_BROKER_MESSAGE, plugin_name_,
@@ -83,14 +90,6 @@
   return true;
 }
 
-base::string16 PepperBrokerInfoBarDelegate::GetLinkText() const {
-  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-}
-
-GURL PepperBrokerInfoBarDelegate::GetLinkURL() const {
-  return GURL("https://support.google.com/chrome/?p=ib_pepper_broker");
-}
-
 void PepperBrokerInfoBarDelegate::DispatchCallback(bool result) {
   base::RecordAction(
       result ? base::UserMetricsAction("PPAPI.BrokerInfobarClickedAllow")
diff --git a/chrome/browser/pepper_broker_infobar_delegate.h b/chrome/browser/pepper_broker_infobar_delegate.h
index 57e15a5a..1d9659e 100644
--- a/chrome/browser/pepper_broker_infobar_delegate.h
+++ b/chrome/browser/pepper_broker_infobar_delegate.h
@@ -40,12 +40,12 @@
   // ConfirmInfoBarDelegate:
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
+  base::string16 GetLinkText() const override;
+  GURL GetLinkURL() const override;
   base::string16 GetMessageText() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
   bool Cancel() override;
-  base::string16 GetLinkText() const override;
-  GURL GetLinkURL() const override;
 
   void DispatchCallback(bool result);
 
diff --git a/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc b/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc
index 8178f1a..85e9fec 100644
--- a/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc
+++ b/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc
@@ -77,6 +77,17 @@
   return IDR_ANDROID_INFOBAR_NOTIFICATIONS_OFF;
 }
 
+bool GroupedPermissionInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  details_expanded_ = true;
+  return false;
+}
+
+void GroupedPermissionInfoBarDelegate::InfoBarDismissed() {
+  if (permission_prompt_)
+    permission_prompt_->Closing();
+}
+
 base::string16 GroupedPermissionInfoBarDelegate::GetMessageText() const {
   return l10n_util::GetStringUTF16(
       IDS_NOTIFICATION_QUIET_PERMISSION_INFOBAR_TITLE);
@@ -93,17 +104,6 @@
   return false;
 }
 
-void GroupedPermissionInfoBarDelegate::InfoBarDismissed() {
-  if (permission_prompt_)
-    permission_prompt_->Closing();
-}
-
-bool GroupedPermissionInfoBarDelegate::LinkClicked(
-    WindowOpenDisposition disposition) {
-  details_expanded_ = true;
-  return false;
-}
-
 // static
 bool GroupedPermissionInfoBarDelegate::ShouldShowMiniInfobar(
     content::WebContents* web_contents,
diff --git a/chrome/browser/permissions/grouped_permission_infobar_delegate_android.h b/chrome/browser/permissions/grouped_permission_infobar_delegate_android.h
index d1c765f..ca820b7c 100644
--- a/chrome/browser/permissions/grouped_permission_infobar_delegate_android.h
+++ b/chrome/browser/permissions/grouped_permission_infobar_delegate_android.h
@@ -44,15 +44,13 @@
   // Returns the secondary string to show in the infobar in the expanded state.
   base::string16 GetDescriptionText() const;
 
-  // InfoBarDelegate:
-  int GetIconId() const override;
-
   // ConfirmInfoBarDelegate:
+  int GetIconId() const override;
+  bool LinkClicked(WindowOpenDisposition disposition) override;
+  void InfoBarDismissed() override;
   base::string16 GetMessageText() const override;
   bool Accept() override;
   bool Cancel() override;
-  void InfoBarDismissed() override;
-  bool LinkClicked(WindowOpenDisposition disposition) override;
 
   // Returns true if we should show the permission request as a mini-infobar.
   static bool ShouldShowMiniInfobar(content::WebContents* web_contents,
diff --git a/chrome/browser/plugins/flash_deprecation_infobar_delegate.cc b/chrome/browser/plugins/flash_deprecation_infobar_delegate.cc
index 23d74e75..5a7ce62 100644
--- a/chrome/browser/plugins/flash_deprecation_infobar_delegate.cc
+++ b/chrome/browser/plugins/flash_deprecation_infobar_delegate.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/feature_list.h"
-#include "base/time/time.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -26,33 +25,6 @@
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
-namespace {
-
-constexpr base::TimeDelta kMessageCooldown = base::TimeDelta::FromDays(14);
-
-// This duration is the same as the "default browser" banner's duration.
-constexpr base::TimeDelta kMinimumDurationBeforeExpiryOnNavigation =
-    base::TimeDelta::FromSeconds(8);
-
-bool IsFlashDeprecationWarningCooldownActive(Profile* profile) {
-  base::Time last_dismissal =
-      profile->GetPrefs()->GetTime(prefs::kPluginsDeprecationInfobarLastShown);
-
-  // More than |kMessageCooldown| days have passed.
-  if (base::Time::Now() - last_dismissal > kMessageCooldown) {
-    return false;
-  }
-
-  return true;
-}
-
-void ActivateFlashDeprecationWarningCooldown(Profile* profile) {
-  profile->GetPrefs()->SetTime(prefs::kPluginsDeprecationInfobarLastShown,
-                               base::Time::Now());
-}
-
-}  // namespace
-
 // static
 void FlashDeprecationInfoBarDelegate::Create(InfoBarService* infobar_service,
                                              Profile* profile) {
@@ -63,38 +35,39 @@
 // static
 bool FlashDeprecationInfoBarDelegate::ShouldDisplayFlashDeprecation(
     Profile* profile) {
-  HostContentSettingsMap* host_content_settings_map =
-      HostContentSettingsMapFactory::GetForProfile(profile);
-
-  DCHECK(host_content_settings_map);
-
   if (!base::FeatureList::IsEnabled(features::kFlashDeprecationWarning))
     return false;
 
+  // Generally, display the infobar if the Flash setting is anything other than
+  // BLOCK.
+  HostContentSettingsMap* host_content_settings_map =
+      HostContentSettingsMapFactory::GetForProfile(profile);
+  DCHECK(host_content_settings_map);
   bool is_managed = false;
   ContentSetting flash_setting =
       PluginUtils::UnsafeGetRawDefaultFlashContentSetting(
           host_content_settings_map, &is_managed);
-
-  // If the user can't do anything about their browser's Flash behavior
-  // there's no point to showing a Flash deprecation warning infobar.
-  //
-  // Also limit showing the infobar to at most once per |kMessageCooldown|.
-  // Users should be periodically reminded that they need to take action, but
-  // if they couldn't take action and turn off flash it's unlikely they will
-  // able to the next time they start a session. The message become more
-  // annoying than informative in that case.
-  if (is_managed || IsFlashDeprecationWarningCooldownActive(profile)) {
+  if (flash_setting == CONTENT_SETTING_BLOCK)
     return false;
-  }
 
-  // Display the infobar if the Flash setting is anything other than BLOCK.
-  return flash_setting != CONTENT_SETTING_BLOCK;
+  // However, if the user can't do anything about their browser's Flash
+  // behavior, there's no point to showing a Flash deprecation warning infobar.
+  if (is_managed)
+    return false;
+
+  // Also limit how frequently the infobar is shown. Users should be
+  // periodically reminded that they need to take action, but if they couldn't
+  // take action and turn off flash it's unlikely they will able to the next
+  // time they start a session. The message becomes more annoying than
+  // informative in that case.
+  const base::Time last_dismissal =
+      profile->GetPrefs()->GetTime(prefs::kPluginsDeprecationInfobarLastShown);
+  return (base::Time::Now() - last_dismissal) > base::TimeDelta::FromDays(14);
 }
 
 FlashDeprecationInfoBarDelegate::FlashDeprecationInfoBarDelegate(
     Profile* profile)
-    : profile_(profile), display_start_(base::Time::Now()) {}
+    : profile_(profile) {}
 
 infobars::InfoBarDelegate::InfoBarIdentifier
 FlashDeprecationInfoBarDelegate::GetIdentifier() const {
@@ -105,6 +78,29 @@
   return kExtensionIcon;
 }
 
+base::string16 FlashDeprecationInfoBarDelegate::GetLinkText() const {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+GURL FlashDeprecationInfoBarDelegate::GetLinkURL() const {
+  return GURL(
+      "https://www.blog.google/products/chrome/saying-goodbye-flash-chrome/");
+}
+
+bool FlashDeprecationInfoBarDelegate::ShouldExpire(
+    const NavigationDetails& details) const {
+  // This duration is the same as the "default browser" banner's duration.
+  const bool minimum_duration_elapsed =
+      (base::Time::Now() - display_start_) > base::TimeDelta::FromSeconds(8);
+  return minimum_duration_elapsed &&
+         ConfirmInfoBarDelegate::ShouldExpire(details);
+}
+
+void FlashDeprecationInfoBarDelegate::InfoBarDismissed() {
+  profile_->GetPrefs()->SetTime(prefs::kPluginsDeprecationInfobarLastShown,
+                                base::Time::Now());
+}
+
 base::string16 FlashDeprecationInfoBarDelegate::GetMessageText() const {
   return l10n_util::GetStringUTF16(IDS_PLUGIN_FLASH_DEPRECATION_PROMPT);
 }
@@ -115,39 +111,16 @@
 
 base::string16 FlashDeprecationInfoBarDelegate::GetButtonLabel(
     InfoBarButton button) const {
-  DCHECK_EQ(button, BUTTON_OK);
   return l10n_util::GetStringUTF16(IDS_TURN_OFF);
 }
 
 bool FlashDeprecationInfoBarDelegate::Accept() {
   HostContentSettingsMap* host_content_settings_map =
       HostContentSettingsMapFactory::GetForProfile(profile_);
-  // Can be nullptr in tests.
-  if (!host_content_settings_map)
-    return true;
-
-  host_content_settings_map->SetDefaultContentSetting(
-      ContentSettingsType::PLUGINS, CONTENT_SETTING_DEFAULT);
+  // Can be null in tests.
+  if (host_content_settings_map) {
+    host_content_settings_map->SetDefaultContentSetting(
+        ContentSettingsType::PLUGINS, CONTENT_SETTING_DEFAULT);
+  }
   return true;
 }
-
-base::string16 FlashDeprecationInfoBarDelegate::GetLinkText() const {
-  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-}
-
-GURL FlashDeprecationInfoBarDelegate::GetLinkURL() const {
-  return GURL(
-      "https://www.blog.google/products/chrome/saying-goodbye-flash-chrome/");
-}
-
-void FlashDeprecationInfoBarDelegate::InfoBarDismissed() {
-  ActivateFlashDeprecationWarningCooldown(profile_);
-}
-
-bool FlashDeprecationInfoBarDelegate::ShouldExpire(
-    const NavigationDetails& details) const {
-  bool minimum_duration_elapsed = base::Time::Now() - display_start_ >
-                                  kMinimumDurationBeforeExpiryOnNavigation;
-  return minimum_duration_elapsed &&
-         ConfirmInfoBarDelegate::ShouldExpire(details);
-}
diff --git a/chrome/browser/plugins/flash_deprecation_infobar_delegate.h b/chrome/browser/plugins/flash_deprecation_infobar_delegate.h
index 9c62464..61b2a1f 100644
--- a/chrome/browser/plugins/flash_deprecation_infobar_delegate.h
+++ b/chrome/browser/plugins/flash_deprecation_infobar_delegate.h
@@ -5,15 +5,12 @@
 #ifndef CHROME_BROWSER_PLUGINS_FLASH_DEPRECATION_INFOBAR_DELEGATE_H_
 #define CHROME_BROWSER_PLUGINS_FLASH_DEPRECATION_INFOBAR_DELEGATE_H_
 
+#include "base/time/time.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 
 class Profile;
 class InfoBarService;
 
-namespace base {
-class Time;
-}
-
 class FlashDeprecationInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   static void Create(InfoBarService* infobar_service, Profile* profile);
@@ -27,14 +24,14 @@
   // ConfirmInfobarDelegate:
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
+  base::string16 GetLinkText() const override;
+  GURL GetLinkURL() const override;
+  bool ShouldExpire(const NavigationDetails& details) const override;
+  void InfoBarDismissed() override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
-  base::string16 GetLinkText() const override;
-  GURL GetLinkURL() const override;
-  void InfoBarDismissed() override;
-  bool ShouldExpire(const NavigationDetails& details) const override;
 
  private:
   // The profile associated with this infobar.
@@ -43,7 +40,7 @@
   // The time at which the banner has started to be displayed. Used to determine
   // if the banner should expire on navigation, based on how long it has been
   // visible.
-  base::Time display_start_;
+  base::Time display_start_ = base::Time::Now();
 };
 
 #endif  // CHROME_BROWSER_PLUGINS_FLASH_DEPRECATION_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.cc b/chrome/browser/plugins/plugin_infobar_delegates.cc
index 0b84d2bb8..bf7f2671 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.cc
+++ b/chrome/browser/plugins/plugin_infobar_delegates.cc
@@ -102,14 +102,22 @@
   return OUTDATED_PLUGIN_INFOBAR_DELEGATE;
 }
 
-void OutdatedPluginInfoBarDelegate::InfoBarDismissed() {
-  base::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
-}
-
 const gfx::VectorIcon& OutdatedPluginInfoBarDelegate::GetVectorIcon() const {
   return kExtensionIcon;
 }
 
+base::string16 OutdatedPluginInfoBarDelegate::GetLinkText() const {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+GURL OutdatedPluginInfoBarDelegate::GetLinkURL() const {
+  return GURL(chrome::kOutdatedPluginLearnMoreURL);
+}
+
+void OutdatedPluginInfoBarDelegate::InfoBarDismissed() {
+  base::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
+}
+
 base::string16 OutdatedPluginInfoBarDelegate::GetMessageText() const {
   return message_;
 }
@@ -155,14 +163,6 @@
   return true;
 }
 
-base::string16 OutdatedPluginInfoBarDelegate::GetLinkText() const {
-  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-}
-
-GURL OutdatedPluginInfoBarDelegate::GetLinkURL() const {
-  return GURL(chrome::kOutdatedPluginLearnMoreURL);
-}
-
 void OutdatedPluginInfoBarDelegate::DownloadFinished() {
   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_UPDATING,
                                                 plugin_metadata_->name()));
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.h b/chrome/browser/plugins/plugin_infobar_delegates.h
index f1ab84c..4125df3 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.h
+++ b/chrome/browser/plugins/plugin_infobar_delegates.h
@@ -40,15 +40,15 @@
 
   // ConfirmInfoBarDelegate:
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  void InfoBarDismissed() override;
   const gfx::VectorIcon& GetVectorIcon() const override;
+  base::string16 GetLinkText() const override;
+  GURL GetLinkURL() const override;
+  void InfoBarDismissed() override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
   bool Cancel() override;
-  base::string16 GetLinkText() const override;
-  GURL GetLinkURL() const override;
 
   // PluginInstallerObserver:
   void DownloadFinished() override;
diff --git a/chrome/browser/previews/previews_lite_page_infobar_delegate.h b/chrome/browser/previews/previews_lite_page_infobar_delegate.h
index 767f23c..d20508ff 100644
--- a/chrome/browser/previews/previews_lite_page_infobar_delegate.h
+++ b/chrome/browser/previews/previews_lite_page_infobar_delegate.h
@@ -38,7 +38,7 @@
   PreviewsLitePageInfoBarDelegate();
 
   // ConfirmInfoBarDelegate:
-  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+  InfoBarIdentifier GetIdentifier() const override;
   void InfoBarDismissed() override;
   int GetButtons() const override;
   base::string16 GetMessageText() const override;
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc
index 4d21045..0af8ae0 100644
--- a/chrome/browser/printing/print_browsertest.cc
+++ b/chrome/browser/printing/print_browsertest.cc
@@ -28,6 +28,7 @@
 #include "components/printing/browser/features.h"
 #include "components/printing/browser/print_composite_client.h"
 #include "components/printing/browser/print_manager_utils.h"
+#include "components/printing/common/print.mojom.h"
 #include "components/printing/common/print_messages.h"
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/render_frame_host.h"
@@ -39,6 +40,7 @@
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 
 namespace printing {
 
@@ -260,11 +262,16 @@
     frame_host->GetProcess()->AddFilter(filter.get());
   }
 
-  static PrintMsg_PrintFrame_Params GetDefaultPrintFrameParams() {
-    PrintMsg_PrintFrame_Params params;
-    params.printable_area = gfx::Rect(800, 600);
-    params.document_cookie = kDefaultDocumentCookie;
-    return params;
+  static mojom::PrintFrameContentParamsPtr GetDefaultPrintFrameParams() {
+    return mojom::PrintFrameContentParams::New(gfx::Rect(800, 600),
+                                               kDefaultDocumentCookie);
+  }
+
+  static const mojo::AssociatedRemote<mojom::PrintRenderFrame>
+  GetPrintRenderFrame(content::RenderFrameHost* rfh) {
+    mojo::AssociatedRemote<mojom::PrintRenderFrame> remote;
+    rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote);
+    return remote;
   }
 
  private:
@@ -377,8 +384,7 @@
   content::RenderFrameHost* rfh = original_contents->GetMainFrame();
   AddFilterForFrame(rfh);
 
-  rfh->Send(new PrintMsg_PrintFrameContent(rfh->GetRoutingID(),
-                                           GetDefaultPrintFrameParams()));
+  GetPrintRenderFrame(rfh)->PrintFrameContent(GetDefaultPrintFrameParams());
 
   // The printed result will be received and checked in
   // TestPrintFrameContentMsgFilter.
@@ -402,8 +408,8 @@
 
   AddFilterForFrame(test_frame);
 
-  test_frame->Send(new PrintMsg_PrintFrameContent(
-      test_frame->GetRoutingID(), GetDefaultPrintFrameParams()));
+  GetPrintRenderFrame(test_frame)
+      ->PrintFrameContent(GetDefaultPrintFrameParams());
 
   // The printed result will be received and checked in
   // TestPrintFrameContentMsgFilter.
@@ -447,8 +453,8 @@
     AddFilterForFrame(grandchild_frame);
   }
 
-  main_frame->Send(new PrintMsg_PrintFrameContent(
-      main_frame->GetRoutingID(), GetDefaultPrintFrameParams()));
+  GetPrintRenderFrame(main_frame)
+      ->PrintFrameContent(GetDefaultPrintFrameParams());
 
   // The printed result will be received and checked in
   // TestPrintFrameContentMsgFilter.
@@ -491,8 +497,8 @@
   if (oopif_enabled)
     AddFilterForFrame(child_frame);
 
-  main_frame->Send(new PrintMsg_PrintFrameContent(
-      main_frame->GetRoutingID(), GetDefaultPrintFrameParams()));
+  GetPrintRenderFrame(main_frame)
+      ->PrintFrameContent(GetDefaultPrintFrameParams());
 
   // The printed result will be received and checked in
   // TestPrintFrameContentMsgFilter.
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index cc1d53d..1cd31474 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -2304,8 +2304,7 @@
     }
 
     case IDC_RELOAD:
-      embedder_web_contents_->GetController().Reload(
-          content::ReloadType::NORMAL, true);
+      chrome::Reload(GetBrowser(), WindowOpenDisposition::CURRENT_TAB);
       break;
 
     case IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP:
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index 5d09fc4..9cf5370 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -1043,15 +1043,6 @@
 
 void TabLifecycleUnitSource::TabLifecycleUnit::OnVisibilityChanged(
     content::Visibility visibility) {
-  // Ensure that the tab is not considered focused when not visible.
-  //
-  // TabLifeycleUnitSource calls SetFocused(false) when focus changes to another
-  // tab. The code below is also required to cover the case where the focused
-  // tab is hidden but no other tab is focused, which can happen when the
-  // focused window is minimized or occluded.
-  if (visibility != content::Visibility::VISIBLE)
-    SetFocused(false);
-
   OnLifecycleUnitVisibilityChanged(visibility);
 }
 
diff --git a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
index 499ef169..cb6700c 100644
--- a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
@@ -1490,66 +1490,71 @@
 
 }  // namespace
 
-IN_PROC_BROWSER_TEST_F(TabManagerTest, DiscardTabsWithMinimizedWindow) {
+// Flaky on Linux.  Times out on Windows and Mac debug builds.
+// http://crbug.com/772839.
+#if defined(OS_LINUX) || \
+    ((defined(OS_WIN) || defined(OS_MACOSX)) && !defined(NDEBUG))
+#define MAYBE_DiscardTabsWithMinimizedAndOccludedWindows \
+  DISABLED_DiscardTabsWithMinimizedAndOccludedWindows
+#else
+#define MAYBE_DiscardTabsWithMinimizedAndOccludedWindows \
+  DiscardTabsWithMinimizedAndOccludedWindows
+#endif
+IN_PROC_BROWSER_TEST_F(TabManagerTest,
+                       MAYBE_DiscardTabsWithMinimizedAndOccludedWindows) {
+  // Covered by |browser2|.
+  Browser* browser1 = browser();
+  EnsureTabsInBrowser(browser1, 2);
+  browser1->window()->SetBounds(gfx::Rect(10, 10, 10, 10));
+  // Covers |browser1|.
+  Browser* browser2 = CreateBrowserWithTabs(2);
+  EXPECT_NE(browser1, browser2);
+  browser2->window()->SetBounds(gfx::Rect(0, 0, 100, 100));
+  // Active browser.
+  Browser* browser3 = CreateBrowserWithTabs(2);
+  EXPECT_NE(browser1, browser3);
+  EXPECT_NE(browser2, browser3);
+  browser3->window()->SetBounds(gfx::Rect(110, 0, 100, 100));
   // Minimized browser.
-  EnsureTabsInBrowser(browser(), 2);
-  browser()->window()->Minimize();
-  // Other browser that will be last active. This browser exists because the
-  // last active tab cannot be discarded on
+  Browser* browser4 = CreateBrowserWithTabs(2);
+  browser4->window()->Minimize();
+  EXPECT_NE(browser1, browser4);
+  EXPECT_NE(browser2, browser4);
+  EXPECT_NE(browser3, browser4);
 
   // Advance time so everything is urgent discardable.
   test_clock_.Advance(kBackgroundUrgentProtectionTime);
 
-  for (int i = 0; i < 2; ++i)
-    tab_manager()->DiscardTab(LifecycleUnitDiscardReason::URGENT);
+  for (int i = 0; i < 8; ++i)
+    tab_manager()->DiscardTab(LifecycleUnitDiscardReason::PROACTIVE);
 
   base::RunLoop().RunUntilIdle();
 
 // On ChromeOS, active tabs are discarded if their window is non-visible. On
 // other platforms, they are never discarded.
 #if defined(OS_CHROMEOS)
-  EXPECT_TRUE(
-      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_TRUE(IsTabDiscarded(browser1->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_FALSE(
+      IsTabDiscarded(browser2->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_FALSE(
+      IsTabDiscarded(browser3->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_TRUE(IsTabDiscarded(browser4->tab_strip_model()->GetWebContentsAt(0)));
 #else
   EXPECT_FALSE(
-      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
+      IsTabDiscarded(browser1->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_FALSE(
+      IsTabDiscarded(browser2->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_FALSE(
+      IsTabDiscarded(browser3->tab_strip_model()->GetWebContentsAt(0)));
+  EXPECT_FALSE(
+      IsTabDiscarded(browser4->tab_strip_model()->GetWebContentsAt(0)));
 #endif
 
   // Non-active tabs can be discarded on all platforms.
-  EXPECT_TRUE(
-      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(1)));
-}
-
-IN_PROC_BROWSER_TEST_F(TabManagerTest, DiscardTabsWithOccludedWindow) {
-  // Occluded browser.
-  EnsureTabsInBrowser(browser(), 2);
-  browser()->window()->SetBounds(gfx::Rect(10, 10, 10, 10));
-  // Other browser that covers the occluded browser.
-  Browser* other_browser = CreateBrowserWithTabs(1);
-  EXPECT_NE(other_browser, browser());
-  other_browser->window()->SetBounds(gfx::Rect(0, 0, 100, 100));
-
-  // Advance time so everything is urgent discardable.
-  test_clock_.Advance(kBackgroundUrgentProtectionTime);
-
-  for (int i = 0; i < 3; ++i)
-    tab_manager()->DiscardTab(LifecycleUnitDiscardReason::URGENT);
-
-  base::RunLoop().RunUntilIdle();
-
-// On ChromeOS, active tabs are discarded if their window is non-visible. On
-// other platforms, they are never discarded.
-#if defined(OS_CHROMEOS)
-  EXPECT_TRUE(
-      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
-#else
-  EXPECT_FALSE(
-      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(0)));
-#endif
-
-  // Non-active tabs can be discarded on all platforms.
-  EXPECT_TRUE(
-      IsTabDiscarded(browser()->tab_strip_model()->GetWebContentsAt(1)));
+  EXPECT_TRUE(IsTabDiscarded(browser1->tab_strip_model()->GetWebContentsAt(1)));
+  EXPECT_TRUE(IsTabDiscarded(browser2->tab_strip_model()->GetWebContentsAt(1)));
+  EXPECT_TRUE(IsTabDiscarded(browser3->tab_strip_model()->GetWebContentsAt(1)));
+  EXPECT_TRUE(IsTabDiscarded(browser4->tab_strip_model()->GetWebContentsAt(1)));
 }
 
 IN_PROC_BROWSER_TEST_F(TabManagerTest, UnfreezeTabOnNavigationEvent) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_da.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_da.xtb
index e5622561..f75e2a0 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_da.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_da.xtb
@@ -936,7 +936,7 @@
 <translation id="744163271241493234">pwded</translation>
 <translation id="7491962110804786152">fane</translation>
 <translation id="7492049978501397201">Indtastet dialog</translation>
-<translation id="7505149250476994901">Sig "stor" før bogstav</translation>
+<translation id="7505149250476994901">Sig "stort" før bogstav</translation>
 <translation id="7518543783849163354">Tryk på Ctrl for midlertidigt at afbryde oplæsning i ChromeVox.</translation>
 <translation id="7521682724501952239">Du kan bruge ChromeVox med touchskærmen</translation>
 <translation id="7532613204005497612">Juni</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_de.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_de.xtb
index fb27cb79..9ab38c5e 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_de.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_de.xtb
@@ -418,7 +418,7 @@
 <translation id="3914732343065571127">ChromeVox – Befehle in der Übersicht</translation>
 <translation id="3930383913623796990">Frühlingsgrün</translation>
 <translation id="3930498801443296724">Textzitat</translation>
-<translation id="3935615366277838204">Großbuchstabe <ph name="LETTER" /></translation>
+<translation id="3935615366277838204">Großes <ph name="LETTER" /></translation>
 <translation id="3936394396199829062">Lavendelrosa</translation>
 <translation id="3941269780691800708">Text unter dem Mauszeiger vorlesen.</translation>
 <translation id="394953087167197343">Rechtschreibfehler angeben:</translation>
@@ -935,7 +935,7 @@
 <translation id="744163271241493234">pwded</translation>
 <translation id="7491962110804786152">tab</translation>
 <translation id="7492049978501397201">Dialogfeldtext eingegeben</translation>
-<translation id="7505149250476994901">Sagen Sie "Großbuchstabe" vor dem Buchstaben</translation>
+<translation id="7505149250476994901">Vor dem Buchstaben "Großes" ansagen</translation>
 <translation id="7518543783849163354">Um ChromeVox vorübergehend stummzuschalten, drücken Sie die Strg-Taste.</translation>
 <translation id="7521682724501952239">Sie können ChromeVox mit einem Touchscreen verwenden.</translation>
 <translation id="7532613204005497612">Juni</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_fr.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_fr.xtb
index d9be1096..d193c98 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_fr.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_fr.xtb
@@ -61,7 +61,7 @@
 <translation id="1339428534620983148">Colonne précédente du tableau</translation>
 <translation id="1342835525016946179">article</translation>
 <translation id="1346059596910821859">Pourboire</translation>
-<translation id="1346748346194534595">Vers la droite</translation>
+<translation id="1346748346194534595">À droite</translation>
 <translation id="135978014023467274">La version 63 de ChromeVox a été installée !</translation>
 <translation id="1360699455582016846">Cliquez sur l'élément sous la clé de routage <ph name="ROUTING_KEY_NUMBER" /></translation>
 <translation id="136718599399906424">Ligne suivante du tableau</translation>
@@ -76,7 +76,7 @@
 <translation id="1439316808600711881">région</translation>
 <translation id="1452236308086741652"><ph name="VALUE" />, zone de texte du mot de passe</translation>
 <translation id="146450394670219700">Objet graphique</translation>
-<translation id="1467432559032391204">Vers la gauche</translation>
+<translation id="1467432559032391204">À gauche</translation>
 <translation id="1474557363159888097">Aucun ancrage précédent</translation>
 <translation id="1480046233931937785">Remerciements</translation>
 <translation id="1487494366197411587">Sur un Chromebook, la touche de recherche se trouve juste au-dessus de la touche Maj.</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_ko.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_ko.xtb
index 8fe25bf7..921252d 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_ko.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_ko.xtb
@@ -31,7 +31,7 @@
 <translation id="1157843803349774103"><ph name="VALUE" />, <ph name="NAME" />, 콤보 상자</translation>
 <translation id="1161762950103988776">점프</translation>
 <translation id="1167230103353892028"><ph name="NAME" />, 메뉴 항목, 하위 메뉴 포함</translation>
-<translation id="1177863135347784049">맞춤</translation>
+<translation id="1177863135347784049">맞춤설정</translation>
 <translation id="1188858454923323853">상호 보완</translation>
 <translation id="1195238899008218998">후기</translation>
 <translation id="1197088940767939838">오렌지색</translation>
@@ -748,7 +748,7 @@
 <translation id="611827076493383239">vtd</translation>
 <translation id="6119955456199054975">마지막 셀입니다.</translation>
 <translation id="6122013438240733403">btn</translation>
-<translation id="6129953537138746214">공백</translation>
+<translation id="6129953537138746214">Space</translation>
 <translation id="6132506484792346370">목록 상자 또는 콤보 상자</translation>
 <translation id="6142308968191113180">제목 4</translation>
 <translation id="6150023170003443621">옐로우 그린</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_lo.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_lo.xtb
index 919504f..802a00bd 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_lo.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_lo.xtb
@@ -855,7 +855,7 @@
 <translation id="699159175332639490">ຊອກຫາ + O + W</translation>
 <translation id="6994042831499278539">ການອ້າງອີງປະມວນຄຳສັບ</translation>
 <translation id="6996566555547746822">ກ່ອງ combo ຕໍ່ໄປ</translation>
-<translation id="6997224546856374593">ເມື່ອອ່ານອັກສອນຕົວພິມໃຫຍ່</translation>
+<translation id="6997224546856374593">ເມື່ອອ່ານອັກສອນຕົວພິມໃຫຍ່:</translation>
 <translation id="700202842116345659">ລາຍການບັນນານຸກົມ</translation>
 <translation id="7005146664810010831">ບໍ່ພົບ URL</translation>
 <translation id="7010712454773919705">ປຸ່ມເຄື່ອງຂະຫຍາຍ ChromeVox</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_sv.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_sv.xtb
index 7d2ba6c..8a4aa6b 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_sv.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_sv.xtb
@@ -31,7 +31,7 @@
 <translation id="1157843803349774103"><ph name="VALUE" />, <ph name="NAME" />, kombinationsruta</translation>
 <translation id="1161762950103988776">Hoppa</translation>
 <translation id="1167230103353892028"><ph name="NAME" />, menyalternativ, med undermeny</translation>
-<translation id="1177863135347784049">Anpassad</translation>
+<translation id="1177863135347784049">Anpassat</translation>
 <translation id="1188858454923323853">kompletterande</translation>
 <translation id="1195238899008218998">Efterord</translation>
 <translation id="1197088940767939838">Orange</translation>
@@ -626,7 +626,7 @@
 <translation id="5291783959063340370">Objekt</translation>
 <translation id="5302089807023311274">Bibliografisk referens</translation>
 <translation id="5304943142864553931">Fliken <ph name="TITLE" /></translation>
-<translation id="5308380583665731573">Ansluta</translation>
+<translation id="5308380583665731573">Anslut</translation>
 <translation id="5310788376443009632">har tagits bort:</translation>
 <translation id="5320727453979144100">Låsta knappar har aktiverats</translation>
 <translation id="5321085947096604457">{COUNT,plural, =1{komma}other{# komman}}</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-CN.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-CN.xtb
index 2caf50f..ca08c5d 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-CN.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-CN.xtb
@@ -702,7 +702,7 @@
 <translation id="5748623122140342504">上一个5级标题</translation>
 <translation id="5750633686117194034">尚未按下任何辅助键;请按住一个或多个辅助键;完成后即可松开您的手指,此时您会听到相应键已成功设置的提示音。要退出,请按Tab键。</translation>
 <translation id="5760594853119905566">附录</translation>
-<translation id="5788275253279308023">在隐身窗口中打开“<ph name="TITLE" />”标签页</translation>
+<translation id="5788275253279308023">在无痕式窗口中打开“<ph name="TITLE" />”标签页</translation>
 <translation id="5805940204952508776">用两根手指点按</translation>
 <translation id="5806206155699461681">改善特定网站(如Google搜索)的用户体验。</translation>
 <translation id="5819072574982403430">树状目录项</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-TW.xtb b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-TW.xtb
index 9a5d22a..30d81d0f 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-TW.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings_zh-TW.xtb
@@ -668,7 +668,7 @@
 <translation id="5561345396546889625">下一個清單</translation>
 <translation id="5562645715554321347">hdnggrp</translation>
 <translation id="5574412348552378458">ChromeVox 學習模式</translation>
-<translation id="5583640892426849032">Backspace 鍵</translation>
+<translation id="5583640892426849032">Backspace</translation>
 <translation id="5585044216466955529">編輯文字,電子郵件項目</translation>
 <translation id="5586942249556966598">不要處理</translation>
 <translation id="5597170376237141345">下一個核取方塊</translation>
diff --git a/chrome/browser/resources/chromeos/camera/src/js/background_ops.js b/chrome/browser/resources/chromeos/camera/src/js/background_ops.js
index e57d433..e167946 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/background_ops.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/background_ops.js
@@ -2,23 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
-/**
- * Namespace for the Camera app.
- */
-var cca = cca || {};
-
-/**
- * Namespace for the background page.
- */
-cca.bg = cca.bg || {};
+// eslint-disable-next-line no-unused-vars
+import {Intent} from './intent.js';
+// eslint-disable-next-line no-unused-vars
+import {PerfLogger} from './perf.js';
 
 /**
  * Operations supported by foreground window.
  * @interface
  */
-cca.bg.ForegroundOps = class {
+export class ForegroundOps {
   /**
    * Suspend foreground window.
    * @return {!Promise}
@@ -31,29 +24,29 @@
    * @abstract
    */
   resume() {}
-};
+}
 
 /**
  * Operations supported by background window.
  * @interface
  */
-cca.bg.BackgroundOps = class {
+export class BackgroundOps {
   /**
    * Sets the implementation of ForegroundOps from foreground window.
-   * @param {!cca.bg.ForegroundOps} ops
+   * @param {!ForegroundOps} ops
    */
   bindForegroundOps(ops) {}
 
   /**
-   * Gets intent associate with cca.bg.Window object.
-   * @return {?cca.intent.Intent}
+   * Gets intent associate with CCA Window object.
+   * @return {?Intent}
    * @abstract
    */
   getIntent() {}
 
   /**
-   * Gets the perf logger associate with cca.bg.Window object.
-   * @return {!cca.perf.PerfLogger}
+   * Gets the perf logger associate with CCA Window object.
+   * @return {!PerfLogger}
    * @abstract
    */
   getPerfLogger() {}
@@ -69,4 +62,9 @@
    * @abstract
    */
   notifySuspension() {}
-};
+}
+
+/** @const */
+cca.bg.ForegroundOps = ForegroundOps;
+/** @const */
+cca.bg.BackgroundOps = BackgroundOps;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/namespace.js b/chrome/browser/resources/chromeos/camera/src/js/namespace.js
index fe9c406f..be8ae65 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/namespace.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/namespace.js
@@ -9,6 +9,7 @@
 
 // eslint-disable-next-line no-unused-vars
 var cca = {
+  bg: {},
   device: {},
   intent: {},
   metrics: {},
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr.xtb
index ef68c860b..43ab8a1a 100644
--- a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr.xtb
+++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr.xtb
@@ -72,5 +72,5 @@
 <translation id="8815966864175525708">Bouton permettant de prendre une photo en mode portrait</translation>
 <translation id="8870695351537079478">Impossible de démarrer l'enregistrement</translation>
 <translation id="9045155556724273246">10 secondes</translation>
-<translation id="945522503751344254">Envoyer le commentaire</translation>
+<translation id="945522503751344254">Envoyer un commentaire</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/views/background.html b/chrome/browser/resources/chromeos/camera/src/views/background.html
index 2a4e73a..4a4e914 100644
--- a/chrome/browser/resources/chromeos/camera/src/views/background.html
+++ b/chrome/browser/resources/chromeos/camera/src/views/background.html
@@ -12,7 +12,6 @@
     <script type="module" src="../js/type.js"></script>
     <script type="module" src="../js/perf.js"></script>
     <script type="module" src="../js/intent.js"></script>
-    <script defer src="../js/background_ops.js"></script>
     <script defer src="../js/background.js"></script>
   </head>
 </html>
diff --git a/chrome/browser/resources/chromeos/crostini_upgrader/app.js b/chrome/browser/resources/chromeos/crostini_upgrader/app.js
index a7bfed9..7787333 100644
--- a/chrome/browser/resources/chromeos/crostini_upgrader/app.js
+++ b/chrome/browser/resources/chromeos/crostini_upgrader/app.js
@@ -22,6 +22,7 @@
   PROMPT: 'prompt',
   BACKUP: 'backup',
   BACKUP_SUCCEEDED: 'backupSucceeded',
+  PRECHECKS_FAILED: 'prechecksFailed',
   UPGRADING: 'upgrading',
   ERROR: 'error',
   CANCELING: 'canceling',
@@ -86,14 +87,31 @@
         this.state_ = State.BACKUP_SUCCEEDED;
         // We do a short (2 second) interstitial display of the backup success
         // message before continuing the upgrade.
-        setTimeout(() => {
+        var timeout = new Promise((resolve, reject) => {
+          setTimeout(resolve, 2000);
+        });
+        // We also want to wait for the prechecks to finish.
+        var callback = new Promise((resolve, reject) => {
+          this.startPrechecks_(resolve, reject);
+        });
+        Promise.all([timeout, callback]).then(() => {
           this.startUpgrade_();
-        }, 2000);
+        });
       }),
       callbackRouter.onBackupFailed.addListener(() => {
         assert(this.state_ === State.BACKUP);
         this.state_ = State.ERROR;
       }),
+      callbackRouter.precheckStatus.addListener((status) => {
+        this.precheckStatus_ = status;
+        if (status ===
+            chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus.OK) {
+          this.precheckSuccessCallback_();
+        } else {
+          this.state_ = State.PRECHECKS_FAILED;
+          this.precheckFailureCallback_();
+        }
+      }),
       callbackRouter.onUpgradeProgress.addListener((progressMessages) => {
         assert(this.state_ === State.UPGRADING);
         this.progressMessages_.push(...progressMessages);
@@ -134,11 +152,17 @@
         BrowserProxy.getInstance().handler.launch();
         this.closeDialog_();
         break;
+      case State.PRECHECKS_FAILED:
+        this.startPrechecks_(() => {
+          this.startUpgrade_();
+        }, () => {});
       case State.PROMPT:
         if (this.backupCheckboxChecked_) {
           this.startBackup_();
         } else {
-          this.startUpgrade_();
+          this.startPrechecks_(() => {
+            this.startUpgrade_();
+          }, () => {});
         }
         break;
     }
@@ -154,6 +178,7 @@
         this.state_ = State.CANCELING;
         BrowserProxy.getInstance().handler.cancel();
         break;
+      case State.PRECHECKS_FAILED:
       case State.ERROR:
       case State.SUCCEEDED:
         this.closeDialog_();
@@ -175,6 +200,13 @@
   },
 
   /** @private */
+  startPrechecks_: function(success, failure) {
+    this.precheckSuccessCallback_ = success;
+    this.precheckFailureCallback_ = failure;
+    BrowserProxy.getInstance().handler.startPrechecks();
+  },
+
+  /** @private */
   startUpgrade_: function() {
     this.state_ = State.UPGRADING;
     BrowserProxy.getInstance().handler.upgrade();
@@ -203,6 +235,7 @@
   canDoAction_: function(state) {
     switch (state) {
       case State.PROMPT:
+      case State.PRECHECKS_FAILED:
       case State.SUCCEEDED:
         return true;
     }
@@ -240,6 +273,9 @@
       case State.BACKUP_SUCCEEDED:
         titleId = 'backupSucceededTitle';
         break;
+      case State.PRECHECKS_FAILED:
+        titleId = 'prechecksFailedTitle';
+        break;
       case State.UPGRADING:
         titleId = 'upgradingTitle';
         break;
@@ -267,6 +303,8 @@
     switch (state) {
       case State.PROMPT:
         return loadTimeData.getString('upgrade');
+      case State.PRECHECKS_FAILED:
+        return loadTimeData.getString('retry');
       case State.ERROR:
         return loadTimeData.getString('cancel');
       case State.SUCCEEDED:
@@ -306,6 +344,22 @@
       case State.BACKUP_SUCCEEDED:
         messageId = 'backupSucceededMessage';
         break;
+      case State.PRECHECKS_FAILED:
+        switch (this.precheckStatus_) {
+          case chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus
+              .NETWORK_FAILURE:
+            messageId = 'precheckNoNetwork';
+            break;
+          case chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus.LOW_POWER:
+            messageId = 'precheckNoPower';
+            break;
+          case chromeos.crostiniUpgrader.mojom.UpgradePrecheckStatus
+              .INSUFFICIENT_SPACE:
+            messageId = 'precheckNoSpace';
+            break;
+          default:
+            assertNotReached();
+        }
       case State.UPGRADING:
         messageId = 'upgradingMessage';
         break;
@@ -334,6 +388,7 @@
   getIllustrationStyle_: function(state) {
     switch (state) {
       case State.BACKUP_SUCCEEDED:
+      case State.PRECHECKS_FAILED:
       case State.ERROR:
         return 'img-square-illustration';
     }
@@ -349,6 +404,7 @@
     switch (state) {
       case State.BACKUP_SUCCEEDED:
         return 'images/success_illustration.png';
+      case State.PRECHECKS_FAILED:
       case State.ERROR:
         return 'images/error_illustration.png';
     }
diff --git a/chrome/browser/resources/new_tab_page/browser_proxy.js b/chrome/browser/resources/new_tab_page/browser_proxy.js
index 7606f276..da7d49946 100644
--- a/chrome/browser/resources/new_tab_page/browser_proxy.js
+++ b/chrome/browser/resources/new_tab_page/browser_proxy.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
 import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
 
 import './skcolor.mojom-lite.js';
diff --git a/chrome/browser/resources/new_tab_page/most_visited.html b/chrome/browser/resources/new_tab_page/most_visited.html
index 9a1aef6f..29f3ee61 100644
--- a/chrome/browser/resources/new_tab_page/most_visited.html
+++ b/chrome/browser/resources/new_tab_page/most_visited.html
@@ -69,7 +69,6 @@
 
   .tile-title {
     color: var(--tile-title-color);
-    direction: ltr;
     font-weight: 500;
     margin-top:  16px;
     overflow: hidden;
@@ -79,6 +78,14 @@
     width: 88px;
   }
 
+  .title-rtl {
+    direction: rtl;
+  }
+
+  .title-ltr {
+    direction: ltr;
+  }
+
   .tile.dragging {
     background-color: var(--tile-hover-color);
     transition-property: none;
@@ -138,7 +145,9 @@
         <div class="tile-icon">
           <img src$="[[getFaviconUrl_(item.url)]]" draggable="false"></img>
         </div>
-        <div class="tile-title">[[item.title]]</div>
+        <div class$="tile-title [[getTileTitleDirectionClass_(item)]]">
+          [[item.title]]
+        </div>
       </a>
     </template>
   </dom-repeat>
@@ -152,8 +161,9 @@
   <cr-dialog id="dialog" on-close="onDialogClose_">
     <div slot="title">[[dialogTitle_]]</div>
     <div slot="body">
-      <cr-input id="dialogInputName" label="$i18n{nameField}"
-          value="{{dialogTileTitle_}}" autofocus spellcheck="false"></cr-input>
+      <cr-input id="dialogInputName" class$="[[dialogTileTitleDirectionClass_]]"
+          label="$i18n{nameField}" value="{{dialogTileTitle_}}"
+          spellcheck="false" autofocus></cr-input>
       <cr-input id="dialogInputUrl" label="$i18n{urlField}"
           value="{{dialogTileUrl_}}" invalid="[[dialogTileUrlInvalid_]]"
           error-message="$i18n{invalidUrl}" spellcheck="false" type="url">
diff --git a/chrome/browser/resources/new_tab_page/most_visited.js b/chrome/browser/resources/new_tab_page/most_visited.js
index e7f0871..d0392555 100644
--- a/chrome/browser/resources/new_tab_page/most_visited.js
+++ b/chrome/browser/resources/new_tab_page/most_visited.js
@@ -10,6 +10,8 @@
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.m.js';
 import 'chrome://resources/cr_elements/hidden_style_css.m.js';
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
 import './strings.m.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
@@ -88,6 +90,9 @@
       dialogTileTitle_: String,
 
       /** @private */
+      dialogTileTitleDirectionClass_: String,
+
+      /** @private */
       dialogTileUrl_: String,
 
       /** @private */
@@ -443,6 +448,17 @@
   }
 
   /**
+   * @param {!newTabPage.mojom.MostVisitedTile} tile
+   * @return {string}
+   * @private
+   */
+  getTileTitleDirectionClass_(tile) {
+    return tile.titleDirection === mojoBase.mojom.TextDirection.RIGHT_TO_LEFT ?
+        'title-rtl' :
+        'title-ltr';
+  }
+
+  /**
    * @return {string}
    * @private
    */
@@ -463,6 +479,7 @@
   onAdd_() {
     this.dialogTitle_ = loadTimeData.getString('addLinkTitle');
     this.dialogTileTitle_ = '';
+    this.dialogTileTitleDirectionClass_ = '';
     this.dialogTileUrl_ = '';
     this.dialogTileUrlInvalid_ = false;
     this.adding_ = true;
@@ -560,9 +577,11 @@
   onEdit_() {
     this.$.actionMenu.close();
     this.dialogTitle_ = loadTimeData.getString('editLinkTitle');
-    const {title, url} = this.tiles_[this.actionMenuTargetIndex_];
-    this.dialogTileTitle_ = title;
-    this.dialogTileUrl_ = url.url;
+    const tile = this.tiles_[this.actionMenuTargetIndex_];
+    this.dialogTileTitle_ = tile.title;
+    this.dialogTileTitleDirectionClass_ =
+        this.getTileTitleDirectionClass_(tile);
+    this.dialogTileUrl_ = tile.url.url;
     this.dialogTileUrlInvalid_ = false;
     this.$.dialog.showModal();
   }
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog.html b/chrome/browser/resources/print_preview/ui/destination_dialog.html
index a9873cd..38c1c35 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dialog.html
+++ b/chrome/browser/resources/print_preview/ui/destination_dialog.html
@@ -139,7 +139,6 @@
         destinations="[[destinations_]]"
         loading-destinations="[[loadingDestinations_]]"
         search-query="[[searchQuery_]]"
-        list-name="$i18n{printDestinationsTitle}"
         on-destination-selected="onDestinationSelected_">
     </print-preview-destination-list>
     <print-preview-provisional-destination-resolver id="provisionalResolver"
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog.js b/chrome/browser/resources/print_preview/ui/destination_dialog.js
index c58867d..8cfd4ec 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dialog.js
+++ b/chrome/browser/resources/print_preview/ui/destination_dialog.js
@@ -330,7 +330,6 @@
         this.$$('select').value = this.activeUser;
       });
     }
-    this.$.printList.forceIronResize();
   },
 
   /** @return {boolean} Whether the dialog is open. */
diff --git a/chrome/browser/resources/print_preview/ui/destination_list.js b/chrome/browser/resources/print_preview/ui/destination_list.js
index 9cf81ca..76c9603 100644
--- a/chrome/browser/resources/print_preview/ui/destination_list.js
+++ b/chrome/browser/resources/print_preview/ui/destination_list.js
@@ -15,6 +15,8 @@
 
 import {Destination} from '../data/destination.js';
 
+const DESTINATION_ITEM_HEIGHT = 32;
+
 Polymer({
   is: 'print-preview-destination-list',
 
@@ -35,8 +37,6 @@
       value: false,
     },
 
-    listName: String,
-
     /** @private {!Array<!Destination>} */
     matchingDestinations_: {
       type: Array,
@@ -57,19 +57,20 @@
   },
 
   observers: [
-    'updateMatchingDestinations_(destinations.*, searchQuery)',
-    'matchingDestinationsChanged_(' +
-        'matchingDestinations_.*, loadingDestinations)',
-    'updateThrobberHidden_(matchingDestinations_.*, loadingDestinations)',
+    'updateMatchingDestinations_(' +
+        'destinations.*, searchQuery, loadingDestinations)',
   ],
 
-  // This is a workaround to ensure that the iron-list correctly updates the
-  // displayed destination information when the elements in the
-  // |matchingDestinations_| array change, instead of using stale information
-  // (a known iron-list issue). The event needs to be fired while the list is
-  // visible, so firing it immediately when the change occurs does not always
-  // work.
-  forceIronResize: function() {
+  /**
+   * This is a workaround to ensure that the iron-list correctly updates the
+   * displayed destination information when the elements in the
+   * |matchingDestinations_| array change, instead of using stale information
+   * (a known iron-list issue). The event needs to be fired while the list is
+   * visible, so firing it immediately when the change occurs does not always
+   * work.
+   * @private
+   */
+  forceIronResize_: function() {
     this.$.list.fire('iron-resize');
   },
 
@@ -79,18 +80,30 @@
       return;
     }
 
+    const matchingDestinations = this.searchQuery ?
+        this.destinations.filter(
+            d => d.matches(/** @type {!RegExp} */ (this.searchQuery))) :
+        this.destinations.slice();
+
+    const maxDisplayedItems = this.offsetHeight / DESTINATION_ITEM_HEIGHT;
+    const isListFullHeight = maxDisplayedItems <= matchingDestinations.length;
+    const listHeight = isListFullHeight ?
+        this.offsetHeight :
+        matchingDestinations.length * DESTINATION_ITEM_HEIGHT;
+
+    // Update the throbber and "No destinations" message.
+    this.hasDestinations_ =
+        matchingDestinations.length > 0 || this.loadingDestinations;
+    this.throbberHidden_ =
+        !this.loadingDestinations || isListFullHeight || !this.hasDestinations_;
+
+    // Update the height before updating the list.
+    this.$.list.style.height = `${listHeight}px`;
     this.updateList(
         'matchingDestinations_', destination => destination.key,
-        this.searchQuery ?
-            this.destinations.filter(
-                d => d.matches(/** @type {!RegExp} */ (this.searchQuery))) :
-            this.destinations.slice());
-  },
+        matchingDestinations);
 
-  /** @private */
-  matchingDestinationsChanged_: function() {
-    const count = this.matchingDestinations_.length;
-    this.hasDestinations_ = count > 0 || this.loadingDestinations;
+    this.forceIronResize_();
   },
 
   /**
@@ -115,20 +128,4 @@
 
     this.fire('destination-selected', e.target);
   },
-
-  /** @private */
-  updateThrobberHidden_: function() {
-    if (!this.loadingDestinations) {
-      this.throbberHidden_ = true;
-    } else if (!this.matchingDestinations_) {
-      this.throbberHidden_ = false;
-    } else {
-      const maxDisplayedItems = this.offsetHeight / 32;
-      this.throbberHidden_ =
-          maxDisplayedItems <= this.matchingDestinations_.length;
-    }
-    afterNextRender(this, () => {
-      this.forceIronResize();
-    });
-  }
 });
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index cb47cfd..daa4366 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -99,6 +99,7 @@
       "ui_manager.h",
     ]
     deps += [
+      "//chrome/browser/engagement:mojo_bindings",
       "//chrome/common/safe_browsing:proto",
       "//components/safe_browsing:csd_proto",
       "//components/safe_browsing:safe_browsing",
diff --git a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
index 64833651..8480f4a 100644
--- a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
@@ -29,6 +29,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/extension_set.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/settings/BUILD.gn b/chrome/browser/settings/BUILD.gn
index a2dc60f..43d47c6 100644
--- a/chrome/browser/settings/BUILD.gn
+++ b/chrome/browser/settings/BUILD.gn
@@ -9,11 +9,23 @@
     "android/java/src/org/chromium/chrome/browser/settings/SettingsUtils.java",
   ]
   deps = [
+    ":java_resources",
     "//base:base_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
     "//third_party/android_deps:androidx_annotation_annotation_java",
-    "//third_party/android_deps:com_android_support_design_java",
     "//third_party/android_deps:com_android_support_preference_v7_java",
+
+    # TODO(crbug.com/1017190): Remove these 2 deps once we stop linting individual targets.
+    "//third_party/android_deps:com_android_support_design_java",
     "//ui/android:ui_java",
   ]
 }
+
+android_resources("java_resources") {
+  deps = [
+    "//third_party/android_deps:com_android_support_design_java",
+    "//ui/android:ui_java_resources",
+  ]
+  resource_dirs = []
+  custom_package = "org.chromium.chrome.browser.settings"
+}
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsUtils.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsUtils.java
index 8d642a1..bf518ef 100644
--- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsUtils.java
+++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsUtils.java
@@ -22,7 +22,7 @@
 import androidx.annotation.XmlRes;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.ui.R;
+
 /**
  * A helper class for Settings.
  */
@@ -85,8 +85,7 @@
      */
     public static boolean setOverflowMenuVisibility(@Nullable Activity activity, int visibility) {
         if (activity == null) return false;
-        // TODO(chouinard): Remove R qualification once this package has its own android_resources.
-        ViewGroup actionBar = activity.findViewById(android.support.design.R.id.action_bar);
+        ViewGroup actionBar = activity.findViewById(R.id.action_bar);
         int i = actionBar.getChildCount();
         ActionMenuView menuView = null;
         while (i-- > 0) {
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc b/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc
index baf955f2..e9035f6 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc
+++ b/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc
@@ -116,10 +116,6 @@
       elapsed, kMinTime, kMaxTime, kBuckets);
 }
 
-void LogClickToCallHelpTextClicked(SharingDialogType type) {
-  base::UmaHistogramEnumeration("Sharing.ClickToCallHelpTextClicked", type);
-}
-
 void LogClickToCallUKM(content::WebContents* web_contents,
                        SharingClickToCallEntryPoint entry_point,
                        bool has_devices,
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_metrics.h b/chrome/browser/sharing/click_to_call/click_to_call_metrics.h
index 57be4762c..7e501fa 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_metrics.h
+++ b/chrome/browser/sharing/click_to_call/click_to_call_metrics.h
@@ -9,7 +9,6 @@
 
 #include "base/timer/elapsed_timer.h"
 #include "chrome/browser/sharing/click_to_call/phone_number_regex.h"
-#include "chrome/browser/sharing/sharing_metrics.h"
 
 namespace content {
 class WebContents;
@@ -65,10 +64,6 @@
   const base::ElapsedTimer timer_;
 };
 
-// Logs the dialog type when a user clicks on the help text in the Click to Call
-// dialog.
-void LogClickToCallHelpTextClicked(SharingDialogType type);
-
 // Records a Click to Call selection to UKM. This is logged after a completed
 // action like selecting an app or a device to send the phone number to.
 void LogClickToCallUKM(content::WebContents* web_contents,
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc
index 16827d3..0377834 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc
+++ b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc
@@ -175,11 +175,6 @@
   return SharingFeatureName::kClickToCall;
 }
 
-void ClickToCallUiController::OnHelpTextClicked(SharingDialogType dialog_type) {
-  LogClickToCallHelpTextClicked(dialog_type);
-  SharingUiController::OnHelpTextClicked(dialog_type);
-}
-
 SharingDialogData ClickToCallUiController::CreateDialogData(
     SharingDialogType dialog_type) {
   SharingDialogData data = SharingUiController::CreateDialogData(dialog_type);
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h
index d4b32d7..010ec301 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h
+++ b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h
@@ -52,7 +52,6 @@
   const gfx::VectorIcon& GetVectorIcon() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
   SharingFeatureName GetFeatureMetricsPrefix() const override;
-  void OnHelpTextClicked(SharingDialogType dialog_type) override;
   void OnDialogShown(bool has_devices, bool has_apps) override;
 
  protected:
diff --git a/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.cc b/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.cc
index e273886..e231137 100644
--- a/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.cc
+++ b/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/time/clock.h"
-#include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -26,24 +25,12 @@
 #include "chrome/browser/ssl/known_interception_disclosure_infobar.h"
 #endif
 
-namespace {
-
-// How long to suppress the disclosure UI after showing it to the user. On
-// Android, this is measured across browser sessions (which tend to be short)
-// by storing the last dismissal time in a pref. On Desktop, the last dismissal
-// time is stored in memory, so this is is only measured within the same
-// browsing session (and thus will trigger on every browser startup).
-constexpr base::TimeDelta kMessageCooldown = base::TimeDelta::FromDays(7);
-
-}  // namespace
-
 KnownInterceptionDisclosureCooldown*
 KnownInterceptionDisclosureCooldown::GetInstance() {
   return base::Singleton<KnownInterceptionDisclosureCooldown>::get();
 }
 
-bool KnownInterceptionDisclosureCooldown::
-    IsKnownInterceptionDisclosureCooldownActive(Profile* profile) {
+bool KnownInterceptionDisclosureCooldown::IsActive(Profile* profile) {
   base::Time last_dismissal;
 
 #if defined(OS_ANDROID)
@@ -53,15 +40,11 @@
   last_dismissal = last_dismissal_time_;
 #endif
 
-  // More than |kMessageCooldown| days have passed.
-  if (clock_->Now() - last_dismissal > kMessageCooldown)
-    return false;
-
-  return true;
+  // Suppress the disclosure UI for 7 days after showing it to the user.
+  return (clock_->Now() - last_dismissal) <= base::TimeDelta::FromDays(7);
 }
 
-void KnownInterceptionDisclosureCooldown::
-    ActivateKnownInterceptionDisclosureCooldown(Profile* profile) {
+void KnownInterceptionDisclosureCooldown::Activate(Profile* profile) {
 #if defined(OS_ANDROID)
   profile->GetPrefs()->SetTime(
       prefs::kKnownInterceptionDisclosureInfobarLastShown, clock_->Now());
@@ -75,16 +58,16 @@
   clock_ = std::move(clock);
 }
 
-KnownInterceptionDisclosureCooldown::KnownInterceptionDisclosureCooldown()
-    : clock_(std::make_unique<base::DefaultClock>()) {}
+KnownInterceptionDisclosureCooldown::KnownInterceptionDisclosureCooldown() =
+    default;
+
 KnownInterceptionDisclosureCooldown::~KnownInterceptionDisclosureCooldown() =
     default;
 
 void MaybeShowKnownInterceptionDisclosureDialog(
     content::WebContents* web_contents,
     net::CertStatus cert_status) {
-  KnownInterceptionDisclosureCooldown* disclosure_tracker =
-      KnownInterceptionDisclosureCooldown::GetInstance();
+  auto* disclosure_tracker = KnownInterceptionDisclosureCooldown::GetInstance();
   if (!(cert_status & net::CERT_STATUS_KNOWN_INTERCEPTION_DETECTED) &&
       !disclosure_tracker->get_has_seen_known_interception()) {
     return;
@@ -100,8 +83,7 @@
       std::make_unique<KnownInterceptionDisclosureInfoBarDelegate>(profile);
 
   infobars::InfoBar* infobar = nullptr;
-  if (!KnownInterceptionDisclosureCooldown::GetInstance()
-           ->IsKnownInterceptionDisclosureCooldownActive(profile)) {
+  if (!KnownInterceptionDisclosureCooldown::GetInstance()->IsActive(profile)) {
 #if defined(OS_ANDROID)
     infobar = infobar_service->AddInfoBar(
         KnownInterceptionDisclosureInfoBar::CreateInfoBar(std::move(delegate)));
@@ -116,6 +98,29 @@
     KnownInterceptionDisclosureInfoBarDelegate(Profile* profile)
     : profile_(profile) {}
 
+infobars::InfoBarDelegate::InfoBarIdentifier
+KnownInterceptionDisclosureInfoBarDelegate::GetIdentifier() const {
+  return KNOWN_INTERCEPTION_DISCLOSURE_INFOBAR_DELEGATE;
+}
+
+base::string16 KnownInterceptionDisclosureInfoBarDelegate::GetLinkText() const {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+GURL KnownInterceptionDisclosureInfoBarDelegate::GetLinkURL() const {
+  return GURL("chrome://connection-monitoring-detected/");
+}
+
+bool KnownInterceptionDisclosureInfoBarDelegate::ShouldExpire(
+    const NavigationDetails& details) const {
+  return false;
+}
+
+void KnownInterceptionDisclosureInfoBarDelegate::InfoBarDismissed() {
+  KnownInterceptionDisclosureCooldown::GetInstance()->Activate(profile_);
+  Cancel();
+}
+
 base::string16 KnownInterceptionDisclosureInfoBarDelegate::GetMessageText()
     const {
   return l10n_util::GetStringUTF16(IDS_KNOWN_INTERCEPTION_HEADER);
@@ -129,58 +134,22 @@
 #endif
 }
 
-base::string16 KnownInterceptionDisclosureInfoBarDelegate::GetButtonLabel(
-    InfoBarButton button) const {
-#if defined(OS_ANDROID)
-  switch (button) {
-    case BUTTON_OK:
-      return l10n_util::GetStringUTF16(
-          IDS_KNOWN_INTERCEPTION_INFOBAR_BUTTON_TEXT);
-    case BUTTON_CANCEL:
-      FALLTHROUGH;
-    case BUTTON_NONE:
-      NOTREACHED();
-  }
-#endif
-  NOTREACHED();
-  return base::string16();
-}
-
 bool KnownInterceptionDisclosureInfoBarDelegate::Accept() {
-  KnownInterceptionDisclosureCooldown::GetInstance()
-      ->ActivateKnownInterceptionDisclosureCooldown(profile_);
+  KnownInterceptionDisclosureCooldown::GetInstance()->Activate(profile_);
   return true;
 }
 
-base::string16 KnownInterceptionDisclosureInfoBarDelegate::GetLinkText() const {
-  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-}
-GURL KnownInterceptionDisclosureInfoBarDelegate::GetLinkURL() const {
-  return GURL("chrome://connection-monitoring-detected/");
-}
-
-infobars::InfoBarDelegate::InfoBarIdentifier
-KnownInterceptionDisclosureInfoBarDelegate::GetIdentifier() const {
-  return KNOWN_INTERCEPTION_DISCLOSURE_INFOBAR_DELEGATE;
-}
-
-void KnownInterceptionDisclosureInfoBarDelegate::InfoBarDismissed() {
-  KnownInterceptionDisclosureCooldown::GetInstance()
-      ->ActivateKnownInterceptionDisclosureCooldown(profile_);
-  Cancel();
-}
-
-bool KnownInterceptionDisclosureInfoBarDelegate::ShouldExpire(
-    const NavigationDetails& details) const {
-  return false;
-}
-
 // Platform specific implementations.
 #if defined(OS_ANDROID)
 int KnownInterceptionDisclosureInfoBarDelegate::GetIconId() const {
   return IDR_ANDROID_INFOBAR_WARNING;
 }
 
+base::string16 KnownInterceptionDisclosureInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16(IDS_KNOWN_INTERCEPTION_INFOBAR_BUTTON_TEXT);
+}
+
 base::string16 KnownInterceptionDisclosureInfoBarDelegate::GetDescriptionText()
     const {
   return l10n_util::GetStringUTF16(IDS_KNOWN_INTERCEPTION_BODY1);
diff --git a/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.h b/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.h
index ae79341..a5b945d 100644
--- a/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.h
+++ b/chrome/browser/ssl/known_interception_disclosure_infobar_delegate.h
@@ -7,6 +7,7 @@
 
 #include <algorithm>
 #include "base/memory/singleton.h"
+#include "base/time/default_clock.h"
 #include "build/build_config.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar_delegate.h"
@@ -27,13 +28,17 @@
 
 class Profile;
 
-// Singleton that tracks the known interception disclosure cooldown time.
+// Singleton that tracks the known interception disclosure cooldown time. On
+// Android, this is measured across browser sessions (which tend to be short) by
+// storing the last dismissal time in a pref. On Desktop, the last dismissal
+// time is stored in memory, so this is is only measured within the same
+// browsing session (and thus will trigger on every browser startup).
 class KnownInterceptionDisclosureCooldown {
  public:
   static KnownInterceptionDisclosureCooldown* GetInstance();
 
-  bool IsKnownInterceptionDisclosureCooldownActive(Profile* profile);
-  void ActivateKnownInterceptionDisclosureCooldown(Profile* profile);
+  bool IsActive(Profile* profile);
+  void Activate(Profile* profile);
 
   bool get_has_seen_known_interception() {
     return has_seen_known_interception_;
@@ -51,7 +56,7 @@
   KnownInterceptionDisclosureCooldown();
   ~KnownInterceptionDisclosureCooldown();
 
-  std::unique_ptr<base::Clock> clock_;
+  std::unique_ptr<base::Clock> clock_ = std::make_unique<base::DefaultClock>();
   bool has_seen_known_interception_ = false;
 
 #if !defined(OS_ANDROID)
@@ -72,26 +77,25 @@
   ~KnownInterceptionDisclosureInfoBarDelegate() override = default;
 
   // ConfirmInfoBarDelegate:
-  base::string16 GetMessageText() const override;
-  int GetButtons() const override;
-  base::string16 GetButtonLabel(InfoBarButton button) const override;
-  bool Accept() override;
+  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   base::string16 GetLinkText() const override;
   GURL GetLinkURL() const override;
-
-  // infobars::InfoBarDelegate:
-  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  void InfoBarDismissed() override;
   bool ShouldExpire(const NavigationDetails& details) const override;
+  void InfoBarDismissed() override;
+  base::string16 GetMessageText() const override;
+  int GetButtons() const override;
+  bool Accept() override;
 
 #if defined(OS_ANDROID)
   int GetIconId() const override;
+  base::string16 GetButtonLabel(InfoBarButton button) const override;
+
   // This function is the equivalent of GetMessageText(), but for the portion of
   // the infobar below the 'message' title for the Android infobar.
   base::string16 GetDescriptionText() const;
-#endif
 
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+#endif
 
  private:
   Profile* profile_;
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 6c8a7ed..0a3df66 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -779,18 +779,6 @@
   return may_load;
 }
 
-bool SupervisedUserService::UserMayModifySettings(const Extension* extension,
-                                                  base::string16* error) const {
-  DCHECK(ProfileIsSupervised());
-  ExtensionState result = GetExtensionState(*extension);
-  // Only allow the supervised user to modify the settings and enable or disable
-  // the extension if the supervised user has full control.
-  bool may_modify = result == ExtensionState::ALLOWED;
-  if (!may_modify && error)
-    *error = GetExtensionsLockedMessage();
-  return may_modify;
-}
-
 bool SupervisedUserService::MustRemainDisabled(
     const Extension* extension,
     extensions::disable_reason::DisableReason* reason,
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h
index f8938f4..88c738b2 100644
--- a/chrome/browser/supervised_user/supervised_user_service.h
+++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -215,8 +215,6 @@
   std::string GetDebugPolicyProviderName() const override;
   bool UserMayLoad(const extensions::Extension* extension,
                    base::string16* error) const override;
-  bool UserMayModifySettings(const extensions::Extension* extension,
-                             base::string16* error) const override;
   bool MustRemainDisabled(const extensions::Extension* extension,
                           extensions::disable_reason::DisableReason* reason,
                           base::string16* error) const override;
diff --git a/chrome/browser/supervised_user/supervised_user_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_service_unittest.cc
index aa64d0d9..77352bf 100644
--- a/chrome/browser/supervised_user/supervised_user_service_unittest.cc
+++ b/chrome/browser/supervised_user/supervised_user_service_unittest.cc
@@ -531,9 +531,9 @@
     EXPECT_FALSE(error_3.empty());
 
     base::string16 error_4;
-    EXPECT_FALSE(supervised_user_service->UserMayModifySettings(extension.get(),
-                                                                &error_4));
-    EXPECT_FALSE(error_4.empty());
+    EXPECT_TRUE(supervised_user_service->UserMayModifySettings(extension.get(),
+                                                               &error_4));
+    EXPECT_TRUE(error_4.empty());
 
     base::string16 error_5;
     EXPECT_TRUE(
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc
index 9e611de..ca6e27f 100644
--- a/chrome/browser/themes/theme_service_unittest.cc
+++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -41,14 +41,53 @@
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
 #endif
 
-using extensions::ExtensionRegistry;
+namespace {
+
+// A class that ensures any installed extension is uninstalled before it goes
+// out of scope.  This ensures the temporary directory used to load the
+// extension is unlocked and can be deleted.
+class ThemeScoper {
+ public:
+  ThemeScoper() = default;
+  ThemeScoper(extensions::ExtensionService* extension_service,
+              extensions::ExtensionRegistry* extension_registry)
+      : extension_service_(extension_service),
+        extension_registry_(extension_registry) {}
+  ThemeScoper(ThemeScoper&&) noexcept = default;
+  ThemeScoper& operator=(ThemeScoper&&) = default;
+  ~ThemeScoper() {
+    if (!extension_id_.empty() &&
+        extension_registry_->GetInstalledExtension(extension_id_)) {
+      extension_service_->UninstallExtension(
+          extension_id_, extensions::UNINSTALL_REASON_FOR_TESTING, nullptr);
+    }
+  }
+
+  std::string extension_id() const { return extension_id_; }
+  void set_extension_id(std::string extension_id) {
+    extension_id_ = std::move(extension_id);
+  }
+
+  base::FilePath GetTempPath() {
+    return temp_dir_.CreateUniqueTempDir() ? temp_dir_.GetPath()
+                                           : base::FilePath();
+  }
+
+ private:
+  extensions::ExtensionService* extension_service_ = nullptr;
+  extensions::ExtensionRegistry* extension_registry_ = nullptr;
+  std::string extension_id_;
+  base::ScopedTempDir temp_dir_;
+};
+
+}  // namespace
 
 namespace theme_service_internal {
 
 class ThemeServiceTest : public extensions::ExtensionServiceTestBase {
  public:
-  ThemeServiceTest() : registry_(NULL) {}
-  ~ThemeServiceTest() override {}
+  ThemeServiceTest() = default;
+  ~ThemeServiceTest() override = default;
 
   void SetUp() override {
     extensions::ExtensionServiceTestBase::SetUp();
@@ -56,19 +95,16 @@
         CreateDefaultInitParams();
     InitializeExtensionService(params);
     service_->Init();
-    registry_ = ExtensionRegistry::Get(profile_.get());
+    registry_ = extensions::ExtensionRegistry::Get(profile());
     ASSERT_TRUE(registry_);
+    theme_service_ = ThemeServiceFactory::GetForProfile(profile());
+    ASSERT_TRUE(theme_service_);
   }
 
-  // Moves a minimal theme to |temp_dir_path| and unpacks it from that
-  // directory.
-  std::string LoadUnpackedMinimalThemeAt(const base::FilePath& temp_dir) {
-    return LoadUnpackedTheme(temp_dir,
-                             "extensions/theme_minimal/manifest.json");
-  }
-
-  std::string LoadUnpackedTheme(const base::FilePath& temp_dir,
-                                const std::string source_file_path) {
+  ThemeScoper LoadUnpackedTheme(const std::string& source_file_path =
+                                    "extensions/theme_minimal/manifest.json") {
+    ThemeScoper scoper(service_, registry_);
+    base::FilePath temp_dir = scoper.GetTempPath();
     base::FilePath dst_manifest_path = temp_dir.AppendASCII("manifest.json");
     base::FilePath test_data_dir;
     EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
@@ -78,14 +114,13 @@
 
     scoped_refptr<extensions::UnpackedInstaller> installer(
         extensions::UnpackedInstaller::Create(service_));
-    extensions::TestExtensionRegistryObserver observer(
-        ExtensionRegistry::Get(profile()));
+    extensions::TestExtensionRegistryObserver observer(registry_);
     installer->Load(temp_dir);
-    std::string extension_id = observer.WaitForExtensionLoaded()->id();
+    scoper.set_extension_id(observer.WaitForExtensionLoaded()->id());
 
     WaitForThemeInstall();
 
-    return extension_id;
+    return scoper;
   }
 
   // Update the theme with |extension_id|.
@@ -96,14 +131,13 @@
     scoped_refptr<extensions::UnpackedInstaller> installer(
         extensions::UnpackedInstaller::Create(service_));
     if (service_->IsExtensionEnabled(extension_id)) {
-      extensions::TestExtensionRegistryObserver observer(
-          ExtensionRegistry::Get(profile()));
+      extensions::TestExtensionRegistryObserver observer(registry_);
       installer->Load(path);
       observer.WaitForExtensionLoaded();
     } else {
       content::WindowedNotificationObserver observer(
           extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
-          content::Source<Profile>(profile_.get()));
+          content::Source<Profile>(profile()));
       installer->Load(path);
       observer.Wait();
     }
@@ -134,11 +168,15 @@
   void WaitForThemeInstall() {
     content::WindowedNotificationObserver theme_change_observer(
         chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
-        content::Source<ThemeService>(
-            ThemeServiceFactory::GetForProfile(profile())));
+        content::Source<ThemeService>(theme_service_));
     theme_change_observer.Wait();
   }
 
+  bool IsExtensionDisabled(const std::string& id) const {
+    return registry_->GetExtensionById(id,
+                                       extensions::ExtensionRegistry::DISABLED);
+  }
+
   // Returns the separator color as the opaque result of blending it atop the
   // frame color (which is the color we use when calculating the contrast of the
   // separator with the tab and frame colors).
@@ -148,159 +186,117 @@
   }
 
  protected:
-  ExtensionRegistry* registry_;
+  extensions::ExtensionRegistry* registry_ = nullptr;
+  ThemeService* theme_service_ = nullptr;
 };
 
 // Installs then uninstalls a theme and makes sure that the ThemeService
 // reverts to the default theme after the uninstall.
 TEST_F(ThemeServiceTest, ThemeInstallUninstall) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  // Let the ThemeService uninstall unused themes.
-  base::RunLoop().RunUntilIdle();
-
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const std::string& extension_id =
-      LoadUnpackedMinimalThemeAt(temp_dir.GetPath());
-  EXPECT_FALSE(theme_service->UsingDefaultTheme());
-  EXPECT_TRUE(theme_service->UsingExtensionTheme());
-  EXPECT_EQ(extension_id, theme_service->GetThemeID());
+  ThemeScoper scoper = LoadUnpackedTheme();
+  EXPECT_FALSE(theme_service_->UsingDefaultTheme());
+  EXPECT_TRUE(theme_service_->UsingExtensionTheme());
+  EXPECT_EQ(scoper.extension_id(), theme_service_->GetThemeID());
 
   // Now uninstall the extension, should revert to the default theme.
-  service_->UninstallExtension(extension_id,
-                               extensions::UNINSTALL_REASON_FOR_TESTING,
-                               NULL);
-  EXPECT_TRUE(theme_service->UsingDefaultTheme());
-  EXPECT_FALSE(theme_service->UsingExtensionTheme());
+  service_->UninstallExtension(
+      scoper.extension_id(), extensions::UNINSTALL_REASON_FOR_TESTING, nullptr);
+  EXPECT_TRUE(theme_service_->UsingDefaultTheme());
+  EXPECT_FALSE(theme_service_->UsingExtensionTheme());
 }
 
 // Test that a theme extension is disabled when not in use. A theme may be
 // installed but not in use if it there is an infobar to revert to the previous
 // theme.
 TEST_F(ThemeServiceTest, DisableUnusedTheme) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-
-  base::ScopedTempDir temp_dir1;
-  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dir2;
-  ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
-
   // 1) Installing a theme should disable the previously active theme.
-  const std::string& extension1_id =
-      LoadUnpackedMinimalThemeAt(temp_dir1.GetPath());
-  EXPECT_FALSE(theme_service->UsingDefaultTheme());
-  EXPECT_EQ(extension1_id, theme_service->GetThemeID());
-  EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
+  ThemeScoper scoper1 = LoadUnpackedTheme();
+  EXPECT_FALSE(theme_service_->UsingDefaultTheme());
+  EXPECT_EQ(scoper1.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(service_->IsExtensionEnabled(scoper1.extension_id()));
 
   // Create theme reinstaller to prevent the current theme from being
   // uninstalled.
   std::unique_ptr<ThemeService::ThemeReinstaller> reinstaller =
-      theme_service->BuildReinstallerForCurrentTheme();
+      theme_service_->BuildReinstallerForCurrentTheme();
 
-  const std::string& extension2_id =
-      LoadUnpackedMinimalThemeAt(temp_dir2.GetPath());
-  EXPECT_EQ(extension2_id, theme_service->GetThemeID());
-  EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id));
-  EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
-                                          ExtensionRegistry::DISABLED));
+  ThemeScoper scoper2 = LoadUnpackedTheme();
+  EXPECT_EQ(scoper2.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(service_->IsExtensionEnabled(scoper2.extension_id()));
+  EXPECT_TRUE(IsExtensionDisabled(scoper1.extension_id()));
 
   // 2) Enabling a disabled theme extension should swap the current theme.
-  service_->EnableExtension(extension1_id);
+  service_->EnableExtension(scoper1.extension_id());
   WaitForThemeInstall();
-  EXPECT_EQ(extension1_id, theme_service->GetThemeID());
-  EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
-  EXPECT_TRUE(registry_->GetExtensionById(extension2_id,
-                                          ExtensionRegistry::DISABLED));
+  EXPECT_EQ(scoper1.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(service_->IsExtensionEnabled(scoper1.extension_id()));
+  EXPECT_TRUE(IsExtensionDisabled(scoper2.extension_id()));
 
   // 3) Using RevertToExtensionTheme() with a disabled theme should enable and
   // set the theme. This is the case when the user reverts to the previous theme
   // via an infobar.
-  theme_service->RevertToExtensionTheme(extension2_id);
+  theme_service_->RevertToExtensionTheme(scoper2.extension_id());
   WaitForThemeInstall();
-  EXPECT_EQ(extension2_id, theme_service->GetThemeID());
-  EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id));
-  EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
-                                          ExtensionRegistry::DISABLED));
+  EXPECT_EQ(scoper2.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(service_->IsExtensionEnabled(scoper2.extension_id()));
+  EXPECT_TRUE(IsExtensionDisabled(scoper1.extension_id()));
 
   // 4) Disabling the current theme extension should revert to the default theme
   // and disable any installed theme extensions.
-  EXPECT_FALSE(theme_service->UsingDefaultTheme());
-  service_->DisableExtension(extension2_id,
+  EXPECT_FALSE(theme_service_->UsingDefaultTheme());
+  service_->DisableExtension(scoper2.extension_id(),
                              extensions::disable_reason::DISABLE_USER_ACTION);
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(theme_service->UsingDefaultTheme());
-  EXPECT_FALSE(service_->IsExtensionEnabled(extension1_id));
-  EXPECT_FALSE(service_->IsExtensionEnabled(extension2_id));
+  EXPECT_TRUE(theme_service_->UsingDefaultTheme());
+  EXPECT_FALSE(service_->IsExtensionEnabled(scoper1.extension_id()));
+  EXPECT_FALSE(service_->IsExtensionEnabled(scoper2.extension_id()));
 }
 
 // Test the ThemeService's behavior when a theme is upgraded.
 TEST_F(ThemeServiceTest, ThemeUpgrade) {
-  // Setup.
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  // Let the ThemeService uninstall unused themes.
-  base::RunLoop().RunUntilIdle();
-
   std::unique_ptr<ThemeService::ThemeReinstaller> reinstaller =
-      theme_service->BuildReinstallerForCurrentTheme();
+      theme_service_->BuildReinstallerForCurrentTheme();
 
-  base::ScopedTempDir temp_dir1;
-  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dir2;
-  ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
-
-  const std::string& extension1_id =
-      LoadUnpackedMinimalThemeAt(temp_dir1.GetPath());
-  const std::string& extension2_id =
-      LoadUnpackedMinimalThemeAt(temp_dir2.GetPath());
+  ThemeScoper scoper1 = LoadUnpackedTheme();
+  ThemeScoper scoper2 = LoadUnpackedTheme();
 
   // Test the initial state.
-  EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
-                                          ExtensionRegistry::DISABLED));
-  EXPECT_EQ(extension2_id, theme_service->GetThemeID());
+  EXPECT_TRUE(IsExtensionDisabled(scoper1.extension_id()));
+  EXPECT_EQ(scoper2.extension_id(), theme_service_->GetThemeID());
 
   // 1) Upgrading the current theme should not revert to the default theme.
   content::WindowedNotificationObserver theme_change_observer(
       chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
-      content::Source<ThemeService>(theme_service));
-  UpdateUnpackedTheme(extension2_id);
+      content::Source<ThemeService>(theme_service_));
+  UpdateUnpackedTheme(scoper2.extension_id());
 
   // The ThemeService should have sent an theme change notification even though
   // the id of the current theme did not change.
   theme_change_observer.Wait();
 
-  EXPECT_EQ(extension2_id, theme_service->GetThemeID());
-  EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
-                                          ExtensionRegistry::DISABLED));
+  EXPECT_EQ(scoper2.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(IsExtensionDisabled(scoper1.extension_id()));
 
   // 2) Upgrading a disabled theme should not change the current theme.
-  UpdateUnpackedTheme(extension1_id);
-  EXPECT_EQ(extension2_id, theme_service->GetThemeID());
-  EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
-                                          ExtensionRegistry::DISABLED));
+  UpdateUnpackedTheme(scoper1.extension_id());
+  EXPECT_EQ(scoper2.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(IsExtensionDisabled(scoper1.extension_id()));
 }
 
 TEST_F(ThemeServiceTest, IncognitoTest) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  // Let the ThemeService uninstall unused themes.
-  base::RunLoop().RunUntilIdle();
+  // This test relies on incognito being meaningfully different than default,
+  // which is not currently true in dark mode.
+  ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(false);
 
   // Should get the same ThemeService for incognito and original profiles.
   ThemeService* otr_theme_service =
       ThemeServiceFactory::GetForProfile(profile_->GetOffTheRecordProfile());
-  EXPECT_EQ(theme_service, otr_theme_service);
+  EXPECT_EQ(theme_service_, otr_theme_service);
 
 #if !defined(OS_MACOSX)
   // Should get a different ThemeProvider for incognito and original profiles.
   const ui::ThemeProvider& provider =
-      ThemeService::GetThemeProviderForProfile(profile_.get());
+      ThemeService::GetThemeProviderForProfile(profile());
   const ui::ThemeProvider& otr_provider =
       ThemeService::GetThemeProviderForProfile(
           profile_->GetOffTheRecordProfile());
@@ -312,49 +308,37 @@
 }
 
 TEST_F(ThemeServiceTest, GetDefaultThemeProviderForProfile) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  // Let the ThemeService uninstall unused themes.
-  base::RunLoop().RunUntilIdle();
-
   SkColor default_toolbar_color =
-      ThemeService::GetThemeProviderForProfile(profile_.get())
-          .GetColor(ThemeProperties::COLOR_TOOLBAR);
+      ThemeService::GetThemeProviderForProfile(profile()).GetColor(
+          ThemeProperties::COLOR_TOOLBAR);
 
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  LoadUnpackedMinimalThemeAt(temp_dir.GetPath());
+  ThemeScoper scoper = LoadUnpackedTheme();
 
   // Should get a new color after installing a theme.
-  EXPECT_NE(ThemeService::GetThemeProviderForProfile(profile_.get())
-                .GetColor(ThemeProperties::COLOR_TOOLBAR),
+  EXPECT_NE(ThemeService::GetThemeProviderForProfile(profile()).GetColor(
+                ThemeProperties::COLOR_TOOLBAR),
             default_toolbar_color);
 
   // Should get the same color when requesting a default color.
-  EXPECT_EQ(ThemeService::GetDefaultThemeProviderForProfile(profile_.get())
-                .GetColor(ThemeProperties::COLOR_TOOLBAR),
+  EXPECT_EQ(ThemeService::GetDefaultThemeProviderForProfile(profile()).GetColor(
+                ThemeProperties::COLOR_TOOLBAR),
             default_toolbar_color);
 }
 
 TEST_F(ThemeServiceTest, GetColorForToolbarButton) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  // Let the ThemeService uninstall unused themes.
-  base::RunLoop().RunUntilIdle();
+  // This test relies on toolbar buttons having no tint, which is not currently
+  // true in dark mode.
+  ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(false);
 
   const ui::ThemeProvider& theme_provider =
-      ThemeService::GetThemeProviderForProfile(profile_.get());
+      ThemeService::GetThemeProviderForProfile(profile());
   SkColor default_toolbar_button_color =
       theme_provider.GetColor(ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON);
   EXPECT_FALSE(theme_provider.HasCustomColor(
       ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON));
 
-  base::ScopedTempDir temp_dir1;
-  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-  LoadUnpackedTheme(temp_dir1.GetPath(),
-                    "extensions/theme_test_toolbar_button_color/manifest.json");
+  ThemeScoper scoper1 = LoadUnpackedTheme(
+      "extensions/theme_test_toolbar_button_color/manifest.json");
 
   // Should get a new color after installing a theme.
   SkColor toolbar_button_explicit_color =
@@ -363,10 +347,8 @@
   EXPECT_TRUE(theme_provider.HasCustomColor(
       ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON));
 
-  base::ScopedTempDir temp_dir2;
-  ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
-  LoadUnpackedTheme(temp_dir2.GetPath(),
-                    "extensions/theme_test_toolbar_button_tint/manifest.json");
+  ThemeScoper scoper2 = LoadUnpackedTheme(
+      "extensions/theme_test_toolbar_button_tint/manifest.json");
 
   // Should get the color based on a tint.
   SkColor toolbar_button_tinted_color =
@@ -378,19 +360,13 @@
 }
 
 TEST_F(ThemeServiceTest, NTPLogoAlternate) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  // Let the ThemeService uninstall unused themes.
-  base::RunLoop().RunUntilIdle();
+  // TODO(https://crbug.com/1039006): Fix ScopedTempDir deletion errors on Win.
 
   const ui::ThemeProvider& theme_provider =
-      ThemeService::GetThemeProviderForProfile(profile_.get());
+      ThemeService::GetThemeProviderForProfile(profile());
   {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    LoadUnpackedTheme(temp_dir.GetPath(),
-                      "extensions/theme_grey_ntp/manifest.json");
+    ThemeScoper scoper =
+        LoadUnpackedTheme("extensions/theme_grey_ntp/manifest.json");
     // When logo alternate is not specified and ntp is grey, logo should be
     // colorful.
     EXPECT_EQ(0, theme_provider.GetDisplayProperty(
@@ -398,20 +374,16 @@
   }
 
   {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    LoadUnpackedTheme(temp_dir.GetPath(),
-                      "extensions/theme_grey_ntp_white_logo/manifest.json");
+    ThemeScoper scoper =
+        LoadUnpackedTheme("extensions/theme_grey_ntp_white_logo/manifest.json");
     // Logo alternate should match what is specified in the manifest.
     EXPECT_EQ(1, theme_provider.GetDisplayProperty(
                      ThemeProperties::NTP_LOGO_ALTERNATE));
   }
 
   {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    LoadUnpackedTheme(temp_dir.GetPath(),
-                      "extensions/theme_color_ntp_white_logo/manifest.json");
+    ThemeScoper scoper = LoadUnpackedTheme(
+        "extensions/theme_color_ntp_white_logo/manifest.json");
     // When logo alternate is not specified and ntp is colorful, logo should be
     // white.
     EXPECT_EQ(1, theme_provider.GetDisplayProperty(
@@ -419,10 +391,8 @@
   }
 
   {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-    LoadUnpackedTheme(temp_dir.GetPath(),
-                      "extensions/theme_color_ntp_colorful_logo/manifest.json");
+    ThemeScoper scoper = LoadUnpackedTheme(
+        "extensions/theme_color_ntp_colorful_logo/manifest.json");
     // Logo alternate should match what is specified in the manifest.
     EXPECT_EQ(0, theme_provider.GetDisplayProperty(
                      ThemeProperties::NTP_LOGO_ALTERNATE));
@@ -431,119 +401,88 @@
 
 // crbug.com/468280
 TEST_F(ThemeServiceTest, UninstallThemeWhenNoReinstallers) {
-  // Setup.
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  // Let the ThemeService uninstall unused themes.
-  base::RunLoop().RunUntilIdle();
+  ThemeScoper scoper1 = LoadUnpackedTheme();
+  ASSERT_EQ(scoper1.extension_id(), theme_service_->GetThemeID());
 
-  base::ScopedTempDir temp_dir1;
-  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-  base::ScopedTempDir temp_dir2;
-  ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
-
-  const std::string& extension1_id =
-      LoadUnpackedMinimalThemeAt(temp_dir1.GetPath());
-  ASSERT_EQ(extension1_id, theme_service->GetThemeID());
-
-  std::string extension2_id = "";
+  ThemeScoper scoper2;
   {
     // Show an infobar.
     std::unique_ptr<ThemeService::ThemeReinstaller> reinstaller =
-        theme_service->BuildReinstallerForCurrentTheme();
+        theme_service_->BuildReinstallerForCurrentTheme();
 
     // Install another theme. The first extension shouldn't be uninstalled yet
     // as it should be possible to revert to it.
-    extension2_id = LoadUnpackedMinimalThemeAt(temp_dir2.GetPath());
-    EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
-                                            ExtensionRegistry::DISABLED));
-    EXPECT_EQ(extension2_id, theme_service->GetThemeID());
+    scoper2 = LoadUnpackedTheme();
+    EXPECT_TRUE(IsExtensionDisabled(scoper1.extension_id()));
+    EXPECT_EQ(scoper2.extension_id(), theme_service_->GetThemeID());
 
     reinstaller->Reinstall();
     WaitForThemeInstall();
     base::RunLoop().RunUntilIdle();
-    EXPECT_TRUE(registry_->GetExtensionById(extension2_id,
-                                            ExtensionRegistry::DISABLED));
-    EXPECT_EQ(extension1_id, theme_service->GetThemeID());
+    EXPECT_TRUE(IsExtensionDisabled(scoper2.extension_id()));
+    EXPECT_EQ(scoper1.extension_id(), theme_service_->GetThemeID());
   }
 
   // extension 2 should get uninstalled as no reinstallers are in scope.
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(registry_->GetExtensionById(extension2_id,
-                                           ExtensionRegistry::EVERYTHING));
+  EXPECT_FALSE(registry_->GetInstalledExtension(scoper2.extension_id()));
 }
 
 TEST_F(ThemeServiceTest, BuildFromColorTest) {
   // Set theme from color.
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  theme_service->UseDefaultTheme();
-  EXPECT_TRUE(theme_service->UsingDefaultTheme());
-  EXPECT_FALSE(theme_service->UsingAutogeneratedTheme());
-  theme_service->BuildAutogeneratedThemeFromColor(SkColorSetRGB(100, 100, 100));
-  EXPECT_FALSE(theme_service->UsingDefaultTheme());
-  EXPECT_TRUE(theme_service->UsingAutogeneratedTheme());
+  EXPECT_TRUE(theme_service_->UsingDefaultTheme());
+  EXPECT_FALSE(theme_service_->UsingAutogeneratedTheme());
+  theme_service_->BuildAutogeneratedThemeFromColor(
+      SkColorSetRGB(100, 100, 100));
+  EXPECT_FALSE(theme_service_->UsingDefaultTheme());
+  EXPECT_TRUE(theme_service_->UsingAutogeneratedTheme());
 
   // Set theme from data pack and then override it with theme from color.
-  base::ScopedTempDir temp_dir1;
-  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-  const std::string& extension1_id =
-      LoadUnpackedMinimalThemeAt(temp_dir1.GetPath());
-  EXPECT_EQ(extension1_id, theme_service->GetThemeID());
-  EXPECT_FALSE(theme_service->UsingDefaultTheme());
-  EXPECT_FALSE(theme_service->UsingAutogeneratedTheme());
+  ThemeScoper scoper = LoadUnpackedTheme();
+  EXPECT_EQ(scoper.extension_id(), theme_service_->GetThemeID());
+  EXPECT_FALSE(theme_service_->UsingDefaultTheme());
+  EXPECT_FALSE(theme_service_->UsingAutogeneratedTheme());
   base::FilePath path =
       profile_->GetPrefs()->GetFilePath(prefs::kCurrentThemePackFilename);
   EXPECT_FALSE(path.empty());
 
-  theme_service->BuildAutogeneratedThemeFromColor(SkColorSetRGB(100, 100, 100));
-  EXPECT_FALSE(theme_service->UsingDefaultTheme());
-  EXPECT_TRUE(theme_service->UsingAutogeneratedTheme());
-  EXPECT_EQ(ThemeService::kAutogeneratedThemeID, theme_service->GetThemeID());
+  theme_service_->BuildAutogeneratedThemeFromColor(
+      SkColorSetRGB(100, 100, 100));
+  EXPECT_FALSE(theme_service_->UsingDefaultTheme());
+  EXPECT_TRUE(theme_service_->UsingAutogeneratedTheme());
+  EXPECT_EQ(ThemeService::kAutogeneratedThemeID, theme_service_->GetThemeID());
   path = profile_->GetPrefs()->GetFilePath(prefs::kCurrentThemePackFilename);
   EXPECT_TRUE(path.empty());
 }
 
 TEST_F(ThemeServiceTest, BuildFromColor_DisableExtensionTest) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  base::ScopedTempDir temp_dir1;
-  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-  const std::string& extension1_id =
-      LoadUnpackedMinimalThemeAt(temp_dir1.GetPath());
-  EXPECT_EQ(extension1_id, theme_service->GetThemeID());
-  EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
+  ThemeScoper scoper = LoadUnpackedTheme();
+  EXPECT_EQ(scoper.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(service_->IsExtensionEnabled(scoper.extension_id()));
 
   // Setting autogenerated theme should disable previous theme.
-  theme_service->BuildAutogeneratedThemeFromColor(SkColorSetRGB(100, 100, 100));
-  EXPECT_TRUE(theme_service->UsingAutogeneratedTheme());
-  EXPECT_FALSE(service_->IsExtensionEnabled(extension1_id));
+  theme_service_->BuildAutogeneratedThemeFromColor(
+      SkColorSetRGB(100, 100, 100));
+  EXPECT_TRUE(theme_service_->UsingAutogeneratedTheme());
+  EXPECT_FALSE(service_->IsExtensionEnabled(scoper.extension_id()));
 }
 
 TEST_F(ThemeServiceTest, UseDefaultTheme_DisableExtensionTest) {
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-  base::ScopedTempDir temp_dir1;
-  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
-  const std::string& extension1_id =
-      LoadUnpackedMinimalThemeAt(temp_dir1.GetPath());
-  EXPECT_EQ(extension1_id, theme_service->GetThemeID());
-  EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
+  ThemeScoper scoper = LoadUnpackedTheme();
+  EXPECT_EQ(scoper.extension_id(), theme_service_->GetThemeID());
+  EXPECT_TRUE(service_->IsExtensionEnabled(scoper.extension_id()));
 
   // Resetting to default theme should disable previous theme.
-  theme_service->UseDefaultTheme();
-  EXPECT_FALSE(service_->IsExtensionEnabled(extension1_id));
+  theme_service_->UseDefaultTheme();
+  EXPECT_FALSE(service_->IsExtensionEnabled(scoper.extension_id()));
 }
 
 TEST_F(ThemeServiceTest, OmniboxContrast) {
   using TP = ThemeProperties;
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
   for (bool dark : {false, true}) {
     for (bool high_contrast : {false, true}) {
       set_theme_supplier(
-          theme_service,
+          theme_service_,
           high_contrast
               ? base::MakeRefCounted<IncreasedContrastThemeSupplier>(dark)
               : nullptr);
@@ -595,8 +534,8 @@
       };
       auto check_sufficient_contrast = [&](int id1, int id2) {
         const float contrast = color_utils::GetContrastRatio(
-            GetOmniboxColor(theme_service, id1, dark),
-            GetOmniboxColor(theme_service, id2, dark));
+            GetOmniboxColor(theme_service_, id1, dark),
+            GetOmniboxColor(theme_service_, id2, dark));
         EXPECT_GE(contrast, color_utils::kMinimumReadableContrastRatio);
       };
       for (const int* ids : contrasting_ids)
@@ -612,9 +551,6 @@
 // COLOR_OMNIBOX_TEXT are translucent (https://crbug.com/1006102).
 TEST_F(ThemeServiceTest, TranslucentOmniboxBackgroundAndText) {
   using TP = ThemeProperties;
-  ThemeService* theme_service =
-      ThemeServiceFactory::GetForProfile(profile_.get());
-
   class TranslucentOmniboxThemeSupplier : public CustomThemeSupplier {
    public:
     TranslucentOmniboxThemeSupplier()
@@ -634,7 +570,7 @@
    private:
     ~TranslucentOmniboxThemeSupplier() override = default;
   };
-  set_theme_supplier(theme_service,
+  set_theme_supplier(theme_service_,
                      base::MakeRefCounted<TranslucentOmniboxThemeSupplier>());
 
   constexpr int ids[] = {
@@ -661,8 +597,8 @@
   };
 
   for (int id : ids) {
-    GetOmniboxColor(theme_service, id, false);
-    GetOmniboxColor(theme_service, id, true);
+    GetOmniboxColor(theme_service_, id, false);
+    GetOmniboxColor(theme_service_, id, true);
   }
 }
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 63807dbd..f998bfb5 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3793,6 +3793,8 @@
       "ash/launcher/arc_app_window.cc",
       "ash/launcher/arc_app_window.h",
       "ash/launcher/arc_app_window_delegate.h",
+      "ash/launcher/arc_app_window_info.cc",
+      "ash/launcher/arc_app_window_info.h",
       "ash/launcher/arc_app_window_launcher_controller.cc",
       "ash/launcher/arc_app_window_launcher_controller.h",
       "ash/launcher/arc_app_window_launcher_item_controller.cc",
@@ -4033,6 +4035,7 @@
       "webui/print_preview/printer_handler.h",
     ]
     deps += [
+      "//components/printing/common:mojo_interfaces",
       "//services/device/public/cpp/usb",
       "//services/device/public/mojom:usb",
     ]
diff --git a/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc b/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc
index c46ef72..85b59ea 100644
--- a/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc
+++ b/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc
@@ -25,10 +25,7 @@
       base::WrapUnique(new AdsBlockedInfobarDelegate())));
 }
 
-AdsBlockedInfobarDelegate::AdsBlockedInfobarDelegate()
-    : ConfirmInfoBarDelegate() {}
-
-AdsBlockedInfobarDelegate::~AdsBlockedInfobarDelegate() {}
+AdsBlockedInfobarDelegate::~AdsBlockedInfobarDelegate() = default;
 
 base::string16 AdsBlockedInfobarDelegate::GetExplanationText() const {
   return l10n_util::GetStringUTF16(IDS_BLOCKED_ADS_PROMPT_EXPLANATION);
@@ -47,6 +44,24 @@
   return IDR_ANDROID_INFOBAR_BLOCKED_POPUPS;
 }
 
+GURL AdsBlockedInfobarDelegate::GetLinkURL() const {
+  DCHECK(infobar_expanded_);
+  return GURL(subresource_filter::kLearnMoreLink);
+}
+
+bool AdsBlockedInfobarDelegate::LinkClicked(WindowOpenDisposition disposition) {
+  if (infobar_expanded_) {
+    ChromeSubresourceFilterClient::LogAction(
+        SubresourceFilterAction::kClickedLearnMore);
+    return ConfirmInfoBarDelegate::LinkClicked(disposition);
+  }
+
+  ChromeSubresourceFilterClient::LogAction(
+      SubresourceFilterAction::kDetailsShown);
+  infobar_expanded_ = true;
+  return false;
+}
+
 base::string16 AdsBlockedInfobarDelegate::GetMessageText() const {
   return l10n_util::GetStringUTF16(IDS_BLOCKED_ADS_INFOBAR_MESSAGE);
 }
@@ -57,39 +72,15 @@
 
 base::string16 AdsBlockedInfobarDelegate::GetButtonLabel(
     InfoBarButton button) const {
-  if (button == BUTTON_OK)
-    return l10n_util::GetStringUTF16(IDS_OK);
-  return l10n_util::GetStringUTF16(IDS_APP_MENU_RELOAD);
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ? IDS_OK
+                                                         : IDS_APP_MENU_RELOAD);
 }
 
 bool AdsBlockedInfobarDelegate::Cancel() {
-  content::WebContents* web_contents =
-      InfoBarService::WebContentsFromInfoBar(infobar());
-  ChromeSubresourceFilterClient::FromWebContents(web_contents)
-      ->OnReloadRequested();
+  auto* filter_client = ChromeSubresourceFilterClient::FromWebContents(
+      InfoBarService::WebContentsFromInfoBar(infobar()));
+  filter_client->OnReloadRequested();
   return true;
 }
 
-GURL AdsBlockedInfobarDelegate::GetLinkURL() const {
-  DCHECK(infobar_expanded_);
-  return GURL(subresource_filter::kLearnMoreLink);
-}
-
-bool AdsBlockedInfobarDelegate::LinkClicked(WindowOpenDisposition disposition) {
-  if (infobar_expanded_) {
-    DCHECK_EQ(disposition, WindowOpenDisposition::NEW_FOREGROUND_TAB);
-    infobar()->owner()->OpenURL(GetLinkURL(),
-                                WindowOpenDisposition::NEW_FOREGROUND_TAB);
-    ChromeSubresourceFilterClient::LogAction(
-        SubresourceFilterAction::kClickedLearnMore);
-  } else {
-    ChromeSubresourceFilterClient::LogAction(
-        SubresourceFilterAction::kDetailsShown);
-    infobar_expanded_ = true;
-  }
-  // Returning false keeps the infobar up, which is the behavior we want in all
-  // cases. If the user is navigating via a new foreground tab we do not want
-  // the infobar going away on the tab (and therefore invoking our smart-hiding
-  // logic).
-  return false;
-}
+AdsBlockedInfobarDelegate::AdsBlockedInfobarDelegate() = default;
diff --git a/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.h b/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.h
index 4452cfc..17c2235f 100644
--- a/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.h
+++ b/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.h
@@ -28,14 +28,14 @@
   base::string16 GetToggleText() const;
 
   // ConfirmInfoBarDelegate:
-  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+  InfoBarIdentifier GetIdentifier() const override;
   int GetIconId() const override;
+  GURL GetLinkURL() const override;
+  bool LinkClicked(WindowOpenDisposition disposition) override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Cancel() override;
-  GURL GetLinkURL() const override;
-  bool LinkClicked(WindowOpenDisposition disposition) override;
 
  private:
   AdsBlockedInfobarDelegate();
diff --git a/chrome/browser/ui/android/infobars/save_password_infobar.cc b/chrome/browser/ui/android/infobars/save_password_infobar.cc
index f56e114..b16bdd46 100644
--- a/chrome/browser/ui/android/infobars/save_password_infobar.cc
+++ b/chrome/browser/ui/android/infobars/save_password_infobar.cc
@@ -48,5 +48,5 @@
 
 void SavePasswordInfoBar::OnLinkClicked(JNIEnv* env,
                                         const JavaParamRef<jobject>& obj) {
-  GetDelegate()->LinkClicked(WindowOpenDisposition::NEW_FOREGROUND_TAB);
+  delegate()->LinkClicked(WindowOpenDisposition::NEW_FOREGROUND_TAB);
 }
diff --git a/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc b/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc
index 22ee70bf..6f525eb2 100644
--- a/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc
+++ b/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc
@@ -38,15 +38,15 @@
   // ConfirmInfoBarDelegate:
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   gfx::Image GetIcon() const override;
+  base::string16 GetLinkText() const override;
   bool ShouldExpire(const NavigationDetails& details) const override;
+  bool LinkClicked(WindowOpenDisposition disposition) override;
   void InfoBarDismissed() override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
   bool Cancel() override;
-  base::string16 GetLinkText() const override;
-  bool LinkClicked(WindowOpenDisposition disposition) override;
 
  private:
   base::android::ScopedJavaGlobalRef<jobject> java_listener_;
@@ -93,11 +93,21 @@
                                 : icon_bitmap_;
 }
 
+base::string16 SimpleConfirmInfoBarDelegate::GetLinkText() const {
+  return link_text_str_;
+}
+
 bool SimpleConfirmInfoBarDelegate::ShouldExpire(
     const NavigationDetails& details) const {
   return auto_expire_ && ConfirmInfoBarDelegate::ShouldExpire(details);
 }
 
+bool SimpleConfirmInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  return !Java_SimpleConfirmInfoBarBuilder_onInfoBarLinkClicked(
+      base::android::AttachCurrentThread(), java_listener_);
+}
+
 void SimpleConfirmInfoBarDelegate::InfoBarDismissed() {
   Java_SimpleConfirmInfoBarBuilder_onInfoBarDismissed(
       base::android::AttachCurrentThread(), java_listener_);
@@ -127,16 +137,6 @@
       base::android::AttachCurrentThread(), java_listener_, false);
 }
 
-base::string16 SimpleConfirmInfoBarDelegate::GetLinkText() const {
-  return link_text_str_;
-}
-
-bool SimpleConfirmInfoBarDelegate::LinkClicked(
-    WindowOpenDisposition disposition) {
-  return !Java_SimpleConfirmInfoBarBuilder_onInfoBarLinkClicked(
-      base::android::AttachCurrentThread(), java_listener_);
-}
-
 }  // anonymous namespace
 
 // Native JNI methods ---------------------------------------------------------
diff --git a/chrome/browser/ui/android/infobars/update_password_infobar.cc b/chrome/browser/ui/android/infobars/update_password_infobar.cc
index 41388b0..249b107 100644
--- a/chrome/browser/ui/android/infobars/update_password_infobar.cc
+++ b/chrome/browser/ui/android/infobars/update_password_infobar.cc
@@ -63,5 +63,5 @@
 
 void UpdatePasswordInfoBar::OnLinkClicked(JNIEnv* env,
                                           const JavaParamRef<jobject>& obj) {
-  GetDelegate()->LinkClicked(WindowOpenDisposition::NEW_FOREGROUND_TAB);
+  delegate()->LinkClicked(WindowOpenDisposition::NEW_FOREGROUND_TAB);
 }
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
index b6e532e..1eeb8bf 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
@@ -591,7 +591,7 @@
 <translation id="5487521232677179737">محو البيانات</translation>
 <translation id="5494752089476963479">حظر الإعلانات في المواقع الإلكترونية التي تعرض إعلانات مضلِّلة أو غير مرغوب فيها</translation>
 <translation id="5500777121964041360">قد لا تتوفَّر هذه الميزة في موقعك الجغرافي</translation>
-<translation id="5505264765875738116">منع المواقع الإلكترونية من طلب إرسال إشعارات.</translation>
+<translation id="5505264765875738116">منع المواقع الإلكترونية من طلب إرسال إشعارات</translation>
 <translation id="5512137114520586844">تتم إدارة هذا الحساب بواسطة <ph name="PARENT_NAME" />.</translation>
 <translation id="5514904542973294328">تم الإيقاف من قبل مشرف هذا الجهاز</translation>
 <translation id="5515439363601853141">إلغاء القفل لعرض كلمة المرور</translation>
@@ -695,7 +695,7 @@
 على سبيل المثال، قد تستجيب بعض مواقع الويب لهذا الطلب عبر عرض إعلانات لا تستند إلى مواقع الويب الأخرى التي زرتها، بينما ستظل العديد من مواقع الويب تجمع بيانات تصفّحك وتستخدمها - مثلاً لتحسين الأمان وتقديم محتوى وخدمات وإعلانات واقتراحات وإعداد تقارير بالإحصاءات.</translation>
 <translation id="624789221780392884">التحديث جاهز</translation>
 <translation id="6255999984061454636">اقتراحات المحتوى</translation>
-<translation id="6270391203985052864">السماح للمواقع الإلكترونية طلب إرسال إشعارات.</translation>
+<translation id="6270391203985052864">السماح للمواقع الإلكترونية بطلب إرسال إشعارات</translation>
 <translation id="6277522088822131679">حدثت مشكلة أثناء طباعة الصفحة. يُرجى إعادة المحاولة.</translation>
 <translation id="6295158916970320988">جميع المواقع</translation>
 <translation id="629730747756840877">الحساب</translation>
@@ -739,7 +739,7 @@
 <translation id="6545864417968258051">البحث عن بلوتوث</translation>
 <translation id="6560414384669816528">‏البحث باستخدام Sogou</translation>
 <translation id="656065428026159829">عرض المزيد</translation>
-<translation id="6561560012278703671">استخدام طريقة أقل بروزًا لإرسال الإشعارات (منع رسائل الإشعارات من إزعاجك).</translation>
+<translation id="6561560012278703671">استخدام طريقة أقل بروزًا لإرسال الإشعارات (منع رسائل الإشعارات من إزعاجك)</translation>
 <translation id="6566259936974865419">‏لقد وفر Chrome لك <ph name="GIGABYTES" /> غيغابايت</translation>
 <translation id="6573096386450695060">السماح دومًا</translation>
 <translation id="6573431926118603307">‏ستظهر هنا علامات التبويب التي فتحتها في Chrome من أجهزتك الأخرى.</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb
index cd2b880b..6325b7f 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb
@@ -820,7 +820,7 @@
 <translation id="7176368934862295254"><ph name="KILOBYTES" /> KB</translation>
 <translation id="7177466738963138057">Nahi duzunean alda dezakezu Ezarpenak atalean</translation>
 <translation id="7180611975245234373">Freskatu</translation>
-<translation id="7189372733857464326">Google Play zerbitzuak eguneratzen amaitzeko zain</translation>
+<translation id="7189372733857464326">Google Play-ren zerbitzuak eguneratzen amaitzeko zain</translation>
 <translation id="7191430249889272776">Atzeko planoan ireki da fitxa.</translation>
 <translation id="723171743924126238">Hautatu irudiak</translation>
 <translation id="7233236755231902816">Eskuratu Chrome-ren azken bertsioa webgunea zure hizkuntzan ikusteko</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
index 921deab..d81ef041 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
@@ -743,7 +743,7 @@
 <translation id="6566259936974865419">‏Chrome‏ <ph name="GIGABYTES" /> گیگابایت از داده‌های شما را ذخیره کرده است</translation>
 <translation id="6573096386450695060">همیشه مجاز</translation>
 <translation id="6573431926118603307">‏برگه‌هایی که در دستگاه‌های دیگر در Chrome باز کرده‌اید، در اینجا نمایان می‌شوند.</translation>
-<translation id="6583199322650523874">نشانک گذاشتن صفحه کنونی</translation>
+<translation id="6583199322650523874">نشانک‌گذاری صفحه کنونی</translation>
 <translation id="6593061639179217415">سایت مخصوص رایانه</translation>
 <translation id="6600954340915313787">‏کپی در Chrome</translation>
 <translation id="6608650720463149374"><ph name="GIGABYTES" /> گیگابایت</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb
index 5bbef91..c62fade 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb
@@ -436,7 +436,7 @@
 <translation id="4415276339145661267">Ylläpidä Google-tiliäsi</translation>
 <translation id="4432792777822557199">Kielellä <ph name="SOURCE_LANGUAGE" /> kirjoitetut sivut käännetään tästä lähtien kielelle <ph name="TARGET_LANGUAGE" />.</translation>
 <translation id="4433925000917964731">Googlen tarjoama yksinkertaistettu sivu</translation>
-<translation id="4434045419905280838">Ponn.ikkunat ja uudelleenohj.</translation>
+<translation id="4434045419905280838">Ponn.ikkunat ja uudelleenohjaus</translation>
 <translation id="4440958355523780886">Googlen tarjoama yksinkertaistettu sivu. Lataa alkuperäinen napauttamalla.</translation>
 <translation id="4452411734226507615">Sulje välilehti <ph name="TAB_TITLE" /></translation>
 <translation id="4452548195519783679">Lisätty kirjanmerkiksi kansioon <ph name="FOLDER_NAME" /></translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
index cb748da..b990f2549 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
@@ -211,7 +211,7 @@
 <translation id="2536728043171574184">Affichage d'une copie hors connexion de la page</translation>
 <translation id="2537178555904266562">Erreur lors de la synchronisation des mots de passe</translation>
 <translation id="2537296579376733324">Tous les cookies (sur ce site uniquement)</translation>
-<translation id="2546283357679194313">Cookies et données de site</translation>
+<translation id="2546283357679194313">Cookies et données de sites</translation>
 <translation id="2567385386134582609">IMAGE</translation>
 <translation id="257088987046510401">Thèmes</translation>
 <translation id="2570922361219980984">L'accès à la position est également désactivé pour cet appareil. Activez-le dans les <ph name="BEGIN_LINK" />paramètres Android<ph name="END_LINK" />.</translation>
@@ -793,7 +793,7 @@
 <translation id="6945221475159498467">Sélectionner</translation>
 <translation id="6963642900430330478">Cette page est dangereuse. Informations sur le site</translation>
 <translation id="6963766334940102469">Supprimer des favoris</translation>
-<translation id="6979737339423435258">Toutes les périodes</translation>
+<translation id="6979737339423435258">Toutes les données</translation>
 <translation id="6981982820502123353">Accessibilité</translation>
 <translation id="6989267951144302301">Échec du téléchargement</translation>
 <translation id="6990079615885386641">Télécharger l'application sur le Google Play Store : <ph name="APP_ACTION" /></translation>
@@ -1067,7 +1067,7 @@
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# vidéo}one{# vidéo}other{# vidéos}}</translation>
 <translation id="9050666287014529139">Phrase secrète</translation>
 <translation id="9063523880881406963">Désactiver "Voir version ordinateur"</translation>
-<translation id="9065203028668620118">Édition</translation>
+<translation id="9065203028668620118">Modifier</translation>
 <translation id="9070377983101773829">Démarrer la recherche vocale</translation>
 <translation id="9074336505530349563">Connectez-vous et activez la synchronisation pour obtenir des suggestions de contenu personnalisées de la part de Google</translation>
 <translation id="9086455579313502267">Impossible d'accéder au réseau.</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
index b9f105e7..01c22bc6 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
@@ -923,7 +923,7 @@
 <translation id="7963646190083259054">ベンダー:</translation>
 <translation id="7971136598759319605">最終同期: 1 日前</translation>
 <translation id="7975379999046275268">ページをプレビュー <ph name="BEGIN_NEW" />New<ph name="END_NEW" /></translation>
-<translation id="7981313251711023384">ページをプリロードして、閲覧と検索をすばやく行えるようにします</translation>
+<translation id="7981313251711023384">ページをプリロードして、閲覧と検索をすばやく行えるようにする</translation>
 <translation id="79859296434321399">拡張現実(AR)コンテンツを表示するには ARCore をインストールしてください</translation>
 <translation id="7986741934819883144">連絡先の選択</translation>
 <translation id="7987073022710626672">Chrome 利用規約</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb
index b0890e7..07b17be 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb
@@ -6,7 +6,7 @@
 <translation id="1036727731225946849"><ph name="WEBAPK_NAME" /> 추가 중...</translation>
 <translation id="1041308826830691739">웹사이트 알림</translation>
 <translation id="1049743911850919806">시크릿</translation>
-<translation id="10614374240317010">저장되지 않음</translation>
+<translation id="10614374240317010">저장하지 않음</translation>
 <translation id="1067922213147265141">다른 Google 서비스</translation>
 <translation id="1068672505746868501"><ph name="SOURCE_LANGUAGE" />로 된 페이지는 번역하지 않음</translation>
 <translation id="107147699690128016">파일 확장자를 변경하면 파일이 다른 애플리케이션에서 열리고 기기가 위험에 노출될 수도 있습니다.</translation>
@@ -247,7 +247,7 @@
 <translation id="2860954141821109167">이 기기에서 전화 앱이 사용 설정되어 있는지 확인하세요.</translation>
 <translation id="2870560284913253234">사이트</translation>
 <translation id="2874939134665556319">이전 트랙</translation>
-<translation id="2876369937070532032">보안상의 위험이 있을 때 일부 방문 페이지의 URL을 Google로 전송함</translation>
+<translation id="2876369937070532032">보안상의 위험이 있을 때 일부 방문 페이지의 URL을 Google로 전송합니다.</translation>
 <translation id="2888126860611144412">Chrome 정보</translation>
 <translation id="2891154217021530873">페이지 로딩 중지</translation>
 <translation id="2893180576842394309">Google에서 내 방문 기록을 사용하여 Google 검색 및 다른 Google 서비스를 맞춤설정할 수 있습니다.</translation>
@@ -416,12 +416,12 @@
 <translation id="4226663524361240545">알림이 있으면 진동이 울릴 수도 있습니다.</translation>
 <translation id="423219824432660969"><ph name="TIME" />에 Google 비밀번호를 사용하여 동기화된 데이터 암호화</translation>
 <translation id="4242533952199664413">설정 열기</translation>
-<translation id="4250229828105606438">캡처화면</translation>
+<translation id="4250229828105606438">스크린샷</translation>
 <translation id="4256782883801055595">오픈소스 라이선스</translation>
 <translation id="4259722352634471385">탐색이 차단됨: <ph name="URL" /></translation>
 <translation id="4269820728363426813">링크 주소 복사</translation>
 <translation id="4275663329226226506">미디어</translation>
-<translation id="4278390842282768270">허용됨</translation>
+<translation id="4278390842282768270">허용</translation>
 <translation id="429312253194641664">사이트에서 미디어 재생 중</translation>
 <translation id="4298388696830689168">연결된 사이트</translation>
 <translation id="4307992518367153382">기본설정</translation>
@@ -476,7 +476,7 @@
 <translation id="4695891336199304370">{SHIPPING_OPTIONS,plural, =1{<ph name="SHIPPING_OPTION_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />개}other{<ph name="SHIPPING_OPTION_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />개}}</translation>
 <translation id="4696983787092045100">기기로 SMS 전송</translation>
 <translation id="4698034686595694889"><ph name="APP_NAME" />에서 오프라인으로 보기</translation>
-<translation id="4699172675775169585">캐시된 이미지 또는 파일</translation>
+<translation id="4699172675775169585">캐시된 이미지 및 파일</translation>
 <translation id="4714588616299687897">데이터 최대 60% 절약</translation>
 <translation id="4719927025381752090">번역 옵션 제공</translation>
 <translation id="4720023427747327413"><ph name="PRODUCT_NAME" />에서 열기</translation>
@@ -619,7 +619,7 @@
 <translation id="5659593005791499971">이메일</translation>
 <translation id="5665379678064389456"><ph name="APP_NAME" />에 일정 만들기</translation>
 <translation id="5668404140385795438">웹사이트의 확대 방지 요청 무시</translation>
-<translation id="5677928146339483299">차단됨</translation>
+<translation id="5677928146339483299">차단</translation>
 <translation id="5684874026226664614">죄송합니다. 이 페이지를 번역할 수 없습니다.</translation>
 <translation id="5686790454216892815">파일 이름이 너무 깁니다.</translation>
 <translation id="5689516760719285838">위치</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
index 88135dd..ac774373 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
@@ -421,7 +421,7 @@
 <translation id="4259722352634471385">Webbadressen har blockerats: <ph name="URL" /></translation>
 <translation id="4269820728363426813">Kopiera länkadress</translation>
 <translation id="4275663329226226506">Media</translation>
-<translation id="4278390842282768270">Tillåtet</translation>
+<translation id="4278390842282768270">Tillåts</translation>
 <translation id="429312253194641664">Media spelas upp på en webbplats</translation>
 <translation id="4298388696830689168">Länkade webbplatser</translation>
 <translation id="4307992518367153382">Grunderna</translation>
@@ -561,7 +561,7 @@
 <translation id="5292796745632149097">Skicka till</translation>
 <translation id="5304593522240415983">Fältet får inte vara tomt</translation>
 <translation id="5307446750509046227">Rensa webbplatslagring</translation>
-<translation id="5308380583665731573">Ansluta</translation>
+<translation id="5308380583665731573">Anslut</translation>
 <translation id="5313967007315987356">Lägg till webbplats</translation>
 <translation id="5324858694974489420">Föräldrainställningar</translation>
 <translation id="5327248766486351172">Namn</translation>
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayout.java b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayout.java
index 34febbf..a1d784c 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayout.java
+++ b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayout.java
@@ -10,6 +10,8 @@
 import android.view.ViewGroup;
 import android.widget.RadioGroup;
 
+import androidx.annotation.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -160,6 +162,7 @@
      *
      * @param childIndex Index of the child to select.
      */
+    @VisibleForTesting
     void selectChildAtIndexForTesting(int childIndex) {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayoutTest.java b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayoutTest.java
index e8e00f4..a9f0b09 100644
--- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayoutTest.java
+++ b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayoutTest.java
@@ -9,9 +9,11 @@
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.UiThreadTestRule;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup.MarginLayoutParams;
+import android.widget.EditText;
 import android.widget.TextView;
 
 import org.junit.Assert;
@@ -35,13 +37,20 @@
             "First N-1 items should have a non-zero margin";
     private static final String ZERO_MARGIN_ASSERT_MESSAGE =
             "The last item should have a zero margin";
-    private static final String TITLE_MATCH_ASSERT_MESSAGE =
+    private static final String PRIMARY_MATCH_ASSERT_MESSAGE =
             "Primary text set through addButtons should match the view's primary text.";
     private static final String DESCRIPTION_MATCH_ASSERT_MESSAGE =
             "Description set through addButtons should match the view's description.";
     private static final String TAG_MATCH_ASSERT_MESSAGE =
             "Tag set through addButtons should match the view's tag.";
 
+    private static final String PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE =
+            "Primary text set through layout should match the view's primary text.";
+    private static final String DESC_MATCH_FROM_XML_ASSERT_MESSAGE =
+            "Description text set through layout should match the view's description.";
+    private static final String HINT_MATCH_FROM_XML_ASSERT_MESSAGE =
+            "Hint message set through layout should match the view's hint message.";
+
     @Rule
     public UiThreadTestRule mRule = new UiThreadTestRule();
 
@@ -115,10 +124,11 @@
 
         for (int i = 0; i < layout.getChildCount(); i++) {
             RadioButtonWithDescription b = (RadioButtonWithDescription) layout.getChildAt(i);
-            Assert.assertEquals(TITLE_MATCH_ASSERT_MESSAGE, buttons.get(i).getPrimaryText(),
-                    b.getPrimaryText());
+            Assert.assertEquals(PRIMARY_MATCH_ASSERT_MESSAGE,
+                    buttons.get(i).getPrimaryText().toString(), b.getPrimaryText().toString());
             Assert.assertEquals(DESCRIPTION_MATCH_ASSERT_MESSAGE,
-                    buttons.get(i).getDescriptionText(), b.getDescriptionText());
+                    buttons.get(i).getDescriptionText().toString(),
+                    b.getDescriptionText().toString());
             Assert.assertEquals(TAG_MATCH_ASSERT_MESSAGE, buttons.get(i).getTag(), b.getTag());
         }
 
@@ -131,18 +141,21 @@
         Assert.assertEquals(6, layout.getChildCount());
         for (int i = 0; i < 3; i++) {
             RadioButtonWithDescription b = (RadioButtonWithDescription) layout.getChildAt(i);
-            Assert.assertEquals(TITLE_MATCH_ASSERT_MESSAGE, buttons.get(i).getPrimaryText(),
-                    b.getPrimaryText());
+            Assert.assertEquals(PRIMARY_MATCH_ASSERT_MESSAGE,
+                    buttons.get(i).getPrimaryText().toString(), b.getPrimaryText().toString());
             Assert.assertEquals(DESCRIPTION_MATCH_ASSERT_MESSAGE,
-                    buttons.get(i).getDescriptionText(), b.getDescriptionText());
+                    buttons.get(i).getDescriptionText().toString(),
+                    b.getDescriptionText().toString());
             Assert.assertEquals(TAG_MATCH_ASSERT_MESSAGE, buttons.get(i).getTag(), b.getTag());
         }
         for (int i = 3; i < 6; i++) {
             RadioButtonWithDescription b = (RadioButtonWithDescription) layout.getChildAt(i);
-            Assert.assertEquals(TITLE_MATCH_ASSERT_MESSAGE, moreButtons.get(i - 3).getPrimaryText(),
-                    b.getPrimaryText());
+            Assert.assertEquals(PRIMARY_MATCH_ASSERT_MESSAGE,
+                    moreButtons.get(i - 3).getPrimaryText().toString(),
+                    b.getPrimaryText().toString());
             Assert.assertEquals(DESCRIPTION_MATCH_ASSERT_MESSAGE,
-                    moreButtons.get(i - 3).getDescriptionText(), b.getDescriptionText());
+                    moreButtons.get(i - 3).getDescriptionText().toString(),
+                    b.getDescriptionText().toString());
             Assert.assertEquals(
                     TAG_MATCH_ASSERT_MESSAGE, moreButtons.get(i - 3).getTag(), b.getTag());
         }
@@ -244,34 +257,6 @@
     public void testCombinedRadioButtons() {
         // Test if radio buttons are set up correctly when there are multiple classes in the same
         // layout.
-        final RadioButtonWithDescriptionLayout layout =
-                new RadioButtonWithDescriptionLayout(mContext);
-
-        RadioButtonWithDescription b1 = createRadioButtonWithDescription("a", "a_desc", null);
-        RadioButtonWithDescription b2 = createRadioButtonWithDescription("b", "b_desc", null);
-
-        RadioButtonWithEditText b3 = new RadioButtonWithEditText(mContext, null);
-        b3.setPrimaryText("c");
-        b3.setDescriptionText("c_desc");
-
-        List<RadioButtonWithDescription> buttons = Arrays.asList(b1, b2, b3);
-        layout.addButtons(buttons);
-
-        layout.selectChildAtIndexForTesting(3);
-        for (int i = 0; i < layout.getChildCount(); i++) {
-            RadioButtonWithDescription b = (RadioButtonWithDescription) layout.getChildAt(i);
-            Assert.assertEquals(TITLE_MATCH_ASSERT_MESSAGE, buttons.get(i).getPrimaryText(),
-                    b.getPrimaryText());
-            Assert.assertEquals(DESCRIPTION_MATCH_ASSERT_MESSAGE,
-                    buttons.get(i).getDescriptionText(), b.getDescriptionText());
-            Assert.assertEquals(i == 3, b.isChecked());
-        }
-    }
-
-    @Test
-    @SmallTest
-    @UiThreadTest
-    public void testInflateFromLayout() {
         View content = LayoutInflater.from(mContext).inflate(
                 R.layout.radio_button_with_description_layout_test, null, false);
 
@@ -287,6 +272,38 @@
         Assert.assertNotNull(b2);
         Assert.assertNotNull(b3);
         Assert.assertNotNull(b4);
+
+        layout.selectChildAtIndexForTesting(3);
+
+        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b1.getPrimaryText().toString(),
+                mContext.getResources().getString(R.string.test_primary_1));
+        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b2.getPrimaryText().toString(),
+                mContext.getResources().getString(R.string.test_primary_2));
+        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b3.getPrimaryText().toString(),
+                mContext.getResources().getString(R.string.test_primary_3));
+        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b4.getPrimaryText().toString(),
+                mContext.getResources().getString(R.string.test_primary_4));
+
+        Assert.assertTrue(
+                DESC_MATCH_FROM_XML_ASSERT_MESSAGE, TextUtils.isEmpty(b1.getDescriptionText()));
+        Assert.assertEquals(DESC_MATCH_FROM_XML_ASSERT_MESSAGE, b2.getDescriptionText().toString(),
+                mContext.getResources().getString(R.string.test_desc_2));
+        Assert.assertTrue(
+                DESC_MATCH_FROM_XML_ASSERT_MESSAGE, TextUtils.isEmpty(b3.getDescriptionText()));
+        Assert.assertEquals(DESC_MATCH_FROM_XML_ASSERT_MESSAGE, b4.getDescriptionText().toString(),
+                mContext.getResources().getString(R.string.test_desc_4));
+
+        Assert.assertEquals(HINT_MATCH_FROM_XML_ASSERT_MESSAGE,
+                ((EditText) b3.getPrimaryTextView()).getHint().toString(),
+                mContext.getResources().getString(R.string.test_uri));
+        Assert.assertEquals(HINT_MATCH_FROM_XML_ASSERT_MESSAGE,
+                ((EditText) b4.getPrimaryTextView()).getHint().toString(),
+                mContext.getResources().getString(R.string.test_uri));
+
+        Assert.assertFalse(b1.isChecked());
+        Assert.assertFalse(b2.isChecked());
+        Assert.assertFalse(b3.isChecked());
+        Assert.assertTrue(b4.isChecked());
     }
 
     private RadioButtonWithDescription createRadioButtonWithDescription(
diff --git a/chrome/browser/ui/android/widget/test/java/res/layout/radio_button_with_description_layout_test.xml b/chrome/browser/ui/android/widget/test/java/res/layout/radio_button_with_description_layout_test.xml
index c29761c..f16e248 100644
--- a/chrome/browser/ui/android/widget/test/java/res/layout/radio_button_with_description_layout_test.xml
+++ b/chrome/browser/ui/android/widget/test/java/res/layout/radio_button_with_description_layout_test.xml
@@ -18,15 +18,15 @@
               android:id="@+id/test_radio_description_1"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
-              app:primaryText="@string/test_string" />
+              app:primaryText="@string/test_primary_1" />
 
         <!-- RadioButtonWithDescription - With primary and description. -->
         <org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
             android:id="@+id/test_radio_description_2"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            app:primaryText="@string/test_string"
-            app:descriptionText="@string/test_string" />
+            app:primaryText="@string/test_primary_2"
+            app:descriptionText="@string/test_desc_2" />
 
         <!-- RadioButtonWithDescription - With primary, without description. -->
         <org.chromium.chrome.browser.ui.widget.RadioButtonWithEditText
@@ -38,7 +38,7 @@
             android:paddingBottom="8dp"
             android:inputType="text"
             android:hint="@string/test_uri"
-            app:primaryText="@string/test_string" />
+            app:primaryText="@string/test_primary_3" />
 
         <!-- RadioButtonWithDescription - With primary and description. -->
         <org.chromium.chrome.browser.ui.widget.RadioButtonWithEditText
@@ -50,7 +50,7 @@
             android:paddingBottom="8dp"
             android:inputType="text"
             android:hint="@string/test_uri"
-            app:primaryText="@string/test_string"
-            app:descriptionText="@string/test_string" />
+            app:primaryText="@string/test_primary_4"
+            app:descriptionText="@string/test_desc_4" />
     </org.chromium.chrome.browser.ui.widget.RadioButtonWithDescriptionLayout>
 </FrameLayout>
diff --git a/chrome/browser/ui/android/widget/test/java/res/values/strings.xml b/chrome/browser/ui/android/widget/test/java/res/values/strings.xml
index 234b9a8..7f899fc 100644
--- a/chrome/browser/ui/android/widget/test/java/res/values/strings.xml
+++ b/chrome/browser/ui/android/widget/test/java/res/values/strings.xml
@@ -12,4 +12,12 @@
 
     <string name="test_string">A String used for tests</string>
     <string name="test_uri">https://www.example.com</string>
+
+    <string name="test_primary_1">Test Primary 1</string>
+    <string name="test_primary_2">Test Primary 2</string>
+    <string name="test_primary_3">Test Primary 3</string>
+    <string name="test_primary_4">Test Primary 4</string>
+
+    <string name="test_desc_2">Test Description 2</string>
+    <string name="test_desc_4">Test Description 4</string>
 </resources>
\ No newline at end of file
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
index 0ebc473..f5f33cf9 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
@@ -198,11 +198,11 @@
   // to.
   std::list<TestSearchResult> test_search_results_;
 
+  ScopedTempDir temp_dir_;
   content::BrowserTaskEnvironment task_environment_;
   data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
 
   ScopedFeatureList scoped_feature_list_;
-  ScopedTempDir temp_dir_;
 
   std::unique_ptr<history::HistoryService> history_service_;
   std::unique_ptr<Profile> profile_;
@@ -502,15 +502,24 @@
                                               HasIdScore("untrained", 0.5f)));
   }
 
-  // Now delete |url_1| from the history service and ensure we save the model to
-  // disk.
+  // Delete the model file from disk and make sure it's gone.
   base::DeleteFile(model_path, false);
   EXPECT_FALSE(base::PathExists(model_path));
+
+  // Advance mock time by more than |min_seconds_between_saves| to make sure the
+  // file will be written again upon modification.
+  task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(2 * 1000));
+
+  // Modify the history.
   history_service()->AddPage(GURL(url_1), base::Time::Now(),
                              history::VisitSource::SOURCE_BROWSED);
   history_service()->DeleteURLs({GURL(url_1)});
+
+  // Wait for history transactions to be complete.
   history::BlockUntilHistoryProcessesPendingRequests(history_service());
   Wait();
+
+  // Verify that the modifications triggered a write of the model.
   EXPECT_TRUE(base::PathExists(model_path));
 
   // Force cache expiry.
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc
index 12e252c..2297e66 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc
@@ -22,76 +22,12 @@
 #include "chrome/browser/ui/ash/launcher/app_window_base.h"
 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h"
 #include "chrome/browser/ui/ash/launcher/arc_app_window.h"
+#include "chrome/browser/ui/ash/launcher/arc_app_window_info.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/views/widget/widget.h"
 
-namespace {
-
-constexpr size_t kMaxIconPngSize = 64 * 1024;  // 64 kb
-
-}  // namespace
-
-// The information about the ARC application window which has to be kept
-// even when its AppWindow is not present.
-class AppServiceAppWindowArcTracker::ArcAppWindowInfo {
- public:
-  ArcAppWindowInfo(const arc::ArcAppShelfId& app_shelf_id,
-                   const std::string& launch_intent,
-                   const std::string& package_name)
-      : app_shelf_id_(app_shelf_id),
-        launch_intent_(launch_intent),
-        package_name_(package_name) {}
-  ~ArcAppWindowInfo() = default;
-
-  ArcAppWindowInfo(const ArcAppWindowInfo&) = delete;
-  ArcAppWindowInfo& operator=(const ArcAppWindowInfo&) = delete;
-
-  void SetDescription(const std::string& title,
-                      const std::vector<uint8_t>& icon_data_png) {
-    DCHECK(base::IsStringUTF8(title));
-    title_ = title;
-
-    // Chrome has custom Play Store icon. Don't overwrite it.
-    if (app_shelf_id_.app_id() == arc::kPlayStoreAppId)
-      return;
-    if (icon_data_png.size() < kMaxIconPngSize)
-      icon_data_png_ = icon_data_png;
-    else
-      VLOG(1) << "Task icon size is too big " << icon_data_png.size() << ".";
-  }
-
-  void set_window(aura::Window* window) { window_ = window; }
-
-  aura::Window* window() { return window_; }
-
-  const arc::ArcAppShelfId& app_shelf_id() const { return app_shelf_id_; }
-
-  const ash::ShelfID shelf_id() const {
-    return ash::ShelfID(app_shelf_id_.ToString());
-  }
-
-  const std::string& launch_intent() const { return launch_intent_; }
-
-  const std::string& package_name() const { return package_name_; }
-
-  const std::string& title() const { return title_; }
-
-  const std::vector<uint8_t>& icon_data_png() const { return icon_data_png_; }
-
- private:
-  const arc::ArcAppShelfId app_shelf_id_;
-  const std::string launch_intent_;
-  const std::string package_name_;
-  // Keeps overridden window title.
-  std::string title_;
-  // Keeps overridden window icon.
-  std::vector<uint8_t> icon_data_png_;
-
-  aura::Window* window_ = nullptr;
-};
-
 AppServiceAppWindowArcTracker::AppServiceAppWindowArcTracker(
     AppServiceAppWindowLauncherController* app_service_controller)
     : observed_profile_(app_service_controller->owner()->profile()),
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.h b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.h
index 0d36c92..18a7baa 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.h
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.h
@@ -34,6 +34,7 @@
 
 class AppServiceAppWindowLauncherController;
 class AppServiceAppWindowLauncherItemController;
+class ArcAppWindowInfo;
 class Profile;
 
 // AppServiceAppWindowArcTracker observes the ArcAppListPrefs to handle ARC app
@@ -90,8 +91,6 @@
   int active_task_id() const { return active_task_id_; }
 
  private:
-  class ArcAppWindowInfo;
-
   using TaskIdToArcAppWindowInfo =
       std::map<int, std::unique_ptr<ArcAppWindowInfo>>;
 
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_info.cc b/chrome/browser/ui/ash/launcher/arc_app_window_info.cc
new file mode 100644
index 0000000..667eb27
--- /dev/null
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_info.cc
@@ -0,0 +1,69 @@
+// 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/ash/launcher/arc_app_window_info.h"
+
+#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+
+namespace {
+
+constexpr size_t kMaxIconPngSize = 64 * 1024;  // 64 kb
+
+}  // namespace
+
+ArcAppWindowInfo::ArcAppWindowInfo(const arc::ArcAppShelfId& app_shelf_id,
+                                   const std::string& launch_intent,
+                                   const std::string& package_name)
+    : app_shelf_id_(app_shelf_id),
+      launch_intent_(launch_intent),
+      package_name_(package_name) {}
+
+ArcAppWindowInfo::~ArcAppWindowInfo() = default;
+
+void ArcAppWindowInfo::SetDescription(
+    const std::string& title,
+    const std::vector<uint8_t>& icon_data_png) {
+  DCHECK(base::IsStringUTF8(title));
+  title_ = title;
+
+  // Chrome has custom Play Store icon. Don't overwrite it.
+  if (app_shelf_id_.app_id() == arc::kPlayStoreAppId)
+    return;
+  if (icon_data_png.size() < kMaxIconPngSize)
+    icon_data_png_ = icon_data_png;
+  else
+    VLOG(1) << "Task icon size is too big " << icon_data_png.size() << ".";
+}
+
+void ArcAppWindowInfo::set_window(aura::Window* window) {
+  window_ = window;
+}
+
+aura::Window* ArcAppWindowInfo::ArcAppWindowInfo::window() {
+  return window_;
+}
+
+const arc::ArcAppShelfId& ArcAppWindowInfo::app_shelf_id() const {
+  return app_shelf_id_;
+}
+
+const ash::ShelfID ArcAppWindowInfo::shelf_id() const {
+  return ash::ShelfID(app_shelf_id_.ToString());
+}
+
+const std::string& ArcAppWindowInfo::launch_intent() const {
+  return launch_intent_;
+}
+
+const std::string& ArcAppWindowInfo::package_name() const {
+  return package_name_;
+}
+
+const std::string& ArcAppWindowInfo::title() const {
+  return title_;
+}
+
+const std::vector<uint8_t>& ArcAppWindowInfo::icon_data_png() const {
+  return icon_data_png_;
+}
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_info.h b/chrome/browser/ui/ash/launcher/arc_app_window_info.h
new file mode 100644
index 0000000..dbc3842
--- /dev/null
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_info.h
@@ -0,0 +1,58 @@
+// 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_ASH_LAUNCHER_ARC_APP_WINDOW_INFO_H_
+#define CHROME_BROWSER_UI_ASH_LAUNCHER_ARC_APP_WINDOW_INFO_H_
+
+#include <string>
+#include <vector>
+
+#include "ash/public/cpp/shelf_types.h"
+#include "chrome/browser/ui/ash/launcher/arc_app_shelf_id.h"
+#include "ui/aura/window.h"
+
+// The information about the ARC application window which has to be kept
+// even when its AppWindow is not present.
+class ArcAppWindowInfo {
+ public:
+  ArcAppWindowInfo(const arc::ArcAppShelfId& app_shelf_id,
+                   const std::string& launch_intent,
+                   const std::string& package_name);
+  ~ArcAppWindowInfo();
+
+  ArcAppWindowInfo(const ArcAppWindowInfo&) = delete;
+  ArcAppWindowInfo& operator=(const ArcAppWindowInfo&) = delete;
+
+  void SetDescription(const std::string& title,
+                      const std::vector<uint8_t>& icon_data_png);
+
+  void set_window(aura::Window* window);
+
+  aura::Window* window();
+
+  const arc::ArcAppShelfId& app_shelf_id() const;
+
+  const ash::ShelfID shelf_id() const;
+
+  const std::string& launch_intent() const;
+
+  const std::string& package_name() const;
+
+  const std::string& title() const;
+
+  const std::vector<uint8_t>& icon_data_png() const;
+
+ private:
+  const arc::ArcAppShelfId app_shelf_id_;
+  const std::string launch_intent_;
+  const std::string package_name_;
+  // Keeps overridden window title.
+  std::string title_;
+  // Keeps overridden window icon.
+  std::vector<uint8_t> icon_data_png_;
+
+  aura::Window* window_ = nullptr;
+};
+
+#endif  // CHROME_BROWSER_UI_ASH_LAUNCHER_ARC_APP_WINDOW_INFO_H_
diff --git a/chrome/browser/ui/extensions/installation_error_infobar_delegate.cc b/chrome/browser/ui/extensions/installation_error_infobar_delegate.cc
index d4cc5aa..1fb5665e2 100644
--- a/chrome/browser/ui/extensions/installation_error_infobar_delegate.cc
+++ b/chrome/browser/ui/extensions/installation_error_infobar_delegate.cc
@@ -29,14 +29,6 @@
   return INSTALLATION_ERROR_INFOBAR_DELEGATE;
 }
 
-base::string16 InstallationErrorInfoBarDelegate::GetMessageText() const {
-  return error_.message();
-}
-
-int InstallationErrorInfoBarDelegate::GetButtons() const {
-  return BUTTON_OK;
-}
-
 base::string16 InstallationErrorInfoBarDelegate::GetLinkText() const {
   return error_.type() == extensions::CrxInstallErrorType::OTHER &&
                  error_.detail() == extensions::CrxInstallErrorDetail::
@@ -48,3 +40,11 @@
 GURL InstallationErrorInfoBarDelegate::GetLinkURL() const {
   return GURL("https://support.google.com/chrome_webstore/?p=crx_warning");
 }
+
+base::string16 InstallationErrorInfoBarDelegate::GetMessageText() const {
+  return error_.message();
+}
+
+int InstallationErrorInfoBarDelegate::GetButtons() const {
+  return BUTTON_OK;
+}
diff --git a/chrome/browser/ui/extensions/installation_error_infobar_delegate.h b/chrome/browser/ui/extensions/installation_error_infobar_delegate.h
index 9adb936..87425bc 100644
--- a/chrome/browser/ui/extensions/installation_error_infobar_delegate.h
+++ b/chrome/browser/ui/extensions/installation_error_infobar_delegate.h
@@ -26,10 +26,10 @@
 
   // ConfirmInfoBarDelegate:
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  base::string16 GetMessageText() const override;
-  int GetButtons() const override;
   base::string16 GetLinkText() const override;
   GURL GetLinkURL() const override;
+  base::string16 GetMessageText() const override;
+  int GetButtons() const override;
 
   extensions::CrxInstallError error_;
 
diff --git a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc
index 849d1c5..e80d6c7e 100644
--- a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc
+++ b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc
@@ -37,28 +37,6 @@
           search_url))));
 }
 
-AlternateNavInfoBarDelegate::AlternateNavInfoBarDelegate(
-    Profile* profile,
-    const base::string16& text,
-    std::unique_ptr<AutocompleteMatch> match,
-    const GURL& destination_url,
-    const GURL& original_url)
-    : infobars::InfoBarDelegate(),
-      profile_(profile),
-      text_(text),
-      match_(std::move(match)),
-      destination_url_(destination_url),
-      original_url_(original_url) {
-  if (match_)
-    DCHECK_EQ(destination_url_, match_->destination_url);
-
-  DCHECK(destination_url_.is_valid());
-  DCHECK(original_url_.is_valid());
-}
-
-// AlternateNavInfoBarDelegate::CreateInfoBar() is implemented in
-// platform-specific files.
-
 base::string16 AlternateNavInfoBarDelegate::GetMessageTextWithOffset(
     size_t* link_offset) const {
   const base::string16 label = l10n_util::GetStringFUTF16(
@@ -66,6 +44,15 @@
   return label;
 }
 
+infobars::InfoBarDelegate::InfoBarIdentifier
+AlternateNavInfoBarDelegate::GetIdentifier() const {
+  return ALTERNATE_NAV_INFOBAR_DELEGATE;
+}
+
+const gfx::VectorIcon& AlternateNavInfoBarDelegate::GetVectorIcon() const {
+  return kGlobeIcon;
+}
+
 base::string16 AlternateNavInfoBarDelegate::GetLinkText() const {
   return base::UTF8ToUTF16(destination_url_.spec());
 }
@@ -105,11 +92,24 @@
   return true;
 }
 
-infobars::InfoBarDelegate::InfoBarIdentifier
-AlternateNavInfoBarDelegate::GetIdentifier() const {
-  return ALTERNATE_NAV_INFOBAR_DELEGATE;
+AlternateNavInfoBarDelegate::AlternateNavInfoBarDelegate(
+    Profile* profile,
+    const base::string16& text,
+    std::unique_ptr<AutocompleteMatch> match,
+    const GURL& destination_url,
+    const GURL& original_url)
+    : infobars::InfoBarDelegate(),
+      profile_(profile),
+      text_(text),
+      match_(std::move(match)),
+      destination_url_(destination_url),
+      original_url_(original_url) {
+  if (match_)
+    DCHECK_EQ(destination_url_, match_->destination_url);
+
+  DCHECK(destination_url_.is_valid());
+  DCHECK(original_url_.is_valid());
 }
 
-const gfx::VectorIcon& AlternateNavInfoBarDelegate::GetVectorIcon() const {
-  return kGlobeIcon;
-}
+// AlternateNavInfoBarDelegate::CreateInfoBar() is implemented in
+// platform-specific files.
diff --git a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h
index 10733c41..9985c24 100644
--- a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h
+++ b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h
@@ -36,9 +36,13 @@
                                          const GURL& search_url);
 
   base::string16 GetMessageTextWithOffset(size_t* link_offset) const;
-  base::string16 GetLinkText() const;
-  GURL GetLinkURL() const;
-  bool LinkClicked(WindowOpenDisposition disposition);
+
+  // InfoBarDelegate:
+  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+  const gfx::VectorIcon& GetVectorIcon() const override;
+  base::string16 GetLinkText() const override;
+  GURL GetLinkURL() const override;
+  bool LinkClicked(WindowOpenDisposition disposition) override;
 
  private:
   AlternateNavInfoBarDelegate(Profile* profile,
@@ -51,10 +55,6 @@
   static std::unique_ptr<infobars::InfoBar> CreateInfoBar(
       std::unique_ptr<AlternateNavInfoBarDelegate> delegate);
 
-  // InfoBarDelegate:
-  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  const gfx::VectorIcon& GetVectorIcon() const override;
-
   Profile* profile_;
   const base::string16 text_;
 
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index 59b2a113e0..d65572b 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -531,14 +531,8 @@
             UTF16ToUTF8(omnibox_view->GetText()));
 }
 
-// TODO(https://crbug.com/1030551): This test flakily times out on ASAN and
-// TSAN.
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
-#define MAYBE_DesiredTLD DISABLED_DesiredTLD
-#else
-#define MAYBE_DesiredTLD DesiredTLD
-#endif
-IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_DesiredTLD) {
+// TODO(https://crbug.com/1030551): This test flakily times out.
+IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_DesiredTLD) {
   OmniboxView* omnibox_view = NULL;
   ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
   OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
diff --git a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc
index f7af1a5..f2d4a63 100644
--- a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc
@@ -31,14 +31,6 @@
   return GOOGLE_API_KEYS_INFOBAR_DELEGATE;
 }
 
-base::string16 GoogleApiKeysInfoBarDelegate::GetMessageText() const {
-  return l10n_util::GetStringUTF16(IDS_MISSING_GOOGLE_API_KEYS);
-}
-
-int GoogleApiKeysInfoBarDelegate::GetButtons() const {
-  return BUTTON_NONE;
-}
-
 base::string16 GoogleApiKeysInfoBarDelegate::GetLinkText() const {
   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
 }
@@ -46,3 +38,11 @@
 GURL GoogleApiKeysInfoBarDelegate::GetLinkURL() const {
   return GURL(google_apis::kAPIKeysDevelopersHowToURL);
 }
+
+base::string16 GoogleApiKeysInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringUTF16(IDS_MISSING_GOOGLE_API_KEYS);
+}
+
+int GoogleApiKeysInfoBarDelegate::GetButtons() const {
+  return BUTTON_NONE;
+}
diff --git a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h
index 5f67ffa..deb839a 100644
--- a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h
+++ b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h
@@ -25,10 +25,10 @@
   ~GoogleApiKeysInfoBarDelegate() override;
 
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  base::string16 GetMessageText() const override;
-  int GetButtons() const override;
   base::string16 GetLinkText() const override;
   GURL GetLinkURL() const override;
+  base::string16 GetMessageText() const override;
+  int GetButtons() const override;
 
   DISALLOW_COPY_AND_ASSIGN(GoogleApiKeysInfoBarDelegate);
 };
diff --git a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
index f4f948f..2deb84f 100644
--- a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
@@ -29,14 +29,6 @@
   return OBSOLETE_SYSTEM_INFOBAR_DELEGATE;
 }
 
-base::string16 ObsoleteSystemInfoBarDelegate::GetMessageText() const {
-  return ObsoleteSystem::LocalizedObsoleteString();
-}
-
-int ObsoleteSystemInfoBarDelegate::GetButtons() const {
-  return BUTTON_NONE;
-}
-
 base::string16 ObsoleteSystemInfoBarDelegate::GetLinkText() const {
   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
 }
@@ -44,3 +36,11 @@
 GURL ObsoleteSystemInfoBarDelegate::GetLinkURL() const {
   return GURL(ObsoleteSystem::GetLinkURL());
 }
+
+base::string16 ObsoleteSystemInfoBarDelegate::GetMessageText() const {
+  return ObsoleteSystem::LocalizedObsoleteString();
+}
+
+int ObsoleteSystemInfoBarDelegate::GetButtons() const {
+  return BUTTON_NONE;
+}
diff --git a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h
index 081db02..bc5f2d2 100644
--- a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h
+++ b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h
@@ -26,10 +26,10 @@
   ~ObsoleteSystemInfoBarDelegate() override;
 
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  base::string16 GetMessageText() const override;
-  int GetButtons() const override;
   base::string16 GetLinkText() const override;
   GURL GetLinkURL() const override;
+  base::string16 GetMessageText() const override;
+  int GetButtons() const override;
 
   DISALLOW_COPY_AND_ASSIGN(ObsoleteSystemInfoBarDelegate);
 };
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
index 1993633..0c67302b 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
@@ -89,6 +89,12 @@
   // Fullscreen doesn't always imply immersive mode (see
   // ShouldEnableImmersive()).
   window->SetProperty(ash::kImmersiveImpliedByFullscreen, false);
+  // TODO(https://crbug.com/997480): Determine if all non-resizable windows
+  // should have this behavior, or just the feedback app.
+  if (app_window->extension_id() == extension_misc::kFeedbackExtensionId) {
+    window->SetProperty(ash::kBackdropWindowMode,
+                        ash::BackdropWindowMode::kAutoSemiOpaque);
+  }
   observed_window_.Add(window);
 }
 
diff --git a/chrome/browser/ui/views/chrome_typography.cc b/chrome/browser/ui/views/chrome_typography.cc
index 2a60f42..65c71bf 100644
--- a/chrome/browser/ui/views/chrome_typography.cc
+++ b/chrome/browser/ui/views/chrome_typography.cc
@@ -13,6 +13,23 @@
 
 int GetFontSizeDeltaBoundedByAvailableHeight(int available_height,
                                              int desired_font_size) {
+  int size_delta =
+      GetFontSizeDeltaIgnoringUserOrLocaleSettings(desired_font_size);
+  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+  gfx::FontList base_font = bundle.GetFontListWithDelta(size_delta);
+
+  // Shrink large fonts to ensure they fit. Default fonts should fit already.
+  // TODO(tapted): Move DeriveWithHeightUpperBound() to ui::ResourceBundle to
+  // take advantage of the font cache.
+  int user_or_locale_delta =
+      size_delta + gfx::PlatformFont::kDefaultBaseFontSize - desired_font_size;
+  base_font = base_font.DeriveWithHeightUpperBound(available_height);
+
+  return base_font.GetFontSize() - gfx::PlatformFont::kDefaultBaseFontSize +
+         user_or_locale_delta;
+}
+
+int GetFontSizeDeltaIgnoringUserOrLocaleSettings(int desired_font_size) {
   int size_delta = desired_font_size - gfx::PlatformFont::kDefaultBaseFontSize;
   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
   gfx::FontList base_font = bundle.GetFontListWithDelta(size_delta);
@@ -28,11 +45,6 @@
   }
   DCHECK_EQ(desired_font_size, base_font.GetFontSize());
 
-  // Shrink large fonts to ensure they fit. Default fonts should fit already.
-  // TODO(tapted): Move DeriveWithHeightUpperBound() to ui::ResourceBundle to
-  // take advantage of the font cache.
-  base_font = base_font.DeriveWithHeightUpperBound(available_height);
-
   // To ensure a subsequent request from the ResourceBundle ignores the delta
   // due to user or locale settings, include it here.
   return base_font.GetFontSize() - gfx::PlatformFont::kDefaultBaseFontSize +
@@ -45,13 +57,17 @@
                            gfx::Font::Weight* weight) {
   switch (context) {
     case CONTEXT_TOOLBAR_BUTTON: {
-      // TODO(pbos): Instead of fixing the toolbar button height this way
-      // consider dynamically resizing all of the toolbar based on the actual
-      // final item height.
-      const int height = ui::MaterialDesignController::touch_ui() ? 22 : 17;
-      static const int toolbar_button_delta =
-          GetFontSizeDeltaBoundedByAvailableHeight(height, height);
-      *size_delta = toolbar_button_delta;
+      int height = ui::MaterialDesignController::touch_ui() ? 22 : 17;
+      // We only want the font size to be constrained by available height, and
+      // don't actually have a target font size, so we just need to supply any
+      // sufficiently-large value for the second argument here. |height| will
+      // always be sufficiently large, since dips are smaller than pts.
+      *size_delta = GetFontSizeDeltaBoundedByAvailableHeight(height, height);
+      break;
+    }
+    case CONTEXT_WEB_UI_TAB_COUNTER: {
+      *size_delta = GetFontSizeDeltaIgnoringUserOrLocaleSettings(14);
+      *weight = gfx::Font::Weight::BOLD;
       break;
     }
     case CONTEXT_OMNIBOX_PRIMARY:
diff --git a/chrome/browser/ui/views/chrome_typography.h b/chrome/browser/ui/views/chrome_typography.h
index 6721a75..575c163a 100644
--- a/chrome/browser/ui/views/chrome_typography.h
+++ b/chrome/browser/ui/views/chrome_typography.h
@@ -34,6 +34,9 @@
   // Text of the page title in the tab hover card.
   CONTEXT_TAB_HOVER_CARD_TITLE,
 
+  // Text of the number of tabs in the webui tab counter.
+  CONTEXT_WEB_UI_TAB_COUNTER,
+
   // Text in the location bar entry, and primary text in the omnibox dropdown.
   CONTEXT_OMNIBOX_PRIMARY,
 
@@ -85,6 +88,11 @@
 int GetFontSizeDeltaBoundedByAvailableHeight(int available_height,
                                              int desired_font_size);
 
+// Takes a desired font size and returns the size delta to request from
+// ui::ResourceBundle that will result in exactly that font size, canceling
+// out any font size changes made to account for locale or user settings.
+int GetFontSizeDeltaIgnoringUserOrLocaleSettings(int desired_font_size);
+
 // Sets the |size_delta| and |font_weight| for text that should not be affected
 // by the Harmony spec.
 void ApplyCommonFontStyles(int context,
diff --git a/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc b/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc
index cc2b4e2..3481eb2 100644
--- a/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc
+++ b/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc
@@ -40,7 +40,7 @@
   AddChildView(label_1_);
 
   link_text_ = delegate_ptr->GetLinkText();
-  link_ = CreateLink(link_text_, this);
+  link_ = CreateLink(link_text_);
   AddChildView(link_);
 
   label_2_text_ = message_text.substr(offset);
@@ -92,16 +92,6 @@
   return label_1_width ? label_1_width : link_->GetMinimumSize().width();
 }
 
-void AlternateNavInfoBarView::LinkClicked(views::Link* source,
-                                          int event_flags) {
-  if (!owner())
-    return;  // We're closing; don't call anything, it might access the owner.
-  DCHECK(link_ != NULL);
-  DCHECK_EQ(link_, source);
-  if (GetDelegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags)))
-    RemoveSelf();
-}
-
 AlternateNavInfoBarDelegate* AlternateNavInfoBarView::GetDelegate() {
   return static_cast<AlternateNavInfoBarDelegate*>(delegate());
 }
diff --git a/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.h b/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.h
index 2483d7f..9c69bba 100644
--- a/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.h
+++ b/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.h
@@ -9,13 +9,11 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/views/infobars/infobar_view.h"
-#include "ui/views/controls/link_listener.h"
 
 class AlternateNavInfoBarDelegate;
 
 // An infobar that shows a string with an embedded link.
-class AlternateNavInfoBarView : public InfoBarView,
-                                public views::LinkListener {
+class AlternateNavInfoBarView : public InfoBarView {
  public:
   explicit AlternateNavInfoBarView(
       std::unique_ptr<AlternateNavInfoBarDelegate> delegate);
@@ -35,9 +33,6 @@
   void Layout() override;
   int ContentMinimumWidth() const override;
 
-  // views::LinkListener:
-  void LinkClicked(views::Link* source, int event_flags) override;
-
   AlternateNavInfoBarDelegate* GetDelegate();
 
   base::string16 label_1_text_;
diff --git a/chrome/browser/ui/views/infobars/confirm_infobar.cc b/chrome/browser/ui/views/infobars/confirm_infobar.cc
index 503f0fe..29dad7f 100644
--- a/chrome/browser/ui/views/infobars/confirm_infobar.cc
+++ b/chrome/browser/ui/views/infobars/confirm_infobar.cc
@@ -54,7 +54,7 @@
       cancel_button_->SetProminent(true);
   }
 
-  link_ = CreateLink(delegate_ptr->GetLinkText(), this);
+  link_ = CreateLink(delegate_ptr->GetLinkText());
   AddChildView(link_);
 }
 
@@ -109,14 +109,6 @@
   }
 }
 
-void ConfirmInfoBar::LinkClicked(views::Link* source, int event_flags) {
-  if (!owner())
-    return;  // We're closing; don't call anything, it might access the owner.
-  DCHECK_EQ(link_, source);
-  if (GetDelegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags)))
-    RemoveSelf();
-}
-
 int ConfirmInfoBar::ContentMinimumWidth() const {
   return label_->GetMinimumSize().width() + link_->GetMinimumSize().width() +
          NonLabelWidth();
diff --git a/chrome/browser/ui/views/infobars/confirm_infobar.h b/chrome/browser/ui/views/infobars/confirm_infobar.h
index 81c268c..9ad0b2e 100644
--- a/chrome/browser/ui/views/infobars/confirm_infobar.h
+++ b/chrome/browser/ui/views/infobars/confirm_infobar.h
@@ -9,7 +9,6 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/views/infobars/infobar_view.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
-#include "ui/views/controls/link_listener.h"
 
 class ElevationIconSetter;
 
@@ -22,8 +21,7 @@
 // An infobar that shows a message, up to two optional buttons, and an optional,
 // right-aligned link.  This is commonly used to do things like:
 // "Would you like to do X?  [Yes]  [No]               _Learn More_ [x]"
-class ConfirmInfoBar : public InfoBarView,
-                       public views::LinkListener {
+class ConfirmInfoBar : public InfoBarView {
  public:
   explicit ConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate> delegate);
   ~ConfirmInfoBar() override;
@@ -32,9 +30,6 @@
   void Layout() override;
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
-  // views::LinkListener:
-  void LinkClicked(views::Link* source, int event_flags) override;
-
  protected:
   // InfoBarView:
   int ContentMinimumWidth() const override;
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc
index 8131c5c..73ff07048 100644
--- a/chrome/browser/ui/views/infobars/infobar_view.cc
+++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -259,6 +259,13 @@
   }
 }
 
+void InfoBarView::LinkClicked(views::Link* source, int event_flags) {
+  if (!owner())
+    return;  // We're closing; don't call anything, it might access the owner.
+  if (delegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags)))
+    RemoveSelf();
+}
+
 void InfoBarView::OnWillChangeFocus(View* focused_before, View* focused_now) {
   views::ExternalFocusTracker::OnWillChangeFocus(focused_before, focused_now);
 
@@ -278,11 +285,10 @@
   return label;
 }
 
-views::Link* InfoBarView::CreateLink(const base::string16& text,
-                                     views::LinkListener* listener) const {
+views::Link* InfoBarView::CreateLink(const base::string16& text) {
   views::Link* link = new views::Link(text, CONTEXT_BODY_TEXT_LARGE);
   SetLabelDetails(link);
-  link->set_listener(listener);
+  link->set_listener(this);
   link->SetProperty(kLabelType, LabelType::kLink);
   return link;
 }
diff --git a/chrome/browser/ui/views/infobars/infobar_view.h b/chrome/browser/ui/views/infobars/infobar_view.h
index 2eb006a..435a0b04b 100644
--- a/chrome/browser/ui/views/infobars/infobar_view.h
+++ b/chrome/browser/ui/views/infobars/infobar_view.h
@@ -11,6 +11,7 @@
 #include "components/infobars/core/infobar_container.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/views/controls/button/button.h"
+#include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/menu/menu_types.h"
 #include "ui/views/focus/external_focus_tracker.h"
 
@@ -19,13 +20,13 @@
 class ImageView;
 class Label;
 class Link;
-class LinkListener;
 class MenuRunner;
 }  // namespace views
 
 class InfoBarView : public infobars::InfoBar,
                     public views::View,
                     public views::ButtonListener,
+                    public views::LinkListener,
                     public views::ExternalFocusTracker {
  public:
   explicit InfoBarView(std::unique_ptr<infobars::InfoBarDelegate> delegate);
@@ -48,6 +49,9 @@
   // calls to ButtonPressed() in this case.)
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
+  // views::LinkListener:
+  void LinkClicked(views::Link* source, int event_flags) override;
+
   // views::ExternalFocusTracker:
   void OnWillChangeFocus(View* focused_before, View* focused_now) override;
 
@@ -59,8 +63,7 @@
 
   // Creates a link with the appropriate font and color for an infobar.
   // NOTE: Subclasses must ignore link clicks if we're unowned.
-  views::Link* CreateLink(const base::string16& text,
-                          views::LinkListener* listener) const;
+  views::Link* CreateLink(const base::string16& text);
 
   // Given |views| and the total |available_width| to display them in, sets
   // each view's size so that the longest view shrinks until it reaches the
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 88d87852..559c327a 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -1075,6 +1075,14 @@
   DCHECK(range.IsValid());
   DCHECK(!model()->user_input_in_progress());
 
+  // Do not style the scheme for non-http/https URLs. For such schemes, styling
+  // could be confusing or misleading. For example, the scheme isn't meaningful
+  // in about:blank URLs. Or in blob: or filesystem: URLs, which have an inner
+  // origin, the URL is likely too syntax-y to be able to meaningfully draw
+  // attention to any part of it.
+  if (!controller()->GetLocationBarModel()->GetURL().SchemeIsHTTPOrHTTPS())
+    return;
+
   security_state::SecurityLevel security_level =
       controller()->GetLocationBarModel()->GetSecurityLevel();
 
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 779701d..43ba4ee 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
@@ -1851,9 +1851,9 @@
 void PressEscapeWhileDetachedStep2(const BrowserList* browser_list) {
   ASSERT_EQ(2u, browser_list->size());
   Browser* new_browser = browser_list->get(1);
-  ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
+  ui_controls::SendKeyPress(
       new_browser->window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false,
-      false, false));
+      false, false);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/views/tabs/tab_group_highlight.cc b/chrome/browser/ui/views/tabs/tab_group_highlight.cc
index 2dd97c2..01e92883 100644
--- a/chrome/browser/ui/views/tabs/tab_group_highlight.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_highlight.cc
@@ -23,9 +23,6 @@
 }
 
 void TabGroupHighlight::OnPaint(gfx::Canvas* canvas) {
-  if (!tab_group_views_->ShouldPaintGroupBackground())
-    return;
-
   SetBoundsRect(tab_group_views_->GetBounds());
 
   SkPath path = GetPath();
diff --git a/chrome/browser/ui/views/tabs/tab_group_views.cc b/chrome/browser/ui/views/tabs/tab_group_views.cc
index c88bbc18..ce47f25 100644
--- a/chrome/browser/ui/views/tabs/tab_group_views.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_views.cc
@@ -91,7 +91,3 @@
                                        TabStyle::kSelectedTabOpacity,
                                        SK_AlphaTRANSPARENT, SK_AlphaOPAQUE));
 }
-
-bool TabGroupViews::ShouldPaintGroupBackground() const {
-  return header_->dragging();
-}
diff --git a/chrome/browser/ui/views/tabs/tab_group_views.h b/chrome/browser/ui/views/tabs/tab_group_views.h
index 2d4aa93..05cfa69 100644
--- a/chrome/browser/ui/views/tabs/tab_group_views.h
+++ b/chrome/browser/ui/views/tabs/tab_group_views.h
@@ -49,10 +49,6 @@
   // tab color. Needed to layer painting for the group background highlight.
   SkColor GetGroupBackgroundColor() const;
 
-  // Returns whether the group highlight background should be shown. Currently
-  // it should only be shown if the entire group is dragging via its header.
-  bool ShouldPaintGroupBackground() const;
-
  private:
   TabStrip* const tab_strip_;
   const tab_groups::TabGroupId group_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 58d02869..c13cced5 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -2686,14 +2686,16 @@
 }
 
 void TabStrip::StoppedDraggingView(TabSlotView* view, bool* is_first_view) {
+  if (view &&
+      view->GetTabSlotViewType() == TabSlotView::ViewType::kTabGroupHeader) {
+    // Ensure all tab group UI is repainted, especially the dragging highlight.
+    view->set_dragging(false);
+    SchedulePaint();
+    return;
+  }
+
   int tab_data_index = GetModelIndexOf(view);
   if (tab_data_index == -1) {
-    // Ensure the drag status is updated even if the view is not a valid tab.
-    // This is primarily to make sure group headers are updated correctly.
-    // Otherwise, tab drag status is only updated in PrepareForAnimation().
-    if (view)
-      view->set_dragging(false);
-
     // The tab was removed before the drag completed. Don't do anything.
     return;
   }
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
index a96f99a9..7274bce 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -1230,13 +1230,6 @@
   std::vector<TabGroupViews*> views = ListGroupViews();
   EXPECT_EQ(1u, views.size());
 
-  // Highlights should not be painted by default.
-  EXPECT_FALSE(views[0]->ShouldPaintGroupBackground());
-
-  // Highlights should be painted when the group header is dragging.
-  views[0]->header()->set_dragging(true);
-  EXPECT_TRUE(views[0]->ShouldPaintGroupBackground());
-
   // The highlight bounds match the group view bounds. Grab this manually
   // here, since there isn't a real paint cycle to trigger OnPaint().
   gfx::Rect bounds = views[0]->GetBounds();
diff --git a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
index f2a7792..00e2bbfb 100644
--- a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
+++ b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/chrome_view_class_properties.h"
 #include "chrome/browser/ui/views/feature_promos/feature_promo_colors.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h"
@@ -67,8 +68,12 @@
 
 class TabCounterUpdater : public TabStripModelObserver {
  public:
-  TabCounterUpdater(views::Button* button, views::Label* tab_counter)
-      : button_(button), tab_counter_(tab_counter), animator_(tab_counter) {}
+  TabCounterUpdater(views::Button* button,
+                    views::Label* tab_counter,
+                    views::View* tab_counter_container)
+      : button_(button),
+        tab_counter_(tab_counter),
+        animator_(tab_counter_container) {}
   ~TabCounterUpdater() override = default;
 
   void UpdateCounter(TabStripModel* model) {
@@ -113,6 +118,7 @@
   std::unique_ptr<TabCounterUpdater> counter_updater_;
   views::InkDropContainerView* ink_drop_container_;
   views::Label* label_;
+  views::View* border_;
 };
 
 WebUITabCounterButton::WebUITabCounterButton(views::ButtonListener* listener)
@@ -137,7 +143,7 @@
           : normal_text_color;
 
   label_->SetEnabledColor(current_text_color);
-  label_->SetBorder(views::CreateRoundedRectBorder(
+  border_->SetBorder(views::CreateRoundedRectBorder(
       2,
       views::LayoutProvider::Get()->GetCornerRadiusMetric(
           views::EMPHASIS_MEDIUM),
@@ -189,17 +195,22 @@
   tab_counter->ink_drop_container_ = ink_drop_container;
   ink_drop_container->SetBoundsRect(tab_counter->GetLocalBounds());
 
-  views::Label* label =
-      tab_counter->AddChildView(std::make_unique<views::Label>());
+  views::View* border =
+      tab_counter->AddChildView(std::make_unique<views::View>());
+  tab_counter->border_ = border;
+
+  views::Label* label = border->AddChildView(std::make_unique<views::Label>(
+      base::string16(), CONTEXT_WEB_UI_TAB_COUNTER));
   tab_counter->label_ = label;
 
-  constexpr int kDesiredBorderHeight = 18;
+  constexpr int kDesiredBorderHeight = 22;
   const int inset_height = (button_height - kDesiredBorderHeight) / 2;
-  label->SetBounds(inset_height, inset_height, kDesiredBorderHeight,
-                   kDesiredBorderHeight);
+  border->SetBounds(inset_height, inset_height, kDesiredBorderHeight,
+                    kDesiredBorderHeight);
+  label->SetBounds(0, 0, kDesiredBorderHeight, kDesiredBorderHeight);
 
   tab_counter->counter_updater_ =
-      std::make_unique<TabCounterUpdater>(tab_counter.get(), label);
+      std::make_unique<TabCounterUpdater>(tab_counter.get(), label, border);
   tab_strip_model->AddObserver(tab_counter->counter_updater_.get());
   tab_counter->counter_updater_->UpdateCounter(tab_strip_model);
 
diff --git a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_browsertest.cc
index 9ca1e3b5..61f26374 100644
--- a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_browsertest.cc
@@ -75,7 +75,7 @@
 
  private:
   // content::WebContentsObserver:
-  void DidChangeThemeColor(base::Optional<SkColor> theme_color) override {
+  void DidChangeThemeColor() override {
     observed_ = true;
 
     if (run_loop_.running())
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.cc b/chrome/browser/ui/web_applications/app_browser_controller.cc
index e9c045f..0876c81 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller.cc
@@ -255,8 +255,7 @@
   SetInitialURL(navigation_handle->GetURL());
 }
 
-void AppBrowserController::DidChangeThemeColor(
-    base::Optional<SkColor> theme_color) {
+void AppBrowserController::DidChangeThemeColor() {
   browser_->window()->UpdateFrameColor();
 }
 
@@ -296,7 +295,7 @@
     const TabStripSelectionChange& selection) {
   if (selection.active_tab_changed()) {
     content::WebContentsObserver::Observe(selection.new_contents);
-    DidChangeThemeColor(GetThemeColor());
+    DidChangeThemeColor();
   }
   if (change.type() == TabStripModelChange::kInserted) {
     for (const auto& contents : change.GetInsert()->contents)
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.h b/chrome/browser/ui/web_applications/app_browser_controller.h
index 0fa13250..ce4e365 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.h
+++ b/chrome/browser/ui/web_applications/app_browser_controller.h
@@ -136,7 +136,7 @@
 
   // content::WebContentsObserver:
   void DidStartNavigation(content::NavigationHandle* handle) override;
-  void DidChangeThemeColor(base::Optional<SkColor> theme_color) override;
+  void DidChangeThemeColor() override;
 
   // TabStripModelObserver:
   void OnTabStripModelChanged(
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom
index 3876fea7..c659a35b 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom
@@ -4,6 +4,18 @@
 
 module chromeos.crostini_upgrader.mojom;
 
+enum UpgradePrecheckStatus {
+  // Good to continue
+  OK,
+  // No network connectivity
+  NETWORK_FAILURE,
+  // Battery is low and not charging
+  LOW_POWER,
+  // Not enough space to do the upgrade
+  INSUFFICIENT_SPACE
+};
+
+
 // Lives in the browser process. A renderer uses this to create a page handler
 // for controlling Crostini upgrade.
 interface PageHandlerFactory {
@@ -17,6 +29,9 @@
 interface PageHandler {
   // Backup the existing container.
   Backup();
+  // Start running upgrade prechecks. Result is asynchronously
+  // returned via Page::PrecheckStatus.
+  StartPrechecks();
   // Start upgrade
   Upgrade();
   // Cancel an on-going upgrade
@@ -43,6 +58,8 @@
   OnBackupSucceeded();
   // This is called when the backup failed.
   OnBackupFailed();
+  // Handle the result of the prechecks.
+  PrecheckStatus(UpgradePrecheckStatus status);
   // Callback to receive the upgrade progress once the upgrade has started.
   OnUpgradeProgress(array<string> progress_messages);
   // This is called when the upgrade succeeded.
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
index 63baa53..4570d41 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
@@ -34,6 +34,10 @@
   upgrader_ui_delegate_->Backup();
 }
 
+void CrostiniUpgraderPageHandler::StartPrechecks() {
+  upgrader_ui_delegate_->StartPrechecks();
+}
+
 void CrostiniUpgraderPageHandler::Upgrade() {
   upgrader_ui_delegate_->Upgrade(
       crostini::ContainerId(crostini::kCrostiniDefaultVmName,
@@ -81,6 +85,11 @@
   page_->OnBackupFailed();
 }
 
+void CrostiniUpgraderPageHandler::PrecheckStatus(
+    chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus status) {
+  page_->PrecheckStatus(status);
+}
+
 void CrostiniUpgraderPageHandler::OnCanceled() {
   page_->OnCanceled();
 }
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h
index 1fbe60c..98f9ff1 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h
@@ -33,6 +33,7 @@
 
   // chromeos::crostini_upgrader::mojom::PageHandler:
   void Backup() override;
+  void StartPrechecks() override;
   void Upgrade() override;
   void Cancel() override;
   void CancelBeforeStart() override;
@@ -43,6 +44,8 @@
   void OnBackupProgress(int percent) override;
   void OnBackupSucceeded() override;
   void OnBackupFailed() override;
+  void PrecheckStatus(chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus
+                          status) override;
   void OnUpgradeProgress(const std::vector<std::string>& messages) override;
   void OnUpgradeSucceeded() override;
   void OnUpgradeFailed() override;
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
index 3622c831..6ab1872 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
@@ -22,6 +22,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/bytes_formatting.h"
 #include "ui/chromeos/devicetype_utils.h"
 #include "ui/resources/grit/webui_resources.h"
 #include "ui/strings/grit/ui_strings.h"
@@ -38,6 +39,7 @@
 void AddStringResources(content::WebUIDataSource* source) {
   static constexpr webui::LocalizedString kStrings[] = {
       {"upgrade", IDS_CROSTINI_UPGRADER_UPGRADE_BUTTON},
+      {"retry", IDS_CROSTINI_INSTALLER_RETRY_BUTTON},
       {"close", IDS_APP_CLOSE},
       {"cancel", IDS_APP_CANCEL},
       {"launch", IDS_CROSTINI_UPGRADER_LAUNCH_BUTTON},
@@ -46,11 +48,15 @@
       {"promptTitle", IDS_CROSTINI_UPGRADER_TITLE},
       {"backingUpTitle", IDS_CROSTINI_UPGRADER_BACKING_UP_TITLE},
       {"backupSucceededTitle", IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_TITLE},
+      {"prechecksFailedTitle", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_TITLE},
       {"upgradingTitle", IDS_CROSTINI_UPGRADER_UPGRADING_TITLE},
       {"succeededTitle", IDS_CROSTINI_UPGRADER_SUCCEEDED_TITLE},
       {"cancelingTitle", IDS_CROSTINI_UPGRADER_CANCELING_TITLE},
       {"errorTitle", IDS_CROSTINI_UPGRADER_ERROR_TITLE},
 
+      {"precheckNoNetwork", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_NETWORK},
+      {"precheckNoPower", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_POWER},
+
       {"promptMessage", IDS_CROSTINI_UPGRADER_BODY},
       {"backingUpMessage", IDS_CROSTINI_UPGRADER_BACKING_UP_MESSAGE},
       {"backupSucceededMessage",
@@ -71,6 +77,12 @@
   source->AddString("offlineError",
                     l10n_util::GetStringFUTF8(
                         IDS_CROSTINI_INSTALLER_OFFLINE_ERROR, device_name));
+  source->AddString("precheckNoSpace",
+                    l10n_util::GetStringFUTF8(
+                        IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_SPACE,
+                        ui::FormatBytesWithUnits(
+                            crostini::CrostiniUpgrader::kDiskRequired,
+                            ui::DATA_UNITS_GIBIBYTE, /*show_units=*/true)));
 }
 
 CrostiniUpgraderUI::CrostiniUpgraderUI(content::WebUI* web_ui)
diff --git a/chrome/browser/ui/webui/components/components_handler.cc b/chrome/browser/ui/webui/components/components_handler.cc
index 806c9f50..1f1381b 100644
--- a/chrome/browser/ui/webui/components/components_handler.cc
+++ b/chrome/browser/ui/webui/components/components_handler.cc
@@ -6,12 +6,15 @@
 
 #include "base/bind.h"
 #include "base/values.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/update_client/crx_update_item.h"
 #include "ui/base/l10n/l10n_util.h"
 
-ComponentsHandler::ComponentsHandler() = default;
+ComponentsHandler::ComponentsHandler(
+    component_updater::ComponentUpdateService* component_updater)
+    : component_updater_(component_updater) {
+  DCHECK(component_updater_);
+}
 ComponentsHandler::~ComponentsHandler() = default;
 
 void ComponentsHandler::RegisterMessages() {
@@ -26,7 +29,7 @@
 }
 
 void ComponentsHandler::OnJavascriptAllowed() {
-  observer_.Add(g_browser_process->component_updater());
+  observer_.Add(component_updater_);
 }
 
 void ComponentsHandler::OnJavascriptDisallowed() {
@@ -67,9 +70,8 @@
   parameters.SetString("event", ComponentEventToString(event));
   if (!id.empty()) {
     if (event == Events::COMPONENT_UPDATED) {
-      auto* component_updater = g_browser_process->component_updater();
       update_client::CrxUpdateItem item;
-      if (component_updater->GetComponentDetails(id, &item) && item.component)
+      if (component_updater_->GetComponentDetails(id, &item) && item.component)
         parameters.SetString("version", item.component->version.GetString());
     }
     parameters.SetString("id", id);
@@ -133,29 +135,21 @@
   return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
 }
 
-// static
 void ComponentsHandler::OnDemandUpdate(const std::string& component_id) {
-  component_updater::ComponentUpdateService* cus =
-      g_browser_process->component_updater();
-  if (cus) {  // TODO(dbeam): can this return nullptr if called from UI thread?
-    cus->GetOnDemandUpdater().OnDemandUpdate(
-        component_id, component_updater::OnDemandUpdater::Priority::FOREGROUND,
-        component_updater::Callback());
-  }
+  component_updater_->GetOnDemandUpdater().OnDemandUpdate(
+      component_id, component_updater::OnDemandUpdater::Priority::FOREGROUND,
+      component_updater::Callback());
 }
 
-// static
 std::unique_ptr<base::ListValue> ComponentsHandler::LoadComponents() {
-  component_updater::ComponentUpdateService* cus =
-      g_browser_process->component_updater();
   std::vector<std::string> component_ids;
-  component_ids = cus->GetComponentIDs();
+  component_ids = component_updater_->GetComponentIDs();
 
   // Construct DictionaryValues to return to UI.
   auto component_list = std::make_unique<base::ListValue>();
   for (size_t j = 0; j < component_ids.size(); ++j) {
     update_client::CrxUpdateItem item;
-    if (cus->GetComponentDetails(component_ids[j], &item)) {
+    if (component_updater_->GetComponentDetails(component_ids[j], &item)) {
       auto component_entry = std::make_unique<base::DictionaryValue>();
       component_entry->SetString("id", component_ids[j]);
       component_entry->SetString("status", ServiceStatusToString(item.state));
diff --git a/chrome/browser/ui/webui/components/components_handler.h b/chrome/browser/ui/webui/components/components_handler.h
index 7041edcb..5ed5d43 100644
--- a/chrome/browser/ui/webui/components/components_handler.h
+++ b/chrome/browser/ui/webui/components/components_handler.h
@@ -22,7 +22,8 @@
 class ComponentsHandler : public content::WebUIMessageHandler,
                           public component_updater::ServiceObserver {
  public:
-  ComponentsHandler();
+  ComponentsHandler(
+      component_updater::ComponentUpdateService* component_updater);
   ComponentsHandler(const ComponentsHandler&) = delete;
   ComponentsHandler& operator=(const ComponentsHandler&) = delete;
   ~ComponentsHandler() override;
@@ -45,8 +46,12 @@
   static base::string16 ComponentEventToString(Events event);
   static base::string16 ServiceStatusToString(
       update_client::ComponentState state);
-  static std::unique_ptr<base::ListValue> LoadComponents();
-  static void OnDemandUpdate(const std::string& component_id);
+
+  std::unique_ptr<base::ListValue> LoadComponents();
+  void OnDemandUpdate(const std::string& component_id);
+
+  // Weak pointer; injected for testing.
+  component_updater::ComponentUpdateService* const component_updater_;
 
   ScopedObserver<component_updater::ComponentUpdateService,
                  component_updater::ComponentUpdateService::Observer>
diff --git a/chrome/browser/ui/webui/components/components_handler_unittest.cc b/chrome/browser/ui/webui/components/components_handler_unittest.cc
new file mode 100644
index 0000000..6f480a6
--- /dev/null
+++ b/chrome/browser/ui/webui/components/components_handler_unittest.cc
@@ -0,0 +1,34 @@
+// Copyright 2019 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/webui/components/components_handler.h"
+
+#include "components/component_updater/mock_component_updater_service.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class TestComponentsHandler : public ComponentsHandler {
+ public:
+  TestComponentsHandler(
+      component_updater::ComponentUpdateService* component_update_service)
+      : ComponentsHandler(component_update_service) {
+    set_web_ui(&test_web_ui_);
+  }
+
+ private:
+  content::TestWebUI test_web_ui_;
+};
+
+TEST(ComponentsHandlerTest, RemovesObserver) {
+  testing::NiceMock<component_updater::MockComponentUpdateService> mock_service;
+  EXPECT_CALL(mock_service, AddObserver(testing::_)).Times(1);
+  EXPECT_CALL(mock_service, RemoveObserver(testing::_)).Times(1);
+
+  {
+    TestComponentsHandler handler(&mock_service);
+    base::ListValue args;
+    args.AppendString("unused");
+    handler.HandleRequestComponentsData(&args);
+  }
+}
diff --git a/chrome/browser/ui/webui/components/components_ui.cc b/chrome/browser/ui/webui/components/components_ui.cc
index df9879b..09fce49 100644
--- a/chrome/browser/ui/webui/components/components_ui.cc
+++ b/chrome/browser/ui/webui/components/components_ui.cc
@@ -77,7 +77,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 ComponentsUI::ComponentsUI(content::WebUI* web_ui) : WebUIController(web_ui) {
-  web_ui->AddMessageHandler(std::make_unique<ComponentsHandler>());
+  web_ui->AddMessageHandler(std::make_unique<ComponentsHandler>(
+      g_browser_process->component_updater()));
 
   // Set up the chrome://components/ source.
   Profile* profile = Profile::FromWebUI(web_ui);
diff --git a/chrome/browser/ui/webui/new_tab_page/BUILD.gn b/chrome/browser/ui/webui/new_tab_page/BUILD.gn
index f7c9b7f..a7f3d9d3 100644
--- a/chrome/browser/ui/webui/new_tab_page/BUILD.gn
+++ b/chrome/browser/ui/webui/new_tab_page/BUILD.gn
@@ -10,6 +10,7 @@
   ]
 
   public_deps = [
+    "//mojo/public/mojom/base",
     "//skia/public/mojom",
     "//url/mojom:url_mojom_gurl",
   ]
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
index a4d5936..c6c27842 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
@@ -6,9 +6,11 @@
 
 import "skia/public/mojom/skcolor.mojom";
 import "url/mojom/url.mojom";
+import "mojo/public/mojom/base/text_direction.mojom";
 
 struct MostVisitedTile {
   string title;
+  mojo_base.mojom.TextDirection title_direction;
   url.mojom.Url url;
 };
 
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
index bb44526..2d78284 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h"
 
 #include "base/bind.h"
+#include "base/i18n/rtl.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -223,7 +224,14 @@
       sections.at(ntp_tiles::SectionType::PERSONALIZED);
   for (const ntp_tiles::NTPTile& tile : tiles) {
     auto value = new_tab_page::mojom::MostVisitedTile::New();
-    value->title = base::UTF16ToUTF8(tile.title);
+    if (tile.title.empty()) {
+      value->title = tile.url.spec();
+      value->title_direction = base::i18n::LEFT_TO_RIGHT;
+    } else {
+      value->title = base::UTF16ToUTF8(tile.title);
+      value->title_direction =
+          base::i18n::GetFirstStrongCharacterDirection(tile.title);
+    }
     value->url = tile.url;
     list.push_back(std::move(value));
   }
diff --git a/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc
new file mode 100644
index 0000000..2a8a69eb
--- /dev/null
+++ b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc
@@ -0,0 +1,48 @@
+// Copyright 2019 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/webui/print_preview/fake_print_render_frame.h"
+
+#include <utility>
+
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+
+namespace printing {
+
+FakePrintRenderFrame::FakePrintRenderFrame(
+    blink::AssociatedInterfaceProvider* provider) {
+  provider->OverrideBinderForTesting(
+      mojom::PrintRenderFrame::Name_,
+      base::BindRepeating(&FakePrintRenderFrame::BindPrintRenderFrameReceiver,
+                          base::Unretained(this)));
+}
+
+FakePrintRenderFrame::~FakePrintRenderFrame() = default;
+
+void FakePrintRenderFrame::PrintRequestedPages() {}
+
+void FakePrintRenderFrame::PrintForSystemDialog() {}
+
+void FakePrintRenderFrame::InitiatePrintPreview(
+    mojo::PendingAssociatedRemote<mojom::PrintRenderer> print_renderer,
+    bool has_selection) {}
+
+void FakePrintRenderFrame::PrintPreview(base::Value settings) {}
+
+void FakePrintRenderFrame::OnPrintPreviewDialogClosed() {}
+
+void FakePrintRenderFrame::PrintFrameContent(
+    mojom::PrintFrameContentParamsPtr params) {}
+
+void FakePrintRenderFrame::PrintingDone(bool success) {}
+
+void FakePrintRenderFrame::SetPrintingEnabled(bool enabled) {}
+
+void FakePrintRenderFrame::BindPrintRenderFrameReceiver(
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  receiver_.Bind(mojo::PendingAssociatedReceiver<mojom::PrintRenderFrame>(
+      std::move(handle)));
+}
+
+}  // namespace printing
diff --git a/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h
new file mode 100644
index 0000000..b45a498
--- /dev/null
+++ b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h
@@ -0,0 +1,45 @@
+// Copyright 2019 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_WEBUI_PRINT_PREVIEW_FAKE_PRINT_RENDER_FRAME_H_
+#define CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_FAKE_PRINT_RENDER_FRAME_H_
+
+#include "base/values.h"
+#include "components/printing/common/print.mojom.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+
+namespace printing {
+
+// This class implements a PrintRenderFrame that can be attached to an
+// AssociatedInterfaceProvider to intercept requests from the browser for unit
+// tests.
+class FakePrintRenderFrame : public mojom::PrintRenderFrame {
+ public:
+  explicit FakePrintRenderFrame(blink::AssociatedInterfaceProvider* provider);
+  ~FakePrintRenderFrame() override;
+
+ private:
+  // printing::mojom::PrintRenderFrame:
+  void PrintRequestedPages() override;
+  void PrintForSystemDialog() override;
+  void InitiatePrintPreview(
+      mojo::PendingAssociatedRemote<mojom::PrintRenderer> print_renderer,
+      bool has_selection) override;
+  void PrintPreview(base::Value settings) override;
+  void OnPrintPreviewDialogClosed() override;
+  void PrintFrameContent(mojom::PrintFrameContentParamsPtr params) override;
+  void PrintingDone(bool success) override;
+  void SetPrintingEnabled(bool enabled) override;
+
+  void BindPrintRenderFrameReceiver(mojo::ScopedInterfaceEndpointHandle handle);
+
+  mojo::AssociatedReceiver<mojom::PrintRenderFrame> receiver_{this};
+};
+
+}  // namespace printing
+
+#endif  // CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_FAKE_PRINT_RENDER_FRAME_H_
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 8bad53bf..dd3d333a 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -62,7 +62,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/printing/browser/printer_capabilities.h"
 #include "components/printing/common/cloud_print_cdd_conversion.h"
-#include "components/printing/common/print_messages.h"
 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
 #include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
 #include "components/url_formatter/url_formatter.h"
@@ -77,6 +76,7 @@
 #include "printing/backend/print_backend_consts.h"
 #include "printing/buildflags/buildflags.h"
 #include "printing/print_settings.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/icu/source/i18n/unicode/ulocdata.h"
 
 #if defined(OS_CHROMEOS)
@@ -839,8 +839,10 @@
 
   VLOG(1) << "Print preview request start";
 
-  rfh->Send(new PrintMsg_PrintPreview(
-      rfh->GetRoutingID(), static_cast<base::DictionaryValue&>(settings)));
+  if (!print_render_frame_.is_bound())
+    rfh->GetRemoteAssociatedInterfaces()->GetInterface(&print_render_frame_);
+
+  print_render_frame_->PrintPreview(settings.Clone());
   last_preview_settings_ = std::move(settings);
 }
 
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
index 4c5948a..ab2dcac 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -18,8 +18,10 @@
 #include "base/timer/timer.h"
 #include "chrome/common/buildflags.h"
 #include "components/prefs/pref_service.h"
+#include "components/printing/common/print.mojom.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "content/public/browser/web_ui_message_handler.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "printing/backend/print_backend.h"
 #include "printing/buildflags/buildflags.h"
 #include "printing/print_job_constants.h"
@@ -367,6 +369,9 @@
   // Set of printer types on the deny list.
   base::flat_set<PrinterType> printer_type_deny_list_;
 
+  // Used to transmit mojo interface method calls to the associated receiver.
+  mojo::AssociatedRemote<mojom::PrintRenderFrame> print_render_frame_;
+
   base::WeakPtrFactory<PrintPreviewHandler> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(PrintPreviewHandler);
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
index 5b8918b..3dc50ab 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -15,13 +15,16 @@
 #include "base/json/json_writer.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/optional.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/icu_test_util.h"
 #include "base/values.h"
 #include "chrome/browser/printing/print_test_utils.h"
 #include "chrome/browser/printing/print_view_manager.h"
+#include "chrome/browser/ui/webui/print_preview/fake_print_render_frame.h"
 #include "chrome/browser/ui/webui/print_preview/policy_settings.h"
 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
 #include "chrome/browser/ui/webui/print_preview/printer_handler.h"
@@ -29,16 +32,13 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
-#include "components/printing/common/print_messages.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui_controller.h"
 #include "content/public/test/browser_task_environment.h"
-#include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_web_ui.h"
-#include "ipc/ipc_test_sink.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace printing {
@@ -208,6 +208,31 @@
   DISALLOW_COPY_AND_ASSIGN(FakePrintPreviewUI);
 };
 
+class TestPrintPreviewPrintRenderFrame : public FakePrintRenderFrame {
+ public:
+  explicit TestPrintPreviewPrintRenderFrame(
+      blink::AssociatedInterfaceProvider* provider)
+      : FakePrintRenderFrame(provider) {}
+
+  ~TestPrintPreviewPrintRenderFrame() final = default;
+
+  const base::Value& GetSettings() { return settings_; }
+
+  void SetCompletionClosure(base::OnceClosure closure) {
+    closure_ = std::move(closure);
+  }
+
+ private:
+  // FakePrintRenderFrame:
+  void PrintPreview(base::Value settings) final {
+    settings_ = std::move(settings);
+    std::move(closure_).Run();
+  }
+
+  base::OnceClosure closure_;
+  base::Value settings_;
+};
+
 class TestPrintPreviewHandler : public PrintPreviewHandler {
  public:
   TestPrintPreviewHandler(std::unique_ptr<PrinterHandler> printer_handler,
@@ -502,28 +527,10 @@
     }
   }
 
-  IPC::TestSink& initiator_sink() {
-    content::RenderFrameHost* rfh = initiator_web_contents_->GetMainFrame();
-    auto* rph = static_cast<content::MockRenderProcessHost*>(rfh->GetProcess());
-    return rph->sink();
-  }
-
-  IPC::TestSink& preview_sink() {
-    content::RenderFrameHost* rfh = preview_web_contents_->GetMainFrame();
-    auto* rph = static_cast<content::MockRenderProcessHost*>(rfh->GetProcess());
-    return rph->sink();
-  }
-
-  base::DictionaryValue VerifyPreviewMessage() {
-    // Verify that the preview was requested from the renderer
-    EXPECT_TRUE(
-        initiator_sink().GetUniqueMessageMatching(PrintMsg_PrintPreview::ID));
-    const IPC::Message* msg =
-        initiator_sink().GetFirstMessageMatching(PrintMsg_PrintPreview::ID);
-    EXPECT_TRUE(msg);
-    PrintMsg_PrintPreview::Param param;
-    PrintMsg_PrintPreview::Read(msg, &param);
-    return std::move(std::get<0>(param));
+  blink::AssociatedInterfaceProvider*
+  GetInitiatorAssociatedInterfaceProvider() {
+    return initiator_web_contents_->GetMainFrame()
+        ->GetRemoteAssociatedInterfaces();
   }
 
   const Profile* profile() { return profile_.get(); }
@@ -837,14 +844,21 @@
 TEST_F(PrintPreviewHandlerTest, GetPreview) {
   Initialize();
 
+  base::RunLoop run_loop;
+  TestPrintPreviewPrintRenderFrame print_render_frame(
+      GetInitiatorAssociatedInterfaceProvider());
+  print_render_frame.SetCompletionClosure(
+      base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
+
   base::Value print_ticket = GetPrintPreviewTicket();
   std::unique_ptr<base::ListValue> list_args =
       ConstructPreviewArgs("test-callback-id-1", print_ticket);
   handler()->HandleGetPreview(list_args.get());
+  run_loop.Run();
 
   // Verify that the preview was requested from the renderer with the
   // appropriate settings.
-  base::DictionaryValue preview_params = VerifyPreviewMessage();
+  const base::Value& preview_params = print_render_frame.GetSettings();
   bool preview_id_found = false;
   for (const auto& it : preview_params.DictItems()) {
     if (it.first == kPreviewUIID) {  // This is added by the handler.
@@ -861,12 +875,19 @@
 TEST_F(PrintPreviewHandlerTest, SendPreviewUpdates) {
   Initialize();
 
+  base::RunLoop run_loop;
+  TestPrintPreviewPrintRenderFrame print_render_frame(
+      GetInitiatorAssociatedInterfaceProvider());
+  print_render_frame.SetCompletionClosure(
+      base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
+
   const char callback_id_in[] = "test-callback-id-1";
   base::Value print_ticket = GetPrintPreviewTicket();
   std::unique_ptr<base::ListValue> list_args =
       ConstructPreviewArgs(callback_id_in, print_ticket);
   handler()->HandleGetPreview(list_args.get());
-  base::DictionaryValue preview_params = VerifyPreviewMessage();
+  run_loop.Run();
+  const base::Value& preview_params = print_render_frame.GetSettings();
 
   // Read the preview UI ID and request ID
   base::Optional<int> request_value =
diff --git a/chrome/browser/updates/update_notification_service.h b/chrome/browser/updates/update_notification_service.h
index 8fffa64..21b8311 100644
--- a/chrome/browser/updates/update_notification_service.h
+++ b/chrome/browser/updates/update_notification_service.h
@@ -21,6 +21,9 @@
   // Try yo schedule an update notification.
   virtual void Schedule(UpdateNotificationInfo data) = 0;
 
+  // Validate the notification is ready to show.
+  virtual bool IsReadyToDisplay() const = 0;
+
   ~UpdateNotificationService() override = default;
 
  protected:
diff --git a/chrome/browser/updates/update_notification_service_bridge.cc b/chrome/browser/updates/update_notification_service_bridge.cc
index 09f3614..1c42630 100644
--- a/chrome/browser/updates/update_notification_service_bridge.cc
+++ b/chrome/browser/updates/update_notification_service_bridge.cc
@@ -56,4 +56,18 @@
              : (base::make_optional(base::Time::FromJavaTime(timestamp)));
 }
 
+void UpdateThrottleInterval(base::TimeDelta interval) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_UpdateNotificationServiceBridge_updateThrottleInterval(
+      env, interval.InMilliseconds());
+}
+
+base::Optional<base::TimeDelta> GetThrottleInterval() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  auto interval = Java_UpdateNotificationServiceBridge_getThrottleInterval(env);
+  return interval == 0 ? base::nullopt
+                       : (base::make_optional(
+                             base::TimeDelta::FromMilliseconds(interval)));
+}
+
 }  // namespace updates
diff --git a/chrome/browser/updates/update_notification_service_bridge.h b/chrome/browser/updates/update_notification_service_bridge.h
index 1ecfb4c..92350a8 100644
--- a/chrome/browser/updates/update_notification_service_bridge.h
+++ b/chrome/browser/updates/update_notification_service_bridge.h
@@ -17,7 +17,14 @@
 
 // Return persisted timestamp of last shown notification from Android shared
 // preference. Return nullopt if there is no data.
-base::Optional<base::Time> GetLastShownTimestamp();
+base::Optional<base::Time> GetLastShownTimeStamp();
+
+// Updates and persists |interval| in Android shared preference.
+void UpdateThrottleInterval(base::TimeDelta interval);
+
+// Return persisted interval that might be throttled from Android shared
+// preference. Return nullopt if there is no data.
+base::Optional<base::TimeDelta> GetThrottleInterval();
 
 }  // namespace updates
 
diff --git a/chrome/browser/updates/update_notification_service_impl.cc b/chrome/browser/updates/update_notification_service_impl.cc
index a4ae6b6..bbfdaff 100644
--- a/chrome/browser/updates/update_notification_service_impl.cc
+++ b/chrome/browser/updates/update_notification_service_impl.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/notifications/scheduler/public/schedule_service_utils.h"
 #include "chrome/browser/updates/update_notification_config.h"
 #include "chrome/browser/updates/update_notification_info.h"
+#include "chrome/browser/updates/update_notification_service_bridge.h"
 
 namespace updates {
 namespace {
@@ -46,6 +47,24 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(data)));
 }
 
+bool UpdateNotificationServiceImpl::IsReadyToDisplay() const {
+  if (config_->is_enabled)
+    return false;
+
+  auto last_shown_timestamp = updates::GetLastShownTimeStamp();
+  if (last_shown_timestamp.has_value()) {
+    return (GetThrottleInterval() <
+            base::Time::Now() - last_shown_timestamp.value());
+  }
+  return true;
+}
+
+base::TimeDelta UpdateNotificationServiceImpl::GetThrottleInterval() const {
+  auto throttle_interval = updates::GetThrottleInterval();
+  return throttle_interval.has_value() ? throttle_interval.value()
+                                       : config_->default_interval;
+}
+
 void UpdateNotificationServiceImpl::OnClientOverviewQueried(
     UpdateNotificationInfo data,
     notifications::ClientOverview overview) {
diff --git a/chrome/browser/updates/update_notification_service_impl.h b/chrome/browser/updates/update_notification_service_impl.h
index ed1b368..b988185 100644
--- a/chrome/browser/updates/update_notification_service_impl.h
+++ b/chrome/browser/updates/update_notification_service_impl.h
@@ -32,6 +32,8 @@
   // UpdateNotificationService implementation.
   void Schedule(UpdateNotificationInfo data) override;
 
+  bool IsReadyToDisplay() const override;
+
   // Called after querying the |ClientOverview| struct from scheduler system
   // completed.
   void OnClientOverviewQueried(UpdateNotificationInfo data,
@@ -40,6 +42,10 @@
   // Build notification ScheduleParams for update notification.
   notifications::ScheduleParams BuildScheduleParams();
 
+  // Return throttle interval from Android shared preference if exists,
+  // otherwise return the default interval from config.
+  base::TimeDelta GetThrottleInterval() const;
+
   // Used to schedule notification to show in the future. Must outlive this
   // class.
   notifications::NotificationScheduleService* schedule_service_;
diff --git a/chrome/browser/vr/testapp/vr_testapp.cc b/chrome/browser/vr/testapp/vr_testapp.cc
index f4929f5..8c4f0723 100644
--- a/chrome/browser/vr/testapp/vr_testapp.cc
+++ b/chrome/browser/vr/testapp/vr_testapp.cc
@@ -233,8 +233,8 @@
   }
 
   is_configuring_ = true;
-  delegate_->GetDisplays(base::BindRepeating(&WindowManager::OnDisplaysAquired,
-                                             base::Unretained(this)));
+  delegate_->GetDisplays(base::BindOnce(&WindowManager::OnDisplaysAquired,
+                                        base::Unretained(this)));
 }
 
 void WindowManager::OnDisplaySnapshotsInvalidated() {}
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 3b8b908..da730126 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -119,6 +119,7 @@
     "test/web_app_install_observer.h",
     "test/web_app_registration_waiter.cc",
     "test/web_app_registration_waiter.h",
+    "test/web_app_test.cc",
     "test/web_app_test.h",
   ]
 
diff --git a/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc
index 95c935e..68d291e 100644
--- a/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc
@@ -22,11 +22,13 @@
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
 #include "chrome/browser/web_applications/components/web_app_tab_helper.h"
+#include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/skia/include/core/SkColor.h"
 
@@ -96,14 +98,24 @@
 
 }  // namespace
 
-class ManifestUpdateManagerBrowserTest : public InProcessBrowserTest {
+class ManifestUpdateManagerBrowserTest
+    : public InProcessBrowserTest,
+      public ::testing::WithParamInterface<ProviderType> {
  public:
   ManifestUpdateManagerBrowserTest() = default;
   ~ManifestUpdateManagerBrowserTest() override = default;
 
   void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeature(
-        features::kDesktopPWAsLocalUpdating);
+    if (GetParam() == ProviderType::kWebApps) {
+      scoped_feature_list_.InitWithFeatures(
+          {features::kDesktopPWAsLocalUpdating,
+           features::kDesktopPWAsWithoutExtensions},
+          {});
+    } else if (GetParam() == ProviderType::kBookmarkApps) {
+      scoped_feature_list_.InitWithFeatures(
+          {features::kDesktopPWAsLocalUpdating},
+          {features::kDesktopPWAsWithoutExtensions});
+    }
 
     http_server_.AddDefaultHandlers(GetChromeTestDataDir());
     http_server_.RegisterRequestHandler(base::BindRepeating(
@@ -224,7 +236,7 @@
   DISALLOW_COPY_AND_ASSIGN(ManifestUpdateManagerBrowserTest);
 };
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckOutOfScopeNavigation) {
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL(), nullptr),
             ManifestUpdateResult::kNoAppInScope);
@@ -237,7 +249,7 @@
   histogram_tester_.ExpectTotalCount(kUpdateHistogramName, 0);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest, CheckIsThrottled) {
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest, CheckIsThrottled) {
   constexpr base::TimeDelta kDelayBetweenChecks = base::TimeDelta::FromDays(1);
   base::Time time_override = base::Time::UnixEpoch();
   SetTimeOverride(time_override);
@@ -272,7 +284,7 @@
                                       ManifestUpdateResult::kAppUpToDate, 3);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckCancelledByWebContentsDestroyed) {
   AppId app_id = InstallWebApp();
   GetManifestUpdateManager(browser()).hang_update_checks_for_testing();
@@ -287,7 +299,7 @@
       kUpdateHistogramName, ManifestUpdateResult::kWebContentsDestroyed, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckCancelledByAppUninstalled) {
   AppId app_id = InstallWebApp();
   GetManifestUpdateManager(browser()).hang_update_checks_for_testing();
@@ -303,7 +315,7 @@
                                       ManifestUpdateResult::kAppUninstalled, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresWhitespaceDifferences) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -325,7 +337,7 @@
                                       ManifestUpdateResult::kAppUpToDate, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresNameChange) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -347,7 +359,7 @@
                                       ManifestUpdateResult::kAppUpToDate, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresShortNameChange) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -371,7 +383,7 @@
                                       ManifestUpdateResult::kAppUpToDate, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresStartUrlChange) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -392,7 +404,7 @@
                                       ManifestUpdateResult::kAppUpToDate, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresNoManifestChange) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -411,7 +423,7 @@
                                       ManifestUpdateResult::kAppUpToDate, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresInvalidManifest) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -433,7 +445,7 @@
                                       ManifestUpdateResult::kAppNotEligible, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresNonLocalApps) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -458,7 +470,7 @@
   histogram_tester_.ExpectTotalCount(kUpdateHistogramName, 0);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckIgnoresPlaceholderApps) {
   // Set up app URL to redirect to force placeholder app to install.
   const GURL app_url = GetAppURL();
@@ -499,7 +511,7 @@
       kUpdateHistogramName, ManifestUpdateResult::kAppIsPlaceholder, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckFindsThemeColorChange) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -523,7 +535,7 @@
   EXPECT_EQ(GetProvider().registrar().GetAppThemeColor(app_id), SK_ColorRED);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest, CheckKeepsSameName) {
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest, CheckKeepsSameName) {
   constexpr char kManifestTemplate[] = R"(
     {
       "name": "$1",
@@ -551,7 +563,7 @@
   EXPECT_EQ(GetProvider().registrar().GetAppShortName(app_id), "App name 1");
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckFindsIconUrlChange) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -572,7 +584,7 @@
                                       ManifestUpdateResult::kAppUpdated, 1);
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckUpdatedPolicyAppsNotUninstallable) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -601,7 +613,7 @@
       GetProvider().install_finalizer().CanUserUninstallFromSync(app_id));
 }
 
-IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest,
                        CheckFindsScopeChange) {
   constexpr char kManifestTemplate[] = R"(
     {
@@ -624,4 +636,9 @@
             http_server_.GetURL("/"));
 }
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         ManifestUpdateManagerBrowserTest,
+                         ::testing::Values(ProviderType::kBookmarkApps,
+                                           ProviderType::kWebApps),
+                         ProviderTypeParamToString);
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_shortcut.cc b/chrome/browser/web_applications/components/web_app_shortcut.cc
index c0a45c3..de3fb6c 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut.cc
+++ b/chrome/browser/web_applications/components/web_app_shortcut.cc
@@ -16,6 +16,14 @@
 #include "chrome/common/chrome_constants.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "extensions/grit/extensions_browser_resources.h"
+#include "skia/ext/image_operations.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image_skia.h"
+
+#if defined(OS_WIN)
+#include "ui/gfx/icon_util.h"
+#endif
 
 using content::BrowserThread;
 
@@ -23,6 +31,25 @@
 
 namespace {
 
+#if defined(OS_MACOSX)
+const int kDesiredIconSizesForShortcut[] = {16, 32, 128, 256, 512};
+const size_t kNumDesiredIconSizesForShortcut =
+    base::size(kDesiredIconSizesForShortcut);
+#elif defined(OS_LINUX)
+// Linux supports icons of any size. FreeDesktop Icon Theme Specification states
+// that "Minimally you should install a 48x48 icon in the hicolor theme."
+const int kDesiredIconSizesForShortcut[] = {16, 32, 48, 128, 256, 512};
+const size_t kNumDesiredIconSizesForShortcut =
+    base::size(kDesiredIconSizesForShortcut);
+#elif defined(OS_WIN)
+const int* kDesiredIconSizesForShortcut = IconUtil::kIconDimensions;
+const size_t kNumDesiredIconSizesForShortcut = IconUtil::kNumIconDimensions;
+#else
+const int kDesiredIconSizesForShortcut[] = {32};
+const size_t kNumDesiredIconSizesForShortcut =
+    base::size(kDesiredIconSizesForShortcut);
+#endif
+
 void DeleteShortcutInfoOnUIThread(std::unique_ptr<ShortcutInfo> shortcut_info,
                                   base::OnceClosure callback) {
   shortcut_info.reset();
@@ -90,6 +117,31 @@
   return app_data_dir.Append(host_path).Append(scheme_port_path);
 }
 
+base::span<const int> GetDesiredIconSizesForShortcut() {
+  return base::span<const int>(kDesiredIconSizesForShortcut,
+                               kNumDesiredIconSizesForShortcut);
+}
+
+gfx::ImageSkia CreateDefaultApplicationIcon(int size) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  // TODO(crbug.com/860581): Create web_app_browser_resources.grd with the
+  // default app icon. Remove dependency on extensions_browser_resources.h and
+  // use IDR_WEB_APP_DEFAULT_ICON here.
+  gfx::Image default_icon =
+      ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+          IDR_APP_DEFAULT_ICON);
+  SkBitmap bmp = skia::ImageOperations::Resize(
+      *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, size,
+      size);
+  gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp);
+  // We are on the UI thread, and this image can be used from the FILE thread,
+  // for creating shortcut icon files.
+  image_skia.MakeThreadSafe();
+
+  return image_skia;
+}
+
 namespace internals {
 
 void PostShortcutIOTask(base::OnceCallback<void(const ShortcutInfo&)> task,
@@ -104,7 +156,7 @@
     ShortcutCreationReason reason,
     std::unique_ptr<ShortcutInfo> shortcut_info,
     CreateShortcutsCallback callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   PostShortcutIOTask(base::BindOnce(&CreatePlatformShortcutsAndPostCallback,
                                     shortcut_data_path, creation_locations,
diff --git a/chrome/browser/web_applications/components/web_app_shortcut.h b/chrome/browser/web_applications/components/web_app_shortcut.h
index fb77e88..e35a961f 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut.h
+++ b/chrome/browser/web_applications/components/web_app_shortcut.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "base/callback_forward.h"
+#include "base/containers/span.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/sequence_checker.h"
@@ -21,6 +22,10 @@
 class TaskRunner;
 }
 
+namespace gfx {
+class ImageSkia;
+}
+
 namespace web_app {
 
 // Represents the info required to create a shortcut for an app.
@@ -106,6 +111,13 @@
 // created.
 using CreateShortcutsCallback = base::OnceCallback<void(bool shortcut_created)>;
 
+// Returns an array of desired icon sizes (in px) to be contained in an app OS
+// shortcut, sorted in ascending order (biggest desired icon size is last).
+base::span<const int> GetDesiredIconSizesForShortcut();
+
+// Load the standard application icon from resources.
+gfx::ImageSkia CreateDefaultApplicationIcon(int size);
+
 namespace internals {
 
 // Implemented for each platform, does the platform specific parts of creating
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc b/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc
index 9ca191f7..7a09aaa 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc
@@ -30,14 +30,10 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_handlers/file_handler_info.h"
 #include "extensions/common/manifest_handlers/icons_handler.h"
-#include "extensions/grit/extensions_browser_resources.h"
-#include "skia/ext/image_operations.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image_skia.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/web_applications/components/web_app_shortcut_win.h"
-#include "ui/gfx/icon_util.h"
 #endif
 
 #if defined(OS_MACOSX)
@@ -50,39 +46,14 @@
 
 namespace {
 
-#if defined(OS_MACOSX)
-const int kDesiredSizes[] = {16, 32, 128, 256, 512};
-const size_t kNumDesiredSizes = base::size(kDesiredSizes);
-#elif defined(OS_LINUX)
-// Linux supports icons of any size. FreeDesktop Icon Theme Specification states
-// that "Minimally you should install a 48x48 icon in the hicolor theme."
-const int kDesiredSizes[] = {16, 32, 48, 128, 256, 512};
-const size_t kNumDesiredSizes = base::size(kDesiredSizes);
-#elif defined(OS_WIN)
-const int* kDesiredSizes = IconUtil::kIconDimensions;
-const size_t kNumDesiredSizes = IconUtil::kNumIconDimensions;
-#else
-const int kDesiredSizes[] = {32};
-const size_t kNumDesiredSizes = base::size(kDesiredSizes);
-#endif
-
 void OnImageLoaded(std::unique_ptr<ShortcutInfo> shortcut_info,
                    ShortcutInfoCallback callback,
                    gfx::ImageFamily image_family) {
   // If the image failed to load (e.g. if the resource being loaded was empty)
   // use the standard application icon.
   if (image_family.empty()) {
-    gfx::Image default_icon =
-        ui::ResourceBundle::GetSharedInstance().GetImageNamed(
-            IDR_APP_DEFAULT_ICON);
-    int size = kDesiredSizes[kNumDesiredSizes - 1];
-    SkBitmap bmp = skia::ImageOperations::Resize(
-        *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, size,
-        size);
-    gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp);
-    // We are on the UI thread, and this image is needed from the FILE thread,
-    // for creating shortcut icon files.
-    image_skia.MakeThreadSafe();
+    int size = GetDesiredIconSizesForShortcut().back();
+    gfx::ImageSkia image_skia = CreateDefaultApplicationIcon(size);
     shortcut_info->favicon.Add(gfx::Image(image_skia));
   } else {
     shortcut_info->favicon = std::move(image_family);
@@ -154,21 +125,21 @@
       ShortcutInfoForExtensionAndProfile(extension, profile));
 
   std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
-  for (size_t i = 0; i < kNumDesiredSizes; ++i) {
-    int size = kDesiredSizes[i];
+
+  for (int size : GetDesiredIconSizesForShortcut()) {
     extensions::ExtensionResource resource =
         extensions::IconsInfo::GetIconResource(extension, size,
                                                ExtensionIconSet::MATCH_EXACTLY);
     if (!resource.empty()) {
       info_list.push_back(extensions::ImageLoader::ImageRepresentation(
           resource, extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
-          gfx::Size(size, size), ui::SCALE_FACTOR_100P));
+          gfx::Size(size, size),
+          GetScaleForScaleFactor(ui::SCALE_FACTOR_100P)));
     }
   }
 
   if (info_list.empty()) {
-    size_t i = kNumDesiredSizes - 1;
-    int size = kDesiredSizes[i];
+    int size = GetDesiredIconSizesForShortcut().back();
 
     // If there is no icon at the desired sizes, we will resize what we can get.
     // Making a large icon smaller is preferred to making a small icon larger,
@@ -182,7 +153,7 @@
     }
     info_list.push_back(extensions::ImageLoader::ImageRepresentation(
         resource, extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
-        gfx::Size(size, size), ui::SCALE_FACTOR_100P));
+        gfx::Size(size, size), GetScaleForScaleFactor(ui::SCALE_FACTOR_100P)));
   }
 
   // |info_list| may still be empty at this point, in which case
@@ -197,7 +168,8 @@
 std::unique_ptr<ShortcutInfo> ShortcutInfoForExtensionAndProfile(
     const extensions::Extension* app,
     Profile* profile) {
-  std::unique_ptr<ShortcutInfo> shortcut_info(new ShortcutInfo);
+  auto shortcut_info = std::make_unique<ShortcutInfo>();
+
   shortcut_info->extension_id = app->id();
   shortcut_info->url = extensions::AppLaunchInfo::GetLaunchWebURL(app);
   shortcut_info->title = base::UTF8ToUTF16(app->name());
@@ -212,6 +184,7 @@
     shortcut_info->file_handler_mime_types =
         web_app::GetMimeTypesFromFileHandlers(*info);
   }
+
   return shortcut_info;
 }
 
diff --git a/chrome/browser/web_applications/extensions/web_app_provider_unittest.cc b/chrome/browser/web_applications/extensions/web_app_provider_unittest.cc
index 6cecb6f..ba443a4 100644
--- a/chrome/browser/web_applications/extensions/web_app_provider_unittest.cc
+++ b/chrome/browser/web_applications/extensions/web_app_provider_unittest.cc
@@ -13,8 +13,6 @@
 
 namespace web_app {
 
-enum class ProviderType { kBookmarkApps, kWebApps };
-
 class WebAppProviderUnitTest
     : public WebAppTest,
       public ::testing::WithParamInterface<ProviderType> {
@@ -23,7 +21,7 @@
     if (GetParam() == ProviderType::kWebApps) {
       scoped_feature_list_.InitAndEnableFeature(
           features::kDesktopPWAsWithoutExtensions);
-    } else {
+    } else if (GetParam() == ProviderType::kBookmarkApps) {
       scoped_feature_list_.InitAndDisableFeature(
           features::kDesktopPWAsWithoutExtensions);
     }
diff --git a/chrome/browser/web_applications/test/web_app_icon_test_utils.cc b/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
index bbcf953e..0eb6c650 100644
--- a/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
@@ -7,7 +7,11 @@
 #include <utility>
 #include <vector>
 
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_applications/components/web_app_utils.h"
+#include "chrome/browser/web_applications/file_utils_wrapper.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
 
 namespace web_app {
 
@@ -54,4 +58,23 @@
          abs_error_b <= threshold && abs_error_a <= threshold;
 }
 
+base::FilePath GetAppIconsDir(Profile* profile, const AppId& app_id) {
+  base::FilePath web_apps_dir = GetWebAppsDirectory(profile);
+  base::FilePath app_dir = web_apps_dir.AppendASCII(app_id);
+  base::FilePath icons_dir = app_dir.AppendASCII("Icons");
+  return icons_dir;
+}
+
+bool ReadBitmap(FileUtilsWrapper* utils,
+                const base::FilePath& file_path,
+                SkBitmap* bitmap) {
+  std::string icon_data;
+  if (!utils->ReadFileToString(file_path, &icon_data))
+    return false;
+
+  return gfx::PNGCodec::Decode(
+      reinterpret_cast<const unsigned char*>(icon_data.c_str()),
+      icon_data.size(), bitmap);
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/test/web_app_icon_test_utils.h b/chrome/browser/web_applications/test/web_app_icon_test_utils.h
index 3a4534c..87865686 100644
--- a/chrome/browser/web_applications/test/web_app_icon_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_icon_test_utils.h
@@ -7,15 +7,20 @@
 
 #include <map>
 
+#include "base/files/file_path.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
 #include "chrome/browser/web_applications/components/web_app_install_utils.h"
 #include "chrome/common/web_application_info.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 class GURL;
+class Profile;
 
 namespace web_app {
 
+class FileUtilsWrapper;
+
 SkBitmap CreateSquareIcon(int size_px, SkColor solid_color);
 
 void AddGeneratedIcon(std::map<SquareSizePx, SkBitmap>* icon_bitmaps,
@@ -31,6 +36,12 @@
                     SkColor actual_color,
                     int threshold);
 
+base::FilePath GetAppIconsDir(Profile* profile, const AppId& app_id);
+
+bool ReadBitmap(FileUtilsWrapper* utils,
+                const base::FilePath& file_path,
+                SkBitmap* bitmap);
+
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_TEST_WEB_APP_ICON_TEST_UTILS_H_
diff --git a/chrome/browser/web_applications/test/web_app_test.cc b/chrome/browser/web_applications/test/web_app_test.cc
new file mode 100644
index 0000000..8a32eaa
--- /dev/null
+++ b/chrome/browser/web_applications/test/web_app_test.cc
@@ -0,0 +1,19 @@
+// 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/web_applications/test/web_app_test.h"
+
+namespace web_app {
+
+std::string ProviderTypeParamToString(
+    const ::testing::TestParamInfo<ProviderType>& provider_type) {
+  switch (provider_type.param) {
+    case ProviderType::kBookmarkApps:
+      return "BookmarkApps";
+    case ProviderType::kWebApps:
+      return "WebApps";
+  }
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/test/web_app_test.h b/chrome/browser/web_applications/test/web_app_test.h
index 27d7231..84be978 100644
--- a/chrome/browser/web_applications/test/web_app_test.h
+++ b/chrome/browser/web_applications/test/web_app_test.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,16 @@
 #define CHROME_BROWSER_WEB_APPLICATIONS_TEST_WEB_APP_TEST_H_
 
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace web_app {
+
+enum class ProviderType { kBookmarkApps, kWebApps };
+
+std::string ProviderTypeParamToString(
+    const ::testing::TestParamInfo<ProviderType>& provider_type);
+
+}  // namespace web_app
 
 // Consider to implement web app specific test harness independent of
 // RenderViewHost.
diff --git a/chrome/browser/web_applications/web_app_icon_manager.cc b/chrome/browser/web_applications/web_app_icon_manager.cc
index 3ea581c..95a5468a 100644
--- a/chrome/browser/web_applications/web_app_icon_manager.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager.cc
@@ -134,6 +134,10 @@
 
   // Commit: move whole app data dir to final destination in one mv operation.
   const base::FilePath app_dir = GetAppDirectory(web_apps_directory, app_id);
+
+  // Try to delete the destination. Needed for update.
+  utils->DeleteFileRecursively(app_dir);
+
   if (!utils->Move(app_temp_dir.GetPath(), app_dir)) {
     LOG(ERROR) << "Could not move temp WebApp directory to final destination.";
     return false;
diff --git a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
index 09a1835..68a4884 100644
--- a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
@@ -4,9 +4,11 @@
 
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 
+#include <algorithm>
 #include <memory>
 
 #include "base/bind_helpers.h"
+#include "base/files/file_enumerator.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
@@ -19,6 +21,7 @@
 #include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/common/web_application_info.h"
 #include "chrome/test/base/testing_profile.h"
@@ -147,6 +150,68 @@
   }
 }
 
+TEST_F(WebAppIconManagerTest, OverwriteIcons) {
+  auto web_app = CreateWebApp();
+  const AppId app_id = web_app->app_id();
+
+  // Write initial red icons to be overwritten.
+  {
+    std::vector<int> sizes_px{icon_size::k32, icon_size::k64, icon_size::k48};
+    const std::vector<SkColor> colors{SK_ColorRED, SK_ColorRED, SK_ColorRED};
+    WriteIcons(app_id, sizes_px, colors);
+
+    web_app->SetDownloadedIconSizes(std::move(sizes_px));
+  }
+
+  controller().RegisterApp(std::move(web_app));
+
+  // k64 and k48 sizes to be overwritten. Skip k32 size and add new k96 size.
+  const std::vector<int> overwritten_sizes_px{icon_size::k48, icon_size::k64,
+                                              icon_size::k96};
+  {
+    std::map<SquareSizePx, SkBitmap> icon_bitmaps;
+    for (int size_px : overwritten_sizes_px)
+      icon_bitmaps[size_px] = CreateSquareIcon(size_px, SK_ColorGREEN);
+
+    base::RunLoop run_loop;
+
+    // Overwrite red icons with green ones.
+    icon_manager().WriteData(app_id, std::move(icon_bitmaps),
+                             base::BindLambdaForTesting([&](bool success) {
+                               EXPECT_TRUE(success);
+                               run_loop.Quit();
+                             }));
+
+    run_loop.Run();
+
+    ScopedRegistryUpdate update(&controller().sync_bridge());
+    update->UpdateApp(app_id)->SetDownloadedIconSizes(overwritten_sizes_px);
+  }
+
+  // Check that all icons are now green. Check that all red icons were deleted
+  // on disk (including the k32 size).
+  base::FilePath icons_dir = GetAppIconsDir(profile(), app_id);
+
+  std::vector<int> sizes_on_disk_px;
+
+  base::FileEnumerator enumerator(icons_dir, true, base::FileEnumerator::FILES);
+  for (base::FilePath path = enumerator.Next(); !path.empty();
+       path = enumerator.Next()) {
+    EXPECT_TRUE(path.MatchesExtension(FILE_PATH_LITERAL(".png")));
+
+    SkBitmap bitmap;
+    EXPECT_TRUE(ReadBitmap(&file_utils(), path, &bitmap));
+    EXPECT_FALSE(bitmap.empty());
+    EXPECT_EQ(bitmap.width(), bitmap.height());
+    EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(0, 0));
+
+    sizes_on_disk_px.push_back(bitmap.width());
+  }
+
+  std::sort(sizes_on_disk_px.begin(), sizes_on_disk_px.end());
+  EXPECT_EQ(overwritten_sizes_px, sizes_on_disk_px);
+}
+
 TEST_F(WebAppIconManagerTest, ReadAllIcons) {
   auto web_app = CreateWebApp();
   const AppId app_id = web_app->app_id();
@@ -282,7 +347,6 @@
 TEST_F(WebAppIconManagerTest, DeleteData_Success) {
   const AppId app1_id = GenerateAppIdFromURL(GURL("https://example.com/"));
   const AppId app2_id = GenerateAppIdFromURL(GURL("https://example.org/"));
-  const GURL icons_root_url;  // url is empty to indicate autogenerated icons.
 
   const std::vector<int> sizes_px{icon_size::k128};
   const std::vector<SkColor> colors{SK_ColorMAGENTA};
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 40fe6c6b..91057845 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -140,7 +140,7 @@
       InferSourceFromMetricsInstallSource(options.install_source);
 
   const AppId app_id = GenerateAppIdFromURL(web_app_info.app_url);
-  const WebApp* existing_web_app = sync_bridge_->registrar().GetAppById(app_id);
+  const WebApp* existing_web_app = GetWebAppRegistrar().GetAppById(app_id);
 
   if (existing_web_app && !existing_web_app->is_in_sync_install()) {
     // There is an existing app from other source(s). Preserve
@@ -177,37 +177,14 @@
   web_app->AddSource(source);
   web_app->SetIsInSyncInstall(false);
 
-  web_app->SetName(base::UTF16ToUTF8(web_app_info.title));
-  web_app->SetDisplayMode(web_app_info.display_mode);
-  web_app->SetDescription(base::UTF16ToUTF8(web_app_info.description));
-  web_app->SetScope(web_app_info.scope);
-  if (web_app_info.theme_color) {
-    web_app->SetThemeColor(
-        SkColorSetA(*web_app_info.theme_color, SK_AlphaOPAQUE));
-  }
-
-  WebApp::SyncData sync_data;
-  sync_data.name = base::UTF16ToUTF8(web_app_info.title);
-  sync_data.theme_color = web_app_info.theme_color;
-  web_app->SetSyncData(std::move(sync_data));
-
-  web_app->SetIconInfos(web_app_info.icon_infos);
-  web_app->SetDownloadedIconSizes(GetSquareSizePxs(web_app_info.icon_bitmaps));
-
-  SetWebAppFileHandlers(web_app_info.file_handlers, web_app.get());
-
-  icon_manager_->WriteData(
-      std::move(app_id), web_app_info.icon_bitmaps,
-      base::BindOnce(&WebAppInstallFinalizer::OnIconsDataWritten,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-                     std::move(web_app)));
+  SetWebAppManifestFieldsAndWriteData(web_app_info, std::move(web_app),
+                                      std::move(callback));
 }
 
 void WebAppInstallFinalizer::FinalizeFallbackInstallAfterSync(
     const AppId& app_id,
     InstallFinalizedCallback callback) {
-  const WebApp* app_in_sync_install =
-      sync_bridge_->registrar().GetAppById(app_id);
+  const WebApp* app_in_sync_install = GetWebAppRegistrar().GetAppById(app_id);
   DCHECK(app_in_sync_install);
   DCHECK(app_in_sync_install->is_in_sync_install());
 
@@ -246,7 +223,7 @@
     UninstallWebAppCallback callback) {
   // WebAppSyncBridge::ApplySyncChangesToRegistrar does the actual
   // unregistration of the app from the registry.
-  DCHECK(!sync_bridge_->registrar().GetAppById(app_id));
+  DCHECK(!GetWebAppRegistrar().GetAppById(app_id));
 
   icon_manager_->DeleteData(
       app_id, base::BindOnce(&WebAppInstallFinalizer::OnIconsDataDeleted,
@@ -254,14 +231,6 @@
                              std::move(callback)));
 }
 
-void WebAppInstallFinalizer::OnIconsDataDeleted(
-    const AppId& app_id,
-    UninstallWebAppCallback callback,
-    bool success) {
-  registrar().NotifyWebAppUninstalled(app_id);
-  std::move(callback).Run(success);
-}
-
 void WebAppInstallFinalizer::UninstallExternalWebApp(
     const GURL& app_url,
     ExternalInstallSource external_install_source,
@@ -283,7 +252,7 @@
 
 bool WebAppInstallFinalizer::CanUserUninstallFromSync(
     const AppId& app_id) const {
-  const WebApp* app = sync_bridge_->registrar().GetAppById(app_id);
+  const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
   return app ? app->IsSynced() : false;
 }
 
@@ -298,14 +267,14 @@
     const AppId& app_id) const {
   // TODO(loyso): Policy Apps: Implement web_app::ManagementPolicy taking
   // extensions::ManagementPolicy::UserMayModifySettings as inspiration.
-  const WebApp* app = sync_bridge_->registrar().GetAppById(app_id);
+  const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
   return app ? app->CanUserUninstallExternalApp() : false;
 }
 
 void WebAppInstallFinalizer::UninstallExternalAppByUser(
     const AppId& app_id,
     UninstallWebAppCallback callback) {
-  const WebApp* app = sync_bridge_->registrar().GetAppById(app_id);
+  const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
   DCHECK(app);
   DCHECK(app->CanUserUninstallExternalApp());
 
@@ -333,9 +302,22 @@
 void WebAppInstallFinalizer::FinalizeUpdate(
     const WebApplicationInfo& web_app_info,
     InstallFinalizedCallback callback) {
-  // TODO(crbug.com/926083): Implement update logic, this requires updating
-  // WebAppIconManager to clean out the existing icons and write new ones.
-  NOTIMPLEMENTED();
+  const AppId app_id = GenerateAppIdFromURL(web_app_info.app_url);
+  const WebApp* existing_web_app = GetWebAppRegistrar().GetAppById(app_id);
+
+  if (!existing_web_app || existing_web_app->is_in_sync_install() ||
+      web_app_info.app_url != existing_web_app->launch_url()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), AppId(),
+                                  InstallResultCode::kWebAppDisabled));
+    return;
+  }
+
+  // Prepare copy-on-write to update existing app.
+  auto web_app = std::make_unique<WebApp>(*existing_web_app);
+
+  SetWebAppManifestFieldsAndWriteData(web_app_info, std::move(web_app),
+                                      std::move(callback));
 }
 
 void WebAppInstallFinalizer::UninstallWebApp(const AppId& app_id,
@@ -355,7 +337,7 @@
     const AppId& app_id,
     Source::Type source,
     UninstallWebAppCallback callback) {
-  const WebApp* app = sync_bridge_->registrar().GetAppById(app_id);
+  const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
   if (!app) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback),
@@ -375,6 +357,38 @@
   }
 }
 
+void WebAppInstallFinalizer::SetWebAppManifestFieldsAndWriteData(
+    const WebApplicationInfo& web_app_info,
+    std::unique_ptr<WebApp> web_app,
+    InstallFinalizedCallback callback) {
+  web_app->SetName(base::UTF16ToUTF8(web_app_info.title));
+  web_app->SetDisplayMode(web_app_info.display_mode);
+  web_app->SetDescription(base::UTF16ToUTF8(web_app_info.description));
+  web_app->SetScope(web_app_info.scope);
+  if (web_app_info.theme_color) {
+    web_app->SetThemeColor(
+        SkColorSetA(*web_app_info.theme_color, SK_AlphaOPAQUE));
+  }
+
+  WebApp::SyncData sync_data;
+  sync_data.name = base::UTF16ToUTF8(web_app_info.title);
+  sync_data.theme_color = web_app_info.theme_color;
+  web_app->SetSyncData(std::move(sync_data));
+
+  web_app->SetIconInfos(web_app_info.icon_infos);
+  web_app->SetDownloadedIconSizes(GetSquareSizePxs(web_app_info.icon_bitmaps));
+
+  SetWebAppFileHandlers(web_app_info.file_handlers, web_app.get());
+
+  AppId app_id = web_app->app_id();
+
+  icon_manager_->WriteData(
+      std::move(app_id), web_app_info.icon_bitmaps,
+      base::BindOnce(&WebAppInstallFinalizer::OnIconsDataWritten,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+                     std::move(web_app)));
+}
+
 void WebAppInstallFinalizer::OnIconsDataWritten(
     InstallFinalizedCallback callback,
     std::unique_ptr<WebApp> web_app,
@@ -399,12 +413,21 @@
       std::move(update),
       base::BindOnce(&WebAppInstallFinalizer::OnDatabaseCommitCompleted,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-                     std::move(app_id)));
+                     std::move(app_id), /*new_app_created=*/!app_to_override));
+}
+
+void WebAppInstallFinalizer::OnIconsDataDeleted(
+    const AppId& app_id,
+    UninstallWebAppCallback callback,
+    bool success) {
+  registrar().NotifyWebAppUninstalled(app_id);
+  std::move(callback).Run(success);
 }
 
 void WebAppInstallFinalizer::OnDatabaseCommitCompleted(
     InstallFinalizedCallback callback,
     const AppId& app_id,
+    bool new_app_created,
     bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success) {
@@ -413,7 +436,9 @@
   }
 
   registrar().NotifyWebAppInstalled(app_id);
-  std::move(callback).Run(app_id, InstallResultCode::kSuccessNewInstall);
+  std::move(callback).Run(
+      app_id, new_app_created ? InstallResultCode::kSuccessNewInstall
+                              : InstallResultCode::kSuccessAlreadyInstalled);
 }
 
 void WebAppInstallFinalizer::OnFallbackInstallFinalized(
@@ -442,4 +467,10 @@
   NOTIMPLEMENTED();
 }
 
+WebAppRegistrar& WebAppInstallFinalizer::GetWebAppRegistrar() const {
+  WebAppRegistrar* web_app_registrar = registrar().AsWebAppRegistrar();
+  DCHECK(web_app_registrar);
+  return *web_app_registrar;
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index 5b3a256..b875d9ce 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -19,6 +19,7 @@
 
 class WebApp;
 class WebAppIconManager;
+class WebAppRegistrar;
 class WebAppSyncBridge;
 
 class WebAppInstallFinalizer final : public InstallFinalizer {
@@ -58,6 +59,11 @@
                                      Source::Type source,
                                      UninstallWebAppCallback callback);
 
+  void SetWebAppManifestFieldsAndWriteData(
+      const WebApplicationInfo& web_app_info,
+      std::unique_ptr<WebApp> web_app,
+      InstallFinalizedCallback callback);
+
   void OnIconsDataWritten(InstallFinalizedCallback callback,
                           std::unique_ptr<WebApp> web_app,
                           bool success);
@@ -66,12 +72,15 @@
                           bool success);
   void OnDatabaseCommitCompleted(InstallFinalizedCallback callback,
                                  const AppId& app_id,
+                                 bool new_app_created,
                                  bool success);
   void OnFallbackInstallFinalized(const AppId& app_in_sync_install_id,
                                   InstallFinalizedCallback callback,
                                   const AppId& installed_app_id,
                                   InstallResultCode code);
 
+  WebAppRegistrar& GetWebAppRegistrar() const;
+
   Profile* const profile_;
   WebAppSyncBridge* const sync_bridge_;
   WebAppIconManager* const icon_manager_;
diff --git a/chrome/browser/web_applications/web_app_install_manager_unittest.cc b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
index 2b176a2..9cdfa2c 100644
--- a/chrome/browser/web_applications/web_app_install_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
@@ -578,7 +578,7 @@
       }));
 
   InstallResult result = InstallWebAppsAfterSync({app});
-  EXPECT_EQ(InstallResultCode::kSuccessNewInstall, result.code);
+  EXPECT_EQ(InstallResultCode::kSuccessAlreadyInstalled, result.code);
   EXPECT_EQ(app->app_id(), result.app_id);
 
   EXPECT_EQ(1u, registrar().GetAppIds().size());
@@ -643,7 +643,7 @@
       }));
 
   InstallResult result = InstallWebAppsAfterSync({app});
-  EXPECT_EQ(InstallResultCode::kSuccessNewInstall, result.code);
+  EXPECT_EQ(InstallResultCode::kSuccessAlreadyInstalled, result.code);
   EXPECT_EQ(app->app_id(), result.app_id);
 
   EXPECT_EQ(1u, registrar().GetAppIds().size());
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index de44e1b..299b748 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -48,7 +48,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/codec/png_codec.h"
 #include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
@@ -66,18 +65,6 @@
 
 namespace {
 
-bool ReadBitmap(FileUtilsWrapper* utils,
-                const base::FilePath& file_path,
-                SkBitmap* bitmap) {
-  std::string icon_data;
-  if (!utils->ReadFileToString(file_path, &icon_data))
-    return false;
-
-  return gfx::PNGCodec::Decode(
-      reinterpret_cast<const unsigned char*>(icon_data.c_str()),
-      icon_data.size(), bitmap);
-}
-
 constexpr int kIconSizes[] = {
     icon_size::k32, icon_size::k64,  icon_size::k48,
     icon_size::k96, icon_size::k128, icon_size::k256,
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 311c8a11..33972ae8 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -521,7 +521,7 @@
   weak_dialog_model_->CollectPIN(attempts, std::move(provide_pin_cb));
 }
 
-void ChromeAuthenticatorRequestDelegate::FinishCollectPIN() {
+void ChromeAuthenticatorRequestDelegate::FinishCollectToken() {
   weak_dialog_model_->SetCurrentStep(
       AuthenticatorRequestDialogModel::Step::kClientPinTapAgain);
 }
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
index 3585be8..62b4f2d 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
@@ -113,7 +113,7 @@
   void CollectPIN(
       base::Optional<int> attempts,
       base::OnceCallback<void(std::string)> provide_pin_cb) override;
-  void FinishCollectPIN() override;
+  void FinishCollectToken() override;
   void SetMightCreateResidentCredential(bool v) override;
 
   // AuthenticatorRequestDialogModel::Observer:
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index c8f1f605..2963b978 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -142,7 +142,7 @@
 const base::Feature kTLS13HardeningForLocalAnchors{
     "TLS13HardeningForLocalAnchors", base::FEATURE_ENABLED_BY_DEFAULT};
 
-#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX)
+#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
 // Enables the dual certificate verification trial feature.
 // https://crbug.com/649026
 const base::Feature kCertDualVerificationTrialFeature{
@@ -507,7 +507,7 @@
 // not shown on the omnibox, since its functionality is replaced by the
 // setting.
 const base::Feature kMixedContentSiteSetting{"MixedContentSiteSetting",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
+                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if !defined(OS_ANDROID)
 const base::Feature kOnConnectNative{"OnConnectNative",
@@ -815,7 +815,7 @@
 
 // Enable USBGuard at the lockscreen on Chrome OS.
 // TODO(crbug.com/874630): Remove this kill-switch
-const base::Feature kUsbguard{"USBGuard", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kUsbguard{"USBGuard", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable USB Bouncer for managing a device whitelist for USBGuard on Chrome OS.
 const base::Feature kUsbbouncer{"USBBouncer",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index ba4af255..b20960d 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -81,7 +81,7 @@
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::Feature kCaptionSettings;
 
-#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX)
+#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::Feature kCertDualVerificationTrialFeature;
 #endif
diff --git a/chrome/credential_provider/gaiacp/reg_utils.cc b/chrome/credential_provider/gaiacp/reg_utils.cc
index 11a7d229..14087b6 100644
--- a/chrome/credential_provider/gaiacp/reg_utils.cc
+++ b/chrome/credential_provider/gaiacp/reg_utils.cc
@@ -17,11 +17,11 @@
 
 namespace credential_provider {
 
-// Root registry key for GCP configuration and state.
+// Root registry key for GCPW configuration and state.
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-#define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Google\\GCP"
+#define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Google\\GCPW"
 #else
-#define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Chromium\\GCP"
+#define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Chromium\\GCPW"
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
 const wchar_t kGcpRootKeyName[] = CREDENTIAL_PROVIDER_REGISTRY_KEY;
diff --git a/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb b/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb
index 54762f9..59d83860 100644
--- a/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb
+++ b/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb
@@ -25,7 +25,7 @@
 <translation id="7209941495304122410">Windows கடவுச்சொல்லை உள்ளிடுக</translation>
 <translation id="7357241217513796177">இணைய இணைப்பு இருப்பதை உறுதிசெய்து மீண்டும் முயலவும்.</translation>
 <translation id="7536769223115622137">பணிக் கணக்கைச் சேர்</translation>
-<translation id="7811865856574012727">சாதனம் இந்த டொமைன்களில் உள்நுழைவதற்கு உங்கள் நிர்வாகி கட்டுப்பாடு விதித்துள்ளார்: <ph name="EMAIL_DOMAINS" />. சரியான கணக்கைப் பயன்படுத்தி மீண்டும் முயலவும்.</translation>
+<translation id="7811865856574012727">சாதனம் இந்த டொமைன்களில் உள்நுழைவதற்கு உங்கள் நிர்வாகி கட்டுப்பாடு விதித்துள்ளார்: <ph name="EMAIL_DOMAINS" />. சரியான பணிக் கணக்கைப் பயன்படுத்தி மீண்டும் முயலவும்.</translation>
 <translation id="7856245195110636219">தற்போதைய Windows கடவுச்சொல்லை உள்ளிடாமல் தொடர முடியாது. சிஸ்டம் நிர்வாகியைத் தொடர்புகொள்ளவும்.</translation>
 <translation id="8639729688781680518">Windows கடவுச்சொல் மறந்துவிட்டது</translation>
 <translation id="866458870819756755">பயனரை உருவாக்க முடியவில்லை.</translation>
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index b4b0b3a..c3e76d3 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -710,7 +710,6 @@
       "//components/resources",
       "//components/safe_browsing:buildflags",
       "//components/safe_browsing/db:test_database_manager",
-      "//components/services/paint_preview_compositor/public/mojom",
       "//components/services/patch/public/mojom",
       "//components/services/quarantine:test_support",
       "//components/signin/core/browser",
@@ -2736,7 +2735,9 @@
       ]
       deps += [
         "//components/paint_preview/browser",
+        "//components/paint_preview/browser:test_support",
         "//components/paint_preview/common",
+        "//components/services/paint_preview_compositor/public/mojom",
       ]
     }
     if (enable_service_discovery && !is_mac) {
@@ -4053,6 +4054,7 @@
       "../browser/ui/toolbar/toolbar_actions_model_unittest.cc",
       "../browser/ui/web_applications/app_browser_controller_unittest.cc",
       "../browser/ui/web_applications/web_app_launch_utils_unittest.cc",
+      "../browser/ui/webui/components/components_handler_unittest.cc",
       "../browser/ui/webui/downloads/downloads_dom_handler_unittest.cc",
       "../browser/ui/webui/downloads/downloads_list_tracker_unittest.cc",
       "../browser/ui/webui/downloads/mock_downloads_page.cc",
@@ -4262,7 +4264,6 @@
       "../browser/extensions/api/terminal/crostini_startup_status_unittest.cc",
       "../browser/google/google_brand_code_map_chromeos_unittest.cc",
       "../browser/media/webrtc/desktop_media_list_ash_unittest.cc",
-      "../browser/metrics/perf/heap_collector_unittest.cc",
       "../browser/metrics/perf/metric_collector_unittest.cc",
       "../browser/metrics/perf/metric_provider_unittest.cc",
       "../browser/metrics/perf/perf_events_collector_unittest.cc",
@@ -4966,6 +4967,8 @@
         "../browser/printing/test_printer_query.cc",
         "../browser/printing/test_printer_query.h",
         "../browser/ui/webui/print_preview/extension_printer_handler_unittest.cc",
+        "../browser/ui/webui/print_preview/fake_print_render_frame.cc",
+        "../browser/ui/webui/print_preview/fake_print_render_frame.h",
         "../browser/ui/webui/print_preview/pdf_printer_handler_unittest.cc",
         "../browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc",
         "../browser/ui/webui/print_preview/print_preview_handler_unittest.cc",
diff --git a/chrome/test/base/in_process_browser_test_browsertest.cc b/chrome/test/base/in_process_browser_test_browsertest.cc
index c8f712a..a7abb83 100644
--- a/chrome/test/base/in_process_browser_test_browsertest.cc
+++ b/chrome/test/base/in_process_browser_test_browsertest.cc
@@ -21,6 +21,7 @@
 #include "content/public/common/content_switches.h"
 #include "net/base/filename_util.h"
 #include "net/base/net_errors.h"
+#include "net/dns/public/resolve_error_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -44,7 +45,8 @@
   explicit LoadFailObserver(content::WebContents* contents)
       : content::WebContentsObserver(contents),
         failed_load_(false),
-        error_code_(net::OK) { }
+        error_code_(net::OK),
+        resolve_error_info_(net::ResolveErrorInfo(net::OK)) {}
 
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override {
@@ -53,16 +55,21 @@
 
     failed_load_ = true;
     error_code_ = navigation_handle->GetNetErrorCode();
+    resolve_error_info_ = navigation_handle->GetResolveErrorInfo();
     validated_url_ = navigation_handle->GetURL();
   }
 
   bool failed_load() const { return failed_load_; }
   net::Error error_code() const { return error_code_; }
+  net::ResolveErrorInfo resolve_error_info() const {
+    return resolve_error_info_;
+  }
   const GURL& validated_url() const { return validated_url_; }
 
  private:
   bool failed_load_;
   net::Error error_code_;
+  net::ResolveErrorInfo resolve_error_info_;
   GURL validated_url_;
 
   DISALLOW_COPY_AND_ASSIGN(LoadFailObserver);
@@ -84,7 +91,8 @@
     LoadFailObserver observer(contents);
     ui_test_utils::NavigateToURL(browser(), url);
     EXPECT_TRUE(observer.failed_load());
-    EXPECT_EQ(net::ERR_NOT_IMPLEMENTED, observer.error_code());
+    EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, observer.error_code());
+    EXPECT_EQ(net::ERR_NOT_IMPLEMENTED, observer.resolve_error_info().error);
     EXPECT_EQ(url, observer.validated_url());
   }
 }
diff --git a/chrome/test/data/extensions/api_test/declarative_net_request/dynamic_rules/background.js b/chrome/test/data/extensions/api_test/declarative_net_request/dynamic_rules/background.js
index ea432fe..ce01e48 100644
--- a/chrome/test/data/extensions/api_test/declarative_net_request/dynamic_rules/background.js
+++ b/chrome/test/data/extensions/api_test/declarative_net_request/dynamic_rules/background.js
@@ -9,6 +9,7 @@
 var createRuleWithID = function(id) {
   return {
     id: id,
+    priority: 1,
     condition: {urlFilter: id.toString()},
     action: {type: 'block'},
   };
diff --git a/chrome/test/data/extensions/api_test/declarative_net_request/get_matched_rules/rules.json b/chrome/test/data/extensions/api_test/declarative_net_request/get_matched_rules/rules.json
index 43f0ab2..0a9f93a 100644
--- a/chrome/test/data/extensions/api_test/declarative_net_request/get_matched_rules/rules.json
+++ b/chrome/test/data/extensions/api_test/declarative_net_request/get_matched_rules/rules.json
@@ -1,5 +1,6 @@
 [{
   "id" : 1,
+  "priority": 1,
   "action": { "type" : "block" },
   "condition" : {"urlFilter" : "abc*", "resourceTypes" : ["main_frame"] }
 }]
diff --git a/chrome/test/data/extensions/api_test/declarative_net_request/header_removal/background.js b/chrome/test/data/extensions/api_test/declarative_net_request/header_removal/background.js
index 3e6dc64..0df6e6a26 100644
--- a/chrome/test/data/extensions/api_test/declarative_net_request/header_removal/background.js
+++ b/chrome/test/data/extensions/api_test/declarative_net_request/header_removal/background.js
@@ -248,6 +248,7 @@
 };
 var allowRule = {
   id: 3,
+  priority: 1,
   condition: {urlFilter: host, resourceTypes: ['main_frame']},
   action: {type: 'allow'}
 };
diff --git a/chrome/test/data/extensions/api_test/declarative_net_request/on_rules_matched_debug/rules.json b/chrome/test/data/extensions/api_test/declarative_net_request/on_rules_matched_debug/rules.json
index 664e5c30..1a6f52b 100644
--- a/chrome/test/data/extensions/api_test/declarative_net_request/on_rules_matched_debug/rules.json
+++ b/chrome/test/data/extensions/api_test/declarative_net_request/on_rules_matched_debug/rules.json
@@ -1,5 +1,6 @@
 [{
   "id" : 1,
+  "priority": 1,
   "action": { "type" : "block" },
   "condition" : {"urlFilter" : "abc*", "resourceTypes" : ["main_frame", "xmlhttprequest"] }
 },
diff --git a/chrome/test/data/webui/new_tab_page/most_visited_focus_test.js b/chrome/test/data/webui/new_tab_page/most_visited_focus_test.js
index 28e9a86..fcc208e 100644
--- a/chrome/test/data/webui/new_tab_page/most_visited_focus_test.js
+++ b/chrome/test/data/webui/new_tab_page/most_visited_focus_test.js
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 import 'chrome://new-tab-page/most_visited.js';
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
 
 import {BrowserProxy} from 'chrome://new-tab-page/browser_proxy.js';
 import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
@@ -41,7 +43,11 @@
   async function addTiles(n) {
     const tiles = Array(n).fill(0).map((x, i) => {
       const char = String.fromCharCode(i + /* 'a' */ 97);
-      return {title: char, url: {url: `https://${char}/`}};
+      return {
+        title: char,
+        titleDirection: mojoBase.mojom.TextDirection.LEFT_TO_RIGHT,
+        url: {url: `https://${char}/`},
+      };
     });
     const tilesRendered = eventToPromise('dom-change', mostVisited.$.tiles);
     testProxy.callbackRouterRemote.setMostVisitedInfo({
diff --git a/chrome/test/data/webui/new_tab_page/most_visited_test.js b/chrome/test/data/webui/new_tab_page/most_visited_test.js
index 66c9f67..9729967 100644
--- a/chrome/test/data/webui/new_tab_page/most_visited_test.js
+++ b/chrome/test/data/webui/new_tab_page/most_visited_test.js
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 import 'chrome://new-tab-page/most_visited.js';
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
 
 import {BrowserProxy} from 'chrome://new-tab-page/browser_proxy.js';
 import {isMac} from 'chrome://resources/js/cr.m.js';
@@ -41,7 +43,11 @@
   async function addTiles(n) {
     const tiles = Array(n).fill(0).map((x, i) => {
       const char = String.fromCharCode(i + /* 'a' */ 97);
-      return {title: char, url: {url: `https://${char}/`}};
+      return {
+        title: char,
+        titleDirection: mojoBase.mojom.TextDirection.LEFT_TO_RIGHT,
+        url: {url: `https://${char}/`},
+      };
     });
     const tilesRendered = eventToPromise('dom-change', mostVisited.$.tiles);
     testProxy.callbackRouterRemote.setMostVisitedInfo({
@@ -560,4 +566,52 @@
     assertEquals('https://b/', newFirst.href);
     assertEquals('https://a/', newSecond.href);
   });
+
+  test('RIGHT_TO_LEFT tile title text direction', async () => {
+    const tilesRendered = eventToPromise('dom-change', mostVisited.$.tiles);
+    testProxy.callbackRouterRemote.setMostVisitedInfo({
+      customLinksEnabled: true,
+      tiles: [{
+        title: 'title',
+        titleDirection: mojoBase.mojom.TextDirection.RIGHT_TO_LEFT,
+        url: {url: 'https://url/'},
+      }],
+      visible: true,
+    });
+    await testProxy.callbackRouterRemote.$.flushForTesting();
+    await tilesRendered;
+    const [tile] = queryTiles();
+    const titleElement = tile.querySelector('.tile-title');
+    assertEquals('rtl', window.getComputedStyle(titleElement).direction);
+
+    tile.querySelector('cr-icon-button').click();
+    mostVisited.$.actionMenuEdit.click();
+    assertEquals(
+        'rtl',
+        window.getComputedStyle(mostVisited.$.dialogInputName).direction);
+  });
+
+  test('LEFT_TO_RIGHT tile title text direction', async () => {
+    const tilesRendered = eventToPromise('dom-change', mostVisited.$.tiles);
+    testProxy.callbackRouterRemote.setMostVisitedInfo({
+      customLinksEnabled: true,
+      tiles: [{
+        title: 'title',
+        titleDirection: mojoBase.mojom.TextDirection.LEFT_TO_RIGHT,
+        url: {url: 'https://url/'},
+      }],
+      visible: true,
+    });
+    await testProxy.callbackRouterRemote.$.flushForTesting();
+    await tilesRendered;
+    const [tile] = queryTiles();
+    const titleElement = tile.querySelector('.tile-title');
+    assertEquals('ltr', window.getComputedStyle(titleElement).direction);
+
+    tile.querySelector('cr-icon-button').click();
+    mostVisited.$.actionMenuEdit.click();
+    assertEquals(
+        'ltr',
+        window.getComputedStyle(mostVisited.$.dialogInputName).direction);
+  });
 });
diff --git a/chrome/test/data/webui/new_tab_page/test_support.js b/chrome/test/data/webui/new_tab_page/test_support.js
index e96cfc7..22053ea 100644
--- a/chrome/test/data/webui/new_tab_page/test_support.js
+++ b/chrome/test/data/webui/new_tab_page/test_support.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
 import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
 import 'chrome://new-tab-page/skcolor.mojom-lite.js';
 import 'chrome://new-tab-page/new_tab_page.mojom-lite.js';
diff --git a/chromecast/app/linux/cast_crash_reporter_client_unittest.cc b/chromecast/app/linux/cast_crash_reporter_client_unittest.cc
index 9ce10ae4..552d6d36 100644
--- a/chromecast/app/linux/cast_crash_reporter_client_unittest.cc
+++ b/chromecast/app/linux/cast_crash_reporter_client_unittest.cc
@@ -46,7 +46,7 @@
 
   static void SetUpTestCase() {
     // Set a callback to be used in place of the |dumpstate| executable.
-    CrashUtil::SetDumpStateCbForTest(base::Bind(&WriteFakeDumpStateFile));
+    CrashUtil::SetDumpStateCbForTest(base::BindOnce(&WriteFakeDumpStateFile));
   }
 
   // testing::Test implementation:
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 1f87790..5f38a408 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -419,6 +419,8 @@
       "webview/webview_controller.h",
       "webview/webview_grpc_service.cc",
       "webview/webview_grpc_service.h",
+      "webview/webview_layout_manager.cc",
+      "webview/webview_layout_manager.h",
       "webview/webview_navigation_throttle.cc",
       "webview/webview_navigation_throttle.h",
       "webview/webview_rpc_instance.cc",
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index f54f7d5e..81b9466 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -144,7 +144,7 @@
     SIGTERM, SIGINT,
 };
 // Closure to run on SIGTERM and SIGINT.
-base::Closure* g_signal_closure = nullptr;
+base::OnceClosure* g_signal_closure = nullptr;
 base::PlatformThreadId g_main_thread_id;
 
 void RunClosureOnSignal(int signum) {
@@ -158,16 +158,18 @@
   RAW_LOG(INFO, message);
 
   DCHECK(g_signal_closure);
-  g_signal_closure->Run();
+  if (*g_signal_closure)
+    std::move(*g_signal_closure).Run();
 }
 
-void RegisterClosureOnSignal(const base::Closure& closure) {
+void RegisterClosureOnSignal(base::OnceClosure closure) {
   DCHECK(!g_signal_closure);
+  DCHECK(closure);
   DCHECK_GT(base::size(kSignalsToRunClosure), 0U);
 
   // Memory leak on purpose, since |g_signal_closure| should live until
   // process exit.
-  g_signal_closure = new base::Closure(closure);
+  g_signal_closure = new base::OnceClosure(std::move(closure));
   g_main_thread_id = base::PlatformThread::CurrentId();
 
   struct sigaction sa_new;
@@ -684,11 +686,10 @@
 #else
   if (run_message_loop_) {
     base::RunLoop run_loop;
-    base::Closure quit_closure(run_loop.QuitClosure());
 
 #if !defined(OS_FUCHSIA)
     // Fuchsia doesn't have signals.
-    RegisterClosureOnSignal(quit_closure);
+    RegisterClosureOnSignal(run_loop.QuitClosure());
 #endif  // !defined(OS_FUCHSIA)
 
     run_loop.Run();
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index ff12c5a..aff2572 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -600,7 +600,7 @@
           web_contents->GetMainFrame()->GetProcess()->GetID(),
           web_contents->GetMainFrame()->GetRoutingID(),
           base::SequencedTaskRunnerHandle::Get(),
-          base::Bind(
+          base::BindOnce(
               &content::ClientCertificateDelegate::ContinueWithCertificate,
               base::Owned(delegate.release()))));
   return base::OnceClosure();
@@ -612,8 +612,8 @@
     int render_process_id,
     int render_frame_id,
     scoped_refptr<base::SequencedTaskRunner> original_runner,
-    const base::Callback<void(scoped_refptr<net::X509Certificate>,
-                              scoped_refptr<net::SSLPrivateKey>)>&
+    base::OnceCallback<void(scoped_refptr<net::X509Certificate>,
+                            scoped_refptr<net::SSLPrivateKey>)>
         continue_callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   CastNetworkDelegate* network_delegate =
@@ -622,8 +622,8 @@
                                       render_process_id, render_frame_id,
                                       false)) {
     original_runner->PostTask(
-        FROM_HERE,
-        base::BindOnce(continue_callback, DeviceCert(), DeviceKey()));
+        FROM_HERE, base::BindOnce(std::move(continue_callback), DeviceCert(),
+                                  DeviceKey()));
     return;
   } else {
     LOG(ERROR) << "Invalid host for client certificate request: "
@@ -632,7 +632,8 @@
                << " and render_frame_id: " << render_frame_id;
   }
   original_runner->PostTask(
-      FROM_HERE, base::BindOnce(continue_callback, nullptr, nullptr));
+      FROM_HERE,
+      base::BindOnce(std::move(continue_callback), nullptr, nullptr));
 }
 
 bool CastContentBrowserClient::CanCreateWindow(
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 4297593..6f41af87 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -295,8 +295,8 @@
       int render_process_id,
       int render_frame_id,
       scoped_refptr<base::SequencedTaskRunner> original_runner,
-      const base::Callback<void(scoped_refptr<net::X509Certificate>,
-                                scoped_refptr<net::SSLPrivateKey>)>&
+      base::OnceCallback<void(scoped_refptr<net::X509Certificate>,
+                              scoped_refptr<net::SSLPrivateKey>)>
           continue_callback);
 
 #if !defined(OS_FUCHSIA)
diff --git a/chromecast/browser/cast_content_browser_client_receiver_bindings.cc b/chromecast/browser/cast_content_browser_client_receiver_bindings.cc
index c1b2598..e82f43d 100644
--- a/chromecast/browser/cast_content_browser_client_receiver_bindings.cc
+++ b/chromecast/browser/cast_content_browser_client_receiver_bindings.cc
@@ -107,8 +107,9 @@
     blink::AssociatedInterfaceRegistry* associated_registry,
     content::RenderProcessHost* render_process_host) {
   registry->AddInterface(
-      base::Bind(&media::MediaCapsImpl::AddReceiver,
-                 base::Unretained(cast_browser_main_parts_->media_caps())),
+      base::BindRepeating(
+          &media::MediaCapsImpl::AddReceiver,
+          base::Unretained(cast_browser_main_parts_->media_caps())),
       base::ThreadTaskRunnerHandle::Get());
 
 #if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
@@ -117,8 +118,8 @@
   }
 
   registry->AddInterface(
-      base::Bind(&MemoryPressureControllerImpl::AddReceiver,
-                 base::Unretained(memory_pressure_controller_.get())),
+      base::BindRepeating(&MemoryPressureControllerImpl::AddReceiver,
+                          base::Unretained(memory_pressure_controller_.get())),
       base::ThreadTaskRunnerHandle::Get());
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 }
diff --git a/chromecast/browser/cast_display_configurator.cc b/chromecast/browser/cast_display_configurator.cc
index ed11ed17..a50e70ca 100644
--- a/chromecast/browser/cast_display_configurator.cc
+++ b/chromecast/browser/cast_display_configurator.cc
@@ -123,7 +123,7 @@
 // display::NativeDisplayObserver interface
 void CastDisplayConfigurator::OnConfigurationChanged() {
   DCHECK(delegate_);
-  delegate_->GetDisplays(base::Bind(
+  delegate_->GetDisplays(base::BindOnce(
       &CastDisplayConfigurator::OnDisplaysAcquired, weak_factory_.GetWeakPtr(),
       false /* force_initial_configure */));
 }
@@ -153,7 +153,7 @@
 void CastDisplayConfigurator::ForceInitialConfigure() {
   if (!delegate_)
     return;
-  delegate_->GetDisplays(base::Bind(
+  delegate_->GetDisplays(base::BindOnce(
       &CastDisplayConfigurator::OnDisplaysAcquired, weak_factory_.GetWeakPtr(),
       true /* force_initial_configure */));
 }
diff --git a/chromecast/browser/devtools/remote_debugging_server.cc b/chromecast/browser/devtools/remote_debugging_server.cc
index 6ac20e5..1b7bfdd4 100644
--- a/chromecast/browser/devtools/remote_debugging_server.cc
+++ b/chromecast/browser/devtools/remote_debugging_server.cc
@@ -57,7 +57,7 @@
   std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
     std::unique_ptr<net::UnixDomainServerSocket> socket(
         new net::UnixDomainServerSocket(
-            base::Bind(&content::CanUserConnectToDevTools),
+            base::BindRepeating(&content::CanUserConnectToDevTools),
             true /* use_abstract_namespace */));
     if (socket->BindAndListen(socket_name_, kBackLog) != net::OK)
       return std::unique_ptr<net::ServerSocket>();
diff --git a/chromecast/browser/extensions/cast_extension_system.cc b/chromecast/browser/extensions/cast_extension_system.cc
index 64b25634..9a3b61c 100644
--- a/chromecast/browser/extensions/cast_extension_system.cc
+++ b/chromecast/browser/extensions/cast_extension_system.cc
@@ -244,12 +244,12 @@
 
 void CastExtensionSystem::RegisterExtensionWithRequestContexts(
     const Extension* extension,
-    const base::Closure& callback) {
+    base::OnceClosure callback) {
   base::PostTaskAndReply(FROM_HERE, {BrowserThread::IO},
                          base::BindOnce(&InfoMap::AddExtension, info_map(),
                                         base::RetainedRef(extension),
                                         base::Time::Now(), false, false),
-                         callback);
+                         std::move(callback));
 }
 
 void CastExtensionSystem::UnregisterExtensionWithRequestContexts(
diff --git a/chromecast/browser/extensions/cast_extension_system.h b/chromecast/browser/extensions/cast_extension_system.h
index ff27b97..0afd025 100644
--- a/chromecast/browser/extensions/cast_extension_system.h
+++ b/chromecast/browser/extensions/cast_extension_system.h
@@ -75,7 +75,7 @@
   AppSorting* app_sorting() override;
   void RegisterExtensionWithRequestContexts(
       const Extension* extension,
-      const base::Closure& callback) override;
+      base::OnceClosure callback) override;
   void UnregisterExtensionWithRequestContexts(
       const std::string& extension_id,
       const UnloadedExtensionReason reason) override;
diff --git a/chromecast/browser/pref_service_helper.cc b/chromecast/browser/pref_service_helper.cc
index f543412..d6c1fb5 100644
--- a/chromecast/browser/pref_service_helper.cc
+++ b/chromecast/browser/pref_service_helper.cc
@@ -67,18 +67,18 @@
 
   RegisterPlatformPrefs(registry);
 
-  PrefServiceFactory prefServiceFactory;
-  prefServiceFactory.set_user_prefs(
+  PrefServiceFactory pref_service_factory;
+  pref_service_factory.set_user_prefs(
       base::MakeRefCounted<JsonPrefStore>(config_path));
-  prefServiceFactory.set_async(false);
+  pref_service_factory.set_async(false);
 
   PersistentPrefStore::PrefReadError prefs_read_error =
       PersistentPrefStore::PREF_READ_ERROR_NONE;
-  prefServiceFactory.set_read_error_callback(
-      base::Bind(&UserPrefsLoadError, &prefs_read_error));
+  pref_service_factory.set_read_error_callback(
+      base::BindRepeating(&UserPrefsLoadError, &prefs_read_error));
 
   std::unique_ptr<PrefService> pref_service(
-      prefServiceFactory.Create(registry));
+      pref_service_factory.Create(registry));
   if (prefs_read_error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
     LOG(ERROR) << "Cannot initialize chromecast config: "
                << config_path.value()
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc
index 73786c7..b94e5b4 100644
--- a/chromecast/browser/webview/web_content_controller.cc
+++ b/chromecast/browser/webview/web_content_controller.cc
@@ -8,6 +8,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chromecast/base/version.h"
 #include "chromecast/browser/webview/proto/webview.pb.h"
+#include "chromecast/browser/webview/webview_layout_manager.h"
 #include "chromecast/browser/webview/webview_navigation_throttle.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browsing_data_remover.h"
@@ -138,11 +139,9 @@
 void WebContentController::AttachTo(aura::Window* window, int window_id) {
   content::WebContents* contents = GetWebContents();
   auto* contents_window = contents->GetNativeView();
+  window->SetLayoutManager(new WebviewLayoutManager(window));
   contents_window->set_id(window_id);
   contents_window->SetBounds(gfx::Rect(window->bounds().size()));
-  // Set the initial webview size as we depend on the client to do further
-  // sizing.
-  contents_window->SetBounds(gfx::Rect(window->bounds().size()));
   // The aura window is hidden to avoid being shown via the usual layer method,
   // instead it is shows via a SurfaceDrawQuad by exo.
   contents_window->Hide();
@@ -156,8 +155,8 @@
   surface_->AddSurfaceObserver(this);
 
   // Unretained is safe because we unset this in the destructor.
-  surface_->SetEmbeddedSurfaceId(
-      base::Bind(&WebContentController::GetSurfaceId, base::Unretained(this)));
+  surface_->SetEmbeddedSurfaceId(base::BindRepeating(
+      &WebContentController::GetSurfaceId, base::Unretained(this)));
 
   current_rfh_ = GetWebContents()->GetMainFrame();
   if (current_rfh_) {
diff --git a/chromecast/browser/webview/webview_controller.cc b/chromecast/browser/webview/webview_controller.cc
index a03c0a1..62f112bb 100644
--- a/chromecast/browser/webview/webview_controller.cc
+++ b/chromecast/browser/webview/webview_controller.cc
@@ -12,6 +12,7 @@
 #include "chromecast/base/version.h"
 #include "chromecast/browser/cast_web_contents_impl.h"
 #include "chromecast/browser/webview/proto/webview.pb.h"
+#include "chromecast/browser/webview/webview_layout_manager.h"
 #include "chromecast/browser/webview/webview_navigation_throttle.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browsing_data_remover.h"
diff --git a/chromecast/browser/webview/webview_layout_manager.cc b/chromecast/browser/webview/webview_layout_manager.cc
new file mode 100644
index 0000000..fed2b397
--- /dev/null
+++ b/chromecast/browser/webview/webview_layout_manager.cc
@@ -0,0 +1,34 @@
+// Copyright 2019 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 "chromecast/browser/webview/webview_layout_manager.h"
+
+#include "ui/aura/window.h"
+
+namespace chromecast {
+
+WebviewLayoutManager::WebviewLayoutManager(aura::Window* root) : root_(root) {}
+
+WebviewLayoutManager::~WebviewLayoutManager() {}
+
+void WebviewLayoutManager::OnWindowResized() {
+  for (aura::Window* child : root_->children())
+    SetChildBoundsDirect(child, gfx::Rect(root_->bounds().size()));
+}
+
+void WebviewLayoutManager::OnWindowAddedToLayout(aura::Window* child) {}
+
+void WebviewLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {}
+
+void WebviewLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {}
+
+void WebviewLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
+                                                          bool visible) {}
+
+void WebviewLayoutManager::SetChildBounds(aura::Window* child,
+                                          const gfx::Rect& requested_bounds) {
+  SetChildBoundsDirect(child, requested_bounds);
+}
+
+}  // namespace chromecast
diff --git a/chromecast/browser/webview/webview_layout_manager.h b/chromecast/browser/webview/webview_layout_manager.h
new file mode 100644
index 0000000..194b85d
--- /dev/null
+++ b/chromecast/browser/webview/webview_layout_manager.h
@@ -0,0 +1,36 @@
+// Copyright 2019 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 CHROMECAST_BROWSER_WEBVIEW_WEBVIEW_LAYOUT_MANAGER_H_
+#define CHROMECAST_BROWSER_WEBVIEW_WEBVIEW_LAYOUT_MANAGER_H_
+
+#include "base/macros.h"
+#include "ui/aura/layout_manager.h"
+
+namespace chromecast {
+
+// Resizes the provided window to be the parent window's size.
+class WebviewLayoutManager : public aura::LayoutManager {
+ public:
+  WebviewLayoutManager(aura::Window* root);
+  ~WebviewLayoutManager() override;
+
+  void OnWindowResized() override;
+  void OnWindowAddedToLayout(aura::Window* child) override;
+  void OnWillRemoveWindowFromLayout(aura::Window* child) override;
+  void OnWindowRemovedFromLayout(aura::Window* child) override;
+  void OnChildWindowVisibilityChanged(aura::Window* child,
+                                      bool visible) override;
+  void SetChildBounds(aura::Window* child,
+                      const gfx::Rect& requested_bounds) override;
+
+ private:
+  aura::Window* root_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebviewLayoutManager);
+};
+
+}  // namespace chromecast
+
+#endif  // CHROMECAST_BROWSER_WEBVIEW_WEBVIEW_LAYOUT_MANAGER_H_
diff --git a/chromecast/crash/linux/crash_util.cc b/chromecast/crash/linux/crash_util.cc
index 6301453..a2de8f6 100644
--- a/chromecast/crash/linux/crash_util.cc
+++ b/chromecast/crash/linux/crash_util.cc
@@ -23,7 +23,7 @@
 // dumpstate routine to avoid calling an executable during an automated test.
 // This value should not be mutated through any other function except
 // CrashUtil::SetDumpStateCbForTest().
-static base::Callback<int(const std::string&)>* g_dumpstate_cb = nullptr;
+static base::OnceCallback<int(const std::string&)>* g_dumpstate_cb = nullptr;
 
 }  // namespace
 
@@ -57,8 +57,8 @@
 
   std::unique_ptr<MinidumpWriter> writer;
   if (g_dumpstate_cb) {
-    writer.reset(new MinidumpWriter(
-        &minidump_generator, filename.value(), params, *g_dumpstate_cb));
+    writer.reset(new MinidumpWriter(&minidump_generator, filename.value(),
+                                    params, std::move(*g_dumpstate_cb)));
   } else {
     writer.reset(
         new MinidumpWriter(&minidump_generator, filename.value(), params));
@@ -85,9 +85,10 @@
 }
 
 void CrashUtil::SetDumpStateCbForTest(
-    const base::Callback<int(const std::string&)>& cb) {
+    base::OnceCallback<int(const std::string&)> cb) {
   DCHECK(!g_dumpstate_cb);
-  g_dumpstate_cb = new base::Callback<int(const std::string&)>(cb);
+  g_dumpstate_cb =
+      new base::OnceCallback<int(const std::string&)>(std::move(cb));
 }
 
 }  // namespace chromecast
diff --git a/chromecast/crash/linux/crash_util.h b/chromecast/crash/linux/crash_util.h
index da66df7..3e8e3ef 100644
--- a/chromecast/crash/linux/crash_util.h
+++ b/chromecast/crash/linux/crash_util.h
@@ -29,7 +29,7 @@
   // in a seperate process. See MinidumpWriter::SetDumpStateCbForTest() for more
   // details on this callback's signature.
   static void SetDumpStateCbForTest(
-      const base::Callback<int(const std::string&)>& cb);
+      base::OnceCallback<int(const std::string&)> cb);
 };
 
 }  // namespace chromecast
diff --git a/chromecast/crash/linux/minidump_uploader.cc b/chromecast/crash/linux/minidump_uploader.cc
index f0588fe..2d7acf0 100644
--- a/chromecast/crash/linux/minidump_uploader.cc
+++ b/chromecast/crash/linux/minidump_uploader.cc
@@ -73,7 +73,7 @@
 MinidumpUploader::MinidumpUploader(CastSysInfo* sys_info,
                                    const std::string& server_url,
                                    CastCrashdumpUploader* const uploader,
-                                   const PrefServiceGeneratorCallback callback)
+                                   PrefServiceGeneratorCallback callback)
     : release_channel_(sys_info->GetSystemReleaseChannel()),
       product_name_(sys_info->GetProductName()),
       device_model_(sys_info->GetDeviceModel()),
@@ -87,14 +87,14 @@
       reboot_scheduled_(false),
       filestate_initialized_(false),
       uploader_(uploader),
-      pref_service_generator_(callback) {}
+      pref_service_generator_(std::move(callback)) {}
 
 MinidumpUploader::MinidumpUploader(CastSysInfo* sys_info,
                                    const std::string& server_url)
     : MinidumpUploader(sys_info,
                        server_url,
                        nullptr,
-                       base::Bind(&CreatePrefService)) {}
+                       base::BindOnce(&CreatePrefService)) {}
 
 MinidumpUploader::~MinidumpUploader() {}
 
@@ -126,7 +126,8 @@
 
   int num_uploaded = 0;
 
-  std::unique_ptr<PrefService> pref_service = pref_service_generator_.Run();
+  std::unique_ptr<PrefService> pref_service =
+      std::move(pref_service_generator_).Run();
   const std::string& client_id(
       pref_service->GetString(::metrics::prefs::kMetricsClientID));
   std::string virtual_channel(pref_service->GetString(kVirtualChannel));
diff --git a/chromecast/crash/linux/minidump_uploader.h b/chromecast/crash/linux/minidump_uploader.h
index 654d222..9721a925 100644
--- a/chromecast/crash/linux/minidump_uploader.h
+++ b/chromecast/crash/linux/minidump_uploader.h
@@ -23,14 +23,14 @@
 class MinidumpUploader : public SynchronizedMinidumpManager {
  public:
   using PrefServiceGeneratorCallback =
-      base::Callback<std::unique_ptr<PrefService>()>;
+      base::OnceCallback<std::unique_ptr<PrefService>()>;
 
   // If |server_url| is empty, a default server url will be chosen.
   MinidumpUploader(CastSysInfo* sys_info, const std::string& server_url);
   MinidumpUploader(CastSysInfo* sys_info,
                    const std::string& server_url,
                    CastCrashdumpUploader* const uploader,
-                   const PrefServiceGeneratorCallback callback);
+                   PrefServiceGeneratorCallback callback);
   ~MinidumpUploader() override;
 
   // Attempts to upload all minidumps in the minidumps directory. Acquires a
@@ -69,7 +69,7 @@
 
   // Used for injecting mocks/inducing different behavior in unittests.
   CastCrashdumpUploader* const uploader_;
-  const PrefServiceGeneratorCallback pref_service_generator_;
+  PrefServiceGeneratorCallback pref_service_generator_;
 
   DISALLOW_COPY_AND_ASSIGN(MinidumpUploader);
 };
diff --git a/chromecast/crash/linux/minidump_uploader_unittest.cc b/chromecast/crash/linux/minidump_uploader_unittest.cc
index 1dd22e8..11d297e 100644
--- a/chromecast/crash/linux/minidump_uploader_unittest.cc
+++ b/chromecast/crash/linux/minidump_uploader_unittest.cc
@@ -147,7 +147,7 @@
     MinidumpUploader* const minidump_uploader_;
   };
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+                            base::BindOnce(&CreateFakePrefService, true));
   // Will lock for the first run to initialize file state.
   ASSERT_TRUE(uploader.UploadAllMinidumps());
 
@@ -162,7 +162,7 @@
   // Write a dump info entry.
   GenerateDumpWithFiles(minidump_path, logfile_path);
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, false));
+                            base::BindOnce(&CreateFakePrefService, false));
 
   // MinidumpUploader should not call upon CastCrashdumpUploader.
   ASSERT_TRUE(uploader.UploadAllMinidumps());
@@ -184,7 +184,7 @@
   std::unique_ptr<DumpInfo> dump(
       GenerateDumpWithFiles(minidump_path, logfile_path));
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+                            base::BindOnce(&CreateFakePrefService, true));
 
   // Induce an upload failure.
   EXPECT_CALL(mock_crash_uploader(),
@@ -213,21 +213,23 @@
   GenerateDumpWithFiles(minidump_path, logfile_path);
   std::unique_ptr<DumpInfo> dump2(
       GenerateDumpWithFiles(minidump_path2, logfile_path2));
-  MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+  {
+    MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
+                              base::BindOnce(&CreateFakePrefService, true));
 
-  // First allow a successful upload, then induce failure.
-  EXPECT_CALL(mock_crash_uploader(),
-              AddAttachment("log_file", logfile_path.value()))
-      .WillOnce(Return(true));
-  EXPECT_CALL(mock_crash_uploader(),
-              AddAttachment("log_file", logfile_path2.value()))
-      .WillOnce(Return(true));
-  EXPECT_CALL(mock_crash_uploader(), SetParameter(_, _)).Times(AtLeast(0));
-  EXPECT_CALL(mock_crash_uploader(), Upload(_))
-      .WillOnce(Return(true))
-      .WillOnce(Return(false));
-  ASSERT_TRUE(uploader.UploadAllMinidumps());
+    // First allow a successful upload, then induce failure.
+    EXPECT_CALL(mock_crash_uploader(),
+                AddAttachment("log_file", logfile_path.value()))
+        .WillOnce(Return(true));
+    EXPECT_CALL(mock_crash_uploader(),
+                AddAttachment("log_file", logfile_path2.value()))
+        .WillOnce(Return(true));
+    EXPECT_CALL(mock_crash_uploader(), SetParameter(_, _)).Times(AtLeast(0));
+    EXPECT_CALL(mock_crash_uploader(), Upload(_))
+        .WillOnce(Return(true))
+        .WillOnce(Return(false));
+    ASSERT_TRUE(uploader.UploadAllMinidumps());
+  }
 
   // Info should exist in the lockfile, but should only be non-uploaded dump.
   DumpList dumps;
@@ -240,13 +242,18 @@
   ASSERT_TRUE(base::PathExists(minidump_path2));
   ASSERT_TRUE(base::PathExists(logfile_path2));
 
-  // Finally, upload successfully.
-  EXPECT_CALL(mock_crash_uploader(),
-              AddAttachment("log_file", logfile_path2.value()))
-      .WillOnce(Return(true));
-  EXPECT_CALL(mock_crash_uploader(), SetParameter(_, _)).Times(AtLeast(0));
-  EXPECT_CALL(mock_crash_uploader(), Upload(_)).WillOnce(Return(true));
-  ASSERT_TRUE(uploader.UploadAllMinidumps());
+  {
+    MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
+                              base::BindOnce(&CreateFakePrefService, true));
+
+    // Finally, upload successfully.
+    EXPECT_CALL(mock_crash_uploader(),
+                AddAttachment("log_file", logfile_path2.value()))
+        .WillOnce(Return(true));
+    EXPECT_CALL(mock_crash_uploader(), SetParameter(_, _)).Times(AtLeast(0));
+    EXPECT_CALL(mock_crash_uploader(), Upload(_)).WillOnce(Return(true));
+    ASSERT_TRUE(uploader.UploadAllMinidumps());
+  }
 
   // Ensure all dump files have been removed, lockfile has been emptied.
   int64_t size = -1;
@@ -265,7 +272,7 @@
   // Write one entry with appropriate files.
   GenerateDumpWithFiles(minidump_path, logfile_path);
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+                            base::BindOnce(&CreateFakePrefService, true));
 
   // No CastCrashdumpUploader methods should be called.
   ASSERT_TRUE(base::DeleteFile(minidump_path, false));
@@ -287,7 +294,7 @@
   // Write one entry with appropriate files.
   GenerateDumpWithFiles(minidump_path, logfile_path);
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+                            base::BindOnce(&CreateFakePrefService, true));
 
   // Delete logfile, crash uploader should still work as intended.
   ASSERT_TRUE(base::DeleteFile(logfile_path, false));
@@ -323,7 +330,7 @@
   // Write a real entry.
   GenerateDumpWithFiles(minidump_path, logfile_path);
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+                            base::BindOnce(&CreateFakePrefService, true));
 
   EXPECT_CALL(mock_crash_uploader(),
               AddAttachment("log_file", logfile_path.value()))
@@ -348,7 +355,7 @@
   const base::FilePath& logfile_path = minidump_dir_.Append("lmao");
 
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+                            base::BindOnce(&CreateFakePrefService, true));
   // Generate max dumps.
   for (int i = 0; i < SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps + 1;
        i++)
@@ -376,7 +383,7 @@
   // Generate one dump for a second pass.
   GenerateDumpWithFiles(minidump_path, logfile_path);
   MinidumpUploader uploader2(&sys_info_dummy(), "", &mock_crash_uploader(),
-                             base::Bind(&CreateFakePrefService, true));
+                             base::BindOnce(&CreateFakePrefService, true));
 
   // MinidumpUploader should not call CastCrashdumpUploader (due to ratelimit).
   // Reboot should NOT be scheduled, as this is second ratelimit.
@@ -393,7 +400,7 @@
 
 TEST_F(MinidumpUploaderTest, UploadInitializesFileState) {
   MinidumpUploader uploader(&sys_info_dummy(), "", &mock_crash_uploader(),
-                            base::Bind(&CreateFakePrefService, true));
+                            base::BindOnce(&CreateFakePrefService, true));
   ASSERT_TRUE(base::IsDirectoryEmpty(minidump_dir_));
   ASSERT_TRUE(uploader.UploadAllMinidumps());
   base::File lockfile(lockfile_, base::File::FLAG_OPEN | base::File::FLAG_READ);
diff --git a/chromecast/crash/linux/minidump_writer.cc b/chromecast/crash/linux/minidump_writer.cc
index bd9e56f3..0fb5a62 100644
--- a/chromecast/crash/linux/minidump_writer.cc
+++ b/chromecast/crash/linux/minidump_writer.cc
@@ -42,12 +42,11 @@
 MinidumpWriter::MinidumpWriter(MinidumpGenerator* minidump_generator,
                                const std::string& minidump_filename,
                                const MinidumpParams& params,
-                               const DumpStateCallback& dump_state_cb)
+                               DumpStateCallback dump_state_cb)
     : minidump_generator_(minidump_generator),
       minidump_path_(minidump_filename),
       params_(params),
-      dump_state_cb_(dump_state_cb) {
-}
+      dump_state_cb_(std::move(dump_state_cb)) {}
 
 MinidumpWriter::MinidumpWriter(MinidumpGenerator* minidump_generator,
                                const std::string& minidump_filename,
@@ -55,8 +54,7 @@
     : MinidumpWriter(minidump_generator,
                      minidump_filename,
                      params,
-                     base::Bind(&DumpState)) {
-}
+                     base::BindOnce(&DumpState)) {}
 
 MinidumpWriter::~MinidumpWriter() {
 }
@@ -80,8 +78,8 @@
   }
 
   // Run the dumpstate callback.
-  DCHECK(!dump_state_cb_.is_null());
-  if (dump_state_cb_.Run(minidump_path_.value()) < 0) {
+  DCHECK(dump_state_cb_);
+  if (std::move(dump_state_cb_).Run(minidump_path_.value()) < 0) {
     LOG(ERROR) << "DumpState callback failed.";
     return false;
   }
@@ -98,4 +96,4 @@
   return true;
 }
 
-}  // namespace crash_manager
+}  // namespace chromecast
diff --git a/chromecast/crash/linux/minidump_writer.h b/chromecast/crash/linux/minidump_writer.h
index c2381f6..3812c4a 100644
--- a/chromecast/crash/linux/minidump_writer.h
+++ b/chromecast/crash/linux/minidump_writer.h
@@ -20,7 +20,7 @@
 // directory.
 class MinidumpWriter : public SynchronizedMinidumpManager {
  public:
-  typedef base::Callback<int(const std::string&)> DumpStateCallback;
+  using DumpStateCallback = base::OnceCallback<int(const std::string&)>;
 
   // Constructs a writer for a minidump. If |minidump_filename| is absolute, it
   // must be a path to a file in the |dump_path_| directory. Otherwise, it
@@ -33,7 +33,7 @@
   MinidumpWriter(MinidumpGenerator* minidump_generator,
                  const std::string& minidump_filename,
                  const MinidumpParams& params,
-                 const base::Callback<int(const std::string&)>& dump_state_cb);
+                 DumpStateCallback dump_state_cb);
 
   // Like the constructor above, but the default implementation of
   // |dump_state_cb_| is used inside DoWork().
diff --git a/chromecast/crash/linux/minidump_writer_unittest.cc b/chromecast/crash/linux/minidump_writer_unittest.cc
index a80b7a02..84a904c6 100644
--- a/chromecast/crash/linux/minidump_writer_unittest.cc
+++ b/chromecast/crash/linux/minidump_writer_unittest.cc
@@ -83,37 +83,29 @@
 };
 
 TEST_F(MinidumpWriterTest, Write_FailsWithIncorrectMinidumpPath) {
-  MinidumpWriter writer(&fake_generator_,
-                        "/path/to/wrong/dir",
-                        MinidumpParams(),
-                        base::Bind(&FakeDumpState));
+  MinidumpWriter writer(&fake_generator_, "/path/to/wrong/dir",
+                        MinidumpParams(), base::BindOnce(&FakeDumpState));
 
   ASSERT_EQ(-1, writer.Write());
 }
 
 TEST_F(MinidumpWriterTest, Write_FailsWithMultiLevelRelativeMinidumpPath) {
-  MinidumpWriter writer(&fake_generator_,
-                        "subdir/dumplog",
-                        MinidumpParams(),
-                        base::Bind(&FakeDumpState));
+  MinidumpWriter writer(&fake_generator_, "subdir/dumplog", MinidumpParams(),
+                        base::BindOnce(&FakeDumpState));
 
   ASSERT_EQ(-1, writer.Write());
 }
 
 TEST_F(MinidumpWriterTest, Write_SucceedsWithSimpleFilename) {
-  MinidumpWriter writer(&fake_generator_,
-                        "dumplog",
-                        MinidumpParams(),
-                        base::Bind(&FakeDumpState));
+  MinidumpWriter writer(&fake_generator_, "dumplog", MinidumpParams(),
+                        base::BindOnce(&FakeDumpState));
 
   ASSERT_EQ(0, writer.Write());
 }
 
 TEST_F(MinidumpWriterTest, Write_SucceedsWithCorrectMinidumpPath) {
-  MinidumpWriter writer(&fake_generator_,
-                        dumplog_file_.value(),
-                        MinidumpParams(),
-                        base::Bind(&FakeDumpState));
+  MinidumpWriter writer(&fake_generator_, dumplog_file_.value(),
+                        MinidumpParams(), base::BindOnce(&FakeDumpState));
 
   ASSERT_EQ(0, writer.Write());
 }
@@ -121,8 +113,7 @@
 TEST_F(MinidumpWriterTest, Write_FailsWithSubdirInCorrectPath) {
   MinidumpWriter writer(&fake_generator_,
                         dumplog_file_.Append("subdir/logfile").value(),
-                        MinidumpParams(),
-                        base::Bind(&FakeDumpState));
+                        MinidumpParams(), base::BindOnce(&FakeDumpState));
   ASSERT_EQ(-1, writer.Write());
 }
 
diff --git a/chromecast/media/audio/cast_audio_manager_alsa_unittest.cc b/chromecast/media/audio/cast_audio_manager_alsa_unittest.cc
index 9a802ec..257c8c5 100644
--- a/chromecast/media/audio/cast_audio_manager_alsa_unittest.cc
+++ b/chromecast/media/audio/cast_audio_manager_alsa_unittest.cc
@@ -70,7 +70,8 @@
 
 TEST_F(CastAudioManagerAlsaTest, MakeAudioInputStream) {
   ::media::AudioInputStream* stream = audio_manager_->MakeAudioInputStream(
-      kDefaultAudioParams, kDefaultAlsaDevice, base::Bind(&OnLogMessage));
+      kDefaultAudioParams, kDefaultAlsaDevice,
+      base::BindRepeating(&OnLogMessage));
   ASSERT_TRUE(stream);
   EXPECT_TRUE(stream->Open());
   stream->Close();
diff --git a/chromecast/media/cdm/cast_cdm.cc b/chromecast/media/cdm/cast_cdm.cc
index 98979c17..b7fc55d 100644
--- a/chromecast/media/cdm/cast_cdm.cc
+++ b/chromecast/media/cdm/cast_cdm.cc
@@ -37,9 +37,10 @@
   ~CastCdmContextImpl() override {}
 
   // CastCdmContext implementation:
-  int RegisterPlayer(const base::Closure& new_key_cb,
-                     const base::Closure& cdm_unset_cb) override {
-    return cast_cdm_->RegisterPlayer(new_key_cb, cdm_unset_cb);
+  int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                     base::RepeatingClosure cdm_unset_cb) override {
+    return cast_cdm_->RegisterPlayer(std::move(new_key_cb),
+                                     std::move(cdm_unset_cb));
   }
 
   void UnregisterPlayer(int registration_id) override {
@@ -135,10 +136,11 @@
   InitializeInternal();
 }
 
-int CastCdm::RegisterPlayer(const base::Closure& new_key_cb,
-                            const base::Closure& cdm_unset_cb) {
+int CastCdm::RegisterPlayer(base::RepeatingClosure new_key_cb,
+                            base::RepeatingClosure cdm_unset_cb) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  return player_tracker_impl_->RegisterPlayer(new_key_cb, cdm_unset_cb);
+  return player_tracker_impl_->RegisterPlayer(std::move(new_key_cb),
+                                              std::move(cdm_unset_cb));
 }
 
 void CastCdm::UnregisterPlayer(int registration_id) {
diff --git a/chromecast/media/cdm/cast_cdm.h b/chromecast/media/cdm/cast_cdm.h
index 2477f63..f692f686 100644
--- a/chromecast/media/cdm/cast_cdm.h
+++ b/chromecast/media/cdm/cast_cdm.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 CHROMECAST_MEDIA_CDM_cast_cdm_H_
-#define CHROMECAST_MEDIA_CDM_cast_cdm_H_
+#ifndef CHROMECAST_MEDIA_CDM_CAST_CDM_H_
+#define CHROMECAST_MEDIA_CDM_CAST_CDM_H_
 
 #include <stdint.h>
 
@@ -50,8 +50,8 @@
       const ::media::SessionKeysChangeCB& session_keys_change_cb,
       const ::media::SessionExpirationUpdateCB& session_expiration_update_cb);
 
-  int RegisterPlayer(const base::Closure& new_key_cb,
-                     const base::Closure& cdm_unset_cb);
+  int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                     base::RepeatingClosure cdm_unset_cb);
   void UnregisterPlayer(int registration_id);
 
   // Returns the decryption context needed to decrypt frames encrypted with
@@ -118,4 +118,4 @@
 }  // namespace media
 }  // namespace chromecast
 
-#endif  // CHROMECAST_MEDIA_CDM_cast_cdm_H_
+#endif  // CHROMECAST_MEDIA_CDM_CAST_CDM_H_
diff --git a/chromecast/media/cdm/cast_cdm_context.h b/chromecast/media/cdm/cast_cdm_context.h
index 5b4296eb..89ed43c 100644
--- a/chromecast/media/cdm/cast_cdm_context.h
+++ b/chromecast/media/cdm/cast_cdm_context.h
@@ -26,8 +26,8 @@
 
   // Register a player with this CDM. |new_key_cb| will be called when a new
   // key is available. |cdm_unset_cb| will be called when the CDM is destroyed.
-  virtual int RegisterPlayer(const base::Closure& new_key_cb,
-                             const base::Closure& cdm_unset_cb) = 0;
+  virtual int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                             base::RepeatingClosure cdm_unset_cb) = 0;
 
   // Unregiester a player with this CDM. |registration_id| should be the id
   // returned by RegisterPlayer().
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
index df91515..3a2ab401 100644
--- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
+++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
@@ -257,7 +257,7 @@
           base::android::AttachCurrentThread(), j_audio_sink_audiotrack_impl_);
   LOG(INFO) << __func__ << "(" << this << "): Hit EOS, playout time left is "
             << playout_time_left_us << "us";
-  wait_for_eos_task_.Reset(base::Bind(
+  wait_for_eos_task_.Reset(base::BindOnce(
       &AudioSinkAndroidAudioTrackImpl::OnPlayoutDone, base::Unretained(this)));
   base::TimeDelta delay =
       base::TimeDelta::FromMicroseconds(playout_time_left_us);
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h
index d3feb44..4c222a35 100644
--- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h
+++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h
@@ -135,7 +135,7 @@
   base::Thread feeder_thread_;
   scoped_refptr<base::SingleThreadTaskRunner> feeder_task_runner_;
 
-  base::CancelableClosure wait_for_eos_task_;
+  base::CancelableOnceClosure wait_for_eos_task_;
 
   const scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
 
diff --git a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
index e20fdf1a..2ba3577 100644
--- a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
+++ b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
@@ -65,9 +65,10 @@
   }
 
   // CastCdmContext implementation:
-  int RegisterPlayer(const base::Closure& new_key_cb,
-                     const base::Closure& cdm_unset_cb) override {
-    return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb);
+  int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                     base::RepeatingClosure cdm_unset_cb) override {
+    return player_tracker_.RegisterPlayer(std::move(new_key_cb),
+                                          std::move(cdm_unset_cb));
   }
 
   void UnregisterPlayer(int registration_id) override {
diff --git a/chromeos/components/quick_answers/search_result_loader.cc b/chromeos/components/quick_answers/search_result_loader.cc
index e56ace1..8f734e7 100644
--- a/chromeos/components/quick_answers/search_result_loader.cc
+++ b/chromeos/components/quick_answers/search_result_loader.cc
@@ -70,8 +70,7 @@
 constexpr base::StringPiece kRawQueryKey = "rawQuery";
 constexpr base::StringPiece kClientTypeKey = "clientType";
 constexpr base::StringPiece kClientIdKey = "clientId";
-// TODO(llin): Update the client type after finalize on the client type.
-constexpr base::StringPiece kClientType = "EXPERIMENTAL";
+constexpr base::StringPiece kClientType = "QUICK_ANSWERS_CROS";
 
 std::string BuildSearchRequestPayload(const std::string& selected_text) {
   Value payload(Value::Type::DICTIONARY);
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc
index de45577..e99104b 100644
--- a/chromeos/login/auth/cryptohome_authenticator.cc
+++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -422,7 +422,7 @@
     }
   }
 
-  SystemSaltGetter::Get()->GetSystemSalt(base::Bind(
+  SystemSaltGetter::Get()->GetSystemSalt(base::BindOnce(
       &OnGetSystemSalt, attempt, resolver, ephemeral, create_if_nonexistent));
 }
 
@@ -657,8 +657,8 @@
   remove_user_data_on_failure_ = false;
   check_key_attempted_ = true;
   SystemSaltGetter::Get()->GetSystemSalt(
-      base::Bind(&CheckKey, current_state_->AsWeakPtr(),
-                 scoped_refptr<CryptohomeAuthenticator>(this)));
+      base::BindOnce(&CheckKey, current_state_->AsWeakPtr(),
+                     scoped_refptr<CryptohomeAuthenticator>(this)));
 }
 
 void CryptohomeAuthenticator::LoginAsSupervisedUser(
@@ -846,7 +846,7 @@
     const std::string& old_password) {
   migrate_attempted_ = true;
   current_state_->ResetCryptohomeStatus();
-  SystemSaltGetter::Get()->GetSystemSalt(base::Bind(
+  SystemSaltGetter::Get()->GetSystemSalt(base::BindOnce(
       &Migrate, current_state_->AsWeakPtr(),
       scoped_refptr<CryptohomeAuthenticator>(this), true, old_password));
 }
@@ -880,7 +880,7 @@
 
   CheckSafeModeOwnership(
       current_state_->user_context,
-      base::Bind(&CryptohomeAuthenticator::OnOwnershipChecked, this));
+      base::BindOnce(&CryptohomeAuthenticator::OnOwnershipChecked, this));
   return false;
 }
 
diff --git a/chromeos/login/auth/cryptohome_authenticator.h b/chromeos/login/auth/cryptohome_authenticator.h
index 8fc7b654..5141db6 100644
--- a/chromeos/login/auth/cryptohome_authenticator.h
+++ b/chromeos/login/auth/cryptohome_authenticator.h
@@ -192,7 +192,7 @@
  protected:
   ~CryptohomeAuthenticator() override;
 
-  typedef base::Callback<void(bool is_owner)> IsOwnerCallback;
+  using IsOwnerCallback = base::OnceCallback<void(bool is_owner)>;
 
   // Method to be implemented in child. Return |true| if user specified in
   // |context| exists on device.
@@ -206,7 +206,7 @@
   // parameter that indicates if user in |context| can act as an owner in
   // safe mode.
   virtual void CheckSafeModeOwnership(const UserContext& context,
-                                      const IsOwnerCallback& callback) = 0;
+                                      IsOwnerCallback callback) = 0;
 
  private:
   friend class CryptohomeAuthenticatorTest;
diff --git a/chromeos/login/auth/extended_authenticator.h b/chromeos/login/auth/extended_authenticator.h
index 76b856a..ca7b8a1b 100644
--- a/chromeos/login/auth/extended_authenticator.h
+++ b/chromeos/login/auth/extended_authenticator.h
@@ -36,8 +36,8 @@
     FAILED_TPM,    // Failed to mount/create cryptohome because of TPM error.
   };
 
-  typedef base::Callback<void(const std::string& result)> ResultCallback;
-  typedef base::Callback<void(const UserContext& context)> ContextCallback;
+  using ResultCallback = base::OnceCallback<void(const std::string& result)>;
+  using ContextCallback = base::OnceCallback<void(const UserContext& context)>;
 
   class NewAuthStatusConsumer {
    public:
@@ -61,12 +61,12 @@
   // an error otherwise. On success, the user ID hash (used as the mount point)
   // will be passed to |success_callback|.
   virtual void AuthenticateToMount(const UserContext& context,
-                                   const ResultCallback& success_callback) = 0;
+                                   ResultCallback success_callback) = 0;
 
   // This call will attempt to authenticate the user with the key (and key
   // label) in |context|. No further actions are taken after authentication.
   virtual void AuthenticateToCheck(const UserContext& context,
-                                   const base::Closure& success_callback) = 0;
+                                   base::OnceClosure success_callback) = 0;
 
   // Attempts to add a new |key| for the user identified/authorized by
   // |context|. If a key with the same label already exists, the behavior
@@ -76,7 +76,7 @@
   virtual void AddKey(const UserContext& context,
                       const cryptohome::KeyDefinition& key,
                       bool replace_existing,
-                      const base::Closure& success_callback) = 0;
+                      base::OnceClosure success_callback) = 0;
 
   // Attempts to perform an authorized update of the key in |context| with the
   // new |key|. The update is authorized by providing the |signature| of the
@@ -86,20 +86,20 @@
   virtual void UpdateKeyAuthorized(const UserContext& context,
                                    const cryptohome::KeyDefinition& key,
                                    const std::string& signature,
-                                   const base::Closure& success_callback) = 0;
+                                   base::OnceClosure success_callback) = 0;
 
   // Attempts to remove the key labeled |key_to_remove| for the user identified/
   // authorized by |context|. It is possible to remove the key used for
   // authorization, although it should be done with extreme care.
   virtual void RemoveKey(const UserContext& context,
                          const std::string& key_to_remove,
-                         const base::Closure& success_callback) = 0;
+                         base::OnceClosure success_callback) = 0;
 
   // Hashes the key in |user_context| with the system salt it its type is
   // KEY_TYPE_PASSWORD_PLAIN and passes the resulting UserContext to the
   // |callback|.
   virtual void TransformKeyIfNeeded(const UserContext& user_context,
-                                    const ContextCallback& callback) = 0;
+                                    ContextCallback callback) = 0;
 
  protected:
   ExtendedAuthenticator();
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc
index 4e48b55..2beca267 100644
--- a/chromeos/login/auth/extended_authenticator_impl.cc
+++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -49,7 +49,7 @@
     NewAuthStatusConsumer* consumer) {
   auto extended_authenticator =
       base::WrapRefCounted(new ExtendedAuthenticatorImpl(consumer));
-  SystemSaltGetter::Get()->GetSystemSalt(base::Bind(
+  SystemSaltGetter::Get()->GetSystemSalt(base::BindOnce(
       &ExtendedAuthenticatorImpl::OnSaltObtained, extended_authenticator));
   return extended_authenticator;
 }
@@ -59,7 +59,7 @@
     AuthStatusConsumer* consumer) {
   auto extended_authenticator =
       base::WrapRefCounted(new ExtendedAuthenticatorImpl(consumer));
-  SystemSaltGetter::Get()->GetSystemSalt(base::Bind(
+  SystemSaltGetter::Get()->GetSystemSalt(base::BindOnce(
       &ExtendedAuthenticatorImpl::OnSaltObtained, extended_authenticator));
   return extended_authenticator;
 }
@@ -80,78 +80,67 @@
 
 void ExtendedAuthenticatorImpl::AuthenticateToMount(
     const UserContext& context,
-    const ResultCallback& success_callback) {
+    ResultCallback success_callback) {
   TransformKeyIfNeeded(
-      context,
-      base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToMount,
-                 this,
-                 success_callback));
+      context, base::BindOnce(&ExtendedAuthenticatorImpl::DoAuthenticateToMount,
+                              this, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::AuthenticateToCheck(
     const UserContext& context,
-    const base::Closure& success_callback) {
+    base::OnceClosure success_callback) {
   TransformKeyIfNeeded(
-      context,
-      base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToCheck,
-                 this,
-                 success_callback));
+      context, base::BindOnce(&ExtendedAuthenticatorImpl::DoAuthenticateToCheck,
+                              this, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::AddKey(const UserContext& context,
                                        const cryptohome::KeyDefinition& key,
                                        bool clobber_if_exists,
-                                       const base::Closure& success_callback) {
+                                       base::OnceClosure success_callback) {
   TransformKeyIfNeeded(
-      context, base::Bind(&ExtendedAuthenticatorImpl::DoAddKey, this, key,
-                          clobber_if_exists, success_callback));
+      context, base::BindOnce(&ExtendedAuthenticatorImpl::DoAddKey, this, key,
+                              clobber_if_exists, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::UpdateKeyAuthorized(
     const UserContext& context,
     const cryptohome::KeyDefinition& key,
     const std::string& signature,
-    const base::Closure& success_callback) {
+    base::OnceClosure success_callback) {
   TransformKeyIfNeeded(
       context,
-      base::Bind(&ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized,
-                 this,
-                 key,
-                 signature,
-                 success_callback));
+      base::BindOnce(&ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized, this,
+                     key, signature, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::RemoveKey(const UserContext& context,
-                                      const std::string& key_to_remove,
-                                      const base::Closure& success_callback) {
-  TransformKeyIfNeeded(context,
-                       base::Bind(&ExtendedAuthenticatorImpl::DoRemoveKey,
-                                  this,
-                                  key_to_remove,
-                                  success_callback));
+                                          const std::string& key_to_remove,
+                                          base::OnceClosure success_callback) {
+  TransformKeyIfNeeded(
+      context, base::BindOnce(&ExtendedAuthenticatorImpl::DoRemoveKey, this,
+                              key_to_remove, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::TransformKeyIfNeeded(
     const UserContext& user_context,
-    const ContextCallback& callback) {
+    ContextCallback callback) {
   if (user_context.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN) {
-    callback.Run(user_context);
+    std::move(callback).Run(user_context);
     return;
   }
 
   if (!salt_obtained_) {
     system_salt_callbacks_.push_back(
-        base::Bind(&ExtendedAuthenticatorImpl::TransformKeyIfNeeded,
-                   this,
-                   user_context,
-                   callback));
+        base::BindOnce(&ExtendedAuthenticatorImpl::TransformKeyIfNeeded, this,
+                       user_context, std::move(callback)));
     return;
   }
 
   UserContext transformed_context = user_context;
   transformed_context.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
                                           system_salt_);
-  callback.Run(transformed_context);
+  std::move(callback).Run(transformed_context);
 }
 
 ExtendedAuthenticatorImpl::~ExtendedAuthenticatorImpl() = default;
@@ -159,17 +148,13 @@
 void ExtendedAuthenticatorImpl::OnSaltObtained(const std::string& system_salt) {
   salt_obtained_ = true;
   system_salt_ = system_salt;
-  for (std::vector<base::Closure>::const_iterator it =
-           system_salt_callbacks_.begin();
-       it != system_salt_callbacks_.end();
-       ++it) {
-    it->Run();
-  }
+  for (auto& callback : system_salt_callbacks_)
+    std::move(callback).Run();
   system_salt_callbacks_.clear();
 }
 
 void ExtendedAuthenticatorImpl::DoAuthenticateToMount(
-    const ResultCallback& success_callback,
+    ResultCallback success_callback,
     const UserContext& user_context) {
   RecordStartMarker("MountEx");
   const Key* const key = user_context.GetKey();
@@ -179,11 +164,11 @@
       cryptohome::CreateAuthorizationRequest(key->GetLabel(), key->GetSecret()),
       cryptohome::MountRequest(),
       base::BindOnce(&ExtendedAuthenticatorImpl::OnMountComplete, this,
-                     "MountEx", user_context, success_callback));
+                     "MountEx", user_context, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::DoAuthenticateToCheck(
-    const base::Closure& success_callback,
+    base::OnceClosure success_callback,
     const UserContext& user_context) {
   RecordStartMarker("CheckKeyEx");
   cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
@@ -192,13 +177,13 @@
           cryptohome_parameter_utils::CreateAuthorizationKeyDefFromUserContext(
               user_context)),
       cryptohome::CheckKeyRequest(),
-      base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
-                 "CheckKeyEx", user_context, success_callback));
+      base::BindOnce(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
+                     "CheckKeyEx", user_context, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::DoAddKey(const cryptohome::KeyDefinition& key,
                                          bool clobber_if_exists,
-                                         const base::Closure& success_callback,
+                                         base::OnceClosure success_callback,
                                          const UserContext& user_context) {
   RecordStartMarker("AddKeyEx");
 
@@ -211,14 +196,14 @@
       cryptohome::CreateAuthorizationRequest(auth_key->GetLabel(),
                                              auth_key->GetSecret()),
       request,
-      base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
-                 "AddKeyEx", user_context, success_callback));
+      base::BindOnce(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
+                     "AddKeyEx", user_context, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized(
     const cryptohome::KeyDefinition& key,
     const std::string& signature,
-    const base::Closure& success_callback,
+    base::OnceClosure success_callback,
     const UserContext& user_context) {
   RecordStartMarker("UpdateKeyAuthorized");
 
@@ -231,13 +216,14 @@
       cryptohome::CreateAuthorizationRequest(auth_key->GetLabel(),
                                              auth_key->GetSecret()),
       request,
-      base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
-                 "UpdateKeyAuthorized", user_context, success_callback));
+      base::BindOnce(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
+                     "UpdateKeyAuthorized", user_context,
+                     std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::DoRemoveKey(const std::string& key_to_remove,
-                                        const base::Closure& success_callback,
-                                        const UserContext& user_context) {
+                                            base::OnceClosure success_callback,
+                                            const UserContext& user_context) {
   RecordStartMarker("RemoveKeyEx");
 
   cryptohome::RemoveKeyRequest request;
@@ -248,14 +234,14 @@
       cryptohome::CreateAuthorizationRequest(auth_key->GetLabel(),
                                              auth_key->GetSecret()),
       request,
-      base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
-                 "RemoveKeyEx", user_context, success_callback));
+      base::BindOnce(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
+                     "RemoveKeyEx", user_context, std::move(success_callback)));
 }
 
 void ExtendedAuthenticatorImpl::OnMountComplete(
     const std::string& time_marker,
     const UserContext& user_context,
-    const ResultCallback& success_callback,
+    ResultCallback success_callback,
     base::Optional<cryptohome::BaseReply> reply) {
   cryptohome::MountError return_code =
       cryptohome::MountExReplyToMountError(reply);
@@ -263,8 +249,8 @@
   if (return_code == cryptohome::MOUNT_ERROR_NONE) {
     const std::string& mount_hash =
         cryptohome::MountExReplyToMountHash(reply.value());
-    if (!success_callback.is_null())
-      success_callback.Run(mount_hash);
+    if (success_callback)
+      std::move(success_callback).Run(mount_hash);
     if (old_consumer_) {
       UserContext copy = user_context;
       copy.SetUserIDHash(mount_hash);
@@ -294,13 +280,13 @@
 void ExtendedAuthenticatorImpl::OnOperationComplete(
     const std::string& time_marker,
     const UserContext& user_context,
-    const base::Closure& success_callback,
+    base::OnceClosure success_callback,
     bool success,
     cryptohome::MountError return_code) {
   RecordEndMarker(time_marker);
   if (return_code == cryptohome::MOUNT_ERROR_NONE) {
-    if (!success_callback.is_null())
-      success_callback.Run();
+    if (success_callback)
+      std::move(success_callback).Run();
     if (old_consumer_)
       old_consumer_->OnAuthSuccess(user_context);
     return;
diff --git a/chromeos/login/auth/extended_authenticator_impl.h b/chromeos/login/auth/extended_authenticator_impl.h
index 6874be3..ead2fc163 100644
--- a/chromeos/login/auth/extended_authenticator_impl.h
+++ b/chromeos/login/auth/extended_authenticator_impl.h
@@ -34,22 +34,22 @@
   // ExtendedAuthenticator:
   void SetConsumer(AuthStatusConsumer* consumer) override;
   void AuthenticateToMount(const UserContext& context,
-                           const ResultCallback& success_callback) override;
+                           ResultCallback success_callback) override;
   void AuthenticateToCheck(const UserContext& context,
-                           const base::Closure& success_callback) override;
+                           base::OnceClosure success_callback) override;
   void AddKey(const UserContext& context,
               const cryptohome::KeyDefinition& key,
               bool clobber_if_exists,
-              const base::Closure& success_callback) override;
+              base::OnceClosure success_callback) override;
   void UpdateKeyAuthorized(const UserContext& context,
                            const cryptohome::KeyDefinition& key,
                            const std::string& signature,
-                           const base::Closure& success_callback) override;
+                           base::OnceClosure success_callback) override;
   void RemoveKey(const UserContext& context,
                  const std::string& key_to_remove,
-                 const base::Closure& success_callback) override;
+                 base::OnceClosure success_callback) override;
   void TransformKeyIfNeeded(const UserContext& user_context,
-                            const ContextCallback& callback) override;
+                            ContextCallback callback) override;
 
  private:
   explicit ExtendedAuthenticatorImpl(NewAuthStatusConsumer* consumer);
@@ -60,36 +60,36 @@
   void OnSaltObtained(const std::string& system_salt);
 
   // Performs actual operation with fully configured |context|.
-  void DoAuthenticateToMount(const ResultCallback& success_callback,
+  void DoAuthenticateToMount(ResultCallback success_callback,
                              const UserContext& context);
-  void DoAuthenticateToCheck(const base::Closure& success_callback,
+  void DoAuthenticateToCheck(base::OnceClosure success_callback,
                              const UserContext& context);
   void DoAddKey(const cryptohome::KeyDefinition& key,
                 bool clobber_if_exists,
-                const base::Closure& success_callback,
+                base::OnceClosure success_callback,
                 const UserContext& context);
   void DoUpdateKeyAuthorized(const cryptohome::KeyDefinition& key,
                              const std::string& signature,
-                             const base::Closure& success_callback,
+                             base::OnceClosure success_callback,
                              const UserContext& context);
   void DoRemoveKey(const std::string& key_to_remove,
-                   const base::Closure& success_callback,
+                   base::OnceClosure success_callback,
                    const UserContext& context);
 
   // Inner operation callbacks.
   void OnMountComplete(const std::string& time_marker,
                        const UserContext& context,
-                       const ResultCallback& success_callback,
+                       ResultCallback success_callback,
                        base::Optional<cryptohome::BaseReply> reply);
   void OnOperationComplete(const std::string& time_marker,
                            const UserContext& context,
-                           const base::Closure& success_callback,
+                           base::OnceClosure success_callback,
                            bool success,
                            cryptohome::MountError return_code);
 
   bool salt_obtained_;
   std::string system_salt_;
-  std::vector<base::Closure> system_salt_callbacks_;
+  std::vector<base::OnceClosure> system_salt_callbacks_;
 
   NewAuthStatusConsumer* consumer_;
   AuthStatusConsumer* old_consumer_;
diff --git a/chromeos/login/auth/fake_extended_authenticator.cc b/chromeos/login/auth/fake_extended_authenticator.cc
index 3824690..836a420 100644
--- a/chromeos/login/auth/fake_extended_authenticator.cc
+++ b/chromeos/login/auth/fake_extended_authenticator.cc
@@ -34,14 +34,14 @@
 
 void FakeExtendedAuthenticator::AuthenticateToMount(
     const UserContext& context,
-    const ResultCallback& success_callback) {
+    ResultCallback success_callback) {
   if (expected_user_context_ == context) {
     UserContext reported_user_context(context);
     const std::string mount_hash =
         reported_user_context.GetAccountId().GetUserEmail() + "-hash";
     reported_user_context.SetUserIDHash(mount_hash);
-    if (!success_callback.is_null())
-      success_callback.Run(mount_hash);
+    if (success_callback)
+      std::move(success_callback).Run(mount_hash);
     OnAuthSuccess(reported_user_context);
     return;
   }
@@ -52,10 +52,10 @@
 
 void FakeExtendedAuthenticator::AuthenticateToCheck(
     const UserContext& context,
-    const base::Closure& success_callback) {
+    base::OnceClosure success_callback) {
   if (expected_user_context_ == context) {
-    if (!success_callback.is_null())
-      success_callback.Run();
+    if (success_callback)
+      std::move(success_callback).Run();
     OnAuthSuccess(context);
     return;
   }
@@ -65,9 +65,9 @@
 }
 
 void FakeExtendedAuthenticator::AddKey(const UserContext& context,
-                    const cryptohome::KeyDefinition& key,
-                    bool replace_existing,
-                    const base::Closure& success_callback) {
+                                       const cryptohome::KeyDefinition& key,
+                                       bool replace_existing,
+                                       base::OnceClosure success_callback) {
   NOTREACHED();
 }
 
@@ -75,21 +75,21 @@
     const UserContext& context,
     const cryptohome::KeyDefinition& key,
     const std::string& signature,
-    const base::Closure& success_callback) {
+    base::OnceClosure success_callback) {
   NOTREACHED();
 }
 
 void FakeExtendedAuthenticator::RemoveKey(const UserContext& context,
-                       const std::string& key_to_remove,
-                       const base::Closure& success_callback) {
+                                          const std::string& key_to_remove,
+                                          base::OnceClosure success_callback) {
   NOTREACHED();
 }
 
 void FakeExtendedAuthenticator::TransformKeyIfNeeded(
     const UserContext& user_context,
-    const ContextCallback& callback) {
-  if (!callback.is_null())
-    callback.Run(user_context);
+    ContextCallback callback) {
+  if (callback)
+    std::move(callback).Run(user_context);
 }
 
 void FakeExtendedAuthenticator::OnAuthSuccess(const UserContext& context) {
diff --git a/chromeos/login/auth/fake_extended_authenticator.h b/chromeos/login/auth/fake_extended_authenticator.h
index 80bb468..ad9c327 100644
--- a/chromeos/login/auth/fake_extended_authenticator.h
+++ b/chromeos/login/auth/fake_extended_authenticator.h
@@ -25,22 +25,22 @@
   // ExtendedAuthenticator:
   void SetConsumer(AuthStatusConsumer* consumer) override;
   void AuthenticateToMount(const UserContext& context,
-                           const ResultCallback& success_callback) override;
+                           ResultCallback success_callback) override;
   void AuthenticateToCheck(const UserContext& context,
-                           const base::Closure& success_callback) override;
+                           base::OnceClosure success_callback) override;
   void AddKey(const UserContext& context,
               const cryptohome::KeyDefinition& key,
               bool replace_existing,
-              const base::Closure& success_callback) override;
+              base::OnceClosure success_callback) override;
   void UpdateKeyAuthorized(const UserContext& context,
                            const cryptohome::KeyDefinition& key,
                            const std::string& signature,
-                           const base::Closure& success_callback) override;
+                           base::OnceClosure success_callback) override;
   void RemoveKey(const UserContext& context,
                  const std::string& key_to_remove,
-                 const base::Closure& success_callback) override;
+                 base::OnceClosure success_callback) override;
   void TransformKeyIfNeeded(const UserContext& user_context,
-                            const ContextCallback& callback) override;
+                            ContextCallback callback) override;
 
  private:
   ~FakeExtendedAuthenticator() override;
diff --git a/chromeos/login/auth/login_performer.cc b/chromeos/login/auth/login_performer.cc
index d0ee3c98..a449179 100644
--- a/chromeos/login/auth/login_performer.cc
+++ b/chromeos/login/auth/login_performer.cc
@@ -133,10 +133,9 @@
   auth_mode_ = auth_mode;
   user_context_ = user_context;
 
-  if (RunTrustedCheck(base::Bind(&LoginPerformer::DoPerformLogin,
-                                 weak_factory_.GetWeakPtr(),
-                                 user_context_,
-                                 auth_mode))) {
+  if (RunTrustedCheck(base::BindOnce(&LoginPerformer::DoPerformLogin,
+                                     weak_factory_.GetWeakPtr(), user_context_,
+                                     auth_mode))) {
     return;
   }
   DoPerformLogin(user_context_, auth_mode);
@@ -159,10 +158,10 @@
     case AuthorizationMode::kExternal: {
       RunOnlineWhitelistCheck(
           account_id, wildcard_match, user_context.GetRefreshToken(),
-          base::Bind(&LoginPerformer::StartLoginCompletion,
-                     weak_factory_.GetWeakPtr()),
-          base::Bind(&LoginPerformer::NotifyWhitelistCheckFailure,
-                     weak_factory_.GetWeakPtr()));
+          base::BindOnce(&LoginPerformer::StartLoginCompletion,
+                         weak_factory_.GetWeakPtr()),
+          base::BindOnce(&LoginPerformer::NotifyWhitelistCheckFailure,
+                         weak_factory_.GetWeakPtr()));
       break;
     }
     case AuthorizationMode::kInternal:
@@ -182,9 +181,9 @@
                << user_context_.GetUserType();
   }
 
-  if (RunTrustedCheck(base::Bind(&LoginPerformer::TrustedLoginAsSupervisedUser,
-                                 weak_factory_.GetWeakPtr(),
-                                 user_context_))) {
+  if (RunTrustedCheck(
+          base::BindOnce(&LoginPerformer::TrustedLoginAsSupervisedUser,
+                         weak_factory_.GetWeakPtr(), user_context_))) {
     return;
   }
   TrustedLoginAsSupervisedUser(user_context_);
diff --git a/chromeos/login/auth/login_performer.h b/chromeos/login/auth/login_performer.h
index 034b66ce..d8ab899 100644
--- a/chromeos/login/auth/login_performer.h
+++ b/chromeos/login/auth/login_performer.h
@@ -139,17 +139,16 @@
   // Run trusted check for a platform. If trusted check have to be performed
   // asynchronously, |false| will be returned, and either delegate's
   // PolicyLoadFailed() or |callback| will be called upon actual check.
-  virtual bool RunTrustedCheck(const base::Closure& callback) = 0;
+  virtual bool RunTrustedCheck(base::OnceClosure callback) = 0;
 
   // This method should run addional online check if user can sign in on device.
   // Either |success_callback| or |failure_callback| should be called upon this
   // check.
-  virtual void RunOnlineWhitelistCheck(
-      const AccountId& account_id,
-      bool wildcard_match,
-      const std::string& refresh_token,
-      const base::Closure& success_callback,
-      const base::Closure& failure_callback) = 0;
+  virtual void RunOnlineWhitelistCheck(const AccountId& account_id,
+                                       bool wildcard_match,
+                                       const std::string& refresh_token,
+                                       base::OnceClosure success_callback,
+                                       base::OnceClosure failure_callback) = 0;
 
   // Supervised users-related methods.
 
diff --git a/chromeos/profiles/airmont.afdo.newest.txt b/chromeos/profiles/airmont.afdo.newest.txt
index 8eb5e0b..cefdc43 100644
--- a/chromeos/profiles/airmont.afdo.newest.txt
+++ b/chromeos/profiles/airmont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-airmont-81-3987.18-1577702544-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-airmont-81-3987.18-1578309018-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/profiles/broadwell.afdo.newest.txt b/chromeos/profiles/broadwell.afdo.newest.txt
index 54af3c8..0dc5db1 100644
--- a/chromeos/profiles/broadwell.afdo.newest.txt
+++ b/chromeos/profiles/broadwell.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-broadwell-81-3987.18-1577704324-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-broadwell-81-3987.18-1578307857-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/profiles/silvermont.afdo.newest.txt b/chromeos/profiles/silvermont.afdo.newest.txt
index 3d369a5e..730ee9d4 100644
--- a/chromeos/profiles/silvermont.afdo.newest.txt
+++ b/chromeos/profiles/silvermont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-silvermont-81-3987.18-1577705382-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-silvermont-81-3987.18-1578307131-benchmark-81.0.4016.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/settings/cros_settings_provider.h b/chromeos/settings/cros_settings_provider.h
index 88ea8205..7bca8e8 100644
--- a/chromeos/settings/cros_settings_provider.h
+++ b/chromeos/settings/cros_settings_provider.h
@@ -48,10 +48,11 @@
   // Requests the provider to fetch its values from a trusted store, if it
   // hasn't done so yet. Returns TRUSTED if the values returned by this provider
   // are trusted during the current loop cycle. Otherwise returns
-  // TEMPORARILY_UNTRUSTED, and |callback| will be invoked later when trusted
-  // values become available, PrepareTrustedValues() should be tried again in
-  // that case. Returns PERMANENTLY_UNTRUSTED if a permanent error has occurred.
-  virtual TrustedStatus PrepareTrustedValues(base::OnceClosure callback) = 0;
+  // TEMPORARILY_UNTRUSTED, takes ownership of |callback|, and will invoke it
+  // later when trusted values become available. PrepareTrustedValues() should
+  // be tried again in that case. Returns PERMANENTLY_UNTRUSTED if a permanent
+  // error has occurred.
+  virtual TrustedStatus PrepareTrustedValues(base::OnceClosure* callback) = 0;
 
   // Gets the namespace prefix provided by this provider.
   virtual bool HandlesSetting(const std::string& path) const = 0;
diff --git a/chromeos/settings/system_settings_provider.cc b/chromeos/settings/system_settings_provider.cc
index 1f3939b..d766af7 100644
--- a/chromeos/settings/system_settings_provider.cc
+++ b/chromeos/settings/system_settings_provider.cc
@@ -73,7 +73,7 @@
 
 // The timezone is always trusted.
 CrosSettingsProvider::TrustedStatus
-SystemSettingsProvider::PrepareTrustedValues(base::OnceClosure cb) {
+SystemSettingsProvider::PrepareTrustedValues(base::OnceClosure* cb) {
   return TRUSTED;
 }
 
diff --git a/chromeos/settings/system_settings_provider.h b/chromeos/settings/system_settings_provider.h
index 96bc3f1..258904f 100644
--- a/chromeos/settings/system_settings_provider.h
+++ b/chromeos/settings/system_settings_provider.h
@@ -31,7 +31,7 @@
 
   // CrosSettingsProvider implementation.
   const base::Value* Get(const std::string& path) const override;
-  TrustedStatus PrepareTrustedValues(base::OnceClosure callback) override;
+  TrustedStatus PrepareTrustedValues(base::OnceClosure* callback) override;
   bool HandlesSetting(const std::string& path) const override;
 
   // TimezoneSettings::Observer implementation.
diff --git a/components/arc/session/arc_session_impl_unittest.cc b/components/arc/session/arc_session_impl_unittest.cc
index d48fd47..fbcf8e3 100644
--- a/components/arc/session/arc_session_impl_unittest.cc
+++ b/components/arc/session/arc_session_impl_unittest.cc
@@ -25,7 +25,6 @@
 #include "components/user_manager/fake_user_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/version_info/channel.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace arc {
diff --git a/components/arc/test/fake_app_instance.h b/components/arc/test/fake_app_instance.h
index 5f792bd..9d7bb7f 100644
--- a/components/arc/test/fake_app_instance.h
+++ b/components/arc/test/fake_app_instance.h
@@ -12,7 +12,6 @@
 
 #include "base/macros.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
 
 namespace arc {
 
diff --git a/components/arc/test/fake_bluetooth_instance.h b/components/arc/test/fake_bluetooth_instance.h
index 95b12b9..5da3d35 100644
--- a/components/arc/test/fake_bluetooth_instance.h
+++ b/components/arc/test/fake_bluetooth_instance.h
@@ -10,7 +10,6 @@
 
 #include "base/macros.h"
 #include "components/arc/mojom/bluetooth.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
 
 namespace device {
 class BluetoothUUID;
diff --git a/components/arc/volume_mounter/arc_volume_mounter_bridge.h b/components/arc/volume_mounter/arc_volume_mounter_bridge.h
index 27cf43fa..3caaa3d 100644
--- a/components/arc/volume_mounter/arc_volume_mounter_bridge.h
+++ b/components/arc/volume_mounter/arc_volume_mounter_bridge.h
@@ -14,7 +14,6 @@
 #include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
-#include "mojo/public/cpp/bindings/binding.h"
 
 namespace content {
 class BrowserContext;
diff --git a/components/browser_watcher/watcher_metrics_provider_win.cc b/components/browser_watcher/watcher_metrics_provider_win.cc
index d535722..79776db 100644
--- a/components/browser_watcher/watcher_metrics_provider_win.cc
+++ b/components/browser_watcher/watcher_metrics_provider_win.cc
@@ -222,12 +222,12 @@
   RecordExitCodes(registry_path_);
 }
 
-void WatcherMetricsProviderWin::AsyncInit(const base::Closure& done_callback) {
+void WatcherMetricsProviderWin::AsyncInit(base::OnceClosure done_callback) {
   task_runner_->PostTaskAndReply(
       FROM_HERE,
       base::BindOnce(&WatcherMetricsProviderWin::CollectPostmortemReportsImpl,
                      weak_ptr_factory_.GetWeakPtr()),
-      done_callback);
+      std::move(done_callback));
 }
 
 // TODO(manzagop): consider mechanisms for partial collection if this is to be
diff --git a/components/browser_watcher/watcher_metrics_provider_win.h b/components/browser_watcher/watcher_metrics_provider_win.h
index ef3c981..9904be6c 100644
--- a/components/browser_watcher/watcher_metrics_provider_win.h
+++ b/components/browser_watcher/watcher_metrics_provider_win.h
@@ -33,7 +33,7 @@
   ~WatcherMetricsProviderWin() override;
 
   // metrics::MetricsProvider implementation.
-  void AsyncInit(const base::Closure& done_callback) override;
+  void AsyncInit(base::OnceClosure done_callback) override;
   void OnRecordingEnabled() override;
   void OnRecordingDisabled() override;
   // Note: this function collects metrics, some of which are related to the
diff --git a/components/cast_channel/cast_socket.cc b/components/cast_channel/cast_socket.cc
index 37ec614b..6386c6f4 100644
--- a/components/cast_channel/cast_socket.cc
+++ b/components/cast_channel/cast_socket.cc
@@ -231,8 +231,8 @@
   // Set up connection timeout.
   if (open_params_.connect_timeout.InMicroseconds() > 0) {
     DCHECK(connect_timeout_callback_.IsCancelled());
-    connect_timeout_callback_.Reset(
-        base::Bind(&CastSocketImpl::OnConnectTimeout, base::Unretained(this)));
+    connect_timeout_callback_.Reset(base::BindOnce(
+        &CastSocketImpl::OnConnectTimeout, base::Unretained(this)));
     GetTimer()->Start(FROM_HERE, open_params_.connect_timeout,
                       connect_timeout_callback_.callback());
   }
diff --git a/components/cast_channel/cast_socket.h b/components/cast_channel/cast_socket.h
index 3226ac8..4d1726d1 100644
--- a/components/cast_channel/cast_socket.h
+++ b/components/cast_channel/cast_socket.h
@@ -374,7 +374,7 @@
   std::vector<OnOpenCallback> connect_callbacks_;
 
   // Callback invoked by |connect_timeout_timer_| to cancel the connection.
-  base::CancelableClosure connect_timeout_callback_;
+  base::CancelableOnceClosure connect_timeout_callback_;
 
   // Timer invoked when the connection has timed out.
   std::unique_ptr<base::OneShotTimer> connect_timeout_timer_;
diff --git a/components/cast_channel/cast_test_util.h b/components/cast_channel/cast_test_util.h
index ff8cd31e..39fd20c 100644
--- a/components/cast_channel/cast_test_util.h
+++ b/components/cast_channel/cast_test_util.h
@@ -96,13 +96,13 @@
 
   MOCK_METHOD2(OpenSocketInternal,
                void(const net::IPEndPoint& ip_endpoint,
-                    const base::Callback<void(CastSocket*)>& open_cb));
+                    const base::RepeatingCallback<void(CastSocket*)>& open_cb));
   MOCK_CONST_METHOD1(GetSocket, CastSocket*(int channel_id));
 };
 
 class MockCastSocket : public CastSocket {
  public:
-  using MockOnOpenCallback = base::Callback<void(CastSocket* socket)>;
+  using MockOnOpenCallback = base::RepeatingCallback<void(CastSocket* socket)>;
 
   MockCastSocket();
   ~MockCastSocket() override;
diff --git a/components/crash/content/app/crashpad_linux.cc b/components/crash/content/app/crashpad_linux.cc
index c09535f02..b0716b9 100644
--- a/components/crash/content/app/crashpad_linux.cc
+++ b/components/crash/content/app/crashpad_linux.cc
@@ -163,6 +163,7 @@
     if (crash_reporter_client->IsRunningUnattended()) {
       arguments.push_back(base::StringPrintf("--minidump-dir-for-tests=%s",
                                              database_path.value().c_str()));
+      arguments.push_back("--always-allow-feedback");
     }
 #endif
 
diff --git a/components/cronet/stale_host_resolver.cc b/components/cronet/stale_host_resolver.cc
index 5097042..58fb0c8 100644
--- a/components/cronet/stale_host_resolver.cc
+++ b/components/cronet/stale_host_resolver.cc
@@ -216,8 +216,10 @@
   cache_parameters.source = net::HostResolverSource::LOCAL_ONLY;
   cache_request_ = resolver_->inner_resolver_->CreateRequest(
       host_, network_isolation_key_, net_log_, cache_parameters);
-  cache_error_ =
+  int error =
       cache_request_->Start(base::BindOnce([](int error) { NOTREACHED(); }));
+  DCHECK_NE(net::ERR_IO_PENDING, error);
+  cache_error_ = cache_request_->GetResolveErrorInfo().error;
   DCHECK_NE(net::ERR_IO_PENDING, cache_error_);
   // If it's a fresh cache hit (or literal), return it synchronously.
   if (cache_error_ != net::ERR_DNS_CACHE_MISS &&
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc
index 39458ff9..f7aaa3e 100644
--- a/components/download/internal/common/in_progress_download_manager.cc
+++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -225,6 +225,14 @@
         url_loader_factory_provider,
     UrlDownloadHandler* downloader,
     DownloadUrlParameters::OnStartedCallback callback) {
+  // If a new download's GUID already exists, skip it.
+  if (!download_create_info->guid.empty() &&
+      download_create_info->is_new_download &&
+      GetDownloadByGuid(download_create_info->guid)) {
+    LOG(WARNING) << "A download with the same GUID already exists, the new "
+                    "request is ignored.";
+    return;
+  }
   StartDownload(std::move(download_create_info), std::move(input_stream),
                 std::move(url_loader_factory_provider),
                 base::BindOnce(&InProgressDownloadManager::CancelUrlDownload,
@@ -380,11 +388,10 @@
 void InProgressDownloadManager::DetermineDownloadTarget(
     DownloadItemImpl* download,
     DownloadTargetCallback callback) {
-#if defined(OS_ANDROID)
   base::FilePath target_path = download->GetForcedFilePath().empty()
                                    ? download->GetTargetFilePath()
                                    : download->GetForcedFilePath();
-
+#if defined(OS_ANDROID)
   if (target_path.empty()) {
     std::move(callback).Run(target_path,
                             DownloadItem::TARGET_DISPOSITION_OVERWRITE,
@@ -416,9 +423,12 @@
                      download->GetDangerType(), intermediate_path_cb_,
                      download->GetForcedFilePath()));
 #else
-  std::move(callback).Run(download->GetTargetFilePath(),
+  // For non-android, the code below is only used by tests.
+  base::FilePath intermediate_path =
+      download->GetFullPath().empty() ? target_path : download->GetFullPath();
+  std::move(callback).Run(target_path,
                           DownloadItem::TARGET_DISPOSITION_OVERWRITE,
-                          download->GetDangerType(), download->GetFullPath(),
+                          download->GetDangerType(), intermediate_path,
                           DOWNLOAD_INTERRUPT_REASON_NONE);
 #endif  // defined(OS_ANDROID)
 }
@@ -500,6 +510,8 @@
       auto download = std::make_unique<DownloadItemImpl>(
           this, DownloadItem::kInvalidId, *info);
       OnNewDownloadCreated(download.get());
+      guid = download->GetGuid();
+      DCHECK(!guid.empty());
       in_progress_downloads_.push_back(std::move(download));
     }
     StartDownloadWithItem(
diff --git a/components/download/internal/common/resource_downloader.cc b/components/download/internal/common/resource_downloader.cc
index 424f8bdf..b188dd5 100644
--- a/components/download/internal/common/resource_downloader.cc
+++ b/components/download/internal/common/resource_downloader.cc
@@ -266,10 +266,6 @@
       FROM_HERE, base::BindOnce(upload_callback_, bytes_uploaded));
 }
 
-void ResourceDownloader::CancelRequest() {
-  Destroy();
-}
-
 void ResourceDownloader::Destroy() {
   if (wake_lock_)
     wake_lock_->CancelWakeLock();
diff --git a/components/download/internal/common/resource_downloader.h b/components/download/internal/common/resource_downloader.h
index 5b9a797..a0ff733d 100644
--- a/components/download/internal/common/resource_downloader.h
+++ b/components/download/internal/common/resource_downloader.h
@@ -101,9 +101,6 @@
       mojo::ScopedDataPipeConsumerHandle response_body,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
 
-  // UrlDownloadHandler implementations.
-  void CancelRequest() override;
-
   // Ask the |delegate_| to destroy this object.
   void Destroy();
 
diff --git a/components/download/public/common/download_file_impl.h b/components/download/public/common/download_file_impl.h
index 24c64cd7..fd53ae860 100644
--- a/components/download/public/common/download_file_impl.h
+++ b/components/download/public/common/download_file_impl.h
@@ -30,7 +30,6 @@
 #include "components/download/public/common/download_save_info.h"
 #include "components/download/public/common/rate_estimator.h"
 #include "components/services/quarantine/public/mojom/quarantine.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 
 namespace download {
diff --git a/components/download/public/common/url_download_handler.h b/components/download/public/common/url_download_handler.h
index 3f4a9d1..f672c71 100644
--- a/components/download/public/common/url_download_handler.h
+++ b/components/download/public/common/url_download_handler.h
@@ -41,15 +41,6 @@
   UrlDownloadHandler() = default;
   virtual ~UrlDownloadHandler() = default;
 
-  // Called on the io thread to pause the url request.
-  virtual void PauseRequest() {}
-
-  // Called on the io thread to resume the url request.
-  virtual void ResumeRequest() {}
-
-  // Called on the io thread to cancel the url request.
-  virtual void CancelRequest() {}
-
   DISALLOW_COPY_AND_ASSIGN(UrlDownloadHandler);
 };
 
diff --git a/components/exo/wayland/clients/perftests.cc b/components/exo/wayland/clients/perftests.cc
index 92112c79..8bca2c2 100644
--- a/components/exo/wayland/clients/perftests.cc
+++ b/components/exo/wayland/clients/perftests.cc
@@ -3,15 +3,30 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "base/strings/stringprintf.h"
 #include "components/exo/wayland/clients/blur.h"
 #include "components/exo/wayland/clients/simple.h"
 #include "components/exo/wayland/clients/test/wayland_client_test.h"
-#include "testing/perf/perf_test.h"
+#include "testing/perf/perf_result_reporter.h"
 
 namespace {
 
 using WaylandClientPerfTests = exo::WaylandClientTest;
 
+constexpr char kMetricPrefixWaylandClient[] = "WaylandClient.";
+constexpr char kMetricFramerate[] = "framerate";
+constexpr char kMetricPresentationLatency[] = "presentation_latency";
+constexpr char kStorySimple[] = "simple";
+constexpr char kStoryPrefixBlurSigma[] = "blur_sigma_%d";
+constexpr char kStoryPrefixBlurSigmaY[] = "blur_sigma_y_%d";
+
+perf_test::PerfResultReporter SetUpReporter(const std::string& story) {
+  perf_test::PerfResultReporter reporter(kMetricPrefixWaylandClient, story);
+  reporter.RegisterImportantMetric(kMetricFramerate, "fps");
+  reporter.RegisterImportantMetric(kMetricPresentationLatency, "us");
+  return reporter;
+}
+
 // Test simple double-buffered client performance.
 TEST_F(WaylandClientPerfTests, Simple) {
   const int kWarmUpFrames = 20;
@@ -32,15 +47,14 @@
   client.Run(kTestFrames, false, &feedback);
   auto time_delta = base::Time::Now() - start_time;
   float fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "SimpleFrameRate", fps,
-                         "frames/s", true);
+  auto reporter = SetUpReporter(kStorySimple);
+  reporter.AddResult(kMetricFramerate, fps);
+
   auto average_latency =
       feedback.num_frames_presented
           ? feedback.total_presentation_latency / feedback.num_frames_presented
           : base::TimeDelta::Max();
-  perf_test::PrintResult(
-      "WaylandClientPerfTests", "", "SimplePresentationLatency",
-      static_cast<size_t>(average_latency.InMicroseconds()), "us", true);
+  reporter.AddResult(kMetricPresentationLatency, average_latency);
 }
 
 class WaylandClientBlurPerfTests
@@ -74,40 +88,16 @@
 
   client.Run(0, 0, 0, false, kWarmUpFrames);
 
-  auto start_time = base::Time::Now();
-  client.Run(0, 0, max_sigma(), kOffscreen, kTestFrames);
-  auto time_delta = base::Time::Now() - start_time;
-  float fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigma0", fps,
-                         "frames/s", true);
+  constexpr int blur_values[] = {0, 5, 15, 30, 50};
 
-  start_time = base::Time::Now();
-  client.Run(5, 5, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigma5", fps,
-                         "frames/s", true);
-
-  start_time = base::Time::Now();
-  client.Run(15, 15, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigma15", fps,
-                         "frames/s", true);
-
-  start_time = base::Time::Now();
-  client.Run(30, 30, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigma30", fps,
-                         "frames/s", true);
-
-  start_time = base::Time::Now();
-  client.Run(50, 50, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigma50", fps,
-                         "frames/s", true);
+  for (int bv : blur_values) {
+    auto start_time = base::Time::Now();
+    client.Run(bv, bv, max_sigma(), kOffscreen, kTestFrames);
+    auto time_delta = base::Time::Now() - start_time;
+    float fps = kTestFrames / time_delta.InSecondsF();
+    SetUpReporter(base::StringPrintf(kStoryPrefixBlurSigma, bv))
+        .AddResult(kMetricFramerate, fps);
+  }
 }
 
 TEST_P(WaylandClientBlurPerfTests, BlurSigmaY) {
@@ -124,40 +114,16 @@
 
   client.Run(0, 0, 0, false, kWarmUpFrames);
 
-  auto start_time = base::Time::Now();
-  client.Run(0, 0, max_sigma(), kOffscreen, kTestFrames);
-  auto time_delta = base::Time::Now() - start_time;
-  float fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigmaY0", fps,
-                         "frames/s", true);
+  constexpr int blur_values[] = {0, 5, 10, 25, 50};
 
-  start_time = base::Time::Now();
-  client.Run(0, 5, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigmaY5", fps,
-                         "frames/s", true);
-
-  start_time = base::Time::Now();
-  client.Run(0, 10, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigmaY10", fps,
-                         "frames/s", true);
-
-  start_time = base::Time::Now();
-  client.Run(0, 25, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigmaY25", fps,
-                         "frames/s", true);
-
-  start_time = base::Time::Now();
-  client.Run(0, 50, max_sigma(), kOffscreen, kTestFrames);
-  time_delta = base::Time::Now() - start_time;
-  fps = kTestFrames / time_delta.InSecondsF();
-  perf_test::PrintResult("WaylandClientPerfTests", "", "BlurSigmaY50", fps,
-                         "frames/s", true);
+  for (int bv : blur_values) {
+    auto start_time = base::Time::Now();
+    client.Run(0, bv, max_sigma(), kOffscreen, kTestFrames);
+    auto time_delta = base::Time::Now() - start_time;
+    float fps = kTestFrames / time_delta.InSecondsF();
+    SetUpReporter(base::StringPrintf(kStoryPrefixBlurSigmaY, bv))
+        .AddResult(kMetricFramerate, fps);
+  }
 }
 
 }  // namespace
diff --git a/components/gwp_asan/OWNERS b/components/gwp_asan/OWNERS
index 26e52daa..5f52e60 100644
--- a/components/gwp_asan/OWNERS
+++ b/components/gwp_asan/OWNERS
@@ -1,3 +1,2 @@
 vitalybuka@chromium.org
-vtsyrklevich@chromium.org
 # COMPONENT: Internals>Instrumentation
diff --git a/components/infobars/core/confirm_infobar_delegate.cc b/components/infobars/core/confirm_infobar_delegate.cc
index e9a01cc4..fc38dc0 100644
--- a/components/infobars/core/confirm_infobar_delegate.cc
+++ b/components/infobars/core/confirm_infobar_delegate.cc
@@ -5,17 +5,13 @@
 #include "components/infobars/core/confirm_infobar_delegate.h"
 
 #include "base/logging.h"
-#include "components/infobars/core/infobar.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/strings/grit/ui_strings.h"
 
-using infobars::InfoBarDelegate;
+ConfirmInfoBarDelegate::~ConfirmInfoBarDelegate() = default;
 
-ConfirmInfoBarDelegate::~ConfirmInfoBarDelegate() {
-}
-
-InfoBarDelegate::InfoBarAutomationType
-    ConfirmInfoBarDelegate::GetInfoBarAutomationType() const {
+infobars::InfoBarDelegate::InfoBarAutomationType
+ConfirmInfoBarDelegate::GetInfoBarAutomationType() const {
   return CONFIRM_INFOBAR;
 }
 
@@ -29,8 +25,8 @@
 
 base::string16 ConfirmInfoBarDelegate::GetButtonLabel(
     InfoBarButton button) const {
-  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
-      IDS_APP_OK : IDS_APP_CANCEL);
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ? IDS_APP_OK
+                                                         : IDS_APP_CANCEL);
 }
 
 bool ConfirmInfoBarDelegate::OKButtonTriggersUACPrompt() const {
@@ -45,22 +41,10 @@
   return true;
 }
 
-base::string16 ConfirmInfoBarDelegate::GetLinkText() const {
-  return base::string16();
-}
+ConfirmInfoBarDelegate::ConfirmInfoBarDelegate() = default;
 
-GURL ConfirmInfoBarDelegate::GetLinkURL() const {
-  return GURL();
-}
-
-bool ConfirmInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
-  infobar()->owner()->OpenURL(GetLinkURL(), disposition);
-  return false;
-}
-
-ConfirmInfoBarDelegate::ConfirmInfoBarDelegate() {}
-
-bool ConfirmInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
+bool ConfirmInfoBarDelegate::EqualsDelegate(
+    infobars::InfoBarDelegate* delegate) const {
   ConfirmInfoBarDelegate* confirm_delegate =
       delegate->AsConfirmInfoBarDelegate();
   return confirm_delegate &&
diff --git a/components/infobars/core/confirm_infobar_delegate.h b/components/infobars/core/confirm_infobar_delegate.h
index 8d0a89a2..b9a6cd32 100644
--- a/components/infobars/core/confirm_infobar_delegate.h
+++ b/components/infobars/core/confirm_infobar_delegate.h
@@ -10,7 +10,6 @@
 #include "components/infobars/core/infobar_delegate.h"
 #include "components/infobars/core/infobar_manager.h"
 #include "ui/gfx/text_constants.h"
-#include "url/gurl.h"
 
 namespace infobars {
 class InfoBar;
@@ -59,23 +58,6 @@
   // in handling this call something triggers the infobar to begin closing.
   virtual bool Cancel();
 
-  // Returns the text of the link to be displayed, if any. Otherwise returns
-  // an empty string.
-  virtual base::string16 GetLinkText() const;
-
-  // Returns the URL of the link to be displayed.
-  virtual GURL GetLinkURL() const;
-
-  // Called when the link (if any) is clicked; if this function returns true,
-  // the infobar is then immediately closed. The default implementation opens
-  // the URL returned by GetLinkURL(), above, and returns false. Subclasses MUST
-  // NOT return true if in handling this call something triggers the infobar to
-  // begin closing.
-  //
-  // The |disposition| specifies how the resulting document should be loaded
-  // (based on the event flags present when the link was clicked).
-  virtual bool LinkClicked(WindowOpenDisposition disposition);
-
  protected:
   ConfirmInfoBarDelegate();
 
diff --git a/components/infobars/core/infobar_delegate.cc b/components/infobars/core/infobar_delegate.cc
index 8a9deef..f0410a6 100644
--- a/components/infobars/core/infobar_delegate.cc
+++ b/components/infobars/core/infobar_delegate.cc
@@ -54,6 +54,14 @@
                    icon_id);
 }
 
+base::string16 InfoBarDelegate::GetLinkText() const {
+  return base::string16();
+}
+
+GURL InfoBarDelegate::GetLinkURL() const {
+  return GURL();
+}
+
 bool InfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
   return false;
 }
@@ -69,6 +77,11 @@
       ((nav_entry_id_ != details.entry_id) || details.is_reload);
 }
 
+bool InfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
+  infobar()->owner()->OpenURL(GetLinkURL(), disposition);
+  return false;
+}
+
 void InfoBarDelegate::InfoBarDismissed() {
 }
 
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
index 5c55e91..7202f5c 100644
--- a/components/infobars/core/infobar_delegate.h
+++ b/components/infobars/core/infobar_delegate.h
@@ -9,6 +9,7 @@
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "ui/base/window_open_disposition.h"
+#include "url/gurl.h"
 
 class ConfirmInfoBarDelegate;
 class HungRendererInfoBarDelegate;
@@ -208,6 +209,13 @@
   // resource bundle as its icon.
   virtual gfx::Image GetIcon() const;
 
+  // Returns the text of the link to be displayed, if any. Otherwise returns
+  // an empty string.
+  virtual base::string16 GetLinkText() const;
+
+  // Returns the URL the link should navigate to.
+  virtual GURL GetLinkURL() const;
+
   // Returns true if the supplied |delegate| is equal to this one. Equality is
   // left to the implementation to define. This function is called by the
   // InfoBarManager when determining whether or not a delegate should be
@@ -222,6 +230,16 @@
   // can override this function.
   virtual bool ShouldExpire(const NavigationDetails& details) const;
 
+  // Called when the link (if any) is clicked; if this function returns true,
+  // the infobar is then immediately closed. The default implementation opens
+  // the URL returned by GetLinkURL(), above, and returns false. Subclasses MUST
+  // NOT return true if in handling this call something triggers the infobar to
+  // begin closing.
+  //
+  // The |disposition| specifies how the resulting document should be loaded
+  // (based on the event flags present when the link was clicked).
+  virtual bool LinkClicked(WindowOpenDisposition disposition);
+
   // Called when the user clicks on the close button to dismiss the infobar.
   virtual void InfoBarDismissed();
 
diff --git a/components/metrics/cloned_install_detector.cc b/components/metrics/cloned_install_detector.cc
index b940288..e326cf4e 100644
--- a/components/metrics/cloned_install_detector.cc
+++ b/components/metrics/cloned_install_detector.cc
@@ -58,9 +58,9 @@
       FROM_HERE,
       {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-      base::Bind(&MachineIdProvider::GetMachineId),
-      base::Bind(&ClonedInstallDetector::SaveMachineId,
-                 weak_ptr_factory_.GetWeakPtr(), local_state));
+      base::BindOnce(&MachineIdProvider::GetMachineId),
+      base::BindOnce(&ClonedInstallDetector::SaveMachineId,
+                     weak_ptr_factory_.GetWeakPtr(), local_state));
 }
 
 void ClonedInstallDetector::SaveMachineId(PrefService* local_state,
diff --git a/components/metrics/delegating_provider.cc b/components/metrics/delegating_provider.cc
index aeeab06c..8d2396b 100644
--- a/components/metrics/delegating_provider.cc
+++ b/components/metrics/delegating_provider.cc
@@ -27,9 +27,9 @@
     provider->Init();
 }
 
-void DelegatingProvider::AsyncInit(const base::Closure& done_callback) {
-  base::Closure barrier =
-      base::BarrierClosure(metrics_providers_.size(), done_callback);
+void DelegatingProvider::AsyncInit(base::OnceClosure done_callback) {
+  base::RepeatingClosure barrier =
+      base::BarrierClosure(metrics_providers_.size(), std::move(done_callback));
   for (auto& provider : metrics_providers_) {
     provider->AsyncInit(barrier);
   }
diff --git a/components/metrics/delegating_provider.h b/components/metrics/delegating_provider.h
index 4e0cd1a..25eb535 100644
--- a/components/metrics/delegating_provider.h
+++ b/components/metrics/delegating_provider.h
@@ -28,7 +28,7 @@
 
   // MetricsProvider:
   void Init() override;
-  void AsyncInit(const base::Closure& done_callback) override;
+  void AsyncInit(base::OnceClosure done_callback) override;
   void OnDidCreateMetricsLog() override;
   void OnRecordingEnabled() override;
   void OnRecordingDisabled() override;
diff --git a/components/metrics/drive_metrics_provider.cc b/components/metrics/drive_metrics_provider.cc
index ad9c95a..2c1c9e0b 100644
--- a/components/metrics/drive_metrics_provider.cc
+++ b/components/metrics/drive_metrics_provider.cc
@@ -32,15 +32,15 @@
                    hardware->mutable_user_data_drive());
 }
 
-void DriveMetricsProvider::AsyncInit(const base::Closure& done_callback) {
+void DriveMetricsProvider::AsyncInit(base::OnceClosure done_callback) {
   base::PostTaskAndReplyWithResult(
       FROM_HERE,
       {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-      base::Bind(&DriveMetricsProvider::GetDriveMetricsOnBackgroundThread,
-                 local_state_path_key_),
-      base::Bind(&DriveMetricsProvider::GotDriveMetrics,
-                 weak_ptr_factory_.GetWeakPtr(), done_callback));
+      base::BindOnce(&DriveMetricsProvider::GetDriveMetricsOnBackgroundThread,
+                     local_state_path_key_),
+      base::BindOnce(&DriveMetricsProvider::GotDriveMetrics,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(done_callback)));
 }
 
 DriveMetricsProvider::SeekPenaltyResponse::SeekPenaltyResponse()
@@ -84,11 +84,11 @@
 }
 
 void DriveMetricsProvider::GotDriveMetrics(
-    const base::Closure& done_callback,
+    base::OnceClosure done_callback,
     const DriveMetricsProvider::DriveMetrics& metrics) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   metrics_ = metrics;
-  done_callback.Run();
+  std::move(done_callback).Run();
 }
 
 void DriveMetricsProvider::FillDriveMetrics(
diff --git a/components/metrics/drive_metrics_provider.h b/components/metrics/drive_metrics_provider.h
index a1f5c0c0..2c431a2 100644
--- a/components/metrics/drive_metrics_provider.h
+++ b/components/metrics/drive_metrics_provider.h
@@ -28,7 +28,7 @@
   ~DriveMetricsProvider() override;
 
   // metrics::MetricsDataProvider:
-  void AsyncInit(const base::Closure& done_callback) override;
+  void AsyncInit(base::OnceClosure done_callback) override;
   void ProvideSystemProfileMetrics(
       metrics::SystemProfileProto* system_profile_proto) override;
 
@@ -65,7 +65,7 @@
   // Called when metrics are done being gathered asynchronously.
   // |done_callback| is the callback that should be called once all metrics are
   // gathered.
-  void GotDriveMetrics(const base::Closure& done_callback,
+  void GotDriveMetrics(base::OnceClosure done_callback,
                        const DriveMetrics& metrics);
 
   // Fills |drive| with information from successful |response|s.
diff --git a/components/metrics/file_metrics_provider_unittest.cc b/components/metrics/file_metrics_provider_unittest.cc
index 7ee0756..fee1a547 100644
--- a/components/metrics/file_metrics_provider_unittest.cc
+++ b/components/metrics/file_metrics_provider_unittest.cc
@@ -237,8 +237,8 @@
                         size_t count) {
     filter_actions_ = actions;
     filter_actions_remaining_ = count;
-    params->filter = base::Bind(&FileMetricsProviderTest::FilterSourcePath,
-                                base::Unretained(this));
+    params->filter = base::BindRepeating(
+        &FileMetricsProviderTest::FilterSourcePath, base::Unretained(this));
   }
 
   const bool create_large_files_;
diff --git a/components/metrics/metrics_log_uploader.h b/components/metrics/metrics_log_uploader.h
index 3b7bad9..63c8ba2 100644
--- a/components/metrics/metrics_log_uploader.h
+++ b/components/metrics/metrics_log_uploader.h
@@ -22,7 +22,7 @@
   // Type for OnUploadComplete callbacks.  These callbacks will receive three
   // parameters: A response code, a net error code, and a boolean specifying
   // if the connection was secure (over HTTPS).
-  typedef base::Callback<void(int, int, bool)> UploadCallback;
+  using UploadCallback = base::RepeatingCallback<void(int, int, bool)>;
 
   // Possible service types. This should correspond to a type from
   // DataUseUserData.
diff --git a/components/metrics/metrics_provider.cc b/components/metrics/metrics_provider.cc
index fb6fd3d..4a17765 100644
--- a/components/metrics/metrics_provider.cc
+++ b/components/metrics/metrics_provider.cc
@@ -17,8 +17,8 @@
 void MetricsProvider::Init() {
 }
 
-void MetricsProvider::AsyncInit(const base::Closure& done_callback) {
-  done_callback.Run();
+void MetricsProvider::AsyncInit(base::OnceClosure done_callback) {
+  std::move(done_callback).Run();
 }
 
 void MetricsProvider::OnDidCreateMetricsLog() {
diff --git a/components/metrics/metrics_provider.h b/components/metrics/metrics_provider.h
index 9560bcb5..108cd7b8 100644
--- a/components/metrics/metrics_provider.h
+++ b/components/metrics/metrics_provider.h
@@ -31,7 +31,7 @@
   // Called during service initialization to allow the provider to start any
   // async initialization tasks.  The service will wait for the provider to
   // call |done_callback| before generating logs for the current session.
-  virtual void AsyncInit(const base::Closure& done_callback);
+  virtual void AsyncInit(base::OnceClosure done_callback);
 
   // Called when a new MetricsLog is created.
   virtual void OnDidCreateMetricsLog();
diff --git a/components/metrics/metrics_rotation_scheduler.cc b/components/metrics/metrics_rotation_scheduler.cc
index 8edba16..9d018a0 100644
--- a/components/metrics/metrics_rotation_scheduler.cc
+++ b/components/metrics/metrics_rotation_scheduler.cc
@@ -10,8 +10,9 @@
 namespace metrics {
 
 MetricsRotationScheduler::MetricsRotationScheduler(
-    const base::Closure& upload_callback,
-    const base::Callback<base::TimeDelta(void)>& upload_interval_callback,
+    const base::RepeatingClosure& upload_callback,
+    const base::RepeatingCallback<base::TimeDelta(void)>&
+        upload_interval_callback,
     bool fast_startup_for_testing)
     : MetricsScheduler(upload_callback, fast_startup_for_testing),
       init_task_complete_(false),
diff --git a/components/metrics/metrics_rotation_scheduler.h b/components/metrics/metrics_rotation_scheduler.h
index bac23af..eea3817 100644
--- a/components/metrics/metrics_rotation_scheduler.h
+++ b/components/metrics/metrics_rotation_scheduler.h
@@ -20,8 +20,8 @@
   // to determine the interval between rotations in steady state.
   // |rotation_callback| must arrange to call RotationFinished on completion.
   MetricsRotationScheduler(
-      const base::Closure& rotation_callback,
-      const base::Callback<base::TimeDelta(void)>& interval_callback,
+      const base::RepeatingClosure& rotation_callback,
+      const base::RepeatingCallback<base::TimeDelta(void)>& interval_callback,
       bool fast_startup_for_testing);
   ~MetricsRotationScheduler() override;
 
@@ -53,7 +53,7 @@
   bool waiting_for_init_task_complete_;
 
   // Callback function used to get the standard upload time.
-  base::Callback<base::TimeDelta(void)> upload_interval_callback_;
+  base::RepeatingCallback<base::TimeDelta(void)> upload_interval_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(MetricsRotationScheduler);
 };
diff --git a/components/metrics/metrics_scheduler.cc b/components/metrics/metrics_scheduler.cc
index b81efc3..793f6be 100644
--- a/components/metrics/metrics_scheduler.cc
+++ b/components/metrics/metrics_scheduler.cc
@@ -21,7 +21,7 @@
 
 }  // namespace
 
-MetricsScheduler::MetricsScheduler(const base::Closure& task_callback,
+MetricsScheduler::MetricsScheduler(const base::RepeatingClosure& task_callback,
                                    bool fast_startup_for_testing)
     : task_callback_(task_callback),
       interval_(base::TimeDelta::FromSeconds(
diff --git a/components/metrics/metrics_scheduler.h b/components/metrics/metrics_scheduler.h
index 10119a2..afb4a76 100644
--- a/components/metrics/metrics_scheduler.h
+++ b/components/metrics/metrics_scheduler.h
@@ -17,7 +17,7 @@
  public:
   // Creates MetricsScheduler object with the given |task_callback|
   // callback to call when a task should happen.
-  MetricsScheduler(const base::Closure& task_callback,
+  MetricsScheduler(const base::RepeatingClosure& task_callback,
                    bool fast_startup_for_testing);
   virtual ~MetricsScheduler();
 
@@ -42,7 +42,7 @@
   void ScheduleNextTask();
 
   // The method to call when task should happen.
-  const base::Closure task_callback_;
+  const base::RepeatingClosure task_callback_;
 
   // Uses a one-shot timer rather than a repeating one because the task may be
   // async, and the length of the interval may change.
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc
index 457085f..158e6713 100644
--- a/components/metrics/metrics_service.cc
+++ b/components/metrics/metrics_service.cc
@@ -242,16 +242,15 @@
   reporting_service_.Initialize();
   InitializeMetricsState();
 
-  base::Closure upload_callback =
-      base::Bind(&MetricsService::StartScheduledUpload,
-                 self_ptr_factory_.GetWeakPtr());
+  base::RepeatingClosure upload_callback = base::BindRepeating(
+      &MetricsService::StartScheduledUpload, self_ptr_factory_.GetWeakPtr());
 
   rotation_scheduler_.reset(new MetricsRotationScheduler(
       upload_callback,
       // MetricsServiceClient outlives MetricsService, and
       // MetricsRotationScheduler is tied to the lifetime of |this|.
-      base::Bind(&MetricsServiceClient::GetUploadInterval,
-                 base::Unretained(client_)),
+      base::BindRepeating(&MetricsServiceClient::GetUploadInterval,
+                          base::Unretained(client_)),
       client_->ShouldStartUpFastForTesting()));
 
   // Init() has to be called after LogCrash() in order for LogCrash() to work.
@@ -329,8 +328,8 @@
   RecordCurrentEnvironment(log_manager_.current_log(), /*complete=*/false);
 
   base::RemoveActionCallback(action_callback_);
-  action_callback_ = base::Bind(&MetricsService::OnUserAction,
-                                base::Unretained(this));
+  action_callback_ = base::BindRepeating(&MetricsService::OnUserAction,
+                                         base::Unretained(this));
   base::AddActionCallback(action_callback_);
 }
 
@@ -612,8 +611,8 @@
 }
 
 void MetricsService::StartInitTask() {
-  delegating_provider_.AsyncInit(base::Bind(&MetricsService::FinishedInitTask,
-                                            self_ptr_factory_.GetWeakPtr()));
+  delegating_provider_.AsyncInit(base::BindOnce(
+      &MetricsService::FinishedInitTask, self_ptr_factory_.GetWeakPtr()));
 }
 
 void MetricsService::CloseCurrentLog() {
diff --git a/components/metrics/metrics_service_client.cc b/components/metrics/metrics_service_client.cc
index 35f363b..a6e1fe7 100644
--- a/components/metrics/metrics_service_client.cc
+++ b/components/metrics/metrics_service_client.cc
@@ -94,7 +94,7 @@
 }
 
 void MetricsServiceClient::SetUpdateRunningServicesCallback(
-    const base::Closure& callback) {
+    const base::RepeatingClosure& callback) {
   update_running_services_ = callback;
 }
 
diff --git a/components/metrics/metrics_service_client.h b/components/metrics/metrics_service_client.h
index 04c8e6d..a85498f 100644
--- a/components/metrics/metrics_service_client.h
+++ b/components/metrics/metrics_service_client.h
@@ -153,7 +153,7 @@
   virtual std::string GetUploadSigningKey();
 
   // Sets the callback to run MetricsServiceManager::UpdateRunningServices.
-  void SetUpdateRunningServicesCallback(const base::Closure& callback);
+  void SetUpdateRunningServicesCallback(const base::RepeatingClosure& callback);
 
   // Notify MetricsServiceManager to UpdateRunningServices using callback.
   void UpdateRunningServices();
@@ -162,7 +162,7 @@
   bool IsMetricsReportingForceEnabled() const;
 
  private:
-  base::Closure update_running_services_;
+  base::RepeatingClosure update_running_services_;
 
   DISALLOW_COPY_AND_ASSIGN(MetricsServiceClient);
 };
diff --git a/components/metrics/metrics_service_unittest.cc b/components/metrics/metrics_service_unittest.cc
index 5c29dc6..4bdaf71 100644
--- a/components/metrics/metrics_service_unittest.cc
+++ b/components/metrics/metrics_service_unittest.cc
@@ -114,7 +114,8 @@
     if (!metrics_state_manager_) {
       metrics_state_manager_ = MetricsStateManager::Create(
           GetLocalState(), enabled_state_provider_.get(), base::string16(),
-          base::Bind(&StoreNoClientInfoBackup), base::Bind(&ReturnNoBackup));
+          base::BindRepeating(&StoreNoClientInfoBackup),
+          base::BindRepeating(&ReturnNoBackup));
     }
     return metrics_state_manager_.get();
   }
diff --git a/components/metrics/metrics_state_manager.h b/components/metrics/metrics_state_manager.h
index d6007b3..517e18a 100644
--- a/components/metrics/metrics_state_manager.h
+++ b/components/metrics/metrics_state_manager.h
@@ -32,12 +32,12 @@
  public:
   // A callback that can be invoked to store client info to persistent storage.
   // Storing an empty client_id will resulted in the backup being voided.
-  typedef base::Callback<void(const ClientInfo& client_info)>
+  typedef base::RepeatingCallback<void(const ClientInfo& client_info)>
       StoreClientInfoCallback;
 
   // A callback that can be invoked to load client info stored through the
   // StoreClientInfoCallback.
-  typedef base::Callback<std::unique_ptr<ClientInfo>(void)>
+  typedef base::RepeatingCallback<std::unique_ptr<ClientInfo>(void)>
       LoadClientInfoCallback;
 
   ~MetricsStateManager();
diff --git a/components/metrics/metrics_state_manager_unittest.cc b/components/metrics/metrics_state_manager_unittest.cc
index 1ffb527..06c26821 100644
--- a/components/metrics/metrics_state_manager_unittest.cc
+++ b/components/metrics/metrics_state_manager_unittest.cc
@@ -58,10 +58,10 @@
   std::unique_ptr<MetricsStateManager> CreateStateManager() {
     return MetricsStateManager::Create(
         &prefs_, enabled_state_provider_.get(), base::string16(),
-        base::Bind(&MetricsStateManagerTest::MockStoreClientInfoBackup,
-                   base::Unretained(this)),
-        base::Bind(&MetricsStateManagerTest::LoadFakeClientInfoBackup,
-                   base::Unretained(this)));
+        base::BindRepeating(&MetricsStateManagerTest::MockStoreClientInfoBackup,
+                            base::Unretained(this)),
+        base::BindRepeating(&MetricsStateManagerTest::LoadFakeClientInfoBackup,
+                            base::Unretained(this)));
   }
 
   // Sets metrics reporting as enabled for testing.
diff --git a/components/metrics/metrics_upload_scheduler.cc b/components/metrics/metrics_upload_scheduler.cc
index a36d189..24594fbb 100644
--- a/components/metrics/metrics_upload_scheduler.cc
+++ b/components/metrics/metrics_upload_scheduler.cc
@@ -59,7 +59,7 @@
 }  // namespace
 
 MetricsUploadScheduler::MetricsUploadScheduler(
-    const base::Closure& upload_callback,
+    const base::RepeatingClosure& upload_callback,
     bool fast_startup_for_testing)
     : MetricsScheduler(upload_callback, fast_startup_for_testing),
       unsent_logs_interval_(GetUnsentLogsInterval()),
diff --git a/components/metrics/metrics_upload_scheduler.h b/components/metrics/metrics_upload_scheduler.h
index e4663b6..709b89d 100644
--- a/components/metrics/metrics_upload_scheduler.h
+++ b/components/metrics/metrics_upload_scheduler.h
@@ -19,7 +19,7 @@
   // Creates MetricsUploadScheduler object with the given |upload_callback|
   // callback to call when uploading should happen.  The callback must
   // arrange to call either UploadFinished or UploadCancelled on completion.
-  MetricsUploadScheduler(const base::Closure& upload_callback,
+  MetricsUploadScheduler(const base::RepeatingClosure& upload_callback,
                          bool fast_startup_for_testing);
   ~MetricsUploadScheduler() override;
 
diff --git a/components/metrics/net/net_metrics_log_uploader_unittest.cc b/components/metrics/net/net_metrics_log_uploader_unittest.cc
index e2eebd24..542f4a2 100644
--- a/components/metrics/net/net_metrics_log_uploader_unittest.cc
+++ b/components/metrics/net/net_metrics_log_uploader_unittest.cc
@@ -42,8 +42,9 @@
     uploader_.reset(new NetMetricsLogUploader(
         test_shared_url_loader_factory_, GURL("https://dummy_server"),
         "dummy_mime", MetricsLogUploader::UMA,
-        base::Bind(&NetMetricsLogUploaderTest::OnUploadCompleteReuseUploader,
-                   base::Unretained(this))));
+        base::BindRepeating(
+            &NetMetricsLogUploaderTest::OnUploadCompleteReuseUploader,
+            base::Unretained(this))));
     uploader_->UploadLog("initial_dummy_data", "initial_dummy_hash",
                          "initial_dummy_signature", reporting_info);
   }
@@ -53,8 +54,8 @@
     uploader_.reset(new NetMetricsLogUploader(
         test_shared_url_loader_factory_, GURL(url), "dummy_mime",
         MetricsLogUploader::UMA,
-        base::Bind(&NetMetricsLogUploaderTest::DummyOnUploadComplete,
-                   base::Unretained(this))));
+        base::BindRepeating(&NetMetricsLogUploaderTest::DummyOnUploadComplete,
+                            base::Unretained(this))));
     uploader_->UploadLog("dummy_data", "dummy_hash", "dummy_signature",
                          dummy_reporting_info);
   }
@@ -64,8 +65,8 @@
     uploader_.reset(new NetMetricsLogUploader(
         test_shared_url_loader_factory_, GURL("http://dummy_insecure_server"),
         "dummy_mime", MetricsLogUploader::UMA,
-        base::Bind(&NetMetricsLogUploaderTest::DummyOnUploadComplete,
-                   base::Unretained(this))));
+        base::BindRepeating(&NetMetricsLogUploaderTest::DummyOnUploadComplete,
+                            base::Unretained(this))));
     std::string compressed_message;
     // Compress the data since the encryption code expects a compressed log,
     // and tries to decompress it before encrypting it.
diff --git a/components/metrics/net/wifi_access_point_info_provider_chromeos.cc b/components/metrics/net/wifi_access_point_info_provider_chromeos.cc
index d97d7ce..91bcfdf 100644
--- a/components/metrics/net/wifi_access_point_info_provider_chromeos.cc
+++ b/components/metrics/net/wifi_access_point_info_provider_chromeos.cc
@@ -55,7 +55,8 @@
   // Retrieve access point info for wifi connection.
   NetworkHandler::Get()->network_configuration_handler()->GetShillProperties(
       default_network->path(),
-      base::Bind(&WifiAccessPointInfoProviderChromeos::ParseInfo, AsWeakPtr()),
+      base::BindRepeating(&WifiAccessPointInfoProviderChromeos::ParseInfo,
+                          AsWeakPtr()),
       chromeos::network_handler::ErrorCallback());
 }
 
diff --git a/components/metrics/reporting_service.cc b/components/metrics/reporting_service.cc
index cc170680..4b1f804 100644
--- a/components/metrics/reporting_service.cc
+++ b/components/metrics/reporting_service.cc
@@ -45,7 +45,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!upload_scheduler_);
   log_store()->LoadPersistedUnsentLogs();
-  base::Closure send_next_log_callback = base::Bind(
+  base::RepeatingClosure send_next_log_callback = base::BindRepeating(
       &ReportingService::SendNextLog, self_ptr_factory_.GetWeakPtr());
   bool fast_startup_for_testing = client_->ShouldStartUpFastForTesting();
   upload_scheduler_.reset(new MetricsUploadScheduler(send_next_log_callback,
@@ -143,8 +143,8 @@
     log_uploader_ = client_->CreateUploader(
         GetUploadUrl(), GetInsecureUploadUrl(), upload_mime_type(),
         service_type(),
-        base::Bind(&ReportingService::OnLogUploadComplete,
-                   self_ptr_factory_.GetWeakPtr()));
+        base::BindRepeating(&ReportingService::OnLogUploadComplete,
+                            self_ptr_factory_.GetWeakPtr()));
   }
 
   reporting_info_.set_attempt_count(reporting_info_.attempt_count() + 1);
diff --git a/components/metrics_services_manager/metrics_services_manager.cc b/components/metrics_services_manager/metrics_services_manager.cc
index 08f69b2..3b3a4b5f 100644
--- a/components/metrics_services_manager/metrics_services_manager.cc
+++ b/components/metrics_services_manager/metrics_services_manager.cc
@@ -80,8 +80,8 @@
     metrics_service_client_ = client_->CreateMetricsServiceClient();
     // base::Unretained is safe since |this| owns the metrics_service_client_.
     metrics_service_client_->SetUpdateRunningServicesCallback(
-        base::Bind(&MetricsServicesManager::UpdateRunningServices,
-                   base::Unretained(this)));
+        base::BindRepeating(&MetricsServicesManager::UpdateRunningServices,
+                            base::Unretained(this)));
   }
   return metrics_service_client_.get();
 }
diff --git a/components/ownership/owner_settings_service.cc b/components/ownership/owner_settings_service.cc
index 8bd4589..46a7ff7 100644
--- a/components/ownership/owner_settings_service.cc
+++ b/components/ownership/owner_settings_service.cc
@@ -97,13 +97,13 @@
   return private_key_.get() && private_key_->key();
 }
 
-void OwnerSettingsService::IsOwnerAsync(const IsOwnerCallback& callback) {
+void OwnerSettingsService::IsOwnerAsync(IsOwnerCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (private_key_.get()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(callback, IsOwner()));
+        FROM_HERE, base::BindOnce(std::move(callback), IsOwner()));
   } else {
-    pending_is_owner_callbacks_.push_back(callback);
+    pending_is_owner_callbacks_.push_back(std::move(callback));
   }
 }
 
@@ -159,14 +159,12 @@
   public_key_ = public_key;
   private_key_ = private_key;
 
-  const bool is_owner = IsOwner();
   std::vector<IsOwnerCallback> is_owner_callbacks;
   is_owner_callbacks.swap(pending_is_owner_callbacks_);
-  for (std::vector<IsOwnerCallback>::iterator it(is_owner_callbacks.begin());
-       it != is_owner_callbacks.end();
-       ++it) {
-    it->Run(is_owner);
-  }
+
+  const bool is_owner = IsOwner();
+  for (auto& callback : is_owner_callbacks)
+    std::move(callback).Run(is_owner);
 
   OnPostKeypairLoadedActions();
 }
diff --git a/components/ownership/owner_settings_service.h b/components/ownership/owner_settings_service.h
index e74e9da2..f57362c 100644
--- a/components/ownership/owner_settings_service.h
+++ b/components/ownership/owner_settings_service.h
@@ -56,7 +56,7 @@
           policy_response)>
       AssembleAndSignPolicyAsyncCallback;
 
-  typedef base::RepeatingCallback<void(bool is_owner)> IsOwnerCallback;
+  using IsOwnerCallback = base::OnceCallback<void(bool is_owner)>;
 
   explicit OwnerSettingsService(
       const scoped_refptr<ownership::OwnerKeyUtil>& owner_key_util);
@@ -82,7 +82,7 @@
   // Determines whether current user is owner or not, responds via |callback|.
   // Reliably returns the correct value, but will not respond on the callback
   // until IsReady() returns true.
-  virtual void IsOwnerAsync(const IsOwnerCallback& callback);
+  virtual void IsOwnerAsync(IsOwnerCallback callback);
 
   // Assembles and signs |policy| on the |task_runner|, responds on
   // the original thread via |callback|.
diff --git a/components/paint_preview/browser/BUILD.gn b/components/paint_preview/browser/BUILD.gn
index e70ceca..0236311c 100644
--- a/components/paint_preview/browser/BUILD.gn
+++ b/components/paint_preview/browser/BUILD.gn
@@ -6,7 +6,7 @@
 
 assert(!is_ios, "Paint Previews are not supported on iOS.")
 
-static_library("browser") {
+source_set("browser") {
   sources = [
     "compositor_utils.cc",
     "compositor_utils.h",
@@ -18,6 +18,10 @@
     "paint_preview_base_service.h",
     "paint_preview_client.cc",
     "paint_preview_client.h",
+    "paint_preview_compositor_client_impl.cc",
+    "paint_preview_compositor_client_impl.h",
+    "paint_preview_compositor_service_impl.cc",
+    "paint_preview_compositor_service_impl.h",
     "paint_preview_policy.h",
   ]
 
@@ -25,7 +29,8 @@
     "//base",
     "//cc/base",
     "//components/discardable_memory/service",
-    "//components/strings:components_strings",
+    "//components/keyed_service/core",
+    "//components/strings:components_strings_grit",
     "//content/public/browser",
     "//mojo/public/cpp/base",
     "//mojo/public/cpp/bindings",
@@ -40,10 +45,28 @@
     "//components/paint_preview/common",
     "//components/paint_preview/common/mojom",
     "//components/paint_preview/common/proto",
+    "//components/paint_preview/public",
     "//components/services/paint_preview_compositor/public/mojom",
   ]
 }
 
+source_set("test_support") {
+  testonly = true
+  sources = [
+    "paint_preview_base_service_test_factory.cc",
+    "paint_preview_base_service_test_factory.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/keyed_service/core",
+  ]
+
+  public_deps = [
+    ":browser",
+  ]
+}
+
 source_set("unit_tests") {
   testonly = true
 
@@ -56,6 +79,7 @@
 
   deps = [
     ":browser",
+    ":test_support",
     "//base",
     "//base/test:test_support",
     "//components/paint_preview/common:test_utils",
diff --git a/components/paint_preview/browser/compositor_utils.cc b/components/paint_preview/browser/compositor_utils.cc
index 8c0e3fa6..3a3f618 100644
--- a/components/paint_preview/browser/compositor_utils.cc
+++ b/components/paint_preview/browser/compositor_utils.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/task/post_task.h"
+#include "build/build_config.h"
 #include "components/discardable_memory/service/discardable_shared_memory_manager.h"
 #include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
 #include "components/strings/grit/components_strings.h"
@@ -35,7 +36,12 @@
   auto collection = content::ServiceProcessHost::Launch<
       mojom::PaintPreviewCompositorCollection>(
       content::ServiceProcessHost::Options()
-          .WithDisplayName(IDS_PAINT_PREVIEW_COMPOSITOR_SERVICE_DISPLAY_NAME)
+          // TODO(crbug/1035118): due to resource whitelisting, resources not
+          // shipped in production fail to compile into the resource pack. For
+          // now, the display name should be disabled until the buildflag hiding
+          // this feature is enabled for official builds.
+
+          // .WithDisplayName(IDS_PAINT_PREVIEW_COMPOSITOR_SERVICE_DISPLAY_NAME)
           .WithSandboxType(service_manager::SandboxType::kPdfCompositor)
           .Pass());
   mojo::PendingRemote<discardable_memory::mojom::DiscardableSharedMemoryManager>
diff --git a/components/paint_preview/browser/paint_preview_base_service.cc b/components/paint_preview/browser/paint_preview_base_service.cc
index 099bf54..4babde5 100644
--- a/components/paint_preview/browser/paint_preview_base_service.cc
+++ b/components/paint_preview/browser/paint_preview_base_service.cc
@@ -10,12 +10,14 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#include "base/task/post_task.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/paint_preview/browser/compositor_utils.h"
 #include "components/paint_preview/browser/file_manager.h"
 #include "components/paint_preview/browser/paint_preview_client.h"
+#include "components/paint_preview/browser/paint_preview_compositor_service_impl.h"
 #include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h"
 #include "content/public/browser/web_contents.h"
+#include "ui/gfx/geometry/rect.h"
 
 namespace paint_preview {
 
@@ -34,6 +36,7 @@
       file_manager_(
           path.AppendASCII(kPaintPreviewDir).AppendASCII(ascii_feature_name)),
       is_off_the_record_(is_off_the_record) {}
+
 PaintPreviewBaseService::~PaintPreviewBaseService() = default;
 
 void PaintPreviewBaseService::CapturePaintPreview(
@@ -75,6 +78,13 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
+std::unique_ptr<PaintPreviewCompositorService>
+PaintPreviewBaseService::StartCompositorService(
+    base::OnceClosure disconnect_handler) {
+  return std::make_unique<PaintPreviewCompositorServiceImpl>(
+      CreateCompositorCollection(), std::move(disconnect_handler));
+}
+
 void PaintPreviewBaseService::OnCaptured(
     OnCapturedCallback callback,
     base::UnguessableToken guid,
diff --git a/components/paint_preview/browser/paint_preview_base_service.h b/components/paint_preview/browser/paint_preview_base_service.h
index d400e63..790b875 100644
--- a/components/paint_preview/browser/paint_preview_base_service.h
+++ b/components/paint_preview/browser/paint_preview_base_service.h
@@ -9,12 +9,14 @@
 
 #include "base/callback.h"
 #include "base/files/file_path.h"
-#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/unguessable_token.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/paint_preview/browser/file_manager.h"
 #include "components/paint_preview/browser/paint_preview_policy.h"
 #include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h"
 #include "components/paint_preview/common/proto/paint_preview.pb.h"
+#include "components/paint_preview/public/paint_preview_compositor_service.h"
 #include "content/public/browser/web_contents.h"
 
 namespace paint_preview {
@@ -94,6 +96,10 @@
                            gfx::Rect clip_rect,
                            OnCapturedCallback callback);
 
+  // Starts the compositor service in a utility process.
+  std::unique_ptr<PaintPreviewCompositorService> StartCompositorService(
+      base::OnceClosure disconnect_handler);
+
  private:
   void OnCaptured(OnCapturedCallback callback,
                   base::UnguessableToken guid,
@@ -106,7 +112,8 @@
 
   base::WeakPtrFactory<PaintPreviewBaseService> weak_ptr_factory_{this};
 
-  DISALLOW_COPY_AND_ASSIGN(PaintPreviewBaseService);
+  PaintPreviewBaseService(const PaintPreviewBaseService&) = delete;
+  PaintPreviewBaseService& operator=(const PaintPreviewBaseService&) = delete;
 };
 
 }  // namespace paint_preview
diff --git a/components/paint_preview/browser/paint_preview_base_service_test_factory.cc b/components/paint_preview/browser/paint_preview_base_service_test_factory.cc
new file mode 100644
index 0000000..8ae8532
--- /dev/null
+++ b/components/paint_preview/browser/paint_preview_base_service_test_factory.cc
@@ -0,0 +1,64 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/paint_preview/browser/paint_preview_base_service_test_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/no_destructor.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/keyed_service/core/simple_dependency_manager.h"
+#include "components/keyed_service/core/simple_factory_key.h"
+#include "components/keyed_service/core/simple_keyed_service_factory.h"
+#include "components/paint_preview/browser/paint_preview_base_service.h"
+
+namespace paint_preview {
+
+const char kTestFeatureDir[] = "test_feature";
+
+PaintPreviewBaseServiceTestFactory*
+PaintPreviewBaseServiceTestFactory::GetInstance() {
+  // Use NoDestructor rather than a singleton due to lifetime behavior in
+  // tests.
+  static base::NoDestructor<PaintPreviewBaseServiceTestFactory> factory;
+  return factory.get();
+}
+
+PaintPreviewBaseService* PaintPreviewBaseServiceTestFactory::GetForKey(
+    SimpleFactoryKey* key) {
+  return static_cast<PaintPreviewBaseService*>(
+      GetInstance()->GetServiceForKey(key, true));
+}
+
+void PaintPreviewBaseServiceTestFactory::Destroy(SimpleFactoryKey* key) {
+  SimpleContextShutdown(key);
+  SimpleContextDestroyed(key);
+}
+
+std::unique_ptr<KeyedService> PaintPreviewBaseServiceTestFactory::Build(
+    SimpleFactoryKey* key) {
+  return std::make_unique<PaintPreviewBaseService>(
+      key->GetPath(), kTestFeatureDir, nullptr, key->IsOffTheRecord());
+}
+
+PaintPreviewBaseServiceTestFactory::~PaintPreviewBaseServiceTestFactory() =
+    default;
+
+PaintPreviewBaseServiceTestFactory::PaintPreviewBaseServiceTestFactory()
+    : SimpleKeyedServiceFactory("PaintPreviewBaseService",
+                                SimpleDependencyManager::GetInstance()) {}
+
+std::unique_ptr<KeyedService>
+PaintPreviewBaseServiceTestFactory::BuildServiceInstanceFor(
+    SimpleFactoryKey* key) const {
+  return Build(key);
+}
+
+SimpleFactoryKey* PaintPreviewBaseServiceTestFactory::GetKeyToUse(
+    SimpleFactoryKey* key) const {
+  return key;
+}
+
+}  // namespace paint_preview
diff --git a/components/paint_preview/browser/paint_preview_base_service_test_factory.h b/components/paint_preview/browser/paint_preview_base_service_test_factory.h
new file mode 100644
index 0000000..42c9629e
--- /dev/null
+++ b/components/paint_preview/browser/paint_preview_base_service_test_factory.h
@@ -0,0 +1,52 @@
+// 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 COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_BASE_SERVICE_TEST_FACTORY_H_
+#define COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_BASE_SERVICE_TEST_FACTORY_H_
+
+#include <memory>
+
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/keyed_service/core/simple_factory_key.h"
+#include "components/keyed_service/core/simple_keyed_service_factory.h"
+#include "components/paint_preview/browser/paint_preview_base_service.h"
+
+namespace paint_preview {
+
+// An approximation of a SimpleKeyedServiceFactory for a keyed
+// PaintPerviewBaseService. This is different than a "real" version as it
+// uses base::NoDestructor rather than base::Singleton due to testing object
+// lifecycle.
+class PaintPreviewBaseServiceTestFactory : public SimpleKeyedServiceFactory {
+ public:
+  static PaintPreviewBaseServiceTestFactory* GetInstance();
+
+  static PaintPreviewBaseService* GetForKey(SimpleFactoryKey* key);
+
+  // The following are unusual methods for an implementer of a
+  // KeyedServiceFactory. They are intended to help with testing.
+
+  static std::unique_ptr<KeyedService> Build(SimpleFactoryKey* key);
+
+  void Destroy(SimpleFactoryKey* key);
+
+  // These are public due to using base::NoDestructor. Don't call directly.
+  PaintPreviewBaseServiceTestFactory();
+  ~PaintPreviewBaseServiceTestFactory() override;
+
+  PaintPreviewBaseServiceTestFactory(
+      const PaintPreviewBaseServiceTestFactory&) = delete;
+  PaintPreviewBaseServiceTestFactory& operator=(
+      const PaintPreviewBaseServiceTestFactory&) = delete;
+
+ private:
+  std::unique_ptr<KeyedService> BuildServiceInstanceFor(
+      SimpleFactoryKey* key) const override;
+
+  SimpleFactoryKey* GetKeyToUse(SimpleFactoryKey* key) const override;
+};
+
+}  // namespace paint_preview
+
+#endif  // COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_BASE_SERVICE_TEST_FACTORY_H_
diff --git a/components/paint_preview/browser/paint_preview_base_service_unittest.cc b/components/paint_preview/browser/paint_preview_base_service_unittest.cc
index 7aa8d23..37d441f 100644
--- a/components/paint_preview/browser/paint_preview_base_service_unittest.cc
+++ b/components/paint_preview/browser/paint_preview_base_service_unittest.cc
@@ -8,10 +8,7 @@
 #include "base/macros.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
-#include "components/keyed_service/core/simple_dependency_manager.h"
-#include "components/keyed_service/core/simple_factory_key.h"
-#include "components/keyed_service/core/simple_key_map.h"
-#include "components/keyed_service/core/simple_keyed_service_factory.h"
+#include "components/paint_preview/browser/paint_preview_base_service_test_factory.h"
 #include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h"
 #include "components/paint_preview/common/test_utils.h"
 #include "content/public/browser/render_process_host.h"
@@ -50,12 +47,6 @@
       std::make_unique<RejectionPaintPreviewPolicy>(), key->IsOffTheRecord());
 }
 
-// Builds a PaintPreviewBaseService associated with |key|.
-std::unique_ptr<KeyedService> BuildService(SimpleFactoryKey* key) {
-  return std::make_unique<PaintPreviewBaseService>(
-      key->GetPath(), kTestFeatureDir, nullptr, key->IsOffTheRecord());
-}
-
 // Returns the GUID corresponding to |rfh|.
 uint64_t FrameGuid(content::RenderFrameHost* rfh) {
   return static_cast<uint64_t>(rfh->GetProcess()->GetID()) << 32 |
@@ -95,6 +86,9 @@
         std::move(handle)));
   }
 
+  MockPaintPreviewRecorder(const MockPaintPreviewRecorder&) = delete;
+  MockPaintPreviewRecorder& operator=(const MockPaintPreviewRecorder&) = delete;
+
  private:
   void CheckParams(mojom::PaintPreviewCaptureParamsPtr input_params) {
     // Ignore GUID and File as this is internal information not known by the
@@ -107,41 +101,6 @@
   mojom::PaintPreviewStatus status_;
   mojom::PaintPreviewCaptureResponsePtr response_;
   mojo::AssociatedReceiver<mojom::PaintPreviewRecorder> binding_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(MockPaintPreviewRecorder);
-};
-
-// An approximation of a SimpleKeyedServiceFactory for a keyed
-// PaintPerviewBaseService. This is different than a "real" version as it
-// uses base::NoDestructor rather than base::Singleton.
-class PaintPreviewBaseServiceFactory : public SimpleKeyedServiceFactory {
- public:
-  static PaintPreviewBaseServiceFactory* GetInstance() {
-    // Use NoDestructor rather than a singleton due to lifetime behavior in
-    // tests.
-    static base::NoDestructor<PaintPreviewBaseServiceFactory> factory;
-    return factory.get();
-  }
-
-  static PaintPreviewBaseService* GetForKey(SimpleFactoryKey* key) {
-    return static_cast<PaintPreviewBaseService*>(
-        GetInstance()->GetServiceForKey(key, true));
-  }
-
-  PaintPreviewBaseServiceFactory()
-      : SimpleKeyedServiceFactory("PaintPreviewBaseService",
-                                  SimpleDependencyManager::GetInstance()) {}
-  ~PaintPreviewBaseServiceFactory() override = default;
-
- private:
-  std::unique_ptr<KeyedService> BuildServiceInstanceFor(
-      SimpleFactoryKey* key) const override {
-    return BuildService(key);
-  }
-
-  SimpleFactoryKey* GetKeyToUse(SimpleFactoryKey* key) const override {
-    return key;
-  }
 };
 
 class PaintPreviewBaseServiceTest : public content::RenderViewHostTestHarness {
@@ -149,17 +108,22 @@
   PaintPreviewBaseServiceTest() = default;
   ~PaintPreviewBaseServiceTest() override = default;
 
+  PaintPreviewBaseServiceTest(const PaintPreviewBaseService&) = delete;
+  PaintPreviewBaseServiceTest& operator=(const PaintPreviewBaseService&) =
+      delete;
+
  protected:
   void SetUp() override {
     content::RenderViewHostTestHarness::SetUp();
     key_ = std::make_unique<SimpleFactoryKey>(
         browser_context()->GetPath(), browser_context()->IsOffTheRecord());
-    PaintPreviewBaseServiceFactory::GetInstance()->SetTestingFactory(
-        key_.get(), base::BindRepeating(&BuildService));
+    PaintPreviewBaseServiceTestFactory::GetInstance()->SetTestingFactory(
+        key_.get(),
+        base::BindRepeating(&PaintPreviewBaseServiceTestFactory::Build));
 
     rejection_policy_key_ = std::make_unique<SimpleFactoryKey>(
         browser_context()->GetPath(), browser_context()->IsOffTheRecord());
-    PaintPreviewBaseServiceFactory::GetInstance()->SetTestingFactory(
+    PaintPreviewBaseServiceTestFactory::GetInstance()->SetTestingFactory(
         rejection_policy_key_.get(),
         base::BindRepeating(&BuildServiceWithRejectionPolicy));
   }
@@ -173,20 +137,18 @@
                             base::Unretained(service)));
   }
 
-  PaintPreviewBaseService* CreateService() {
-    return PaintPreviewBaseServiceFactory::GetForKey(key_.get());
+  PaintPreviewBaseService* GetService() {
+    return PaintPreviewBaseServiceTestFactory::GetForKey(key_.get());
   }
 
-  PaintPreviewBaseService* CreateServiceWithRejectionPolicy() {
-    return PaintPreviewBaseServiceFactory::GetForKey(
+  PaintPreviewBaseService* GetServiceWithRejectionPolicy() {
+    return PaintPreviewBaseServiceTestFactory::GetForKey(
         rejection_policy_key_.get());
   }
 
  private:
   std::unique_ptr<SimpleFactoryKey> key_ = nullptr;
   std::unique_ptr<SimpleFactoryKey> rejection_policy_key_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintPreviewBaseServiceTest);
 };
 
 TEST_F(PaintPreviewBaseServiceTest, CaptureMainFrame) {
@@ -200,7 +162,7 @@
   recorder.SetResponse(mojom::PaintPreviewStatus::kOk, std::move(response));
   OverrideInterface(&recorder);
 
-  auto* service = CreateService();
+  auto* service = GetService();
   EXPECT_FALSE(service->IsOffTheRecord());
   base::FilePath path;
   ASSERT_TRUE(service->GetFileManager()->CreateOrGetDirectoryFor(
@@ -246,7 +208,7 @@
   recorder.SetResponse(mojom::PaintPreviewStatus::kFailed, std::move(response));
   OverrideInterface(&recorder);
 
-  auto* service = CreateService();
+  auto* service = GetService();
   EXPECT_FALSE(service->IsOffTheRecord());
   base::FilePath path;
   ASSERT_TRUE(service->GetFileManager()->CreateOrGetDirectoryFor(
@@ -280,7 +242,7 @@
   recorder.SetResponse(mojom::PaintPreviewStatus::kFailed, std::move(response));
   OverrideInterface(&recorder);
 
-  auto* service = CreateServiceWithRejectionPolicy();
+  auto* service = GetServiceWithRejectionPolicy();
   EXPECT_FALSE(service->IsOffTheRecord());
   base::FilePath path;
   ASSERT_TRUE(service->GetFileManager()->CreateOrGetDirectoryFor(
diff --git a/components/paint_preview/browser/paint_preview_compositor_client_impl.cc b/components/paint_preview/browser/paint_preview_compositor_client_impl.cc
new file mode 100644
index 0000000..0195b8f
--- /dev/null
+++ b/components/paint_preview/browser/paint_preview_compositor_client_impl.cc
@@ -0,0 +1,92 @@
+// 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 "components/paint_preview/browser/paint_preview_compositor_client_impl.h"
+
+#include <utility>
+
+#include "base/callback.h"
+
+namespace paint_preview {
+
+PaintPreviewCompositorClientImpl::PaintPreviewCompositorClientImpl(
+    base::WeakPtr<PaintPreviewCompositorServiceImpl> service)
+    : service_(service) {}
+
+PaintPreviewCompositorClientImpl::~PaintPreviewCompositorClientImpl() {
+  NotifyServiceOfInvalidation();
+}
+
+const base::Optional<base::UnguessableToken>&
+PaintPreviewCompositorClientImpl::Token() const {
+  return token_;
+}
+
+void PaintPreviewCompositorClientImpl::SetDisconnectHandler(
+    base::OnceClosure closure) {
+  user_disconnect_closure_ = std::move(closure);
+}
+
+void PaintPreviewCompositorClientImpl::BeginComposite(
+    mojom::PaintPreviewBeginCompositeRequestPtr request,
+    mojom::PaintPreviewCompositor::BeginCompositeCallback callback) {
+  compositor_->BeginComposite(std::move(request), std::move(callback));
+}
+
+void PaintPreviewCompositorClientImpl::BitmapForFrame(
+    uint64_t frame_guid,
+    const gfx::Rect& clip_rect,
+    float scale_factor,
+    mojom::PaintPreviewCompositor::BitmapForFrameCallback callback) {
+  compositor_->BitmapForFrame(frame_guid, clip_rect, scale_factor,
+                              std::move(callback));
+}
+
+void PaintPreviewCompositorClientImpl::SetRootFrameUrl(const GURL& url) {
+  compositor_->SetRootFrameUrl(url);
+}
+
+bool PaintPreviewCompositorClientImpl::IsBoundAndConnected() const {
+  return compositor_.is_bound() && compositor_.is_connected();
+}
+
+mojo::PendingReceiver<mojom::PaintPreviewCompositor>
+PaintPreviewCompositorClientImpl::BindNewPipeAndPassReceiver() {
+  return compositor_.BindNewPipeAndPassReceiver();
+}
+
+PaintPreviewCompositorClientImpl::OnCompositorCreatedCallback
+PaintPreviewCompositorClientImpl::BuildCompositorCreatedCallback(
+    base::OnceClosure user_closure,
+    OnCompositorCreatedCallback service_callback) {
+  return base::BindOnce(&PaintPreviewCompositorClientImpl::OnCompositorCreated,
+                        weak_ptr_factory_.GetWeakPtr(), std::move(user_closure),
+                        std::move(service_callback));
+}
+
+void PaintPreviewCompositorClientImpl::OnCompositorCreated(
+    base::OnceClosure user_closure,
+    OnCompositorCreatedCallback service_callback,
+    const base::UnguessableToken& token) {
+  token_ = token;
+  std::move(user_closure).Run();
+  std::move(service_callback).Run(token);
+  compositor_.set_disconnect_handler(
+      base::BindOnce(&PaintPreviewCompositorClientImpl::DisconnectHandler,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void PaintPreviewCompositorClientImpl::NotifyServiceOfInvalidation() {
+  if (service_ && token_.has_value())
+    service_->MarkCompositorAsDeleted(token_.value());
+}
+
+void PaintPreviewCompositorClientImpl::DisconnectHandler() {
+  if (user_disconnect_closure_)
+    std::move(user_disconnect_closure_).Run();
+  NotifyServiceOfInvalidation();
+  compositor_.reset();
+}
+
+}  // namespace paint_preview
diff --git a/components/paint_preview/browser/paint_preview_compositor_client_impl.h b/components/paint_preview/browser/paint_preview_compositor_client_impl.h
new file mode 100644
index 0000000..dbfabfcd
--- /dev/null
+++ b/components/paint_preview/browser/paint_preview_compositor_client_impl.h
@@ -0,0 +1,77 @@
+// 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 COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_COMPOSITOR_CLIENT_IMPL_H_
+#define COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_COMPOSITOR_CLIENT_IMPL_H_
+
+#include "base/callback_forward.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
+#include "components/paint_preview/browser/paint_preview_compositor_service_impl.h"
+#include "components/paint_preview/public/paint_preview_compositor_client.h"
+#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "ui/gfx/geometry/rect.h"
+#include "url/gurl.h"
+
+namespace paint_preview {
+
+class PaintPreviewCompositorClientImpl : public PaintPreviewCompositorClient {
+ public:
+  using OnCompositorCreatedCallback =
+      base::OnceCallback<void(const base::UnguessableToken&)>;
+
+  explicit PaintPreviewCompositorClientImpl(
+      base::WeakPtr<PaintPreviewCompositorServiceImpl> service);
+  ~PaintPreviewCompositorClientImpl() override;
+
+  // PaintPreviewCompositorClient implementation.
+  const base::Optional<base::UnguessableToken>& Token() const override;
+  void SetDisconnectHandler(base::OnceClosure closure) override;
+  void BeginComposite(
+      mojom::PaintPreviewBeginCompositeRequestPtr request,
+      mojom::PaintPreviewCompositor::BeginCompositeCallback callback) override;
+  void BitmapForFrame(
+      uint64_t frame_guid,
+      const gfx::Rect& clip_rect,
+      float scale_factor,
+      mojom::PaintPreviewCompositor::BitmapForFrameCallback callback) override;
+  void SetRootFrameUrl(const GURL& url) override;
+
+  // Exposes underlying BindNewPipeAndPassReceiver method of |compositor_|.
+  mojo::PendingReceiver<mojom::PaintPreviewCompositor>
+  BindNewPipeAndPassReceiver();
+
+  bool IsBoundAndConnected() const;
+
+  OnCompositorCreatedCallback BuildCompositorCreatedCallback(
+      base::OnceClosure user_closure,
+      OnCompositorCreatedCallback service_callback);
+
+  PaintPreviewCompositorClientImpl(const PaintPreviewCompositorClientImpl&) =
+      delete;
+  PaintPreviewCompositorClientImpl& operator=(
+      const PaintPreviewCompositorClientImpl&) = delete;
+
+ private:
+  void OnCompositorCreated(base::OnceClosure user_closure,
+                           OnCompositorCreatedCallback service_callback,
+                           const base::UnguessableToken& token);
+
+  void NotifyServiceOfInvalidation();
+
+  void DisconnectHandler();
+
+  base::Optional<base::UnguessableToken> token_;
+  base::WeakPtr<PaintPreviewCompositorServiceImpl> service_;
+  mojo::Remote<mojom::PaintPreviewCompositor> compositor_;
+  base::OnceClosure user_disconnect_closure_;
+
+  base::WeakPtrFactory<PaintPreviewCompositorClientImpl> weak_ptr_factory_{
+      this};
+};
+
+}  // namespace paint_preview
+
+#endif  // COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_COMPOSITOR_CLIENT_IMPL_H_
diff --git a/components/paint_preview/browser/paint_preview_compositor_service_impl.cc b/components/paint_preview/browser/paint_preview_compositor_service_impl.cc
new file mode 100644
index 0000000..ea75e7e
--- /dev/null
+++ b/components/paint_preview/browser/paint_preview_compositor_service_impl.cc
@@ -0,0 +1,70 @@
+// 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 "components/paint_preview/browser/paint_preview_compositor_service_impl.h"
+
+#include "components/paint_preview/browser/paint_preview_compositor_client_impl.h"
+#include "components/paint_preview/public/paint_preview_compositor_client.h"
+
+namespace paint_preview {
+
+PaintPreviewCompositorServiceImpl::PaintPreviewCompositorServiceImpl(
+    mojo::Remote<mojom::PaintPreviewCompositorCollection> remote,
+    base::OnceClosure disconnect_handler)
+    : compositor_service_(std::move(remote)),
+      user_disconnect_closure_(std::move(disconnect_handler)) {
+  compositor_service_.set_disconnect_handler(
+      base::BindOnce(&PaintPreviewCompositorServiceImpl::DisconnectHandler,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+// The destructor for the |compositor_service_| will automatically result in any
+// active compositors being killed.
+PaintPreviewCompositorServiceImpl::~PaintPreviewCompositorServiceImpl() =
+    default;
+
+std::unique_ptr<PaintPreviewCompositorClient>
+PaintPreviewCompositorServiceImpl::CreateCompositor(
+    base::OnceClosure connected_closure) {
+  auto compositor = std::make_unique<PaintPreviewCompositorClientImpl>(
+      weak_ptr_factory_.GetWeakPtr());
+  compositor_service_->CreateCompositor(
+      compositor->BindNewPipeAndPassReceiver(),
+      compositor->BuildCompositorCreatedCallback(
+          std::move(connected_closure),
+          base::BindOnce(
+              &PaintPreviewCompositorServiceImpl::OnCompositorCreated,
+              weak_ptr_factory_.GetWeakPtr())));
+  return compositor;
+}
+
+bool PaintPreviewCompositorServiceImpl::HasActiveClients() const {
+  return !active_clients_.empty();
+}
+
+void PaintPreviewCompositorServiceImpl::MarkCompositorAsDeleted(
+    const base::UnguessableToken& token) {
+  active_clients_.erase(token);
+}
+
+bool PaintPreviewCompositorServiceImpl::IsServiceBoundAndConnected() const {
+  return compositor_service_.is_bound() && compositor_service_.is_connected();
+}
+
+const base::flat_set<base::UnguessableToken>&
+PaintPreviewCompositorServiceImpl::ActiveClientsForTesting() const {
+  return active_clients_;
+}
+
+void PaintPreviewCompositorServiceImpl::OnCompositorCreated(
+    const base::UnguessableToken& token) {
+  active_clients_.insert(token);
+}
+
+void PaintPreviewCompositorServiceImpl::DisconnectHandler() {
+  std::move(user_disconnect_closure_).Run();
+  compositor_service_.reset();
+}
+
+}  // namespace paint_preview
diff --git a/components/paint_preview/browser/paint_preview_compositor_service_impl.h b/components/paint_preview/browser/paint_preview_compositor_service_impl.h
new file mode 100644
index 0000000..93617807
--- /dev/null
+++ b/components/paint_preview/browser/paint_preview_compositor_service_impl.h
@@ -0,0 +1,60 @@
+// 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 COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_COMPOSITOR_SERVICE_IMPL_H_
+#define COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_COMPOSITOR_SERVICE_IMPL_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/containers/flat_set.h"
+#include "base/unguessable_token.h"
+#include "components/paint_preview/public/paint_preview_compositor_service.h"
+#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace paint_preview {
+
+class PaintPreviewCompositorServiceImpl : public PaintPreviewCompositorService {
+ public:
+  explicit PaintPreviewCompositorServiceImpl(
+      mojo::Remote<mojom::PaintPreviewCompositorCollection> remote,
+      base::OnceClosure disconnect_closure);
+  ~PaintPreviewCompositorServiceImpl() override;
+
+  // PaintPreviewCompositorService Implementation.
+  std::unique_ptr<PaintPreviewCompositorClient> CreateCompositor(
+      base::OnceClosure connected_closure) override;
+  bool HasActiveClients() const override;
+
+  // Marks the compositor associated with |token| as deleted in the
+  // |active_clients_| set.
+  void MarkCompositorAsDeleted(const base::UnguessableToken& token);
+
+  bool IsServiceBoundAndConnected() const;
+
+  // Test method to validate internal state.
+  const base::flat_set<base::UnguessableToken>& ActiveClientsForTesting() const;
+
+  PaintPreviewCompositorServiceImpl(const PaintPreviewCompositorServiceImpl&) =
+      delete;
+  PaintPreviewCompositorServiceImpl& operator=(
+      const PaintPreviewCompositorServiceImpl&) = delete;
+
+ private:
+  void OnCompositorCreated(const base::UnguessableToken& token);
+
+  void DisconnectHandler();
+
+  mojo::Remote<mojom::PaintPreviewCompositorCollection> compositor_service_;
+  base::flat_set<base::UnguessableToken> active_clients_;
+  base::OnceClosure user_disconnect_closure_;
+
+  base::WeakPtrFactory<PaintPreviewCompositorServiceImpl> weak_ptr_factory_{
+      this};
+};
+
+}  // namespace paint_preview
+
+#endif  // COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_COMPOSITOR_SERVICE_IMPL_H_
diff --git a/components/paint_preview/public/BUILD.gn b/components/paint_preview/public/BUILD.gn
new file mode 100644
index 0000000..61485c4
--- /dev/null
+++ b/components/paint_preview/public/BUILD.gn
@@ -0,0 +1,21 @@
+# 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.
+
+assert(!is_ios, "Paint Previews are not supported on iOS.")
+
+source_set("public") {
+  sources = [
+    "paint_preview_compositor_client.h",
+    "paint_preview_compositor_service.h",
+  ]
+
+  public_deps = [
+    "//components/services/paint_preview_compositor/public/mojom",
+  ]
+
+  deps = [
+    "//base",
+    "//url",
+  ]
+}
diff --git a/components/paint_preview/public/DEPS b/components/paint_preview/public/DEPS
new file mode 100644
index 0000000..2349e2e
--- /dev/null
+++ b/components/paint_preview/public/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/services/paint_preview_compositor/public/mojom",
+]
diff --git a/components/paint_preview/public/paint_preview_compositor_client.h b/components/paint_preview/public/paint_preview_compositor_client.h
new file mode 100644
index 0000000..91aa417
--- /dev/null
+++ b/components/paint_preview/public/paint_preview_compositor_client.h
@@ -0,0 +1,56 @@
+// 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 COMPONENTS_PAINT_PREVIEW_PUBLIC_PAINT_PREVIEW_COMPOSITOR_CLIENT_H_
+#define COMPONENTS_PAINT_PREVIEW_PUBLIC_PAINT_PREVIEW_COMPOSITOR_CLIENT_H_
+
+#include "base/callback_forward.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
+#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
+#include "url/gurl.h"
+
+namespace gfx {
+class Rect;
+}  // namespace gfx
+
+namespace paint_preview {
+
+// An instance of a paint preview compositor that is running in a utility
+// process service. The class' lifetime is tied to that of the compositor
+// running in the utility process (unless there is some kind of IPC disconnect
+// that occurs).
+class PaintPreviewCompositorClient {
+ public:
+  virtual ~PaintPreviewCompositorClient() = default;
+
+  // Returns the token associated with the client. Will be null if the client
+  // isn't started.
+  virtual const base::Optional<base::UnguessableToken>& Token() const = 0;
+
+  // Adds |closure| as a disconnect handler.
+  virtual void SetDisconnectHandler(base::OnceClosure closure) = 0;
+
+  // mojom::PaintPreviewCompositor API
+  virtual void BeginComposite(
+      mojom::PaintPreviewBeginCompositeRequestPtr request,
+      mojom::PaintPreviewCompositor::BeginCompositeCallback callback) = 0;
+  virtual void BitmapForFrame(
+      uint64_t frame_guid,
+      const gfx::Rect& clip_rect,
+      float scale_factor,
+      mojom::PaintPreviewCompositor::BitmapForFrameCallback callback) = 0;
+  virtual void SetRootFrameUrl(const GURL& url) = 0;
+
+  PaintPreviewCompositorClient(const PaintPreviewCompositorClient&) = delete;
+  PaintPreviewCompositorClient& operator=(const PaintPreviewCompositorClient&) =
+      delete;
+
+ protected:
+  PaintPreviewCompositorClient() = default;
+};
+
+}  // namespace paint_preview
+
+#endif  // COMPONENTS_PAINT_PREVIEW_PUBLIC_PAINT_PREVIEW_COMPOSITOR_CLIENT_H_
diff --git a/components/paint_preview/public/paint_preview_compositor_service.h b/components/paint_preview/public/paint_preview_compositor_service.h
new file mode 100644
index 0000000..a1dffb5
--- /dev/null
+++ b/components/paint_preview/public/paint_preview_compositor_service.h
@@ -0,0 +1,46 @@
+// 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 COMPONENTS_PAINT_PREVIEW_PUBLIC_PAINT_PREVIEW_COMPOSITOR_SERVICE_H_
+#define COMPONENTS_PAINT_PREVIEW_PUBLIC_PAINT_PREVIEW_COMPOSITOR_SERVICE_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "components/paint_preview/public/paint_preview_compositor_client.h"
+
+namespace paint_preview {
+
+// An instance of a paint preview compositor utility process service. This
+// class' lifetime is tied to that of the utility process to which it is
+// connected. As long as the instance of this class is alive the utility process
+// should be as well*. When this class is destructed then the utility process
+// will also exit shortly.
+//
+// * If the utility process is killed by the OS or disconnected via Mojo then
+//   this isn't necessarily the case; however, in the general it is true.
+class PaintPreviewCompositorService {
+ public:
+  virtual ~PaintPreviewCompositorService() = default;
+
+  // Creates a compositor instance tied to the service. |connected_closure| is
+  // run once the compositor is started.
+  virtual std::unique_ptr<PaintPreviewCompositorClient> CreateCompositor(
+      base::OnceClosure connected_closure) = 0;
+
+  // Returns whether there are any active clients. This can be used to
+  // check if killing this service is safe (i.e. won't drop messages).
+  virtual bool HasActiveClients() const = 0;
+
+  PaintPreviewCompositorService(const PaintPreviewCompositorService&) = delete;
+  PaintPreviewCompositorService& operator=(
+      const PaintPreviewCompositorService&) = delete;
+
+ protected:
+  PaintPreviewCompositorService() = default;
+};
+
+}  // namespace paint_preview
+
+#endif  // COMPONENTS_PAINT_PREVIEW_PUBLIC_PAINT_PREVIEW_COMPOSITOR_SERVICE_H_
diff --git a/components/paint_preview_strings.grdp b/components/paint_preview_strings.grdp
index 4f43ed85..7127d2b4 100644
--- a/components/paint_preview_strings.grdp
+++ b/components/paint_preview_strings.grdp
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-
   <message name="IDS_PAINT_PREVIEW_COMPOSITOR_SERVICE_DISPLAY_NAME" desc="The display name (in the system task manager, etc) of the service process used for compositing Paint Previews.">
     Paint Preview Compositor Service
   </message>
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc
index c100e088..8bf618f3 100644
--- a/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -362,6 +362,16 @@
   if (render_accessibility && tree_.size() > 1) {
     ui::AXNode* root = tree_.root();
     ui::AXNodeData root_data = root->data();
+    root_data.AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin, 0);
+    root_data.AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax,
+                              viewport_info.total_scrollable_size.width);
+    root_data.AddIntAttribute(ax::mojom::IntAttribute::kScrollX,
+                              viewport_info.current_scroll_position.x);
+    root_data.AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin, 0);
+    root_data.AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax,
+                              viewport_info.total_scrollable_size.height);
+    root_data.AddIntAttribute(ax::mojom::IntAttribute::kScrollY,
+                              viewport_info.current_scroll_position.y);
     root_data.relative_bounds.transform =
         base::WrapUnique(MakeTransformFromViewInfo());
     root->SetData(root_data);
diff --git a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
index 8d8e4d3..4bcc411 100644
--- a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
+++ b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
@@ -166,6 +166,8 @@
 
     viewport_info_.zoom = 1.0;
     viewport_info_.scale = 1.0;
+    viewport_info_.total_scrollable_size = {0, 0};
+    viewport_info_.current_scroll_position = {0, 0};
     viewport_info_.scroll = {0, 0};
     viewport_info_.offset = {0, 0};
     viewport_info_.selection_start_page_index = 0;
diff --git a/components/performance_manager/graph/node_base.h b/components/performance_manager/graph/node_base.h
index c8e36fca..9740d7a 100644
--- a/components/performance_manager/graph/node_base.h
+++ b/components/performance_manager/graph/node_base.h
@@ -16,7 +16,6 @@
 #include "components/performance_manager/graph/graph_impl.h"
 #include "components/performance_manager/graph/node_type.h"
 #include "components/performance_manager/graph/properties.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 
diff --git a/components/policy/resources/policy_templates_ja.xtb b/components/policy/resources/policy_templates_ja.xtb
index aecb20c..ba2ef54 100644
--- a/components/policy/resources/policy_templates_ja.xtb
+++ b/components/policy/resources/policy_templates_ja.xtb
@@ -1647,7 +1647,7 @@
           この設定が無効な場合、ユーザーは新しいパスワードを保存できませんが、以前保存したパスワードは引き続き使用できます。
 
           このポリシーが有効または無効の場合、ユーザーは <ph name="PRODUCT_NAME" /> でこの設定を変更したりオーバーライドしたりすることはできません。このポリシーが未設定の場合、パスワードは保存されます(ただし、ユーザーはパスワードの保存をオフにできます)。</translation>
-<translation id="3496296378755072552">パスワード マネージャ</translation>
+<translation id="3496296378755072552">パスワード マネージャー</translation>
 <translation id="3500732098526756068">パスワード保護の警告を表示するトリガーを制御できます。パスワード保護の警告は、不審なサイトでユーザーが保護されたパスワードを再使用したときに表示されます。
 
       保護するパスワードを設定するには、「PasswordProtectionLoginURLs」ポリシーと「PasswordProtectionChangePasswordURL」ポリシーを使用します。
@@ -2290,7 +2290,7 @@
       現在、このポリシーで指定できるデータタイプは次のとおりです。"bookmarks"、"preferences"、"passwords"、"autofill"、"themes"、"typedUrls"、"extensions"、"apps"、"tabs"、"wifiConfiguration"データタイプの名前では大文字と小文字が区別されます。</translation>
 <translation id="4454820008017317557"><ph name="PRODUCT_NAME" /> ツールバー アイコンを表示する</translation>
 <translation id="4467952432486360968">サードパーティの Cookie をブロックする</translation>
-<translation id="4474167089968829729">パスワード マネージャへのパスワード保存を有効にする</translation>
+<translation id="4474167089968829729">パスワード マネージャーへのパスワード保存を有効にする</translation>
 <translation id="4476769083125004742">このポリシーを <ph name="BLOCK_GEOLOCATION_SETTING" /> に設定した場合、Android アプリは位置情報にアクセスできません。このポリシーを他の値に設定するか未設定のままにした場合、Android アプリで位置情報へのアクセスが必要になったときには、ユーザーに同意が求められます。</translation>
 <translation id="4480694116501920047">セーフサーチを強制する</translation>
 <translation id="4482640907922304445"><ph name="PRODUCT_NAME" /> のツールバーにホーム ボタンを表示します。この設定を有効にすると、ホーム ボタンが常に表示されます。この設定を無効にすると、ホーム ボタンは表示されません。この設定を有効または無効にすると、ユーザーは <ph name="PRODUCT_NAME" /> でこの設定の変更やオーバーライドができなくなります。このポリシーが未設定の場合、ホーム ボタンを表示するかどうかをユーザーが選択できます。</translation>
@@ -3030,13 +3030,13 @@
       注: このポリシーは、厳密に 1 GB より大きい RAM を搭載した Android デバイスの Chrome のみに適用されます。Android 以外のプラットフォームにこのポリシーを適用するには、IsolateOrigins を使用してください。
       </translation>
 <translation id="5599461642204007579"><ph name="MS_AD_NAME" /> 管理設定</translation>
-<translation id="5618398258385745432">関連付けられている設定は、パスワード表示での再認証が導入される前は使用されていましたが、導入以降は、その設定、つまりこのポリシーは、Chrome の動作に適用されなくなりました。現在の Chrome の動作は、パスワード マネージャの設定ページでパスワードの平文表示を無効にするようポリシーを設定した場合と同じになりました。つまり、設定ページにはプレースホルダのみが表示され、ユーザーが [表示] をクリックして(必要に応じて再認証を行って)初めて Chrome にパスワードが表示されます。ポリシーの元の説明は次のとおりです。
+<translation id="5618398258385745432">関連付けられている設定は、パスワード表示での再認証が導入される前は使用されていましたが、導入以降は、その設定、つまりこのポリシーは、Chrome の動作に適用されなくなりました。現在の Chrome の動作は、パスワード マネージャーの設定ページでパスワードの平文表示を無効にするようポリシーを設定した場合と同じになりました。つまり、設定ページにはプレースホルダのみが表示され、ユーザーが [表示] をクリックして(必要に応じて再認証を行って)初めて Chrome にパスワードが表示されます。ポリシーの元の説明は次のとおりです。
 
-          ユーザーがパスワード マネージャでパスワードの平文表示を行えるかどうかを管理します。
+          ユーザーがパスワード マネージャーでパスワードの平文表示を行えるかどうかを管理します。
 
-          この設定を無効にした場合、保存したパスワードをパスワード マネージャ ウィンドウで平文表示することはできません。
+          この設定を無効にした場合、保存したパスワードをパスワード マネージャー ウィンドウで平文表示することはできません。
 
-          このポリシーが有効または未設定の場合、ユーザーはパスワード マネージャでパスワードを平文表示できます。</translation>
+          このポリシーが有効または未設定の場合、ユーザーはパスワード マネージャーでパスワードを平文表示できます。</translation>
 <translation id="5620392548325769024">OS のアップグレード後に初めてブラウザを起動したときのウェルカム ページの表示を有効にする</translation>
 <translation id="5630352020869108293">最後のセッションを復元する</translation>
 <translation id="5633871703004128675">「テキストカーソルによるハイライト表示」のユーザー補助機能を有効にする</translation>
@@ -3852,7 +3852,7 @@
 
       安定性を重視したタスク スケジューラ設定を使用する場合は「conservative」、パフォーマンスを重視したタスク スケジューラ設定を使用する場合は「performance」と指定します。
       このポリシーを設定しない場合は、ユーザーが設定を選択できます。</translation>
-<translation id="7145335384492396213">デフォルトの PIN 印刷モードです</translation>
+<translation id="7145335384492396213">デフォルトの PIN 印刷モード</translation>
 <translation id="7149042336307555519"> OS アップデートに使用できる接続のタイプです。OS アップデートは、サイズが大きいために接続に大きな負担がかかり、余分な費用が発生する可能性があります。そのためデフォルトでは、費用が高くなる接続タイプ(現時点では「cellular」)を利用できません。
 
       認識される接続タイプ ID は <ph name="CONNECTION_TYPE_ETHERNET_NAME" />、<ph name="CONNECTION_TYPE_WIFI_NAME" />、<ph name="CONNECTION_TYPE_CELLULAR_NAME" /> です。</translation>
@@ -3867,7 +3867,7 @@
       <ph name="ANDROID_VERSION" /> 以上の場合、DNS-over-TLS が有効であれば <ph name="PRODUCT_NAME" /> では安全でない DNS リクエストの送信が行われません。
 
       このポリシーを未設定にした場合、ブラウザは、ユーザーが設定したシステム リゾルバに関連付けられているリゾルバに DNS-over-HTTPS リクエストを送信する可能性があります。</translation>
-<translation id="7167436895080860385">パスワード マネージャでパスワードを表示できるようにする(サポート終了)</translation>
+<translation id="7167436895080860385">パスワード マネージャーでパスワードを表示できるようにする(サポート終了)</translation>
 <translation id="7173856672248996428">一時的なプロフィール</translation>
 <translation id="717630378807352957">設定ファイルのすべてのプリンタを許可する。</translation>
 <translation id="7176721759719212761">画面の起動ロックを許可するかどうかを指定します。画面の起動ロックは拡張機能から Power Management Extension API を使って、または ARC アプリからリクエストされます。
@@ -4409,7 +4409,7 @@
       このポリシーが true に設定されている場合、デバイスでは時刻が 24 時間形式で表示されます。false に設定されている場合、デバイスでは時刻が 12 時間形式で表示されます。
 
       このポリシーが設定されていない場合、デバイスではデフォルトとして時刻が 24 時間形式で表示されます。</translation>
-<translation id="8114382167597081590">YouTube で制限付きモードを強制しない</translation>
+<translation id="8114382167597081590">YouTube で制限モードを強制適用しない</translation>
 <translation id="8117921351531866504">保存されているお支払い方法の確認をウェブサイトに許可するかどうかを設定します。
 
       このポリシーを無効に設定した場合、PaymentRequest.canMakePayment や PaymentRequest.hasEnrolledInstrument の API を使用するウェブサイトには、利用できるお支払い方法がないことが通知されます。
@@ -4475,7 +4475,7 @@
 <translation id="8176035528522326671">企業ユーザーがメインのマルチプロフィール ユーザーとしてのみ操作できるようにする(企業の管理対象ユーザーに対するデフォルトの動作)</translation>
 <translation id="8183108371184777472">ブラウザ ウィンドウの起動を抑制する</translation>
 <translation id="8186911565834244165">ユーザーからのフィードバックを許可する</translation>
-<translation id="8214600119442850823">パスワード マネージャを設定します。</translation>
+<translation id="8214600119442850823">パスワード マネージャーを設定します。</translation>
 <translation id="8217516105848565518">このポリシーはサポートを終了しました。代わりに RemoteAccessHostDomainList を使用してください。</translation>
 <translation id="8236323460664833038">ブロック可能な(アクティブな)混合コンテンツ(HTTPS サイトの HTTP コンテンツ)の表示を許可するサイトと、任意でブロック可能な混合コンテンツのアップグレードを無効にするサイトを URL パターンのリストで設定できます。
 
diff --git a/components/policy/resources/policy_templates_zh-TW.xtb b/components/policy/resources/policy_templates_zh-TW.xtb
index c1344766..0c62031 100644
--- a/components/policy/resources/policy_templates_zh-TW.xtb
+++ b/components/policy/resources/policy_templates_zh-TW.xtb
@@ -349,7 +349,7 @@
 <translation id="1522425503138261032">允許網站追蹤使用者的實際位置</translation>
 <translation id="1523774894176285446">要啟動的替代瀏覽器 (適用於已設定的網站)。</translation>
 <translation id="152657506688053119">預設搜尋的替代網址清單</translation>
-<translation id="1530812829012954197">一律在瀏覽器中顯示以下網址模式</translation>
+<translation id="1530812829012954197">一律在瀏覽器中算繪以下網址模式</translation>
 <translation id="1541170838458414064">限制列印頁面大小</translation>
 <translation id="1553684822621013552">如果將這項政策設為 true,系統會為使用者啟用 ARC
       (需經過額外政策設定檢查 - 如果目前的
@@ -2623,7 +2623,7 @@
 
       如果停用這項設定或不設定,系統只會使用優先程度最高的來源所列出的項目,並將所有其他來源顯示為衝突項目並予以忽略。</translation>
 <translation id="5141670636904227950">設定啟用的螢幕放大鏡在登入畫面的預設類型</translation>
-<translation id="5142301680741828703">一律轉譯下列 <ph name="PRODUCT_FRAME_NAME" /> 中的網址模式</translation>
+<translation id="5142301680741828703">一律算繪下列 <ph name="PRODUCT_FRAME_NAME" /> 中的網址模式</translation>
 <translation id="5148753489738115745">允許你指定 <ph name="PRODUCT_FRAME_NAME" /> 啟動 <ph name="PRODUCT_NAME" /> 時使用的其他參數。
 
           如果未設定這項政策,系統會使用預設命令列。</translation>
@@ -2884,7 +2884,7 @@
 <translation id="5442026853063570579">這項政策也可以控制 Android 開發人員選項的存取權。如果將這項政策設為「DeveloperToolsDisallowed」(值 2),使用者將無法存取開發人員選項。如果將這項政策設為其他值或不予設定,使用者只要在 Android 設定應用程式中輕觸版本號碼七次,即可存取開發人員選項。</translation>
 <translation id="5447306928176905178">在網頁上回報記憶體資訊 (JavaScript 堆積大小) (已不適用)</translation>
 <translation id="5457065417344056871">在瀏覽器中啟用訪客模式</translation>
-<translation id="5457924070961220141">允許你在安裝「<ph name="PRODUCT_FRAME_NAME" />」之後,設定預設的 HTML 轉譯器。如果未設定這項政策,系統就會使用預設設定,允許主機瀏覽器進行轉譯,但是你可以覆寫這項預設,改由「<ph name="PRODUCT_FRAME_NAME" />」轉譯 HTML 網頁。</translation>
+<translation id="5457924070961220141">允許你在安裝「<ph name="PRODUCT_FRAME_NAME" />」之後,設定預設的 HTML 算繪器。如果未設定這項政策,系統就會使用預設設定,允許主機瀏覽器進行算繪,但是你可以覆寫這項預設,改由「<ph name="PRODUCT_FRAME_NAME" />」算繪 HTML 網頁。</translation>
 <translation id="5464816904705580310">為管理化環境下的使用者調整設定。</translation>
 <translation id="546726650689747237">在 AC 供電環境下執行時的螢幕調暗延遲時間</translation>
 <translation id="5469143988693423708">已允許使用者執行 Crostini</translation>
@@ -5054,8 +5054,8 @@
 <translation id="922540222991413931">設定擴充功能、應用程式和使用者指令碼安裝來源</translation>
 <translation id="924557436754151212">第一次執行時從預設瀏覽器匯入已儲存的密碼</translation>
 <translation id="930930237275114205">設定 <ph name="PRODUCT_FRAME_NAME" /> 使用者資料目錄</translation>
-<translation id="943865157632139008">這項政策可讓你在安裝 <ph name="PRODUCT_FRAME_NAME" />後,設定預設的 HTML 轉譯器。
-      系統在預設設定下,會允許主機瀏覽器進行轉譯,但是你可以覆寫預設設定,改由 <ph name="PRODUCT_FRAME_NAME" />轉譯 HTML 網頁。</translation>
+<translation id="943865157632139008">這項政策可讓你在安裝 <ph name="PRODUCT_FRAME_NAME" />後,設定預設的 HTML 算繪器。
+      系統在預設設定下,會允許主機瀏覽器進行算繪,但是你可以覆寫預設設定,改由 <ph name="PRODUCT_FRAME_NAME" />算繪 HTML 網頁。</translation>
 <translation id="944817693306670849">設定磁碟快取大小</translation>
 <translation id="949278212566535827">允許下載受密碼保護的檔案</translation>
 <translation id="966854160628341653">這項政策可控管 <ph name="PRODUCT_OS_NAME" /> 是否允許建立新的使用者帳戶。如果將這項政策設為 False,沒有帳戶的使用者將無法登入裝置。
diff --git a/components/previews/content/previews_user_data.cc b/components/previews/content/previews_user_data.cc
index a276146..08294dc 100644
--- a/components/previews/content/previews_user_data.cc
+++ b/components/previews/content/previews_user_data.cc
@@ -33,8 +33,7 @@
       committed_previews_state_without_holdback_(
           other.committed_previews_state_without_holdback_),
       coin_flip_holdback_result_(other.coin_flip_holdback_result_),
-      preview_eligibility_reasons_(other.preview_eligibility_reasons_),
-      serialized_hint_version_string_(other.serialized_hint_version_string_) {
+      preview_eligibility_reasons_(other.preview_eligibility_reasons_) {
   if (other.server_lite_page_info_) {
     server_lite_page_info_ =
         std::make_unique<ServerLitePageInfo>(*other.server_lite_page_info_);
diff --git a/components/previews/content/previews_user_data.h b/components/previews/content/previews_user_data.h
index 476145c..b9f7233a 100644
--- a/components/previews/content/previews_user_data.h
+++ b/components/previews/content/previews_user_data.h
@@ -181,15 +181,6 @@
     server_lite_page_info_ = std::move(info);
   }
 
-  // The serialized hints version for the hint that was used for the page load.
-  base::Optional<std::string> serialized_hint_version_string() const {
-    return serialized_hint_version_string_;
-  }
-  void set_serialized_hint_version_string(
-      const std::string& serialized_hint_version_string) {
-    serialized_hint_version_string_ = serialized_hint_version_string;
-  }
-
  private:
   // A session unique ID related to this navigation.
   const uint64_t page_id_;
@@ -247,9 +238,6 @@
   std::unordered_map<PreviewsType, PreviewsEligibilityReason>
       preview_eligibility_reasons_ = {};
 
-  // The serialized hints version for the hint that was used for the page load.
-  base::Optional<std::string> serialized_hint_version_string_ = base::nullopt;
-
   DISALLOW_ASSIGN(PreviewsUserData);
 };
 
diff --git a/components/previews/content/previews_user_data_unittest.cc b/components/previews/content/previews_user_data_unittest.cc
index 67bfc8b..acddd0e 100644
--- a/components/previews/content/previews_user_data_unittest.cc
+++ b/components/previews/content/previews_user_data_unittest.cc
@@ -46,7 +46,6 @@
   EXPECT_FALSE(data->black_listed_for_lite_page());
   EXPECT_FALSE(data->offline_preview_used());
   EXPECT_EQ(data->server_lite_page_info(), nullptr);
-  EXPECT_EQ(base::nullopt, data->serialized_hint_version_string());
 
   base::TimeTicks now = base::TimeTicks::Now();
 
@@ -58,7 +57,6 @@
   data->set_server_lite_page_info(
       std::make_unique<PreviewsUserData::ServerLitePageInfo>());
   data->server_lite_page_info()->original_navigation_start = now;
-  data->set_serialized_hint_version_string("someversion");
 
   PreviewsUserData data_copy(*data);
   EXPECT_EQ(id, data_copy.page_id());
@@ -71,7 +69,6 @@
   EXPECT_TRUE(data_copy.offline_preview_used());
   EXPECT_NE(data->server_lite_page_info(), nullptr);
   EXPECT_EQ(data->server_lite_page_info()->original_navigation_start, now);
-  EXPECT_EQ("someversion", data->serialized_hint_version_string());
 }
 
 TEST(PreviewsUserDataTest, TestCoinFlip_HasCommittedPreviewsType) {
diff --git a/components/printing/browser/print_composite_client.cc b/components/printing/browser/print_composite_client.cc
index 89b935e..4390951a 100644
--- a/components/printing/browser/print_composite_client.cc
+++ b/components/printing/browser/print_composite_client.cc
@@ -21,6 +21,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/service_process_host.h"
 #include "printing/printing_utils.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 
 namespace printing {
 
@@ -101,6 +102,8 @@
     }
     pending_subframe_cookies_.erase(iter);
   }
+
+  print_render_frames_.erase(render_frame_host);
 }
 
 void PrintCompositeClient::OnDidPrintFrameContent(
@@ -143,9 +146,7 @@
     const gfx::Rect& rect,
     int document_cookie,
     content::RenderFrameHost* subframe_host) {
-  PrintMsg_PrintFrame_Params params;
-  params.printable_area = rect;
-  params.document_cookie = document_cookie;
+  auto params = mojom::PrintFrameContentParams::New(rect, document_cookie);
   uint64_t frame_guid = GenerateFrameGuid(subframe_host);
   if (!subframe_host->IsRenderFrameLive()) {
     // When the subframe is dead, no need to send message,
@@ -170,8 +171,7 @@
   }
 
   // Send the request to the destination frame.
-  subframe_host->Send(
-      new PrintMsg_PrintFrameContent(subframe_host->GetRoutingID(), params));
+  GetPrintRenderFrame(subframe_host)->PrintFrameContent(std::move(params));
   pending_subframe_cookies_[frame_guid].insert(document_cookie);
 }
 
@@ -328,6 +328,18 @@
   return compositor;
 }
 
+const mojo::AssociatedRemote<mojom::PrintRenderFrame>&
+PrintCompositeClient::GetPrintRenderFrame(content::RenderFrameHost* rfh) {
+  auto it = print_render_frames_.find(rfh);
+  if (it == print_render_frames_.end()) {
+    mojo::AssociatedRemote<mojom::PrintRenderFrame> remote;
+    rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote);
+    it = print_render_frames_.emplace(rfh, std::move(remote)).first;
+  }
+
+  return it->second;
+}
+
 WEB_CONTENTS_USER_DATA_KEY_IMPL(PrintCompositeClient)
 
 }  // namespace printing
diff --git a/components/printing/browser/print_composite_client.h b/components/printing/browser/print_composite_client.h
index cb552ef9..cbefd85c 100644
--- a/components/printing/browser/print_composite_client.h
+++ b/components/printing/browser/print_composite_client.h
@@ -9,9 +9,11 @@
 #include <memory>
 
 #include "base/containers/flat_set.h"
+#include "components/printing/common/print.mojom.h"
 #include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 struct PrintHostMsg_DidPrintContent_Params;
@@ -120,6 +122,11 @@
 
   mojo::Remote<mojom::PdfCompositor> CreateCompositeRequest();
 
+  // Helper method to fetch the PrintRenderFrame remote interface pointer
+  // associated with a given subframe.
+  const mojo::AssociatedRemote<mojom::PrintRenderFrame>& GetPrintRenderFrame(
+      content::RenderFrameHost* rfh);
+
   // Stores the mapping between document cookies and their corresponding
   // requests.
   std::map<int, mojo::Remote<mojom::PdfCompositor>> compositor_map_;
@@ -139,6 +146,13 @@
 
   std::string user_agent_;
 
+  // Stores a PrintRenderFrame associated remote with the RenderFrameHost used
+  // to bind it. The PrintRenderFrame is used to transmit mojo interface method
+  // calls to the associated receiver.
+  std::map<content::RenderFrameHost*,
+           mojo::AssociatedRemote<mojom::PrintRenderFrame>>
+      print_render_frames_;
+
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 
   DISALLOW_COPY_AND_ASSIGN(PrintCompositeClient);
diff --git a/components/printing/common/BUILD.gn b/components/printing/common/BUILD.gn
index 0500aa6..8f5311538 100644
--- a/components/printing/common/BUILD.gn
+++ b/components/printing/common/BUILD.gn
@@ -35,6 +35,7 @@
 
   public_deps = [
     "//mojo/public/mojom/base",
+    "//ui/gfx/geometry/mojom",
   ]
 
   if (enable_print_preview) {
diff --git a/components/printing/common/print.mojom b/components/printing/common/print.mojom
index 34e1cda0..c4707f46 100644
--- a/components/printing/common/print.mojom
+++ b/components/printing/common/print.mojom
@@ -6,6 +6,17 @@
 
 import "mojo/public/mojom/base/shared_memory.mojom";
 import "mojo/public/mojom/base/values.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
+
+// Parameters required to print the content of an out-of-process subframe.
+struct PrintFrameContentParams {
+  // Physical printable area of the page in pixels according to dpi.
+  gfx.mojom.Rect printable_area;
+
+  // Cookie that is unique for each print request. It is used to associate the
+  // printed frame with its original print request.
+  int32 document_cookie;
+};
 
 // Interface implemented by a class that desires to render print documents for
 // Chrome print preview.
@@ -37,10 +48,19 @@
   InitiatePrintPreview(pending_associated_remote<PrintRenderer>? print_renderer,
                        bool has_selection);
 
+  // Tells the RenderFrame to switch the CSS to print media type and render
+  // every requested page for print preview using the given |settings|. This
+  // gets called multiple times as the user updates settings.
+  [EnableIf=enable_print_preview]
+  PrintPreview(mojo_base.mojom.DictionaryValue settings);
+
   // Tells the RenderFrame that the print preview dialog was closed.
   [EnableIf=enable_print_preview]
   OnPrintPreviewDialogClosed();
 
+  // Prints the content of an out-of-process subframe.
+  PrintFrameContent(PrintFrameContentParams params);
+
   // Tells the RenderFrame whether printing is enabled or not.
   SetPrintingEnabled(bool enabled);
 
diff --git a/components/printing/common/print_messages.cc b/components/printing/common/print_messages.cc
index 0b3f189..2b03a80 100644
--- a/components/printing/common/print_messages.cc
+++ b/components/printing/common/print_messages.cc
@@ -127,10 +127,6 @@
   pages = std::vector<int>();
 }
 
-PrintMsg_PrintFrame_Params::PrintMsg_PrintFrame_Params() {}
-
-PrintMsg_PrintFrame_Params::~PrintMsg_PrintFrame_Params() {}
-
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 PrintHostMsg_RequestPrintPreview_Params::
     PrintHostMsg_RequestPrintPreview_Params()
diff --git a/components/printing/common/print_messages.h b/components/printing/common/print_messages.h
index 0633d54e..859514b 100644
--- a/components/printing/common/print_messages.h
+++ b/components/printing/common/print_messages.h
@@ -77,14 +77,6 @@
   std::vector<int> pages;
 };
 
-struct PrintMsg_PrintFrame_Params {
-  PrintMsg_PrintFrame_Params();
-  ~PrintMsg_PrintFrame_Params();
-
-  gfx::Rect printable_area;
-  int document_cookie;
-};
-
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 struct PrintHostMsg_RequestPrintPreview_Params {
   PrintHostMsg_RequestPrintPreview_Params();
@@ -261,15 +253,6 @@
   IPC_STRUCT_TRAITS_MEMBER(pages)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(PrintMsg_PrintFrame_Params)
-  // Physical printable area of the page in pixels according to dpi.
-  IPC_STRUCT_TRAITS_MEMBER(printable_area)
-
-  // Cookie that is unique for each print request.
-  // It is used to associate the printed frame with its original print request.
-  IPC_STRUCT_TRAITS_MEMBER(document_cookie)
-IPC_STRUCT_TRAITS_END()
-
 // Holds the printed content information.
 // The printed content is in shared memory, and passed as a region.
 // A map on out-of-process subframe contents is also included so the printed
@@ -364,17 +347,6 @@
 // node, depending on which mode the RenderFrame is in.
 IPC_MESSAGE_ROUTED0(PrintMsg_PrintNodeUnderContextMenu)
 
-// Print content of an out-of-process subframe.
-IPC_MESSAGE_ROUTED1(PrintMsg_PrintFrameContent, PrintMsg_PrintFrame_Params)
-
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-// Tells the RenderFrame to switch the CSS to print media type, renders every
-// requested pages for print preview using the given |settings|. This gets
-// called multiple times as the user updates settings.
-IPC_MESSAGE_ROUTED1(PrintMsg_PrintPreview,
-                    base::DictionaryValue /* settings */)
-#endif
-
 // Messages sent from the renderer to the browser.
 
 // Tells the browser that the renderer is done calculating the number of
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 8980214..d583eb6 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -1170,21 +1170,6 @@
   // just return.
 }
 
-bool PrintRenderFrameHelper::OnMessageReceived(const IPC::Message& message) {
-  ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
-
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(PrintRenderFrameHelper, message)
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-    IPC_MESSAGE_HANDLER(PrintMsg_PrintPreview, OnPrintPreview)
-#endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
-    IPC_MESSAGE_HANDLER(PrintMsg_PrintFrameContent, OnPrintFrameContent)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  return handled;
-}
-
 void PrintRenderFrameHelper::OnDestruct() {
   if (ipc_nesting_level_ > 0) {
     render_frame_gone_ = true;
@@ -1264,12 +1249,129 @@
                           : PRINT_PREVIEW_USER_INITIATED_ENTIRE_FRAME);
 }
 
+void PrintRenderFrameHelper::PrintPreview(base::Value settings) {
+  ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
+  if (ipc_nesting_level_ > 1)
+    return;
+
+  print_preview_context_.OnPrintPreview();
+
+  base::UmaHistogramEnumeration(print_preview_context_.IsForArc()
+                                    ? "Arc.PrintPreview.PreviewEvent"
+                                    : "PrintPreview.PreviewEvent",
+                                PREVIEW_EVENT_REQUESTED, PREVIEW_EVENT_MAX);
+
+  if (!print_preview_context_.source_frame()) {
+    DidFinishPrinting(FAIL_PREVIEW);
+    return;
+  }
+
+  if (!UpdatePrintSettings(print_preview_context_.source_frame(),
+                           print_preview_context_.source_node(),
+                           base::Value::AsDictionaryValue(settings))) {
+    if (print_preview_context_.last_error() != PREVIEW_ERROR_BAD_SETTING) {
+      DidFinishPrinting(INVALID_SETTINGS);
+    } else {
+      DidFinishPrinting(FAIL_PREVIEW);
+    }
+    return;
+  }
+
+  // Save the job settings if a PrintRenderer will be used to create the preview
+  // document.
+  if (print_renderer_)
+    print_renderer_job_settings_ = std::move(settings);
+
+  // Set the options from document if we are previewing a pdf and send a
+  // message to browser.
+  if (print_pages_params_->params.is_first_request &&
+      !print_preview_context_.IsModifiable()) {
+    PrintHostMsg_SetOptionsFromDocument_Params options;
+    if (SetOptionsFromPdfDocument(&options)) {
+      PrintHostMsg_PreviewIds ids(
+          print_pages_params_->params.preview_request_id,
+          print_pages_params_->params.preview_ui_id);
+      Send(new PrintHostMsg_SetOptionsFromDocument(routing_id(), options, ids));
+    }
+  }
+
+  is_print_ready_metafile_sent_ = false;
+
+  // PDF printer device supports alpha blending.
+  print_pages_params_->params.supports_alpha_blend = true;
+
+  PrepareFrameForPreviewDocument();
+}
+
 void PrintRenderFrameHelper::OnPrintPreviewDialogClosed() {
   ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
   print_preview_context_.source_frame()->DispatchAfterPrintEvent();
 }
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
 
+void PrintRenderFrameHelper::PrintFrameContent(
+    mojom::PrintFrameContentParamsPtr params) {
+  ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
+  if (ipc_nesting_level_ > 1)
+    return;
+
+  // If the last request is not finished yet, do not proceed.
+  if (prep_frame_view_) {
+    DLOG(ERROR) << "Previous request is still ongoing";
+    return;
+  }
+
+  auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+  frame->DispatchBeforePrintEvent();
+  if (!weak_this)
+    return;
+
+  MetafileSkia metafile(SkiaDocumentType::MSKP, params->document_cookie);
+  gfx::Size area_size = params->printable_area.size();
+  // Since GetVectorCanvasForNewPage() starts a new recording, it will return
+  // a valid canvas.
+  cc::PaintCanvas* canvas =
+      metafile.GetVectorCanvasForNewPage(area_size, gfx::Rect(area_size), 1.0f);
+  DCHECK(canvas);
+
+  canvas->SetPrintingMetafile(&metafile);
+
+  // This subframe doesn't need to fit to the page size, thus we are not using
+  // printing layout for it. It just prints with the specified size.
+  blink::WebPrintParams web_print_params(area_size,
+                                         /*use_printing_layout=*/false);
+
+  // Printing embedded pdf plugin has been broken since pdf plugin viewer was
+  // moved out-of-process
+  // (https://bugs.chromium.org/p/chromium/issues/detail?id=464269). So don't
+  // try to handle pdf plugin element until that bug is fixed.
+  if (frame->PrintBegin(web_print_params,
+                        /*constrain_to_node=*/blink::WebElement())) {
+    frame->PrintPage(0, canvas);
+  }
+  frame->PrintEnd();
+
+  // Done printing. Close the canvas to retrieve the compiled metafile.
+  bool ret = metafile.FinishPage();
+  DCHECK(ret);
+
+  metafile.FinishFrameContent();
+
+  // Send the printed result back.
+  PrintHostMsg_DidPrintContent_Params printed_frame_params;
+  if (!CopyMetafileDataToReadOnlySharedMem(metafile, &printed_frame_params)) {
+    DLOG(ERROR) << "CopyMetafileDataToSharedMem failed";
+    return;
+  }
+
+  Send(new PrintHostMsg_DidPrintFrameContent(
+      routing_id(), params->document_cookie, printed_frame_params));
+
+  if (!render_frame_gone_)
+    frame->DispatchAfterPrintEvent();
+}
+
 void PrintRenderFrameHelper::PrintingDone(bool success) {
   ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
   if (ipc_nesting_level_ > 1)
@@ -1306,59 +1408,6 @@
 }
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-void PrintRenderFrameHelper::OnPrintPreview(
-    const base::DictionaryValue& settings) {
-  if (ipc_nesting_level_ > 1)
-    return;
-
-  print_preview_context_.OnPrintPreview();
-
-  base::UmaHistogramEnumeration(print_preview_context_.IsForArc()
-                                    ? "Arc.PrintPreview.PreviewEvent"
-                                    : "PrintPreview.PreviewEvent",
-                                PREVIEW_EVENT_REQUESTED, PREVIEW_EVENT_MAX);
-
-  if (!print_preview_context_.source_frame()) {
-    DidFinishPrinting(FAIL_PREVIEW);
-    return;
-  }
-
-  if (!UpdatePrintSettings(print_preview_context_.source_frame(),
-                           print_preview_context_.source_node(), settings)) {
-    if (print_preview_context_.last_error() != PREVIEW_ERROR_BAD_SETTING) {
-      DidFinishPrinting(INVALID_SETTINGS);
-    } else {
-      DidFinishPrinting(FAIL_PREVIEW);
-    }
-    return;
-  }
-
-  // Save the job settings if a PrintRenderer will be used to create the preview
-  // document.
-  if (print_renderer_)
-    print_renderer_job_settings_ = settings.Clone();
-
-  // Set the options from document if we are previewing a pdf and send a
-  // message to browser.
-  if (print_pages_params_->params.is_first_request &&
-      !print_preview_context_.IsModifiable()) {
-    PrintHostMsg_SetOptionsFromDocument_Params options;
-    if (SetOptionsFromPdfDocument(&options)) {
-      PrintHostMsg_PreviewIds ids(
-          print_pages_params_->params.preview_request_id,
-          print_pages_params_->params.preview_ui_id);
-      Send(new PrintHostMsg_SetOptionsFromDocument(routing_id(), options, ids));
-    }
-  }
-
-  is_print_ready_metafile_sent_ = false;
-
-  // PDF printer device supports alpha blending.
-  print_pages_params_->params.supports_alpha_blend = true;
-
-  PrepareFrameForPreviewDocument();
-}
-
 void PrintRenderFrameHelper::PrepareFrameForPreviewDocument() {
   reset_prep_frame_view_ = false;
 
@@ -1662,68 +1711,6 @@
 }
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
 
-void PrintRenderFrameHelper::OnPrintFrameContent(
-    const PrintMsg_PrintFrame_Params& params) {
-  if (ipc_nesting_level_ > 1)
-    return;
-
-  // If the last request is not finished yet, do not proceed.
-  if (prep_frame_view_) {
-    DLOG(ERROR) << "Previous request is still ongoing";
-    return;
-  }
-
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-  blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
-  frame->DispatchBeforePrintEvent();
-  if (!weak_this)
-    return;
-
-  MetafileSkia metafile(SkiaDocumentType::MSKP, params.document_cookie);
-  gfx::Size area_size = params.printable_area.size();
-  // Since GetVectorCanvasForNewPage() starts a new recording, it will return
-  // a valid canvas.
-  cc::PaintCanvas* canvas =
-      metafile.GetVectorCanvasForNewPage(area_size, gfx::Rect(area_size), 1.0f);
-  DCHECK(canvas);
-
-  canvas->SetPrintingMetafile(&metafile);
-
-  // This subframe doesn't need to fit to the page size, thus we are not using
-  // printing layout for it. It just prints with the specified size.
-  blink::WebPrintParams web_print_params(area_size,
-                                         /*use_printing_layout=*/false);
-
-  // Printing embedded pdf plugin has been broken since pdf plugin viewer was
-  // moved out-of-process
-  // (https://bugs.chromium.org/p/chromium/issues/detail?id=464269). So don't
-  // try to handle pdf plugin element until that bug is fixed.
-  if (frame->PrintBegin(web_print_params,
-                        /*constrain_to_node=*/blink::WebElement())) {
-    frame->PrintPage(0, canvas);
-  }
-  frame->PrintEnd();
-
-  // Done printing. Close the canvas to retrieve the compiled metafile.
-  bool ret = metafile.FinishPage();
-  DCHECK(ret);
-
-  metafile.FinishFrameContent();
-
-  // Send the printed result back.
-  PrintHostMsg_DidPrintContent_Params printed_frame_params;
-  if (!CopyMetafileDataToReadOnlySharedMem(metafile, &printed_frame_params)) {
-    DLOG(ERROR) << "CopyMetafileDataToSharedMem failed";
-    return;
-  }
-
-  Send(new PrintHostMsg_DidPrintFrameContent(
-      routing_id(), params.document_cookie, printed_frame_params));
-
-  if (!render_frame_gone_)
-    frame->DispatchAfterPrintEvent();
-}
-
 bool PrintRenderFrameHelper::IsPrintingEnabled() const {
   return is_printing_enabled_;
 }
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h
index 967a03f..bd00b17 100644
--- a/components/printing/renderer/print_render_frame_helper.h
+++ b/components/printing/renderer/print_render_frame_helper.h
@@ -31,7 +31,6 @@
 
 struct PrintMsg_Print_Params;
 struct PrintMsg_PrintPages_Params;
-struct PrintMsg_PrintFrame_Params;
 struct PrintHostMsg_SetOptionsFromDocument_Params;
 
 // RenderViewTest-based tests crash on Android
@@ -214,7 +213,6 @@
   void DidFailProvisionalLoad() override;
   void DidFinishLoad() override;
   void ScriptedPrint(bool user_initiated) override;
-  bool OnMessageReceived(const IPC::Message& message) override;
 
   void BindPrintRenderFrameReceiver(
       mojo::PendingAssociatedReceiver<mojom::PrintRenderFrame> receiver);
@@ -226,17 +224,13 @@
   void InitiatePrintPreview(
       mojo::PendingAssociatedRemote<mojom::PrintRenderer> print_renderer,
       bool has_selection) override;
+  void PrintPreview(base::Value settings) override;
   void OnPrintPreviewDialogClosed() override;
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
+  void PrintFrameContent(mojom::PrintFrameContentParamsPtr params) override;
   void PrintingDone(bool success) override;
   void SetPrintingEnabled(bool enabled) override;
 
-  // Message handlers ---------------------------------------------------------
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-  void OnPrintPreview(const base::DictionaryValue& settings);
-#endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
-  void OnPrintFrameContent(const PrintMsg_PrintFrame_Params& params);
-
   // Get |page_size| and |content_area| information from
   // |page_layout_in_points|.
   void GetPageSizeAndContentAreaFromPageLayout(
diff --git a/components/printing/test/print_render_frame_helper_browsertest.cc b/components/printing/test/print_render_frame_helper_browsertest.cc
index 49b2080..c3d8de73 100644
--- a/components/printing/test/print_render_frame_helper_browsertest.cc
+++ b/components/printing/test/print_render_frame_helper_browsertest.cc
@@ -267,7 +267,7 @@
     base::RunLoop run_loop;
     DidPreviewPageListener filter(&run_loop);
     render_thread_->sink().AddFilter(&filter);
-    print_render_frame_helper->OnPrintPreview(dict);
+    print_render_frame_helper->PrintPreview(dict.Clone());
     run_loop.Run();
     render_thread_->sink().RemoveFilter(&filter);
   }
diff --git a/components/sessions/core/base_session_service.cc b/components/sessions/core/base_session_service.cc
index 7f0dba7..35c67002 100644
--- a/components/sessions/core/base_session_service.cc
+++ b/components/sessions/core/base_session_service.cc
@@ -24,22 +24,22 @@
 // thread if it's not canceled.
 void RunIfNotCanceled(
     const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
-    const BaseSessionService::GetCommandsCallback& callback,
+    BaseSessionService::GetCommandsCallback callback,
     std::vector<std::unique_ptr<SessionCommand>> commands) {
   if (is_canceled.Run())
     return;
-  callback.Run(std::move(commands));
+  std::move(callback).Run(std::move(commands));
 }
 
 void PostOrRunInternalGetCommandsCallback(
     base::SequencedTaskRunner* task_runner,
-    const BaseSessionService::GetCommandsCallback& callback,
+    BaseSessionService::GetCommandsCallback callback,
     std::vector<std::unique_ptr<SessionCommand>> commands) {
   if (task_runner->RunsTasksInCurrentSequence()) {
-    callback.Run(std::move(commands));
+    std::move(callback).Run(std::move(commands));
   } else {
-    task_runner->PostTask(FROM_HERE,
-                          base::BindOnce(callback, std::move(commands)));
+    task_runner->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), std::move(commands)));
   }
 }
 
@@ -150,23 +150,24 @@
 
 base::CancelableTaskTracker::TaskId
 BaseSessionService::ScheduleGetLastSessionCommands(
-    const GetCommandsCallback& callback,
+    GetCommandsCallback callback,
     base::CancelableTaskTracker* tracker) {
   base::CancelableTaskTracker::IsCanceledCallback is_canceled;
   base::CancelableTaskTracker::TaskId id =
       tracker->NewTrackedTaskId(&is_canceled);
 
   GetCommandsCallback run_if_not_canceled =
-      base::Bind(&RunIfNotCanceled, is_canceled, callback);
+      base::BindOnce(&RunIfNotCanceled, is_canceled, std::move(callback));
 
   GetCommandsCallback callback_runner =
-      base::Bind(&PostOrRunInternalGetCommandsCallback,
-                 base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
-                 run_if_not_canceled);
+      base::BindOnce(&PostOrRunInternalGetCommandsCallback,
+                     base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+                     std::move(run_if_not_canceled));
 
   RunTaskOnBackendThread(
-      FROM_HERE, base::BindOnce(&SessionBackend::ReadLastSessionCommands,
-                                backend_, is_canceled, callback_runner));
+      FROM_HERE,
+      base::BindOnce(&SessionBackend::ReadLastSessionCommands, backend_,
+                     is_canceled, std::move(callback_runner)));
   return id;
 }
 
diff --git a/components/sessions/core/base_session_service.h b/components/sessions/core/base_session_service.h
index 9e63212..70bbdef 100644
--- a/components/sessions/core/base_session_service.h
+++ b/components/sessions/core/base_session_service.h
@@ -37,8 +37,8 @@
     TAB_RESTORE
   };
 
-  typedef base::Callback<void(std::vector<std::unique_ptr<SessionCommand>>)>
-      GetCommandsCallback;
+  using GetCommandsCallback =
+      base::OnceCallback<void(std::vector<std::unique_ptr<SessionCommand>>)>;
 
   // Creates a new BaseSessionService. After creation you need to invoke
   // Init. |delegate| will remain owned by the creator and it is guaranteed
@@ -99,7 +99,7 @@
   // Uses the backend to load the last session commands from disc. |callback|
   // gets called once the data has arrived.
   base::CancelableTaskTracker::TaskId ScheduleGetLastSessionCommands(
-      const GetCommandsCallback& callback,
+      GetCommandsCallback callback,
       base::CancelableTaskTracker* tracker);
 
  private:
diff --git a/components/sessions/core/session_backend.cc b/components/sessions/core/session_backend.cc
index 41936d7..734769b 100644
--- a/components/sessions/core/session_backend.cc
+++ b/components/sessions/core/session_backend.cc
@@ -236,7 +236,7 @@
 
 void SessionBackend::ReadLastSessionCommands(
     const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
-    const sessions::BaseSessionService::GetCommandsCallback& callback) {
+    sessions::BaseSessionService::GetCommandsCallback callback) {
   if (is_canceled.Run())
     return;
 
@@ -244,7 +244,7 @@
 
   std::vector<std::unique_ptr<sessions::SessionCommand>> commands;
   ReadLastSessionCommandsImpl(&commands);
-  callback.Run(std::move(commands));
+  std::move(callback).Run(std::move(commands));
 }
 
 bool SessionBackend::ReadLastSessionCommandsImpl(
diff --git a/components/sessions/core/session_backend.h b/components/sessions/core/session_backend.h
index 765ae5f..7b69c52 100644
--- a/components/sessions/core/session_backend.h
+++ b/components/sessions/core/session_backend.h
@@ -72,7 +72,7 @@
   // session, invokes ReadLastSessionCommandsImpl to do the work.
   void ReadLastSessionCommands(
       const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
-      const sessions::BaseSessionService::GetCommandsCallback& callback);
+      sessions::BaseSessionService::GetCommandsCallback callback);
 
   // Reads the commands from the last file.
   //
diff --git a/components/sessions/core/tab_restore_service_impl.cc b/components/sessions/core/tab_restore_service_impl.cc
index 94c66227..3a31bfee 100644
--- a/components/sessions/core/tab_restore_service_impl.cc
+++ b/components/sessions/core/tab_restore_service_impl.cc
@@ -608,8 +608,8 @@
   // this won't contain the tabs/window that were open at the point of the
   // crash (the call to GetLastSession above requests those).
   base_session_service_->ScheduleGetLastSessionCommands(
-      base::BindRepeating(&PersistenceDelegate::OnGotLastSessionCommands,
-                          base::Unretained(this)),
+      base::BindOnce(&PersistenceDelegate::OnGotLastSessionCommands,
+                     base::Unretained(this)),
       &cancelable_task_tracker_);
 }
 
diff --git a/components/strings/components_strings_ar.xtb b/components/strings/components_strings_ar.xtb
index 23ed7036..a799199 100644
--- a/components/strings/components_strings_ar.xtb
+++ b/components/strings/components_strings_ar.xtb
@@ -607,7 +607,7 @@
 <translation id="3828924085048779000">غير مسموح باستخدام عبارة مرور فارغة.</translation>
 <translation id="3831915413245941253">ثبّت <ph name="ENROLLMENT_DOMAIN" /> الإضافات للوظائف الإضافية. يمكن للإضافات الوصول إلى بعض بياناتك.</translation>
 <translation id="3832522519263485449">عمل عدة ثقوب يسارًا</translation>
-<translation id="3838154488026099170">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب، لذا يٌوصي Chromium بالانتقال إلى <ph name="WEBSITE_1" /> و<ph name="WEBSITE_2" /> و<ph name="WEBSITE_3" /> وأيّة مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه وتغيير الكلمة الآن.</translation>
+<translation id="3838154488026099170">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب. لذا ينصح Chromium بالانتقال إلى <ph name="WEBSITE_1" /> و<ph name="WEBSITE_2" /> و<ph name="WEBSITE_3" />، وأيّ مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه، وتغيير الكلمة الآن.</translation>
 <translation id="385051799172605136">الرجوع إلى الوراء</translation>
 <translation id="3858027520442213535">تحديث التاريخ والوقت</translation>
 <translation id="3884278016824448484">معرف جهاز متضارب</translation>
@@ -645,7 +645,7 @@
 <translation id="4072486802667267160">حدث خطأ أثناء معالجة طلبك. يُرجى إعادة المحاولة.</translation>
 <translation id="4075732493274867456">لا يدعم كل من العميل والخادم مجموعة تشفير أو إصدار بروتوكول طبقة المقابس الآمنة الشائع.</translation>
 <translation id="4075941231477579656">رقم التعريف باللمس</translation>
-<translation id="4077092919748553596">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب، لذا يُوصي Chrome بالانتقال إلى <ph name="WEBSITE_1" /> و<ph name="WEBSITE_2" /> و<ph name="WEBSITE_3" /> وأيّة مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه وتغيير الكلمة الآن.</translation>
+<translation id="4077092919748553596">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب. لذا ينصح Chrome بالانتقال إلى <ph name="WEBSITE_1" /> و<ph name="WEBSITE_2" /> و<ph name="WEBSITE_3" />، وأيّ مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه، وبتغيير الكلمة الآن.</translation>
 <translation id="4079302484614802869">‏تم تعيين تهيئة الخادم الوكيل لاستخدام عنوان URL نص برمجي ‎.pac وليس الخوادم الوكيلة الثابتة.</translation>
 <translation id="4082393374666368382">الإعدادات - الإدارة</translation>
 <translation id="4098354747657067197">أمامك موقع مخادع</translation>
@@ -726,7 +726,7 @@
 <translation id="4356973930735388585">قد يحاول المهاجمون الموجودون على هذا الموقع تثبيت برامج خطيرة على الكمبيوتر التابع لك تسرق معلوماتك أو تحذفها (على سبيل المثال، الصور وكلمات المرور والرسائل وبطاقات الائتمان).</translation>
 <translation id="4358059973562876591">‏قد لا يتم تطبيق النماذج التي حدّدتها بسبب حدوث خطأ في سياسة DnsOverHttpsMode.</translation>
 <translation id="4358461427845829800">إدارة طرق الدفع...</translation>
-<translation id="4359160567981085931">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب، يمكن أن يساعدك Chrome. لتغيير كلمة مرورك وإشعار Google أن حسابك قد يكون معرّضًا للخطر، انقر على "حماية الحساب".</translation>
+<translation id="4359160567981085931">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب. يمكن لـ Chrome مساعدتك. لتغيير كلمة مرورك وإشعار Google أن حسابك قد يكون معرّضًا للخطر، انقر على "حماية الحساب".</translation>
 <translation id="4367563149485757821">‏Number-12 (مغلف)</translation>
 <translation id="437058704415269440">رصيد الحساب</translation>
 <translation id="4372516964750095882">Fanfold-Us</translation>
@@ -1003,7 +1003,7 @@
 <translation id="5728056243719941842">‏C5 (مغلف)</translation>
 <translation id="5730040223043577876">‏يُوصي Chrome بإعادة تحديد كلمة المرور في حال إعادة استخدامها في مواقع ويب أخرى.</translation>
 <translation id="5737183892635480227">{NUM_CARDS,plural, =1{‏حفظ بطاقة واحدة في حسابك على Google}zero{‏حفظ بطاقات في حسابك على Google}two{‏حفظ بطاقتين في حسابك على Google}few{‏حفظ بطاقات في حسابك على Google}many{‏حفظ بطاقات في حسابك على Google}other{‏حفظ بطاقات في حسابك على Google}}</translation>
-<translation id="5745980000221562234">{NUM_CARDS,plural, =1{استخدم رقم افتراضي لهذه البطاقة}zero{ما من بطاقة ليتم اختيارها}two{اختَر بطاقتين}few{اختَر بطاقات}many{اختَر بطاقات}other{اختَر بطاقات}}</translation>
+<translation id="5745980000221562234">{NUM_CARDS,plural, =1{استخدِم رقمًا افتراضيًا لهذه البطاقة}zero{ما من بطاقة ليتم اختيارها}two{اختَر بطاقتين}few{اختَر بطاقات}many{اختَر بطاقات}other{اختَر بطاقات}}</translation>
 <translation id="5763042198335101085">أدخِل عنوان بريد إلكتروني صحيحًا</translation>
 <translation id="5763703224595565476">‏فعّل المشرف ميزة "حماية مستخدم Chrome Enterprise" على المتصفّح الذي تستخدمه. ولدى ميزة "حماية مستخدم Chrome Enterprise" إذن بالوصول إلى بعض بياناتك.</translation>
 <translation id="5765072501007116331">لعرض طرق التسليم ومتطلباته، حدِّد عنوانًا</translation>
@@ -1020,7 +1020,7 @@
 <translation id="5804241973901381774">الأذونات</translation>
 <translation id="5810442152076338065">يتم ترميز اتصالك بالنطاق <ph name="DOMAIN" /> باستخدام مجموعة تشفير قديمة.</translation>
 <translation id="5813119285467412249">إعا&amp;دة الإضافة</translation>
-<translation id="5824687817967109979">{NUM_CARDS,plural, =1{‏سيتم تحصيل الرسوم من هذه البطاقة عند القيام بعملية بالدفع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}zero{‏ما من بطاقات قمت باختيارها لتحصيل الرسوم عند القيام بعملية الدفع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}two{‏سيتم تحصيل الرسوم من البطاقتّين اللتيّن قمت باختيارهما عند القيام بعملية الدفع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}few{‏سيتم تحصيل الرسوم من البطاقات التي قمتَ باختيارها عند القيام بعملية الدفع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}many{‏سيتم تحصيل الرسوم من البطاقات التي قمتَ باختيارها عند القيام بعملية الدفع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}other{‏سيتم تحصيل الرسوم من البطاقات التي قمت باختيارها عند القيام بعملية الدفع، ولن تتم مشاركة رقم البطاقة الفعلي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}}</translation>
+<translation id="5824687817967109979">{NUM_CARDS,plural, =1{‏سيتم تحصيل الرسوم من هذه البطاقة عند إجراء عملية الدفع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}zero{‏لم تختر أي بطاقة لتحصيل الرسوم منها عند إجراء عملية الدفع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}two{‏عند إجراء عملية الدفع، سيتم تحصيل الرسوم من البطاقتين اللتين تختارهما، ولن تتم مشاركة رقمَي البطاقتين الحقيقيَين مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}few{‏عند إجراء عملية الدفع، سيتم تحصيل الرسوم من البطاقات التي تختارها، ولن تتم مشاركة أرقام البطاقات الحقيقية مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}many{‏عند إجراء عملية الدفع، سيتم تحصيل الرسوم من البطاقات التي تختارها، ولن تتم مشاركة أرقام البطاقات الحقيقية مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}other{‏عند إجراء عملية الدفع، سيتم تحصيل الرسوم من البطاقات التي تختارها، ولن تتم مشاركة أرقام البطاقات الحقيقية مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}}</translation>
 <translation id="583281660410589416">غير معروف</translation>
 <translation id="5838278095973806738">يجب عدم إدخال معلومات حسّاسة على هذا الموقع (مثل كلمات المرور أو بطاقات الائتمان) لأنه قد تتم سرقتها من قِبل المهاجمين.</translation>
 <translation id="5851548754964597211">قائمة علامات التبويب</translation>
@@ -1480,7 +1480,7 @@
 <translation id="8042918947222776840">اختيار طريقة الاستلام من المستخدم</translation>
 <translation id="8057711352706143257">لم تتم تهيئة "<ph name="SOFTWARE_NAME" />" بشكل صحيح. يؤدي عادةً إلغاء تثبيت "<ph name="SOFTWARE_NAME" />" إلى إصلاح المشكلة. <ph name="FURTHER_EXPLANATION" /></translation>
 <translation id="8066955247577885446">عذرًا، حدث خطأ.</translation>
-<translation id="8067872629359326442">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب، يمكن أن يساعدك Chromium. لتغيير كلمة مرورك وإشعار Google أن حسابك قد يكون معرّضًا للخطر، انقر على "حماية الحساب".</translation>
+<translation id="8067872629359326442">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب. يمكن لـ Chromium مساعدتك. لتغيير كلمة مرورك وإشعار Google أن حسابك قد يكون معرّضًا للخطر، انقر على "حماية الحساب".</translation>
 <translation id="8074253406171541171">‏10x13 (مغلف)</translation>
 <translation id="8078141288243656252">لا يمكن إضافة تعليق توضيحي عند تدوير المستند</translation>
 <translation id="8079031581361219619">هل تريد إعادة تحميل الموقع؟</translation>
@@ -1497,7 +1497,7 @@
 <translation id="8105368624971345109">إيقاف</translation>
 <translation id="8118489163946903409">طريقة الدفع</translation>
 <translation id="8127301229239896662">لم يتم تثبيت "<ph name="SOFTWARE_NAME" />" بطريقة صحيحة على جهاز الكمبيوتر أو الشبكة. اطلب من مشرف تقنية المعلومات حل هذه المشكلة.</translation>
-<translation id="8128526133099929547">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب، لذا يُوصي Chrome بالانتقال إلى <ph name="WEBSITE_1" /> وأيّة مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه وتغيير الكلمة الآن.</translation>
+<translation id="8128526133099929547">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب. لذا ينصح Chrome بالانتقال إلى <ph name="WEBSITE_1" />، وأيّ مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه، وبتغيير الكلمة الآن.</translation>
 <translation id="8131740175452115882">التأكيد</translation>
 <translation id="8149426793427495338">خضع جهاز الكمبيوتر إلى وضع السكون.</translation>
 <translation id="8150722005171944719">الملف الموجود على <ph name="URL" /> غير قابل للقراءة. ربما تمت إزالته، أو ربما تكون أذونات الملف هي التي تمنع الدخول.</translation>
@@ -1515,7 +1515,7 @@
 <translation id="8218327578424803826">الموقع الذي تم تعيينه:</translation>
 <translation id="8220146938470311105">‏C7/C6 (مغلف)</translation>
 <translation id="8220639454292072926">إعداد التقارير للمؤسسة</translation>
-<translation id="8221250263817408492">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب، لذا يُوصي Chromium بالانتقال إلى <ph name="WEBSITE_1" /> وأيّة مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه وتغيير الكلمة الآن.</translation>
+<translation id="8221250263817408492">‏لقد أدخلت للتو كلمة مرورك في موقع إلكتروني مريب. لذا ينصح Chromium بالانتقال إلى <ph name="WEBSITE_1" />، وأيّ مواقع إلكترونية أخرى تستخدم فيها كلمة المرور هذه، وبتغيير الكلمة الآن.</translation>
 <translation id="8225771182978767009">اختار الشخص الذي أعد جهاز الكمبيوتر حظر موقع الويب هذا.</translation>
 <translation id="822964464349305906"><ph name="TYPE_1" />، <ph name="TYPE_2" /></translation>
 <translation id="8238581221633243064">يمكنك فتح الصفحة في علامة تبويب جديدة للتصفح المتخفي</translation>
diff --git a/components/strings/components_strings_eu.xtb b/components/strings/components_strings_eu.xtb
index b9212e6..f61a22f 100644
--- a/components/strings/components_strings_eu.xtb
+++ b/components/strings/components_strings_eu.xtb
@@ -299,7 +299,7 @@
 <translation id="2337852623177822836">Administratzaileak kontrolatzen du ezarpena</translation>
 <translation id="2346319942568447007">Kopiatu duzun irudia</translation>
 <translation id="2354001756790975382">Beste laster-markak</translation>
-<translation id="2354430244986887761">Google-ren arakatze seguruak <ph name="BEGIN_LINK" />aplikazio kaltegarriak aurkitu ditu<ph name="END_LINK" /> <ph name="SITE" /> webgunean.</translation>
+<translation id="2354430244986887761">Google-ren Arakatze seguruak <ph name="BEGIN_LINK" />aplikazio kaltegarriak aurkitu ditu<ph name="END_LINK" /> <ph name="SITE" /> webgunean.</translation>
 <translation id="2355395290879513365">Baliteke erasotzaileak webgune honetan zer irudi ikusi dituzun hautemateko eta, haiek aldatuz, zu engainatzeko gai izatea.</translation>
 <translation id="2356070529366658676">Galdetu</translation>
 <translation id="2359629602545592467">Bat baino gehiago</translation>
@@ -398,7 +398,7 @@
 <translation id="2792012897584536778">Segurtasun-ziurtagiri batzuk konfiguratu dituzte gailu honen administratzaileek, bisitatzen dituzun webguneen edukia ikusteko aukera eman diezaieketenak.</translation>
 <translation id="2799020568854403057">Webgune honek aplikazio kaltegarriak ditu</translation>
 <translation id="2799223571221894425">Abiarazi berriro</translation>
-<translation id="2803306138276472711">Berriki Google-ren arakatze seguruak <ph name="BEGIN_LINK" />malwarea hauteman du<ph name="END_LINK" /> <ph name="SITE" /> webgunean. Seguruak izan ohi diren webguneak batzuetan malwarearekin kutsatuta egoten dira.</translation>
+<translation id="2803306138276472711">Berriki Google-ren Arakatze seguruak <ph name="BEGIN_LINK" />malwarea hauteman du<ph name="END_LINK" /> <ph name="SITE" /> webgunean. Seguruak izan ohi diren webguneak batzuetan malwarearekin kutsatuta egoten dira.</translation>
 <translation id="2824775600643448204">Helbide- eta bilaketa-barra</translation>
 <translation id="2826760142808435982">Konexioa <ph name="CIPHER" /> bidez enkriptatuta eta autentifikatuta dago eta <ph name="KX" /> erabiltzen du gako-trukaketarako mekanismo gisa.</translation>
 <translation id="2835170189407361413">Garbitu inprimakia</translation>
@@ -1088,7 +1088,7 @@
 <translation id="6203231073485539293">Egiaztatu Internetera konektatuta zaudela</translation>
 <translation id="6218753634732582820">Helbidea Chromium-etik kendu nahi duzu?</translation>
 <translation id="622039917539443112">Tolestura paraleloa</translation>
-<translation id="6221345481584921695">Berriki Google-ren arakatze seguruak <ph name="BEGIN_LINK" />malwarea hauteman du<ph name="END_LINK" /> <ph name="SITE" /> webgunean. Seguruak izan ohi diren webguneak batzuetan malwarearekin kutsatuta egoten dira. Eduki gaiztoa <ph name="SUBRESOURCE_HOST" /> malware-banatzaile ezagunetik dator.</translation>
+<translation id="6221345481584921695">Berriki Google-ren Arakatze seguruak <ph name="BEGIN_LINK" />malwarea hauteman du<ph name="END_LINK" /> <ph name="SITE" /> webgunean. Seguruak izan ohi diren webguneak batzuetan malwarearekin kutsatuta egoten dira. Eduki gaiztoa <ph name="SUBRESOURCE_HOST" /> malware-banatzaile ezagunetik dator.</translation>
 <translation id="6234122620015464377">Moztu dokumentu bakoitzaren ondoren</translation>
 <translation id="6240447795304464094">Google Pay-ren logotipoa</translation>
 <translation id="6241121617266208201">Ezkutatu iradokizunak</translation>
@@ -1596,7 +1596,7 @@
 <translation id="874918643257405732">Egin fitxa honen laster-marka</translation>
 <translation id="8751426954251315517">Saiatu berriro geroago</translation>
 <translation id="8759274551635299824">Iraungita dago txartela</translation>
-<translation id="8761567432415473239">Google-ren arakatze seguruak <ph name="BEGIN_LINK" />programa kaltegarriak aurkitu ditu<ph name="END_LINK" /> <ph name="SITE" /> webgunean.</translation>
+<translation id="8761567432415473239">Google-ren Arakatze seguruak <ph name="BEGIN_LINK" />programa kaltegarriak aurkitu ditu<ph name="END_LINK" /> <ph name="SITE" /> webgunean.</translation>
 <translation id="8763927697961133303">USB bidezko gailua</translation>
 <translation id="877985182522063539">A4</translation>
 <translation id="8790007591277257123">&amp;Berregin ezabatzea</translation>
@@ -1634,7 +1634,7 @@
 <translation id="8971063699422889582">Zerbitzariaren ziurtagiria iraungi egin da.</translation>
 <translation id="8975012916872825179">Informazio hau barne: telefono-zenbakiak, helbide elektronikoak eta bidalketa-helbideak</translation>
 <translation id="8975263830901772334">Inprimatzen dituzun fitxategien izenak</translation>
-<translation id="8978053250194585037">Berriki, Google-ren arakatze seguruak <ph name="BEGIN_LINK" />phishinga hauteman du<ph name="END_LINK" /> <ph name="SITE" /> webgunean. Phishing-webguneek beste webgune batzuk direnaren plantak egiten dituzte zu iruzurtzeko.</translation>
+<translation id="8978053250194585037">Berriki, Google-ren Arakatze seguruak <ph name="BEGIN_LINK" />phishinga hauteman du<ph name="END_LINK" /> <ph name="SITE" /> webgunean. Phishing-webguneek beste webgune batzuk direnaren plantak egiten dituzte zu iruzurtzeko.</translation>
 <translation id="8983003182662520383">Google Pay-rekin erabiltzen dituzun ordainketa-metodoak eta helbideak</translation>
 <translation id="8987927404178983737">Hilabetea</translation>
 <translation id="8989148748219918422"><ph name="ORGANIZATION" /> (<ph name="COUNTRY" />)</translation>
diff --git a/components/strings/components_strings_fa.xtb b/components/strings/components_strings_fa.xtb
index b0f9f1e..f63a54e 100644
--- a/components/strings/components_strings_fa.xtb
+++ b/components/strings/components_strings_fa.xtb
@@ -1603,7 +1603,7 @@
 <translation id="8738058698779197622">‏به منظور برقراری یک اتصال امن، لازم است که ساعت شما به درستی تنظیم شود. زیرا گواهینامه‌هایی که وب‌سایت‌ها برای شناسایی خودشان استفاده می‌کنند تنها برای دوره‌های زمانی خاصی معتبر هستند. از آنجایی که ساعت دستگاه نادرست است، Chromium نمی‌تواند این گواهینامه‌ها را تأیید کند.</translation>
 <translation id="8740359287975076522">‏<ph name="HOST_NAME" />’s &lt;abbr id="dnsDefinition"&gt;آدرس DNS&lt;/abbr&gt; پیدا نشد. درحال بررسی برای تشخیص مشکل.</translation>
 <translation id="874846938927089722">کارت‌های اعتباری و پیش‌پرداخت قابل‌قبول</translation>
-<translation id="874918643257405732">نشانک گذاشتن این برگه</translation>
+<translation id="874918643257405732">نشانک‌گذاری این برگه</translation>
 <translation id="8751426954251315517">لطفاً بعداً دوباره امتحان کنید</translation>
 <translation id="8759274551635299824">کارت منقضی شده است</translation>
 <translation id="8761567432415473239">‏مرور ایمن Google اخیراً <ph name="BEGIN_LINK" />برنامه‌های خطرناک<ph name="END_LINK" /> را در <ph name="SITE" /> پیدا کرده است.</translation>
diff --git a/components/strings/components_strings_fi.xtb b/components/strings/components_strings_fi.xtb
index 90c8331..f5da62ae 100644
--- a/components/strings/components_strings_fi.xtb
+++ b/components/strings/components_strings_fi.xtb
@@ -740,7 +740,7 @@
 <translation id="4424024547088906515">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; Chrome ei luota sen suojausvarmenteeseen. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
 <translation id="443121186588148776">Sarjaportti</translation>
 <translation id="4432688616882109544"><ph name="HOST_NAME" /> ei hyväksynyt kirjautumisvarmennettasi, tai varmennetta ei annettu.</translation>
-<translation id="4434045419905280838">Ponn.ikkunat ja uudelleenohj.</translation>
+<translation id="4434045419905280838">Ponn.ikkunat ja uudelleenohjaus</translation>
 <translation id="4435702339979719576">Postikortti</translation>
 <translation id="443673843213245140">Välityspalvelinta ei saa käyttää, mutta erilliset välityspalvelimen asetukset on määritetty.</translation>
 <translation id="445100540951337728">Hyväksytyt maksukortit</translation>
diff --git a/components/strings/components_strings_fr.xtb b/components/strings/components_strings_fr.xtb
index 822c629..a55d205 100644
--- a/components/strings/components_strings_fr.xtb
+++ b/components/strings/components_strings_fr.xtb
@@ -1613,7 +1613,7 @@
 <translation id="8891727572606052622">Mode proxy non valide.</translation>
 <translation id="8903921497873541725">Zoom avant</translation>
 <translation id="890485472659500557">Engineering-C</translation>
-<translation id="890493561996401738">Bouton "Supprimer la suggestion" (appuyez sur Entrée pour la supprimer, <ph name="REMOVE_BUTTON_FOCUSED_FRIENDLY_MATCH_TEXT" />)</translation>
+<translation id="890493561996401738">Bouton "Supprimer la suggestion" (appuyez sur Entrée pour supprimer <ph name="REMOVE_BUTTON_FOCUSED_FRIENDLY_MATCH_TEXT" />)</translation>
 <translation id="8910670906166981838">Vous êtes passé en mode navigation privée</translation>
 <translation id="8912362522468806198">Compte Google</translation>
 <translation id="8918231688545606538">Cette page est suspecte</translation>
@@ -1639,7 +1639,7 @@
 <translation id="9004367719664099443">Session RV en cours</translation>
 <translation id="9005998258318286617">Échec de chargement du document PDF.</translation>
 <translation id="9008201768610948239">Ignorer</translation>
-<translation id="9011424611726486705">Ouvrir les paramètres du site</translation>
+<translation id="9011424611726486705">Ouvrir les paramètres des sites</translation>
 <translation id="9020200922353704812">Adresse de facturation de la carte obligatoire</translation>
 <translation id="9020542370529661692">Cette page a été traduite en <ph name="TARGET_LANGUAGE" />.</translation>
 <translation id="9020742383383852663">A8</translation>
@@ -1651,7 +1651,7 @@
 <translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
 <translation id="9049981332609050619">Vous avez tenté de contacter <ph name="DOMAIN" />, mais le certificat présenté par le serveur est incorrect.</translation>
 <translation id="9050666287014529139">Phrase secrète</translation>
-<translation id="9065203028668620118">Édition</translation>
+<translation id="9065203028668620118">Modifier</translation>
 <translation id="9065745800631924235">Recherche sur "<ph name="TEXT" />" dans l'historique</translation>
 <translation id="9069693763241529744">Bloqué par une extension</translation>
 <translation id="9076630408993835509">Ce navigateur n'est géré par aucune entreprise ni aucune autre organisation. Il se peut que l'activité sur cet appareil soit gérée en dehors de Chrome. <ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /></translation>
diff --git a/components/strings/components_strings_ko.xtb b/components/strings/components_strings_ko.xtb
index eb695fe9..34cc980 100644
--- a/components/strings/components_strings_ko.xtb
+++ b/components/strings/components_strings_ko.xtb
@@ -13,7 +13,7 @@
 <translation id="1055184225775184556">추가 실행 취소(&amp;U)</translation>
 <translation id="1056898198331236512">경고</translation>
 <translation id="1058479211578257048">카드 저장 중...</translation>
-<translation id="10614374240317010">저장되지 않음</translation>
+<translation id="10614374240317010">저장하지 않음</translation>
 <translation id="1062160989074299343">Prc10(봉투)</translation>
 <translation id="106701514854093668">데스크톱 북마크</translation>
 <translation id="1074497978438210769">주의 요함</translation>
diff --git a/components/strings/components_strings_sv.xtb b/components/strings/components_strings_sv.xtb
index fb4a406..86fba62 100644
--- a/components/strings/components_strings_sv.xtb
+++ b/components/strings/components_strings_sv.xtb
@@ -916,7 +916,7 @@
 <translation id="5295292838686006428">Ditt lösenord har läckt ut efter ett dataintrång på en webbplats eller i en app. Du rekommenderas att kontrollera dina sparade lösenord nu.</translation>
 <translation id="5299298092464848405">Det uppstod ett fel när policyn analyserades</translation>
 <translation id="5300589172476337783">Visa</translation>
-<translation id="5308380583665731573">Ansluta</translation>
+<translation id="5308380583665731573">Anslut</translation>
 <translation id="5308689395849655368">Krashrapportering har  inaktiverats.</translation>
 <translation id="5314967030527622926">Broschyrenhet</translation>
 <translation id="5317780077021120954">Spara</translation>
diff --git a/components/strings/components_strings_ta.xtb b/components/strings/components_strings_ta.xtb
index 0d18d5a..4a3758a 100644
--- a/components/strings/components_strings_ta.xtb
+++ b/components/strings/components_strings_ta.xtb
@@ -5,7 +5,7 @@
 <translation id="1010200102790553230">பக்கத்தைப் பின்னர் ஏற்று</translation>
 <translation id="1015730422737071372">கூடுதல் விவரங்களை வழங்கவும்</translation>
 <translation id="1021110881106174305">ஏற்கப்படும் கார்டுகள்</translation>
-<translation id="1021753677514347426">உங்களாலோ வேறொருவராலோ உங்கள் சாதனத்தில் நிறுவப்பட்டுள்ள சான்றிதழே இந்தச் சிக்கலுக்குக் காரணம் ஆகும். இது நெட்வொர்க்குகளைக் கண்காணிப்பதற்கும் அவற்றில் குறுக்கிடுவதற்கும் பயன்படுத்தப்படும் சான்றிதழ் ஆகும், எனவே இதை Chromium நம்பவில்லை. பள்ளி அல்லது நிறுவன நெட்வொர்க்கைக் கண்காணிக்க வேண்டிய நியாயமான சூழல்கள் இருக்குமெனினும், உங்களால் தடுக்க முடியாதபோதும் இது நிகழ்கிறது என்பதை நீங்கள் அறிய வேண்டுமெனெ Chromium விரும்புகிறது. இணையத்தை அணுகக்கூடிய எந்த உலாவியும் ஆப்ஸும் கண்காணிக்கப்படக்கூடும்.</translation>
+<translation id="1021753677514347426">உங்களாலோ வேறொருவராலோ உங்கள் சாதனத்தில் நிறுவப்பட்டுள்ள சான்றிதழே இந்தச் சிக்கலுக்குக் காரணம் ஆகும். இது நெட்வொர்க்குகளைக் கண்காணிப்பதற்கும் அவற்றில் குறுக்கிடுவதற்கும் பயன்படுத்தப்படும் சான்றிதழ் ஆகும், எனவே இதை Chromium நம்பவில்லை. பள்ளி அல்லது நிறுவன நெட்வொர்க் போன்றதைக் கண்காணிக்க வேண்டிய நியாயமான சூழல்கள் இருக்குமெனினும், உங்களால் தடுக்க முடியாதபோதும் இது நிகழ்கிறது என்பதை நீங்கள் அறிய வேண்டுமென Chromium விரும்புகிறது. இணையத்தை அணுகக்கூடிய எந்த உலாவியும் ஆப்ஸும் கண்காணிக்கப்படக்கூடும்.</translation>
 <translation id="1032854598605920125">கடிகாரத்திசையில் சுழற்று</translation>
 <translation id="1036348656032585052">முடக்கு</translation>
 <translation id="1038842779957582377">அறியப்படாத பெயர்</translation>
@@ -444,7 +444,7 @@
 <translation id="3060227939791841287">C9 (என்வலப்)</translation>
 <translation id="3061707000357573562">பேட்ச் சேவை</translation>
 <translation id="3064966200440839136">வெளிப்புற ஆப்ஸின் மூலம் பணத்தை செலுத்த, மறைநிலையிலிருந்து வெளியேறுகிறீர்கள். தொடரவா?</translation>
-<translation id="3086579638707268289">உங்களின் இணயச் செயல்பாடு கண்காணிக்கப்படுகிறது</translation>
+<translation id="3086579638707268289">உங்களின் இணையச் செயல்பாடு கண்காணிக்கப்படுகிறது</translation>
 <translation id="3095940652251934233">Statement</translation>
 <translation id="3096100844101284527">பிக்அப் முகவரியைச் சேர்</translation>
 <translation id="3105172416063519923">பண்பு ஐடி:</translation>
@@ -1304,7 +1304,7 @@
 <translation id="7349430561505560861">A4-Extra</translation>
 <translation id="7353601530677266744">கட்டளை வரி</translation>
 <translation id="7372973238305370288">தேடல் முடிவு</translation>
-<translation id="7374733840632556089">உங்களாலோ வேறொருவராலோ உங்கள் சாதனத்தில் நிறுவப்பட்டுள்ள சான்றிதழே இந்தச் சிக்கலுக்குக் காரணம் ஆகும். இது நெட்வொர்க்குகளைக் கண்காணிப்பதற்கும் அவற்றில் குறுக்கிடுவதற்கும் பயன்படுத்தப்படும் சான்றிதழ் ஆகும், எனவே இதை Chrome நம்பவில்லை. பள்ளி அல்லது நிறுவன நெட்வொர்க்கைக் கண்காணிக்க வேண்டிய நியாயமான சூழல்கள் இருக்குமெனினும், உங்களால் தடுக்க முடியாதபோதும் இது நிகழ்கிறது என்பதை நீங்கள் அறிய வேண்டுமெனெ Chrome விரும்புகிறது. இணையத்தை அணுகக்கூடிய எந்த உலாவியும் ஆப்ஸும் கண்காணிக்கப்படக்கூடும்.</translation>
+<translation id="7374733840632556089">உங்களாலோ வேறொருவராலோ உங்கள் சாதனத்தில் நிறுவப்பட்டுள்ள சான்றிதழே இந்தச் சிக்கலுக்குக் காரணம் ஆகும். இது நெட்வொர்க்குகளைக் கண்காணிப்பதற்கும் அவற்றில் குறுக்கிடுவதற்கும் பயன்படுத்தப்படும் சான்றிதழ் ஆகும், எனவே இதை Chrome நம்பவில்லை. பள்ளி அல்லது நிறுவன நெட்வொர்க் போன்றதைக் கண்காணிக்க வேண்டிய நியாயமான சூழல்கள் இருக்குமெனினும், உங்களால் தடுக்க முடியாதபோதும் இது நிகழ்கிறது என்பதை நீங்கள் அறிய வேண்டுமென Chrome விரும்புகிறது. இணையத்தை அணுகக்கூடிய எந்த உலாவியும் ஆப்ஸும் கண்காணிக்கப்படக்கூடும்.</translation>
 <translation id="7377249249140280793"><ph name="RELATIVE_DATE" /> - <ph name="FULL_DATE" /></translation>
 <translation id="7378594059915113390">மீடியா கட்டுப்பாடுகள்</translation>
 <translation id="7378627244592794276">வேண்டாம்</translation>
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
index 420c113..647d1556 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -315,11 +315,11 @@
   DCHECK(!in_flight_images_.empty());
 
   if (in_flight_images_.front()) {
-    if (displayed_image_)
-      available_images_.push_back(std::move(displayed_image_));
-    displayed_image_ = std::move(in_flight_images_.front());
-    if (displayed_image_)
+    if (displayed_image_) {
       displayed_image_->EndPresent();
+      available_images_.push_back(std::move(displayed_image_));
+    }
+    displayed_image_ = std::move(in_flight_images_.front());
   }
 
   in_flight_images_.pop_front();
diff --git a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
index f8135fd5..12c9248 100644
--- a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
+++ b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
@@ -76,6 +76,9 @@
 class AXPlatformNodeTextRangeProviderWinBrowserTest
     : public AccessibilityContentBrowserTest {
  protected:
+  const base::string16 kEmbeddedCharacterAsString = {
+      ui::AXPlatformNodeBase::kEmbeddedCharacter};
+
   void SetUpOnMainThread() override {
     host_resolver()->AddRule("*", "127.0.0.1");
     SetupCrossSiteRedirector(embedded_test_server());
@@ -446,7 +449,8 @@
   ComPtr<ITextRangeProvider> text_range_provider;
   GetTextRangeProviderFromTextNode(*input_text_node, &text_range_provider);
   ASSERT_NE(nullptr, text_range_provider.Get());
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"");
+  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider,
+                          kEmbeddedCharacterAsString.c_str());
 
   base::win::ScopedVariant value;
   EXPECT_HRESULT_SUCCEEDED(text_range_provider->GetAttributeValue(
@@ -464,7 +468,8 @@
 
   GetTextRangeProviderFromTextNode(*input_search_node, &text_range_provider);
   ASSERT_NE(nullptr, text_range_provider.Get());
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"");
+  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider,
+                          kEmbeddedCharacterAsString.c_str());
 
   EXPECT_HRESULT_SUCCEEDED(text_range_provider->GetAttributeValue(
       UIA_IsReadOnlyAttributeId, value.Receive()));
@@ -1906,8 +1911,9 @@
        L"bold and italic text more bold and italic text", L" italic text",
        L" plain text"});
 
-  AssertMoveByUnitForMarkup(TextUnit_Format, "before <img src='test'> after",
-                            {L"before ", L" after"});
+  AssertMoveByUnitForMarkup(
+      TextUnit_Format, "before <img src='test'> after",
+      {L"before ", (kEmbeddedCharacterAsString + L" after").c_str()});
 
   AssertMoveByUnitForMarkup(TextUnit_Format,
                             "before <a href='test'>link</a> after",
@@ -1983,6 +1989,47 @@
 }
 
 IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+                       MoveByCharacterWithEmbeddedObject) {
+  const std::string html_markup = R"HTML(<!DOCTYPE html>
+  <html>
+    <body>
+      <div>
+        <label for="input1">Some text</label>
+        <input id="input1">
+        <p>after</p>
+      </div>
+    </body>
+  </html>)HTML";
+
+  const std::vector<const wchar_t*> characters = {
+      L"S", L"o", L"m", L"e", L" ",
+      L"t", L"e", L"x", L"t", kEmbeddedCharacterAsString.c_str(),
+      L"a", L"f", L"t", L"e", L"r"};
+
+  AssertMoveByUnitForMarkup(TextUnit_Character, html_markup, characters);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+                       MoveByWordWithEmbeddedObject) {
+  const std::string html_markup = R"HTML(<!DOCTYPE html>
+  <html>
+    <body>
+      <div>
+        <label for="input1">Some text </label>
+        <input id="input1">
+        <p> after input</p>
+      </div>
+    </body>
+  </html>)HTML";
+
+  const std::vector<const wchar_t*> words = {L"Some ", L"text ",
+                                             kEmbeddedCharacterAsString.c_str(),
+                                             L"after ", L"input"};
+
+  AssertMoveByUnitForMarkup(TextUnit_Word, html_markup, words);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
                        BoundingRectangleOfWordBeforeListItemMarker) {
   LoadInitialAccessibilityTreeFromHtml(
       R"HTML(<!DOCTYPE html>
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index f73fe682d..fcae101 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -130,7 +130,7 @@
       FireUiaTextContainerEvent(UIA_Text_TextChangedEventId, node);
       break;
     case ax::mojom::Event::kTextSelectionChanged:
-      FireUiaTextContainerEvent(UIA_Text_TextSelectionChangedEventId, node);
+      text_selection_changed_events_.insert(node);
       break;
     default:
       break;
@@ -211,8 +211,10 @@
       // Fire the event on the object where the focus of the selection is.
       int32_t focus_id = ax_tree()->GetUnignoredSelection().focus_object_id;
       BrowserAccessibility* focus_object = GetFromID(focus_id);
-      if (focus_object && focus_object->HasVisibleCaretOrSelection())
+      if (focus_object && focus_object->HasVisibleCaretOrSelection()) {
         FireWinAccessibilityEvent(IA2_EVENT_TEXT_CARET_MOVED, focus_object);
+        text_selection_changed_events_.insert(node);
+      }
       break;
     }
     // aria-dropeffect is deprecated in WAI-ARIA 1.1.
@@ -771,6 +773,12 @@
   }
   aria_properties_events_.clear();
 
+  for (auto&& sel_event_node : text_selection_changed_events_) {
+    FireUiaTextContainerEvent(UIA_Text_TextSelectionChangedEventId,
+                              sel_event_node);
+  }
+  text_selection_changed_events_.clear();
+
   for (auto&& selected : selection_events_) {
     auto* container = selected.first;
     auto&& changes = selected.second;
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h
index 9b8a9387..ff425504 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -105,6 +105,13 @@
   // changes, so we only fire the event once for every node.
   std::unordered_set<BrowserAccessibility*> aria_properties_events_;
 
+  // Since there could be duplicate text selection changed events on a node
+  // raised from both FireBlinkEvent and FireGeneratedEvent, we use an unordered
+  // set here to keep track of the unique nodes that had
+  // UIA_Text_TextSelectionChangedEventId, so we only fire the event once for
+  // every node.
+  std::unordered_set<BrowserAccessibility*> text_selection_changed_events_;
+
   // When the ignored state changes for a node, we only want to fire the
   // events relevant to the ignored state change (e.g. show / hide).
   // This set keeps track of what nodes should suppress superfluous events.
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index 9754500..f68ecf9 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -312,6 +312,8 @@
             WebContentsAccessibilityAndroid* accessibility);
   ~Connector() override;
 
+  void DeleteEarly();
+
   // RenderWidgetHostConnector:
   void UpdateRenderProcessConnection(
       RenderWidgetHostViewAndroid* old_rwhva,
@@ -337,6 +339,10 @@
     manager->set_web_contents_accessibility(nullptr);
 }
 
+void WebContentsAccessibilityAndroid::Connector::DeleteEarly() {
+  RenderWidgetHostConnector::DestroyEarly();
+}
+
 void WebContentsAccessibilityAndroid::Connector::UpdateRenderProcessConnection(
     RenderWidgetHostViewAndroid* old_rwhva,
     RenderWidgetHostViewAndroid* new_rwhva) {
@@ -371,6 +377,10 @@
   Java_WebContentsAccessibilityImpl_onNativeObjectDestroyed(env, obj);
 }
 
+void WebContentsAccessibilityAndroid::DeleteEarly(JNIEnv* env) {
+  connector_->DeleteEarly();
+}
+
 jboolean WebContentsAccessibilityAndroid::IsEnabled(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
diff --git a/content/browser/accessibility/web_contents_accessibility_android.h b/content/browser/accessibility/web_contents_accessibility_android.h
index 282ad52..157726b 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.h
+++ b/content/browser/accessibility/web_contents_accessibility_android.h
@@ -42,6 +42,8 @@
   // Methods called from Java via JNI
   // --------------------------------------------------------------------------
 
+  void DeleteEarly(JNIEnv* env);
+
   // Global methods.
   jboolean IsEnabled(JNIEnv* env,
                      const base::android::JavaParamRef<jobject>& obj);
diff --git a/content/browser/android/render_widget_host_connector.cc b/content/browser/android/render_widget_host_connector.cc
index 259924d..fcd28df 100644
--- a/content/browser/android/render_widget_host_connector.cc
+++ b/content/browser/android/render_widget_host_connector.cc
@@ -35,11 +35,14 @@
   void RenderWidgetHostViewDestroyed(
       RenderWidgetHostViewAndroid* rwhva) override;
 
+  void DestroyEarly();
   void UpdateRenderWidgetHostView(RenderWidgetHostViewAndroid* new_rwhva);
   RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid() const;
   RenderWidgetHostViewAndroid* active_rwhva() const { return active_rwhva_; }
 
  private:
+  void DoDestroy(WebContentsAndroid* web_contents_android);
+
   RenderWidgetHostConnector* const connector_;
 
   // Active RenderWidgetHostView connected to this instance. Can also point to
@@ -94,6 +97,16 @@
 
 void RenderWidgetHostConnector::Observer::WebContentsAndroidDestroyed(
     WebContentsAndroid* web_contents_android) {
+  DoDestroy(web_contents_android);
+}
+
+void RenderWidgetHostConnector::Observer::DestroyEarly() {
+  DoDestroy(
+      static_cast<WebContentsImpl*>(web_contents())->GetWebContentsAndroid());
+}
+
+void RenderWidgetHostConnector::Observer::DoDestroy(
+    WebContentsAndroid* web_contents_android) {
   web_contents_android->RemoveDestructionObserver(this);
   DCHECK_EQ(active_rwhva_, GetRenderWidgetHostViewAndroid());
   UpdateRenderWidgetHostView(nullptr);
@@ -153,6 +166,10 @@
   return render_widget_observer_->active_rwhva();
 }
 
+void RenderWidgetHostConnector::DestroyEarly() {
+  render_widget_observer_->DestroyEarly();
+}
+
 WebContents* RenderWidgetHostConnector::web_contents() const {
   return render_widget_observer_->web_contents();
 }
diff --git a/content/browser/android/render_widget_host_connector.h b/content/browser/android/render_widget_host_connector.h
index 95ff1a1..1294d9462 100644
--- a/content/browser/android/render_widget_host_connector.h
+++ b/content/browser/android/render_widget_host_connector.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_ANDROID_RENDER_WIDGET_HOST_CONNECTOR_H_
 #define CONTENT_BROWSER_ANDROID_RENDER_WIDGET_HOST_CONNECTOR_H_
 
+#include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
 #include "content/browser/renderer_host/render_widget_host_view_android.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -16,7 +17,9 @@
 // override |UpdateRenderProcessConnection| to set itself to the RWHVA
 // brought up foreground, and null out its reference in the RWHVA going
 // away so it won't access the object any more.
-// This class owns itself and gets deleted when the Java WebContents is deleted.
+// This class owns itself and gets deleted when the WebContents is deleted.
+// Can also delete this object early (before the WebContents is destroyed)
+// by calling Destroy directly.
 class RenderWidgetHostConnector {
  public:
   explicit RenderWidgetHostConnector(WebContents* web_contents);
@@ -39,8 +42,14 @@
   RenderWidgetHostViewAndroid* GetRWHVAForTesting() const;
 
  protected:
+  FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostConnectorTest, DestroyEarly);
+
   WebContents* web_contents() const;
 
+  // Deletes this now. Note this is usually not required as this is
+  // deleted when the corresponding WebContents is destroyed.
+  void DestroyEarly();
+
  private:
   class Observer;
   std::unique_ptr<Observer> render_widget_observer_;
diff --git a/content/browser/android/render_widget_host_connector_browsertest.cc b/content/browser/android/render_widget_host_connector_browsertest.cc
index b25db76..1d692dc4 100644
--- a/content/browser/android/render_widget_host_connector_browsertest.cc
+++ b/content/browser/android/render_widget_host_connector_browsertest.cc
@@ -119,4 +119,16 @@
   EXPECT_EQ(nullptr, connector->GetRWHVAForTesting());
 }
 
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostConnectorTest, DestroyEarly) {
+  EXPECT_TRUE(
+      NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
+
+  RenderWidgetHostViewAndroid* main_rwhva = render_widget_host_view_android();
+  RenderWidgetHostConnector* connector = render_widget_host_connector();
+  EXPECT_EQ(main_rwhva, connector->GetRWHVAForTesting());
+
+  connector->DestroyEarly();
+  EXPECT_EQ(nullptr, render_widget_host_connector());
+}
+
 }  // namespace content
diff --git a/content/browser/android/web_contents_observer_proxy.cc b/content/browser/android/web_contents_observer_proxy.cc
index 1d5ed90..a8267ac 100644
--- a/content/browser/android/web_contents_observer_proxy.cc
+++ b/content/browser/android/web_contents_observer_proxy.cc
@@ -211,11 +211,9 @@
   Java_WebContentsObserverProxy_didDetachInterstitialPage(env, java_observer_);
 }
 
-void WebContentsObserverProxy::DidChangeThemeColor(
-    base::Optional<SkColor> color) {
+void WebContentsObserverProxy::DidChangeThemeColor() {
   JNIEnv* env = AttachCurrentThread();
-  Java_WebContentsObserverProxy_didChangeThemeColor(
-      env, java_observer_, color.value_or(SK_ColorTRANSPARENT));
+  Java_WebContentsObserverProxy_didChangeThemeColor(env, java_observer_);
 }
 
 void WebContentsObserverProxy::MediaEffectivelyFullscreenChanged(
diff --git a/content/browser/android/web_contents_observer_proxy.h b/content/browser/android/web_contents_observer_proxy.h
index ad9acb7..5864cbea 100644
--- a/content/browser/android/web_contents_observer_proxy.h
+++ b/content/browser/android/web_contents_observer_proxy.h
@@ -61,7 +61,7 @@
   void WebContentsDestroyed() override;
   void DidAttachInterstitialPage() override;
   void DidDetachInterstitialPage() override;
-  void DidChangeThemeColor(base::Optional<SkColor> color) override;
+  void DidChangeThemeColor() override;
   void MediaEffectivelyFullscreenChanged(bool is_fullscreen) override;
   void SetToBaseURLForDataURLIfNeeded(std::string* url);
   void ViewportFitChanged(blink::mojom::ViewportFit value) override;
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index 7afe590..dd7ffa97 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -389,18 +389,12 @@
  public:
   explicit ThemeColorObserver(WebContents* contents)
       : WebContentsObserver(contents) {}
-  void DidChangeThemeColor(base::Optional<SkColor> color) override {
-    observed_ = true;
-    color_ = color;
-  }
-
-  const base::Optional<SkColor>& color() const { return color_; }
+  void DidChangeThemeColor() override { observed_ = true; }
 
   bool did_fire() const { return observed_; }
 
  private:
   bool observed_ = false;
-  base::Optional<SkColor> color_;
 };
 
 class DOMContentLoadedObserver : public WebContentsObserver {
@@ -4046,7 +4040,6 @@
   web_contents()->GetController().GoBack();
   EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
   EXPECT_TRUE(observer.did_fire());
-  EXPECT_EQ(observer.color(), 0xFFFF0000u);
   EXPECT_EQ(web_contents()->GetThemeColor(), 0xFFFF0000u);
 }
 
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc
index 3d20f3d..c7a95973 100644
--- a/content/browser/devtools/protocol/input_handler.cc
+++ b/content/browser/devtools/protocol/input_handler.cc
@@ -672,7 +672,7 @@
   modifiers |= button_modifiers;
   base::TimeTicks timestamp = GetEventTimeTicks(maybe_timestamp);
 
-  std::unique_ptr<blink::WebMouseEvent, ui::WebInputEventDeleter> mouse_event;
+  std::unique_ptr<blink::WebMouseEvent> mouse_event;
   blink::WebMouseWheelEvent* wheel_event = nullptr;
 
   if (type == blink::WebInputEvent::kMouseWheel) {
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index bb0b7ce2..5abfb1c 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -595,6 +595,12 @@
                             should_persist_new_download_);
     OnDownloadStarted(download, std::move(on_started));
   } else {
+    // If the download already in system, it can only be resumed.
+    if (!info->guid.empty() && GetDownloadByGuid(info->guid)) {
+      LOG(WARNING) << "A download with the same GUID already exists, the new "
+                      "request is ignored.";
+      return;
+    }
     GetNextId(base::BindOnce(&DownloadManagerImpl::CreateNewDownloadItemToStart,
                              weak_factory_.GetWeakPtr(), std::move(info),
                              std::move(on_started), std::move(callback)));
diff --git a/content/browser/frame_host/navigation_request_browsertest.cc b/content/browser/frame_host/navigation_request_browsertest.cc
index 1ff7285..38de5db 100644
--- a/content/browser/frame_host/navigation_request_browsertest.cc
+++ b/content/browser/frame_host/navigation_request_browsertest.cc
@@ -1643,7 +1643,7 @@
 
   EXPECT_TRUE(observer.has_committed());
   EXPECT_TRUE(observer.is_error());
-  EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.net_error_code());
+  EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, observer.net_error_code());
   EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.resolve_error_info().error);
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index cd6aea1..b0cf9707 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2636,21 +2636,17 @@
 }
 
 void RenderFrameHostImpl::DidCommitProvisionalLoad(
-    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-        validated_params,
+    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
     mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
-  if (MaybeInterceptCommitCallback(nullptr, validated_params.get(),
-                                   &interface_params)) {
-    DidCommitNavigation(std::move(navigation_request_),
-                        std::move(validated_params),
+  if (MaybeInterceptCommitCallback(nullptr, params.get(), &interface_params)) {
+    DidCommitNavigation(std::move(navigation_request_), std::move(params),
                         std::move(interface_params));
   }
 }
 
 void RenderFrameHostImpl::DidCommitBackForwardCacheNavigation(
     NavigationRequest* committing_navigation_request,
-    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-        validated_params) {
+    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params) {
   auto request = navigation_requests_.find(committing_navigation_request);
   CHECK(request != navigation_requests_.end());
 
@@ -2667,8 +2663,7 @@
   // been fired.
   is_loading_ = true;
 
-  DidCommitNavigationInternal(std::move(owned_request),
-                              std::move(validated_params),
+  DidCommitNavigationInternal(std::move(owned_request), std::move(params),
                               /*is_same_document_navigation=*/false);
 
   // The page is already loaded since it came from the cache, so fire the stop
@@ -2678,13 +2673,11 @@
 
 void RenderFrameHostImpl::DidCommitPerNavigationMojoInterfaceNavigation(
     NavigationRequest* committing_navigation_request,
-    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-        validated_params,
+    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
     mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
   DCHECK(committing_navigation_request);
   committing_navigation_request->IgnoreCommitInterfaceDisconnection();
-  if (!MaybeInterceptCommitCallback(committing_navigation_request,
-                                    validated_params.get(),
+  if (!MaybeInterceptCommitCallback(committing_navigation_request, params.get(),
                                     &interface_params)) {
     return;
   }
@@ -2697,16 +2690,14 @@
 
   std::unique_ptr<NavigationRequest> owned_request = std::move(request->second);
   navigation_requests_.erase(committing_navigation_request);
-  DidCommitNavigation(std::move(owned_request), std::move(validated_params),
+  DidCommitNavigation(std::move(owned_request), std::move(params),
                       std::move(interface_params));
 }
 
 void RenderFrameHostImpl::DidCommitSameDocumentNavigation(
-    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-        validated_params) {
+    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params) {
   ScopedActiveURL scoped_active_url(
-      validated_params->url,
-      frame_tree_node()->frame_tree()->root()->current_origin());
+      params->url, frame_tree_node()->frame_tree()->root()->current_origin());
   ScopedCommitStateResetter commit_state_resetter(this);
 
   // When the frame is pending deletion, the browser is waiting for it to unload
@@ -2723,18 +2714,18 @@
   TRACE_EVENT2("navigation",
                "RenderFrameHostImpl::DidCommitSameDocumentNavigation",
                "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
-               validated_params->url.possibly_invalid_spec());
+               params->url.possibly_invalid_spec());
 
   // Check if the navigation matches a stored same-document NavigationRequest.
   // In that case it is browser-initiated.
   bool is_browser_initiated =
       same_document_navigation_request_ &&
       (same_document_navigation_request_->commit_params().navigation_token ==
-       validated_params->navigation_token);
+       params->navigation_token);
   if (!DidCommitNavigationInternal(
           is_browser_initiated ? std::move(same_document_navigation_request_)
                                : nullptr,
-          std::move(validated_params), true /* is_same_document_navigation*/)) {
+          std::move(params), true /* is_same_document_navigation*/)) {
     return;
   }
 
@@ -6927,7 +6918,7 @@
 
 bool RenderFrameHostImpl::ValidateDidCommitParams(
     NavigationRequest* navigation_request,
-    FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params,
+    FrameHostMsg_DidCommitProvisionalLoad_Params* params,
     bool is_same_document_navigation) {
   RenderProcessHost* process = GetProcess();
 
@@ -6941,8 +6932,8 @@
       // Commits in the error page process must only be failures, otherwise
       // successful navigations could commit documents from origins different
       // than the chrome-error://chromewebdata/ one and violate expectations.
-      if (!validated_params->url_is_unreachable) {
-        DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
+      if (!params->url_is_unreachable) {
+        DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
         bad_message::ReceivedBadMessage(
             process, bad_message::RFH_ERROR_PROCESS_NON_ERROR_COMMIT);
         return false;
@@ -6962,8 +6953,8 @@
 
   // Error pages must commit in a opaque origin. Terminate the renderer
   // process if this is violated.
-  if (bypass_checks_for_error_page && !validated_params->origin.opaque()) {
-    DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
+  if (bypass_checks_for_error_page && !params->origin.opaque()) {
+    DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
     bad_message::ReceivedBadMessage(
         process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
     return false;
@@ -6971,7 +6962,7 @@
 
   // file: URLs can be allowed to access any other origin, based on settings.
   bool bypass_checks_for_file_scheme = false;
-  if (validated_params->origin.scheme() == url::kFileScheme) {
+  if (params->origin.scheme() == url::kFileScheme) {
     WebPreferences prefs = render_view_host_->GetWebkitPreferences();
     if (prefs.allow_universal_access_from_file_urls)
       bypass_checks_for_file_scheme = true;
@@ -6984,8 +6975,7 @@
   bool bypass_checks_for_webview = false;
   if ((navigation_request &&
        IsLoadDataWithBaseURL(navigation_request->common_params())) ||
-      (is_same_document_navigation &&
-       IsLoadDataWithBaseURL(*validated_params))) {
+      (is_same_document_navigation && IsLoadDataWithBaseURL(*params))) {
     // Allow bypass if the process isn't locked. Otherwise run normal checks.
     bypass_checks_for_webview = ChildProcessSecurityPolicyImpl::GetInstance()
                                     ->GetOriginLock(process->GetID())
@@ -6997,21 +6987,19 @@
     // Attempts to commit certain off-limits URL should be caught more strictly
     // than our FilterURL checks.  If a renderer violates this policy, it
     // should be killed.
-    switch (CanCommitOriginAndUrl(validated_params->origin,
-                                  validated_params->url)) {
+    switch (CanCommitOriginAndUrl(params->origin, params->url)) {
       case CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL:
         // The origin and URL are safe to commit.
         break;
       case CanCommitStatus::CANNOT_COMMIT_URL:
-        DLOG(ERROR) << "CANNOT_COMMIT_URL url '" << validated_params->url << "'"
-                    << " origin '" << validated_params->origin << "'"
+        DLOG(ERROR) << "CANNOT_COMMIT_URL url '" << params->url << "'"
+                    << " origin '" << params->origin << "'"
                     << " lock '"
                     << ChildProcessSecurityPolicyImpl::GetInstance()
                            ->GetOriginLock(process->GetID())
                     << "'";
-        VLOG(1) << "Blocked URL " << validated_params->url.spec();
-        LogCannotCommitUrlCrashKeys(validated_params->url,
-                                    is_same_document_navigation,
+        VLOG(1) << "Blocked URL " << params->url.spec();
+        LogCannotCommitUrlCrashKeys(params->url, is_same_document_navigation,
                                     navigation_request);
 
         // Kills the process.
@@ -7019,14 +7007,13 @@
             process, bad_message::RFH_CAN_COMMIT_URL_BLOCKED);
         return false;
       case CanCommitStatus::CANNOT_COMMIT_ORIGIN:
-        DLOG(ERROR) << "CANNOT_COMMIT_ORIGIN url '" << validated_params->url
-                    << "'"
-                    << " origin '" << validated_params->origin << "'"
+        DLOG(ERROR) << "CANNOT_COMMIT_ORIGIN url '" << params->url << "'"
+                    << " origin '" << params->origin << "'"
                     << " lock '"
                     << ChildProcessSecurityPolicyImpl::GetInstance()
                            ->GetOriginLock(process->GetID())
                     << "'";
-        DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
+        DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
         LogCannotCommitOriginCrashKeys(is_same_document_navigation,
                                        navigation_request);
 
@@ -7047,19 +7034,19 @@
   //
   // TODO(https://crbug.com/172694): Currently, when FilterURL detects a bad URL
   // coming from the renderer, it overwrites that URL to about:blank, which
-  // requires |validated_params| to be mutable. Once we kill the renderer
+  // requires |params| to be mutable. Once we kill the renderer
   // instead, the signature of RenderFrameHostImpl::DidCommitProvisionalLoad can
-  // be modified to take |validated_params| by const reference.
-  process->FilterURL(false, &validated_params->url);
-  process->FilterURL(true, &validated_params->referrer.url);
-  for (auto it(validated_params->redirects.begin());
-       it != validated_params->redirects.end(); ++it) {
+  // be modified to take |params| by const reference.
+  process->FilterURL(false, &params->url);
+  process->FilterURL(true, &params->referrer.url);
+  for (auto it(params->redirects.begin()); it != params->redirects.end();
+       ++it) {
     process->FilterURL(false, &(*it));
   }
 
   // Without this check, the renderer can trick the browser into using
   // filenames it can't access in a future session restore.
-  if (!CanAccessFilesOfPageState(validated_params->page_state)) {
+  if (!CanAccessFilesOfPageState(params->page_state)) {
     bad_message::ReceivedBadMessage(
         process, bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
     return false;
@@ -7079,17 +7066,15 @@
 
 bool RenderFrameHostImpl::DidCommitNavigationInternal(
     std::unique_ptr<NavigationRequest> navigation_request,
-    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-        validated_params,
+    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
     bool is_same_document_navigation) {
   // Sanity-check the page transition for frame type.
-  DCHECK_EQ(ui::PageTransitionIsMainFrame(validated_params->transition),
-            !GetParent());
+  DCHECK_EQ(ui::PageTransitionIsMainFrame(params->transition), !GetParent());
 
   // Check that the committing navigation token matches the navigation request.
   if (navigation_request &&
       navigation_request->commit_params().navigation_token !=
-          validated_params->navigation_token) {
+          params->navigation_token) {
     navigation_request.reset();
   }
 
@@ -7100,9 +7085,8 @@
 
     //  1) This was a renderer-initiated navigation to an empty document. Most
     //  of the time: about:blank.
-    is_commit_allowed_to_proceed |=
-        validated_params->url.SchemeIs(url::kAboutScheme) &&
-        validated_params->url != GURL(url::kAboutSrcdocURL);
+    is_commit_allowed_to_proceed |= params->url.SchemeIs(url::kAboutScheme) &&
+                                    params->url != GURL(url::kAboutSrcdocURL);
 
     //  2) This was a same-document navigation.
     //  TODO(clamy): We should enforce having a request on browser-initiated
@@ -7118,13 +7102,13 @@
 
     //  4) Error pages implementations in Chrome can commit twice.
     //  TODO(clamy): Fix this.
-    is_commit_allowed_to_proceed |= validated_params->url_is_unreachable;
+    is_commit_allowed_to_proceed |= params->url_is_unreachable;
 
     //  5) Special case for DOMSerializerBrowsertests which are implemented
     //  entirely renderer-side and unlike normal RenderView based tests load
     //  file URLs instead of data URLs.
     //  TODO(clamy): Rework the tests to remove this exception.
-    is_commit_allowed_to_proceed |= validated_params->url.SchemeIsFile();
+    is_commit_allowed_to_proceed |= params->url.SchemeIsFile();
 
     if (!is_commit_allowed_to_proceed) {
       bad_message::ReceivedBadMessage(
@@ -7134,7 +7118,7 @@
     }
   }
 
-  if (!ValidateDidCommitParams(navigation_request.get(), validated_params.get(),
+  if (!ValidateDidCommitParams(navigation_request.get(), params.get(),
                                is_same_document_navigation)) {
     return false;
   }
@@ -7142,7 +7126,7 @@
   // TODO(clamy): We should stop having a special case for same-document
   // navigation and just put them in the general map of NavigationRequests.
   if (navigation_request &&
-      navigation_request->common_params().url != validated_params->url &&
+      navigation_request->common_params().url != params->url &&
       is_same_document_navigation) {
     same_document_navigation_request_ = std::move(navigation_request);
   }
@@ -7166,7 +7150,7 @@
   // WebContentsObservers.
   if (!navigation_request) {
     navigation_request = CreateNavigationRequestForCommit(
-        *validated_params, is_same_document_navigation, nullptr);
+        *params, is_same_document_navigation, nullptr);
   }
 
   DCHECK(navigation_request);
@@ -7176,14 +7160,14 @@
   // only gives the correct page transition at commit time.
   // TODO(clamy): We should get the correct page transition when starting the
   // request.
-  navigation_request->set_transition(validated_params->transition);
+  navigation_request->set_transition(params->transition);
 
-  navigation_request->set_has_user_gesture(validated_params->gesture ==
+  navigation_request->set_has_user_gesture(params->gesture ==
                                            NavigationGestureUser);
 
-  last_http_status_code_ = validated_params->http_status_code;
-  last_http_method_ = validated_params->method;
-  UpdateSiteURL(validated_params->url, validated_params->url_is_unreachable);
+  last_http_status_code_ = params->http_status_code;
+  last_http_method_ = params->method;
+  UpdateSiteURL(params->url, params->url_is_unreachable);
   if (!is_same_document_navigation)
     UpdateRenderProcessHostFramePriorities();
 
@@ -7219,14 +7203,14 @@
     }));
   }
 
-  frame_tree_node()->navigator()->DidNavigate(this, *validated_params,
+  frame_tree_node()->navigator()->DidNavigate(this, *params,
                                               std::move(navigation_request),
                                               is_same_document_navigation);
 
   if (IsBackForwardCacheEnabled()) {
     // Store the Commit params so they can be reused if the page is ever
     // restored from the BackForwardCache.
-    last_commit_params_ = std::move(validated_params);
+    last_commit_params_ = std::move(params);
   }
 
   if (!is_same_document_navigation) {
@@ -7287,7 +7271,7 @@
 
 std::unique_ptr<base::trace_event::TracedValue>
 RenderFrameHostImpl::CommitAsTracedValue(
-    FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params) const {
+    FrameHostMsg_DidCommitProvisionalLoad_Params* params) const {
   auto value = std::make_unique<base::trace_event::TracedValue>();
 
   value->SetInteger("frame_tree_node", frame_tree_node_->frame_tree_node_id());
@@ -7295,12 +7279,11 @@
   value->SetString("process lock", ChildProcessSecurityPolicyImpl::GetInstance()
                                        ->GetOriginLock(process_->GetID())
                                        .possibly_invalid_spec());
-  value->SetString("origin", validated_params->origin.Serialize());
-  value->SetInteger("transition", validated_params->transition);
+  value->SetString("origin", params->origin.Serialize());
+  value->SetInteger("transition", params->transition);
 
-  if (!validated_params->base_url.is_empty()) {
-    value->SetString("base_url",
-                     validated_params->base_url.possibly_invalid_spec());
+  if (!params->base_url.is_empty()) {
+    value->SetString("base_url", params->base_url.possibly_invalid_spec());
   }
 
   return value;
@@ -7425,8 +7408,7 @@
 // notification containing parameters identifying the navigation.
 void RenderFrameHostImpl::DidCommitNavigation(
     std::unique_ptr<NavigationRequest> committing_navigation_request,
-    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-        validated_params,
+    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
     mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
   NavigationRequest* request;
   if (committing_navigation_request) {
@@ -7436,7 +7418,7 @@
   }
 
   if (request && request->IsNavigationStarted()) {
-    main_frame_request_ids_ = {validated_params->request_id,
+    main_frame_request_ids_ = {params->request_id,
                                request->GetGlobalRequestID()};
     if (deferred_main_frame_load_info_)
       ResourceLoadComplete(std::move(deferred_main_frame_load_info_));
@@ -7445,15 +7427,14 @@
   // committed (not with the *last* committed URL that most other IPCs are
   // associated with).
   ScopedActiveURL scoped_active_url(
-      validated_params->url,
-      frame_tree_node()->frame_tree()->root()->current_origin());
+      params->url, frame_tree_node()->frame_tree()->root()->current_origin());
 
   ScopedCommitStateResetter commit_state_resetter(this);
   RenderProcessHost* process = GetProcess();
 
   TRACE_EVENT2("navigation", "RenderFrameHostImpl::DidCommitProvisionalLoad",
-               "url", validated_params->url.possibly_invalid_spec(), "details",
-               CommitAsTracedValue(validated_params.get()));
+               "url", params->url.possibly_invalid_spec(), "details",
+               CommitAsTracedValue(params.get()));
 
   // If we're waiting for a cross-site beforeunload ack from this renderer and
   // we receive a Navigate message from the main frame, then the renderer was
@@ -7527,7 +7508,7 @@
   }
 
   if (!DidCommitNavigationInternal(std::move(committing_navigation_request),
-                                   std::move(validated_params),
+                                   std::move(params),
                                    false /* is_same_document_navigation */)) {
     return;
   }
@@ -7607,11 +7588,11 @@
 
 bool RenderFrameHostImpl::MaybeInterceptCommitCallback(
     NavigationRequest* navigation_request,
-    FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params,
+    FrameHostMsg_DidCommitProvisionalLoad_Params* params,
     mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params) {
   if (commit_callback_interceptor_) {
     return commit_callback_interceptor_->WillProcessDidCommitNavigation(
-        navigation_request, validated_params, interface_params);
+        navigation_request, params, interface_params);
   }
   return true;
 }
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 597bf645..ed95eddf 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1220,8 +1220,7 @@
   // the back-forward cache.
   void DidCommitBackForwardCacheNavigation(
       NavigationRequest* committing_navigation_request,
-      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-          validated_params);
+      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params);
 
   bool has_committed_any_navigation() const {
     return has_committed_any_navigation_;
@@ -1535,8 +1534,7 @@
   void IssueKeepAliveHandle(
       mojo::PendingReceiver<mojom::KeepAliveHandle> receiver) override;
   void DidCommitProvisionalLoad(
-      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-          validated_params,
+      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
       mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params)
       override;
 
@@ -1546,13 +1544,12 @@
   // replace DidCommitProvisionalLoad in the long run.
   void DidCommitPerNavigationMojoInterfaceNavigation(
       NavigationRequest* committing_navigation_request,
-      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-          validated_params,
+      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
       mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params);
 
   void DidCommitSameDocumentNavigation(
-      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-          validated_params) override;
+      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params)
+      override;
   void BeginNavigation(
       mojom::CommonNavigationParamsPtr common_params,
       mojom::BeginNavigationParamsPtr begin_params,
@@ -1829,7 +1826,7 @@
   // A return value of true means that the commit should proceed.
   bool ValidateDidCommitParams(
       NavigationRequest* navigation_request,
-      FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params,
+      FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       bool is_same_document_navigation);
 
   // Updates the site url if the navigation was successful and the page is not
@@ -1840,8 +1837,7 @@
   // DidCommitPerNavigationMojoInterfaceNavigation.
   void DidCommitNavigation(
       std::unique_ptr<NavigationRequest> committing_navigation_request,
-      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-          validated_params,
+      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
       mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params);
 
   // Called when we receive the confirmation that a navigation committed in the
@@ -1851,8 +1847,7 @@
   // state should be restored to its pre-commit value.
   bool DidCommitNavigationInternal(
       std::unique_ptr<NavigationRequest> navigation_request,
-      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-          validated_params,
+      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
       bool is_same_document_navigation);
 
   // Called by the renderer process when it is done processing a same-document
@@ -1869,7 +1864,7 @@
   // Creates a TracedValue object containing the details of a committed
   // navigation, so it can be logged with the tracing system.
   std::unique_ptr<base::trace_event::TracedValue> CommitAsTracedValue(
-      FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params) const;
+      FrameHostMsg_DidCommitProvisionalLoad_Params* params) const;
 
   // Creates URLLoaderFactory objects for |isolated_world_origins|.
   blink::PendingURLLoaderFactoryBundle::OriginMap
@@ -1916,7 +1911,7 @@
   // Returns true if we should proceed to the Commit callback, false otherwise.
   bool MaybeInterceptCommitCallback(
       NavigationRequest* navigation_request,
-      FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params,
+      FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params);
 
   // If this RenderFrameHost is a local root (i.e., either the main frame or a
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc
index a6c773e2..28a2329f 100644
--- a/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -63,11 +63,6 @@
   web_ui->RegisterMessageCallback(
       "forceClose", base::BindRepeating(&IndexedDBInternalsUI::ForceCloseOrigin,
                                         base::Unretained(this)));
-  web_ui->RegisterMessageCallback(
-      "forceSchemaDowngrade",
-      base::BindRepeating(&IndexedDBInternalsUI::ForceSchemaDowngradeOrigin,
-                          base::Unretained(this)));
-
   WebUIDataSource* source =
       WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost);
   source->OverrideContentSecurityPolicyScriptSrc(
@@ -214,23 +209,6 @@
                      base::Unretained(this), partition_path, context, origin));
 }
 
-void IndexedDBInternalsUI::ForceSchemaDowngradeOrigin(
-    const base::ListValue* args) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  base::FilePath partition_path;
-  Origin origin;
-  scoped_refptr<IndexedDBContextImpl> context;
-  if (!GetOriginData(args, &partition_path, &origin, &context))
-    return;
-
-  context->IDBTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &IndexedDBInternalsUI::ForceSchemaDowngradeOriginOnIndexedDBThread,
-          base::Unretained(this), partition_path, context, origin));
-}
-
 void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
     const base::FilePath& partition_path,
     const scoped_refptr<IndexedDBContextImpl> context,
@@ -281,28 +259,7 @@
   size_t connection_count = context->GetConnectionCount(origin);
 
   base::PostTask(FROM_HERE, {BrowserThread::UI},
-                 base::BindOnce(&IndexedDBInternalsUI::OnForcedSchemaDowngrade,
-                                base::Unretained(this), partition_path, origin,
-                                connection_count));
-}
-
-void IndexedDBInternalsUI::ForceSchemaDowngradeOriginOnIndexedDBThread(
-    const base::FilePath& partition_path,
-    const scoped_refptr<IndexedDBContextImpl> context,
-    const Origin& origin) {
-  DCHECK(context->IDBTaskRunner()->RunsTasksInCurrentSequence());
-
-  // Make sure the database hasn't been deleted since the page was loaded.
-  if (!context->HasOrigin(origin))
-    return;
-
-  context->ForceSchemaDowngrade(origin);
-  context->ForceClose(
-      origin, IndexedDBContextImpl::FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE);
-  size_t connection_count = context->GetConnectionCount(origin);
-
-  base::PostTask(FROM_HERE, {BrowserThread::UI},
-                 base::BindOnce(&IndexedDBInternalsUI::OnForcedSchemaDowngrade,
+                 base::BindOnce(&IndexedDBInternalsUI::OnForcedClose,
                                 base::Unretained(this), partition_path, origin,
                                 connection_count));
 }
@@ -316,16 +273,6 @@
       base::Value(static_cast<double>(connection_count)));
 }
 
-void IndexedDBInternalsUI::OnForcedSchemaDowngrade(
-    const base::FilePath& partition_path,
-    const Origin& origin,
-    size_t connection_count) {
-  web_ui()->CallJavascriptFunctionUnsafe(
-      "indexeddb.onForcedSchemaDowngrade", base::Value(partition_path.value()),
-      base::Value(origin.Serialize()),
-      base::Value(static_cast<double>(connection_count)));
-}
-
 void IndexedDBInternalsUI::OnDownloadDataReady(
     const base::FilePath& partition_path,
     const Origin& origin,
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.h b/content/browser/indexed_db/indexed_db_internals_ui.h
index 1a8a154..7e2e870 100644
--- a/content/browser/indexed_db/indexed_db_internals_ui.h
+++ b/content/browser/indexed_db/indexed_db_internals_ui.h
@@ -74,15 +74,6 @@
                      const url::Origin& origin,
                      size_t connection_count);
 
-  void ForceSchemaDowngradeOrigin(const base::ListValue* args);
-  void ForceSchemaDowngradeOriginOnIndexedDBThread(
-      const base::FilePath& partition_path,
-      const scoped_refptr<IndexedDBContextImpl> context,
-      const url::Origin& origin);
-  void OnForcedSchemaDowngrade(const base::FilePath& partition_path,
-                               const url::Origin& origin,
-                               size_t connection_count);
-
   bool GetOriginContext(const base::FilePath& path,
                         const url::Origin& origin,
                         scoped_refptr<IndexedDBContextImpl>* context);
diff --git a/content/browser/loader/file_url_loader_factory.cc b/content/browser/loader/file_url_loader_factory.cc
index 0496d73..9be5cbf 100644
--- a/content/browser/loader/file_url_loader_factory.cc
+++ b/content/browser/loader/file_url_loader_factory.cc
@@ -891,7 +891,7 @@
   receivers_.Add(this, std::move(loader));
 }
 
-void CreateFileURLLoader(
+void CreateFileURLLoaderBypassingSecurityChecks(
     const network::ResourceRequest& request,
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h
index a1f5ea0..a1cf230b 100644
--- a/content/browser/renderer_host/delegated_frame_host.h
+++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -22,7 +22,6 @@
 #include "content/browser/renderer_host/dip_util.h"
 #include "content/common/content_export.h"
 #include "content/common/tab_switch_time_recorder.h"
-#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
 #include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_observer.h"
@@ -188,9 +187,6 @@
 
   SkColor GetGutterColor() const;
 
-  void CreateCompositorFrameSinkSupport();
-  void ResetCompositorFrameSinkSupport();
-
   void CopyFromCompositingSurfaceInternal(
       const gfx::Rect& src_subrect,
       const gfx::Size& output_size,
diff --git a/content/browser/renderer_host/frame_metadata_util.cc b/content/browser/renderer_host/frame_metadata_util.cc
index e5717aa..06c09529 100644
--- a/content/browser/renderer_host/frame_metadata_util.cc
+++ b/content/browser/renderer_host/frame_metadata_util.cc
@@ -4,7 +4,7 @@
 
 #include "content/browser/renderer_host/frame_metadata_util.h"
 
-#include "components/viz/common/quads/compositor_frame_metadata.h"
+#include "ui/gfx/geometry/size_f.h"
 
 namespace {
 
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 44c32d2..4b3e151 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -66,8 +66,7 @@
         latency_info.ScaledBy(scale));
   }
 
-  return std::make_unique<InputEvent>(ui::WebInputEventTraits::Clone(event),
-                                      latency_info);
+  return std::make_unique<InputEvent>(event.Clone(), latency_info);
 }
 
 }  // namespace
diff --git a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
index b6817d6..e329f917 100644
--- a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
+++ b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
@@ -5,8 +5,9 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
+#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/common/input/synthetic_pinch_gesture_params.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
@@ -18,6 +19,8 @@
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 
+namespace content {
+
 namespace {
 
 const char kTouchpadPinchDataURL[] =
@@ -58,9 +61,31 @@
     "  }"
     "</script>";
 
-}  // namespace
+void PerformTouchpadPinch(WebContents* web_contents,
+                          gfx::PointF position,
+                          float scale_factor) {
+  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
+      web_contents->GetRenderViewHost()->GetWidget());
 
-namespace content {
+  SyntheticPinchGestureParams params;
+  params.gesture_source_type = SyntheticGestureParams::TOUCHPAD_INPUT;
+  params.scale_factor = scale_factor;
+  params.anchor = position;
+  auto pinch_gesture = std::make_unique<SyntheticTouchpadPinchGesture>(params);
+
+  base::RunLoop run_loop;
+  widget_host->QueueSyntheticGesture(
+      std::move(pinch_gesture),
+      base::BindOnce(
+          [](base::OnceClosure quit_closure, SyntheticGesture::Result result) {
+            EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+            std::move(quit_closure).Run();
+          },
+          run_loop.QuitClosure()));
+  run_loop.Run();
+}
+
+}  // namespace
 
 class TouchpadPinchBrowserTest : public ContentBrowserTest,
                                  public testing::WithParamInterface<bool> {
@@ -91,13 +116,16 @@
                                           ->GetRenderWidgetHost());
   }
 
-  void WaitForJavascriptExecution() {
+  // After adding a blocking event listener, we need to wait for the compositor
+  // thread to become aware of the listener. If it receives input events before
+  // that, the compositor thread would handle them.
+  void SynchronizeCompositorAndMainThreads() {
     MainThreadFrameObserver observer(GetRenderWidgetHost());
     observer.Wait();
   }
 
   void EnsureNoScaleChangeWhenCanceled(
-      base::OnceCallback<void(WebContents*, gfx::Point)> send_events);
+      base::OnceCallback<void(WebContents*, gfx::PointF)> send_events);
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -114,10 +142,9 @@
   content::TestPageScaleObserver scale_observer(shell()->web_contents());
 
   const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
-  const gfx::Point pinch_position(contents_rect.width() / 2,
-                                  contents_rect.height() / 2);
-  SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.23,
-                               blink::WebGestureDevice::kTouchpad);
+  const gfx::PointF pinch_position(contents_rect.width() / 2,
+                                   contents_rect.height() / 2);
+  PerformTouchpadPinch(shell()->web_contents(), pinch_position, 1.23);
 
   scale_observer.WaitForPageScaleUpdate();
 }
@@ -128,15 +155,14 @@
   LoadURL();
   ASSERT_TRUE(
       content::ExecuteScript(shell()->web_contents(), "setListener(false);"));
-  WaitForJavascriptExecution();
+  SynchronizeCompositorAndMainThreads();
 
   content::TestPageScaleObserver scale_observer(shell()->web_contents());
 
   const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
-  const gfx::Point pinch_position(contents_rect.width() / 2,
-                                  contents_rect.height() / 2);
-  SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.23,
-                               blink::WebGestureDevice::kTouchpad);
+  const gfx::PointF pinch_position(contents_rect.width() / 2,
+                                   contents_rect.height() / 2);
+  PerformTouchpadPinch(shell()->web_contents(), pinch_position, 1.23);
 
   // Ensure that the page saw the synthetic wheel.
   bool default_prevented = false;
@@ -156,23 +182,22 @@
 // Ensures that the event(s) sent in |send_events| are cancelable by a
 // wheel event listener and that doing so prevents any scale change.
 void TouchpadPinchBrowserTest::EnsureNoScaleChangeWhenCanceled(
-    base::OnceCallback<void(WebContents*, gfx::Point)> send_events) {
+    base::OnceCallback<void(WebContents*, gfx::PointF)> send_events) {
   // Perform an initial pinch so we can figure out the page scale we're
   // starting with for the test proper.
   content::TestPageScaleObserver starting_scale_observer(
       shell()->web_contents());
   const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
-  const gfx::Point pinch_position(contents_rect.width() / 2,
-                                  contents_rect.height() / 2);
-  SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.23,
-                               blink::WebGestureDevice::kTouchpad);
+  const gfx::PointF pinch_position(contents_rect.width() / 2,
+                                   contents_rect.height() / 2);
+  PerformTouchpadPinch(shell()->web_contents(), pinch_position, 1.23);
   const float starting_scale_factor =
       starting_scale_observer.WaitForPageScaleUpdate();
   ASSERT_GT(starting_scale_factor, 0.f);
 
   ASSERT_TRUE(
       content::ExecuteScript(shell()->web_contents(), "setListener(true);"));
-  WaitForJavascriptExecution();
+  SynchronizeCompositorAndMainThreads();
 
   std::move(send_events).Run(shell()->web_contents(), pinch_position);
 
@@ -191,11 +216,10 @@
   ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
                                      "reset(); "
                                      "setListener(false);"));
-  WaitForJavascriptExecution();
+  SynchronizeCompositorAndMainThreads();
 
   content::TestPageScaleObserver scale_observer(shell()->web_contents());
-  SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 2.0,
-                               blink::WebGestureDevice::kTouchpad);
+  PerformTouchpadPinch(shell()->web_contents(), pinch_position, 2.0);
   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
       shell()->web_contents(),
       "handlerPromise.then(function(e) {"
@@ -205,30 +229,26 @@
   EXPECT_FALSE(default_prevented);
 
   const float last_scale_factor = scale_observer.WaitForPageScaleUpdate();
-  EXPECT_FLOAT_EQ(starting_scale_factor * 2.0, last_scale_factor);
+  // The scale changes may be imprecise.
+  constexpr float kScaleEpsilon = 0.001;
+  EXPECT_NEAR(starting_scale_factor * 2.0, last_scale_factor, kScaleEpsilon);
 }
 
-// TODO(https://crbug.com/1033907) Test is flaky on mac bots.
-#if defined(OS_MACOSX)
-#define MAYBE_WheelListenerPreventingPinch DISABLED_WheelListenerPreventingPinch
-#else
-#define MAYBE_WheelListenerPreventingPinch WheelListenerPreventingPinch
-#endif
-IN_PROC_BROWSER_TEST_P(TouchpadPinchBrowserTest,
-                       MAYBE_WheelListenerPreventingPinch) {
+// If the synthetic wheel event for a touchpad pinch is canceled, we should not
+// change the page scale.
+IN_PROC_BROWSER_TEST_P(TouchpadPinchBrowserTest, WheelListenerPreventingPinch) {
   LoadURL();
 
   EnsureNoScaleChangeWhenCanceled(
-      base::BindOnce([](WebContents* web_contents, gfx::Point position) {
-        SimulateGesturePinchSequence(web_contents, position, 1.5,
-                                     blink::WebGestureDevice::kTouchpad);
+      base::BindOnce([](WebContents* web_contents, gfx::PointF position) {
+        PerformTouchpadPinch(web_contents, position, 1.5);
       }));
 }
 
 // If the synthetic wheel event for a touchpad double tap is canceled, we
 // should not change the page scale.
 IN_PROC_BROWSER_TEST_P(TouchpadPinchBrowserTest,
-                       DISABLED_WheelListenerPreventingDoubleTap) {
+                       WheelListenerPreventingDoubleTap) {
   LoadURL();
 
   WebPreferences prefs =
@@ -237,14 +257,14 @@
   shell()->web_contents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
 
   EnsureNoScaleChangeWhenCanceled(
-      base::BindOnce([](WebContents* web_contents, gfx::Point position) {
+      base::BindOnce([](WebContents* web_contents, gfx::PointF position) {
         blink::WebGestureEvent double_tap_zoom(
             blink::WebInputEvent::kGestureDoubleTap,
             blink::WebInputEvent::kNoModifiers,
             blink::WebInputEvent::GetStaticTimeStampForTests(),
             blink::WebGestureDevice::kTouchpad);
-        double_tap_zoom.SetPositionInWidget(gfx::PointF(position));
-        double_tap_zoom.SetPositionInScreen(gfx::PointF(position));
+        double_tap_zoom.SetPositionInWidget(position);
+        double_tap_zoom.SetPositionInScreen(position);
         double_tap_zoom.data.tap.tap_count = 1;
         double_tap_zoom.SetNeedsWheelEvent(true);
 
diff --git a/content/browser/renderer_host/mock_render_widget_host.cc b/content/browser/renderer_host/mock_render_widget_host.cc
index 02e42745..a792ff9 100644
--- a/content/browser/renderer_host/mock_render_widget_host.cc
+++ b/content/browser/renderer_host/mock_render_widget_host.cc
@@ -55,16 +55,6 @@
   EXPECT_EQ(enable, input_router->touch_action_filter_.force_enable_zoom_);
 }
 
-// Mocks out |renderer_compositor_frame_sink_| with a
-// CompositorFrameSinkClient bound to
-// |mock_renderer_compositor_frame_sink|.
-void MockRenderWidgetHost::SetMockRendererCompositorFrameSink(
-    viz::MockCompositorFrameSinkClient* mock_renderer_compositor_frame_sink) {
-  renderer_compositor_frame_sink_.reset();
-  renderer_compositor_frame_sink_.Bind(
-      mock_renderer_compositor_frame_sink->BindInterfaceRemote());
-}
-
 void MockRenderWidgetHost::SetupForInputRouterTest() {
   input_router_.reset(new MockInputRouter(this));
 }
diff --git a/content/browser/renderer_host/mock_render_widget_host.h b/content/browser/renderer_host/mock_render_widget_host.h
index e572577..0f22b62 100644
--- a/content/browser/renderer_host/mock_render_widget_host.h
+++ b/content/browser/renderer_host/mock_render_widget_host.h
@@ -17,10 +17,6 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 
-namespace viz {
-class MockCompositorFrameSinkClient;
-}  // namespace viz
-
 namespace content {
 
 class MockRenderWidgetHost : public RenderWidgetHostImpl {
@@ -56,12 +52,6 @@
     return acked_touch_event_type_;
   }
 
-  // Mocks out |renderer_compositor_frame_sink_| with a
-  // CompositorFrameSinkClient bound to
-  // |mock_renderer_compositor_frame_sink|.
-  void SetMockRendererCompositorFrameSink(
-      viz::MockCompositorFrameSinkClient* mock_renderer_compositor_frame_sink);
-
   void SetupForInputRouterTest();
 
   MockInputRouter* mock_input_router() {
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 5080738..8aa9da1 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -36,10 +36,7 @@
 #include "cc/trees/browser_controls_params.h"
 #include "cc/trees/render_frame_metadata.h"
 #include "components/viz/common/features.h"
-#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/resources/bitmap_allocation.h"
 #include "components/viz/host/host_frame_sink_manager.h"
-#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/browser_main_loop.h"
@@ -324,7 +321,6 @@
       hung_renderer_delay_(TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
       new_content_rendering_delay_(
           TimeDelta::FromMilliseconds(kNewContentRenderingDelayMs)),
-      compositor_frame_sink_receiver_(this),
       frame_token_message_queue_(std::move(frame_token_message_queue)),
       render_frame_metadata_provider_(
 #if defined(OS_MACOSX)
@@ -378,8 +374,6 @@
                             weak_factory_.GetWeakPtr()));
   }
 
-  enable_viz_ = features::IsVizDisplayCompositorEnabled();
-
   delegate_->RenderWidgetCreated(this);
   render_frame_metadata_provider_.AddObserver(this);
 }
@@ -446,15 +440,14 @@
 void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase* view) {
   if (view) {
     view_ = view->GetWeakPtr();
-    if (enable_viz_) {
-      if (!create_frame_sink_callback_.is_null())
-        std::move(create_frame_sink_callback_).Run(view_->GetFrameSinkId());
-    } else {
-      // Views start out not needing begin frames, so only update its state
-      // if the value has changed.
-      if (needs_begin_frames_)
-        view_->SetNeedsBeginFrames(needs_begin_frames_);
-    }
+    if (!create_frame_sink_callback_.is_null())
+      std::move(create_frame_sink_callback_).Run(view_->GetFrameSinkId());
+
+    // Views start out not needing begin frames, so only update its state if the
+    // value has changed. |needs_begin_frames_| should only ever be true for
+    // Android WebView since begin frames are handled by viz everywhere else.
+    if (needs_begin_frames_)
+      view_->SetNeedsBeginFrames(needs_begin_frames_);
   } else {
     view_.reset();
   }
@@ -2021,19 +2014,6 @@
     view_.reset();
   }
 
-  // The display compositor has ownership of shared memory for each
-  // SharedBitmapId that has been reported from the client. Since the client is
-  // gone that memory can be freed. If we don't then it would leak.
-  if (shared_bitmap_manager_) {
-    for (const auto& id : owned_bitmaps_)
-      shared_bitmap_manager_->ChildDeletedSharedBitmap(id);
-  } else {
-    // If the display compositor is not in the browser process, then the
-    // |bitmap_manager| is not present in the process either, and no bitmaps
-    // should have been registered with this class.
-    DCHECK(owned_bitmaps_.empty());
-  }
-
   render_process_blocked_state_changed_subscription_.reset();
   process_->RemovePriorityClient(this);
   process_->RemoveObserver(this);
@@ -2178,31 +2158,6 @@
   Send(new WidgetMsg_SetBounds_ACK(routing_id_));
 }
 
-void RenderWidgetHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
-  // |has_damage| is not transmitted.
-  viz::BeginFrameAck modified_ack = ack;
-  modified_ack.has_damage = false;
-
-  if (view_)
-    view_->OnDidNotProduceFrame(modified_ack);
-}
-
-void RenderWidgetHostImpl::DidAllocateSharedBitmap(
-    base::ReadOnlySharedMemoryRegion region,
-    const viz::SharedBitmapId& id) {
-  if (!shared_bitmap_manager_->ChildAllocatedSharedBitmap(region.Map(), id)) {
-    bad_message::ReceivedBadMessage(GetProcess(),
-                                    bad_message::RWH_SHARED_BITMAP);
-  }
-  owned_bitmaps_.insert(id);
-}
-
-void RenderWidgetHostImpl::DidDeleteSharedBitmap(
-    const viz::SharedBitmapId& id) {
-  shared_bitmap_manager_->ChildDeletedSharedBitmap(id);
-  owned_bitmaps_.erase(id);
-}
-
 void RenderWidgetHostImpl::DidUpdateVisualProperties(
     const cc::RenderFrameMetadata& metadata) {
   TRACE_EVENT_WITH_FLOW1(
@@ -2910,41 +2865,23 @@
         compositor_frame_sink_receiver,
     mojo::PendingRemote<viz::mojom::CompositorFrameSinkClient>
         compositor_frame_sink_client) {
-  if (enable_viz_) {
-      // Connects the viz process end of CompositorFrameSink message pipes. The
-      // renderer compositor may request a new CompositorFrameSink on context
-      // loss, which will destroy the existing CompositorFrameSink.
-      auto callback = base::BindOnce(
-          [](viz::HostFrameSinkManager* manager,
-             mojo::PendingReceiver<viz::mojom::CompositorFrameSink> receiver,
-             mojo::PendingRemote<viz::mojom::CompositorFrameSinkClient> client,
-             const viz::FrameSinkId& frame_sink_id) {
-            manager->CreateCompositorFrameSink(
-                frame_sink_id, std::move(receiver), std::move(client));
-          },
-          base::Unretained(GetHostFrameSinkManager()),
-          std::move(compositor_frame_sink_receiver),
-          std::move(compositor_frame_sink_client));
-
-      if (view_)
-        std::move(callback).Run(view_->GetFrameSinkId());
-      else
-        create_frame_sink_callback_ = std::move(callback);
-
-      return;
-  }
-
-  // Consider any bitmaps registered with the old CompositorFrameSink as gone,
-  // they will be re-registered on the newly requested CompositorFrameSink if
-  // they are meant to be used still. https://crbug.com/862584.
-  for (const auto& id : owned_bitmaps_)
-    shared_bitmap_manager_->ChildDeletedSharedBitmap(id);
-  owned_bitmaps_.clear();
-
-  compositor_frame_sink_receiver_.reset();
-  compositor_frame_sink_receiver_.Bind(
+  // Connects the viz process end of CompositorFrameSink message pipes. The
+  // renderer compositor may request a new CompositorFrameSink on context
+  // loss, which will destroy the existing CompositorFrameSink.
+  auto callback = base::BindOnce(
+      [](mojo::PendingReceiver<viz::mojom::CompositorFrameSink> receiver,
+         mojo::PendingRemote<viz::mojom::CompositorFrameSinkClient> client,
+         const viz::FrameSinkId& frame_sink_id) {
+        GetHostFrameSinkManager()->CreateCompositorFrameSink(
+            frame_sink_id, std::move(receiver), std::move(client));
+      },
       std::move(compositor_frame_sink_receiver),
-      BrowserMainLoop::GetInstance()->GetResizeTaskRunner());
+      std::move(compositor_frame_sink_client));
+
+  if (view_)
+    std::move(callback).Run(view_->GetFrameSinkId());
+  else
+    create_frame_sink_callback_ = std::move(callback);
 }
 
 void RenderWidgetHostImpl::RegisterRenderFrameMetadataObserver(
@@ -2987,38 +2924,6 @@
     view_->SetNeedsBeginFrames(needs_begin_frames_);
 }
 
-void RenderWidgetHostImpl::SetWantsAnimateOnlyBeginFrames() {
-  if (view_)
-    view_->SetWantsAnimateOnlyBeginFrames();
-}
-
-void RenderWidgetHostImpl::SubmitCompositorFrameSync(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list,
-    uint64_t submit_time,
-    const SubmitCompositorFrameSyncCallback callback) {
-  NOTIMPLEMENTED();
-}
-
-void RenderWidgetHostImpl::SubmitCompositorFrame(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list,
-    uint64_t submit_time) {
-  if (view_) {
-    // If Surface Synchronization is on, then |new_content_rendering_timeout_|
-    // is stopped in DidReceiveFirstFrameAfterNavigation.
-    view_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                                 std::move(hit_test_region_list));
-    view_->DidReceiveRendererFrame();
-  } else {
-    std::vector<viz::ReturnedResource> resources =
-        viz::TransferableResource::ReturnResources(frame.resource_list);
-    renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
-  }
-}
-
 void RenderWidgetHostImpl::DidProcessFrame(uint32_t frame_token) {
   frame_token_message_queue_->DidProcessFrame(frame_token);
 }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 15a23f95..03c3f3d 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -11,7 +11,6 @@
 #include <list>
 #include <map>
 #include <memory>
-#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -31,7 +30,6 @@
 #include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
 #include "build/build_config.h"
-#include "components/viz/common/resources/shared_bitmap.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "content/browser/renderer_host/event_with_latency_info.h"
 #include "content/browser/renderer_host/frame_token_message_queue.h"
@@ -85,10 +83,6 @@
 class WebMouseEvent;
 }
 
-namespace cc {
-struct BeginFrameAck;
-}  // namespace cc
-
 namespace gfx {
 class Image;
 class Range;
@@ -99,10 +93,6 @@
 enum class DomCode;
 }
 
-namespace viz {
-class ServerSharedBitmapManager;
-}
-
 namespace content {
 class BrowserAccessibilityManager;
 class FlingSchedulerBase;
@@ -158,7 +148,6 @@
       public RenderProcessHostImpl::PriorityClient,
       public RenderProcessHostObserver,
       public SyntheticGestureController::Delegate,
-      public viz::mojom::CompositorFrameSink,
       public IPC::Listener,
       public RenderFrameMetadataProvider::Observer {
  public:
@@ -678,24 +667,8 @@
 
   bool HasGestureStopped() override;
 
-  // viz::mojom::CompositorFrameSink implementation.
-  void SetNeedsBeginFrame(bool needs_begin_frame) override;
-  void SetWantsAnimateOnlyBeginFrames() override;
-  void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list,
-      uint64_t submit_time) override;
-  void SubmitCompositorFrameSync(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list,
-      uint64_t submit_time,
-      const SubmitCompositorFrameSyncCallback callback) override;
-  void DidNotProduceFrame(const viz::BeginFrameAck& ack) override;
-  void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,
-                               const viz::SharedBitmapId& id) override;
-  void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override;
+  // Begin frames related functionality is only used by Android WebView.
+  void SetNeedsBeginFrame(bool needs_begin_frame);
 
   // Signals that a frame with token |frame_token| was finished processing. If
   // there are any queued messages belonging to it, they will be processed.
@@ -908,7 +881,6 @@
                                    std::vector<IPC::Message> messages);
   void OnForceRedrawComplete(int snapshot_id);
   void OnFirstVisuallyNonEmptyPaint();
-  void OnCommitAndDrawCompositorFrame();
   void OnHasTouchEventHandlers(bool has_handlers);
   void OnIntrinsicSizingInfoChanged(blink::WebIntrinsicSizingInfo info);
   void OnAnimateDoubleTapZoomInMainFrame(const gfx::Point& point,
@@ -1248,19 +1220,12 @@
   mojo::Remote<device::mojom::WakeLock> wake_lock_;
 #endif
 
-  mojo::Receiver<viz::mojom::CompositorFrameSink>
-      compositor_frame_sink_receiver_;
-  mojo::Remote<viz::mojom::CompositorFrameSinkClient>
-      renderer_compositor_frame_sink_;
-
-  // Stash a request to create a CompositorFrameSink if it arrives before
-  // we have a view. This is only used if |enable_viz_| is true.
+  // Stash a request to create a CompositorFrameSink if it arrives before we
+  // have a view.
   base::OnceCallback<void(const viz::FrameSinkId&)> create_frame_sink_callback_;
 
   std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue_;
 
-  bool enable_viz_ = false;
-
   // If the |associated_widget_input_handler_| is set it should always be
   // used to ensure in order delivery of related messages that may occur
   // at the frame input level; see FrameInputHandler. Note that when the
@@ -1274,17 +1239,6 @@
   base::Optional<uint16_t> screen_orientation_angle_for_testing_;
   base::Optional<ScreenOrientationValues> screen_orientation_type_for_testing_;
 
-  // When the viz display compositor is in the browser process, this is used to
-  // register and unregister the bitmaps (stored in |owned_bitmaps_| reported to
-  // this class from the renderer.
-  viz::ServerSharedBitmapManager* shared_bitmap_manager_ = nullptr;
-  // The set of SharedBitmapIds that have been reported as allocated to this
-  // interface. On closing this interface, the display compositor should drop
-  // ownership of the bitmaps with these ids to avoid leaking them. This is only
-  // used when SharedBitmaps are reported to this class because the display
-  // compositor is in the browser process.
-  std::set<viz::SharedBitmapId> owned_bitmaps_;
-
   bool force_enable_zoom_ = false;
 
   RenderFrameMetadataProviderImpl render_frame_metadata_provider_;
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index bf936b09..6b9bfa4b 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -25,8 +25,6 @@
 #include "components/viz/common/surfaces/local_surface_id.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/test/begin_frame_args_test.h"
-#include "components/viz/test/compositor_frame_helpers.h"
-#include "components/viz/test/mock_compositor_frame_sink_client.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/input/mock_input_router.h"
@@ -47,7 +45,6 @@
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/mock_widget_impl.h"
 #include "content/test/mock_widget_input_handler.h"
 #include "content/test/stub_render_widget_host_owner_delegate.h"
@@ -185,10 +182,6 @@
     local_surface_id_allocator_.GenerateId();
   }
 
-  const viz::BeginFrameAck& last_did_not_produce_frame_ack() {
-    return last_did_not_produce_frame_ack_;
-  }
-
   // RenderWidgetHostView override.
   gfx::Rect GetViewBounds() override { return bounds_; }
   const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation()
@@ -218,9 +211,6 @@
       return mock_compositor_viewport_pixel_size_;
     return TestRenderWidgetHostView::GetCompositorViewportPixelSize();
   }
-  void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override {
-    last_did_not_produce_frame_ack_ = ack;
-  }
 
  protected:
   WebMouseWheelEvent unhandled_wheel_event_;
@@ -232,7 +222,6 @@
   bool use_fake_compositor_viewport_pixel_size_;
   gfx::Size mock_compositor_viewport_pixel_size_;
   InputEventAckState ack_result_;
-  viz::BeginFrameAck last_did_not_produce_frame_ack_;
   viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
   ScreenInfo screen_info_;
 
@@ -526,14 +515,6 @@
     host_->Init();
     host_->DisableGestureDebounce();
 
-    mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink;
-    mojo::PendingReceiver<viz::mojom::CompositorFrameSink> sink_receiver =
-        sink.InitWithNewPipeAndPassReceiver();
-    renderer_compositor_frame_sink_ =
-        std::make_unique<FakeRendererCompositorFrameSink>(
-            std::move(sink), renderer_compositor_frame_sink_remote_
-                                 .BindNewPipeAndPassReceiver());
-
     mojo::PendingRemote<mojom::RenderFrameMetadataObserver>
         renderer_render_frame_metadata_observer_remote;
     mojo::PendingRemote<mojom::RenderFrameMetadataObserverClient>
@@ -548,9 +529,6 @@
                 .InitWithNewPipeAndPassReceiver(),
             std::move(render_frame_metadata_observer_remote));
 
-    host_->RequestCompositorFrameSink(
-        std::move(sink_receiver),
-        renderer_compositor_frame_sink_remote_.Unbind());
     host_->RegisterRenderFrameMetadataObserver(
         std::move(render_frame_metadata_observer_client_receiver),
         std::move(renderer_render_frame_metadata_observer_remote));
@@ -745,17 +723,12 @@
   base::TimeTicks last_simulated_event_time_;
   base::TimeDelta simulated_event_time_delta_;
   IPC::TestSink* sink_;
-  std::unique_ptr<FakeRendererCompositorFrameSink>
-      renderer_compositor_frame_sink_;
   std::unique_ptr<FakeRenderFrameMetadataObserver>
       renderer_render_frame_metadata_observer_;
 
  private:
   SyntheticWebTouchEvent touch_event_;
 
-  mojo::Remote<viz::mojom::CompositorFrameSinkClient>
-      renderer_compositor_frame_sink_remote_;
-
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
 };
 
@@ -1734,27 +1707,19 @@
 // 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) {
-  const viz::LocalSurfaceId local_surface_id(1,
-                                             base::UnguessableToken::Create());
+  constexpr uint32_t frame_token = 1;
   std::vector<IPC::Message> messages;
   messages.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
 
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  auto frame = viz::CompositorFrameBuilder()
-                   .AddDefaultRenderPass()
-                   .SetSendFrameTokenToEmbedder(true)
-                   .Build();
-  const uint32_t frame_token = frame.metadata.frame_token;
-
   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());
 
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(1u, host_->processed_frame_messages_count());
 }
@@ -1762,21 +1727,14 @@
 // Check that if a frame arrives earlier than its messages, we process the
 // messages immedtiately.
 TEST_F(RenderWidgetHostTest, FrameToken_FrameThenMessage) {
-  const viz::LocalSurfaceId local_surface_id(1,
-                                             base::UnguessableToken::Create());
+  constexpr uint32_t frame_token = 1;
   std::vector<IPC::Message> messages;
   messages.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
 
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  auto frame = viz::CompositorFrameBuilder()
-                   .AddDefaultRenderPass()
-                   .SetSendFrameTokenToEmbedder(true)
-                   .Build();
-  const uint32_t frame_token = frame.metadata.frame_token;
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
@@ -1789,8 +1747,8 @@
 // Check that if messages of multiple frames arrive before the frames, we
 // process each message once it frame arrives.
 TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
-  const viz::LocalSurfaceId local_surface_id(1,
-                                             base::UnguessableToken::Create());
+  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_DidFirstVisuallyNonEmptyPaint(5));
@@ -1799,17 +1757,6 @@
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  auto frame1 = viz::CompositorFrameBuilder()
-                    .AddDefaultRenderPass()
-                    .SetSendFrameTokenToEmbedder(true)
-                    .Build();
-  const uint32_t frame_token1 = frame1.metadata.frame_token;
-  auto frame2 = viz::CompositorFrameBuilder()
-                    .AddDefaultRenderPass()
-                    .SetSendFrameTokenToEmbedder(true)
-                    .Build();
-  const uint32_t frame_token2 = frame2.metadata.frame_token;
-
   host_->OnMessageReceived(
       WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
   EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
@@ -1820,12 +1767,10 @@
   EXPECT_EQ(2u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame1),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token1);
   EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(1u, host_->processed_frame_messages_count());
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame2),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token2);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(2u, host_->processed_frame_messages_count());
 }
@@ -1833,8 +1778,8 @@
 // Check that if multiple frames arrive before their messages, each message is
 // processed immediately as soon as it arrives.
 TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
-  const viz::LocalSurfaceId local_surface_id(1,
-                                             base::UnguessableToken::Create());
+  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_DidFirstVisuallyNonEmptyPaint(5));
@@ -1843,23 +1788,11 @@
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  auto frame = viz::CompositorFrameBuilder()
-                   .AddDefaultRenderPass()
-                   .SetSendFrameTokenToEmbedder(true)
-                   .Build();
-  const uint32_t frame_token1 = frame.metadata.frame_token;
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token1);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  frame = viz::CompositorFrameBuilder()
-              .AddDefaultRenderPass()
-              .SetSendFrameTokenToEmbedder(true)
-              .Build();
-  const uint32_t frame_token2 = frame.metadata.frame_token;
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token2);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
@@ -1877,9 +1810,8 @@
 // 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) {
-  const uint32_t frame_token1 = 1;
-  const viz::LocalSurfaceId local_surface_id(1,
-                                             base::UnguessableToken::Create());
+  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_DidFirstVisuallyNonEmptyPaint(5));
@@ -1893,18 +1825,12 @@
   EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  auto frame = viz::CompositorFrameBuilder()
-                   .AddDefaultRenderPass()
-                   .SetSendFrameTokenToEmbedder(true)
-                   .Build();
-  const uint32_t frame_token2 = frame.metadata.frame_token;
   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());
 
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token2);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(2u, host_->processed_frame_messages_count());
 }
@@ -1912,30 +1838,19 @@
 // Check that if the renderer crashes, we drop all queued messages and allow
 // smaller frame tokens to be sent by the renderer.
 TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
-  const viz::LocalSurfaceId local_surface_id(1,
-                                             base::UnguessableToken::Create());
+  constexpr uint32_t frame_token1 = 10;
+  constexpr uint32_t frame_token2 = 1;
+  constexpr uint32_t frame_token3 = 1;
+
   std::vector<IPC::Message> messages1;
   std::vector<IPC::Message> messages3;
   messages1.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
   messages3.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(6));
 
-  // Mocking |renderer_compositor_frame_sink_| to prevent crashes in
-  // renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources).
-  std::unique_ptr<viz::MockCompositorFrameSinkClient>
-      mock_compositor_frame_sink_client =
-          std::make_unique<viz::MockCompositorFrameSinkClient>();
-  host_->SetMockRendererCompositorFrameSink(
-      mock_compositor_frame_sink_client.get());
-
   // If we don't do this, then RWHI destroys the view in RendererExited and
   // then a crash occurs when we attempt to destroy it again in TearDown().
   host_->SetView(nullptr);
 
-  auto frame = viz::CompositorFrameBuilder()
-                   .AddDefaultRenderPass()
-                   .SetSendFrameTokenToEmbedder(true)
-                   .Build();
-  const uint32_t frame_token1 = frame.metadata.frame_token;
   host_->OnMessageReceived(
       WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
   EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
@@ -1946,13 +1861,7 @@
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
   host_->Init();
 
-  frame = viz::CompositorFrameBuilder()
-              .AddDefaultRenderPass()
-              .SetSendFrameTokenToEmbedder(true)
-              .Build();
-  const uint32_t frame_token2 = frame.metadata.frame_token;
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token2);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
@@ -1963,16 +1872,11 @@
   host_->Init();
 
   host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token2, messages3));
+      WidgetHostMsg_FrameSwapMessages(0, frame_token3, messages3));
   EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
 
-  frame = viz::CompositorFrameBuilder()
-              .AddDefaultRenderPass()
-              .SetSendFrameTokenToEmbedder(true)
-              .Build();
-  host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                               base::nullopt, 0);
+  view_->OnFrameTokenChanged(frame_token3);
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(1u, host_->processed_frame_messages_count());
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index f32d86f93..0c9b436 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -766,10 +766,6 @@
     ClearBeginFrameRequest(PERSISTENT_BEGIN_FRAME);
 }
 
-void RenderWidgetHostViewAndroid::SetWantsAnimateOnlyBeginFrames() {
-  wants_animate_only_begin_frames_ = true;
-}
-
 viz::FrameSinkId RenderWidgetHostViewAndroid::GetRootFrameSinkId() {
   if (view_.GetWindowAndroid() && view_.GetWindowAndroid()->GetCompositor())
     return view_.GetWindowAndroid()->GetCompositor()->GetFrameSinkId();
@@ -1089,24 +1085,6 @@
   }
 }
 
-void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  NOTREACHED();
-}
-
-void RenderWidgetHostViewAndroid::OnDidNotProduceFrame(
-    const viz::BeginFrameAck& ack) {
-  if (!delegated_frame_host_) {
-    // We are not using the browser compositor and there's no DisplayScheduler
-    // that needs to be notified about the BeginFrameAck, so we can drop it.
-    DCHECK(!using_browser_compositor_);
-    return;
-  }
-  NOTREACHED();
-}
-
 void RenderWidgetHostViewAndroid::ResetFallbackToFirstNavigationSurface() {
   if (delegated_frame_host_)
     delegated_frame_host_->ResetFallbackToFirstNavigationSurface();
@@ -2156,20 +2134,14 @@
 void RenderWidgetHostViewAndroid::OnBeginFrame(
     const viz::BeginFrameArgs& args) {
   TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnBeginFrame");
-  if (!host()) {
-    OnDidNotProduceFrame(viz::BeginFrameAck(
-        args.frame_id.source_id, args.frame_id.sequence_number, false));
+  if (!host())
     return;
-  }
 
   // In sync mode, we disregard missed frame args to ensure that
   // SynchronousCompositorBrowserFilter::SyncStateAfterVSync will be called
   // during WindowAndroid::WindowBeginFrameSource::OnVSync() observer iteration.
-  if (sync_compositor_ && args.type == viz::BeginFrameArgs::MISSED) {
-    OnDidNotProduceFrame(viz::BeginFrameAck(
-        args.frame_id.source_id, args.frame_id.sequence_number, false));
+  if (sync_compositor_ && args.type == viz::BeginFrameArgs::MISSED)
     return;
-  }
 
   bool webview_fling = sync_compositor_ && is_currently_scrolling_viewport_;
   if (!webview_fling) {
@@ -2190,9 +2162,6 @@
       (outstanding_begin_frame_requests_ & PERSISTENT_BEGIN_FRAME)) {
     ClearBeginFrameRequest(BEGIN_FRAME);
     SendBeginFrame(args);
-  } else {
-    OnDidNotProduceFrame(viz::BeginFrameAck(
-        args.frame_id.source_id, args.frame_id.sequence_number, false));
   }
 }
 
@@ -2202,7 +2171,7 @@
 }
 
 bool RenderWidgetHostViewAndroid::WantsAnimateOnlyBeginFrames() const {
-  return wants_animate_only_begin_frames_;
+  return false;
 }
 
 void RenderWidgetHostViewAndroid::SendBeginFramePaused() {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 4c80fbc..8588a114 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -152,11 +152,6 @@
       bool for_root_frame) override;
   bool LockMouse(bool request_unadjusted_movement) override;
   void UnlockMouse() override;
-  void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
-  void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
   void ResetFallbackToFirstNavigationSurface() override;
   bool RequestRepaintForTesting() override;
   void SetIsInVR(bool is_in_vr) override;
@@ -169,7 +164,6 @@
       override;
   void OnDidNavigateMainFrameToNewPage() override;
   void SetNeedsBeginFrames(bool needs_begin_frames) override;
-  void SetWantsAnimateOnlyBeginFrames() override;
   const viz::FrameSinkId& GetFrameSinkId() const override;
   viz::FrameSinkId GetRootFrameSinkId() override;
   viz::SurfaceId GetCurrentSurfaceId() const override;
@@ -472,7 +466,6 @@
   viz::BeginFrameSource* begin_frame_source_;
   viz::BeginFrameArgs last_begin_frame_args_;
   bool begin_frame_paused_ = false;
-  bool wants_animate_only_begin_frames_ = false;
 
   // Indicates whether and for what reason a request for begin frames has been
   // issued. Used to control action dispatch at the next |OnBeginFrame()| call.
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 322ccfe..441803dd 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -866,18 +866,6 @@
 }
 #endif
 
-void RenderWidgetHostViewAura::SubmitCompositorFrame(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  NOTREACHED();
-}
-
-void RenderWidgetHostViewAura::OnDidNotProduceFrame(
-    const viz::BeginFrameAck& ack) {
-  NOTREACHED();
-}
-
 void RenderWidgetHostViewAura::ResetFallbackToFirstNavigationSurface() {
   if (delegated_frame_host_)
     delegated_frame_host_->ResetFallbackToFirstNavigationSurface();
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 17ac9191..45c91f8 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -108,7 +108,6 @@
   gfx::Size GetVisibleViewportSize() override;
   void SetInsets(const gfx::Insets& insets) override;
   void SetNeedsBeginFrames(bool needs_begin_frames) override {}
-  void SetWantsAnimateOnlyBeginFrames() override {}
   TouchSelectionControllerClientManager*
   GetTouchSelectionControllerClientManager() override;
 
@@ -158,11 +157,6 @@
   void UnlockKeyboard() override;
   bool IsKeyboardLocked() override;
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
-  void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
-  void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
   void ResetFallbackToFirstNavigationSurface() override;
   bool RequestRepaintForTesting() override;
   void DidStopFlinging() override;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 764618c9..9afdb76 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -28,17 +28,13 @@
 #include "cc/trees/render_frame_metadata.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
-#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/quads/compositor_frame_metadata.h"
 #include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
-#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/hit_test/hit_test_manager.h"
 #include "components/viz/service/surfaces/surface.h"
 #include "components/viz/test/begin_frame_args_test.h"
-#include "components/viz/test/compositor_frame_helpers.h"
 #include "components/viz/test/fake_external_begin_frame_source.h"
 #include "components/viz/test/fake_surface_observer.h"
 #include "components/viz/test/test_latest_local_surface_id_lookup_delegate.h"
@@ -71,7 +67,6 @@
 #include "content/public/common/context_menu_params.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/mock_render_widget_host_delegate.h"
 #include "content/test/mock_widget_impl.h"
 #include "content/test/test_overscroll_delegate.h"
@@ -293,8 +288,6 @@
 
  private:
   FakeDelegatedFrameHostClientAura* delegated_frame_host_client_;
-  mojo::Remote<viz::mojom::CompositorFrameSinkClient>
-      renderer_compositor_frame_sink_remote_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeRenderWidgetHostViewAura);
 };
@@ -2980,83 +2973,6 @@
   EXPECT_EQ(0, cursor_client.calls_to_set_cursor());
 }
 
-viz::CompositorFrame MakeDelegatedFrame(float scale_factor,
-                                        gfx::Size size,
-                                        gfx::Rect damage) {
-  viz::CompositorFrame frame;
-  frame.metadata.device_scale_factor = scale_factor;
-  frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
-
-  std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create();
-  pass->SetNew(1, gfx::Rect(size), damage, gfx::Transform());
-  frame.render_pass_list.push_back(std::move(pass));
-  if (!size.IsEmpty()) {
-    viz::TransferableResource resource;
-    resource.id = 1;
-    frame.resource_list.push_back(std::move(resource));
-  }
-  return frame;
-}
-
-// Resizing in fullscreen mode should send the up-to-date screen info.
-// http://crbug.com/324350
-TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
-  aura::Window* root_window = aura_test_helper_->root_window();
-  root_window->SetLayoutManager(new FullscreenLayoutManager(root_window));
-  view_->InitAsFullscreen(parent_view_);
-  view_->Show();
-  widget_host_->ResetSentVisualProperties();
-  sink_->ClearMessages();
-
-  // Call SynchronizeVisualProperties to flush the old screen info.
-  view_->GetRenderWidgetHost()->SynchronizeVisualProperties();
-  {
-    // 0 is CreatingNew message.
-    const IPC::Message* msg = sink_->GetMessageAt(0);
-    EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_UpdateVisualProperties::ID),
-              msg->type());
-    WidgetMsg_UpdateVisualProperties::Param params;
-    WidgetMsg_UpdateVisualProperties::Read(msg, &params);
-    EXPECT_EQ(gfx::Rect(800, 600),
-              std::get<0>(params).screen_info.available_rect);
-    EXPECT_EQ(gfx::Size(800, 600), std::get<0>(params).new_size);
-    // Resizes are blocked until we swapped a frame of the correct size, and
-    // we've committed it.
-    view_->SubmitCompositorFrame(
-        kArbitraryLocalSurfaceId,
-        MakeDelegatedFrame(1.f, std::get<0>(params).new_size,
-                           gfx::Rect(std::get<0>(params).new_size)),
-        base::nullopt);
-    ui::DrawWaiterForTest::WaitForCommit(
-        root_window->GetHost()->compositor());
-  }
-
-  widget_host_->ResetSentVisualProperties();
-  sink_->ClearMessages();
-
-  // Make sure the corrent screen size is set along in the resize
-  // request when the screen size has changed.
-  aura_test_helper_->test_screen()->SetUIScale(0.5);
-  ASSERT_EQ(1u, sink_->message_count());
-  {
-    const IPC::Message* msg = sink_->GetMessageAt(0);
-    EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_UpdateVisualProperties::ID),
-              msg->type());
-    WidgetMsg_UpdateVisualProperties::Param params;
-    WidgetMsg_UpdateVisualProperties::Read(msg, &params);
-    EXPECT_EQ(gfx::Rect(1600, 1200),
-              std::get<0>(params).screen_info.available_rect);
-    EXPECT_EQ(gfx::Size(1600, 1200), std::get<0>(params).new_size);
-    view_->SubmitCompositorFrame(
-        kArbitraryLocalSurfaceId,
-        MakeDelegatedFrame(1.f, std::get<0>(params).new_size,
-                           gfx::Rect(std::get<0>(params).new_size)),
-        base::nullopt);
-    ui::DrawWaiterForTest::WaitForCommit(
-        root_window->GetHost()->compositor());
-  }
-}
-
 TEST_F(RenderWidgetHostViewAuraTest, ZeroSizeStillGetsLocalSurfaceId) {
   parent_local_surface_id_allocator_.GenerateId();
   viz::LocalSurfaceId local_surface_id =
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 2dcc608..a662f8b 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -19,7 +19,6 @@
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/surfaces/scoped_surface_id_allocator.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/viz/host/hit_test/hit_test_query.h"
@@ -31,7 +30,6 @@
 #include "content/public/common/input_event_ack_state.h"
 #include "content/public/common/screen_info.h"
 #include "content/public/common/widget_type.h"
-#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
 #include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom.h"
 #include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h"
 #include "third_party/blink/public/platform/web_intrinsic_sizing_info.h"
@@ -48,10 +46,6 @@
 
 struct WidgetHostMsg_SelectionBounds_Params;
 
-namespace cc {
-struct BeginFrameAck;
-}  // namespace cc
-
 namespace blink {
 class WebMouseEvent;
 class WebMouseWheelEvent;
@@ -84,9 +78,6 @@
     : public RenderWidgetHostView,
       public RenderFrameMetadataProvider::Observer {
  public:
-  using CreateCompositorFrameSinkCallback =
-      base::OnceCallback<void(const viz::FrameSinkId&)>;
-
   ~RenderWidgetHostViewBase() override;
 
   float current_device_scale_factor() const {
@@ -273,19 +264,6 @@
   virtual void FocusedNodeChanged(bool is_editable_node,
                                   const gfx::Rect& node_bounds_in_screen) {}
 
-  // This is called by the RenderWidgetHostImpl to provide a new compositor
-  // frame that was received from the renderer process. if Viz service hit
-  // testing is enabled then a HitTestRegionList provides hit test data
-  // that is used for routing input events.
-  // TODO(kenrb): When Viz service is enabled on all platforms,
-  // |hit_test_region_list| should stop being an optional argument.
-  virtual void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list) = 0;
-
-  virtual void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {}
-
   // This method will reset the fallback to the first surface after navigation.
   virtual void ResetFallbackToFirstNavigationSurface() = 0;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index 8c9cd641..0baf858 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -559,18 +559,6 @@
     frame_connector_->FirstSurfaceActivation(surface_info);
 }
 
-void RenderWidgetHostViewChildFrame::SubmitCompositorFrame(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  NOTREACHED();
-}
-
-void RenderWidgetHostViewChildFrame::OnDidNotProduceFrame(
-    const viz::BeginFrameAck& ack) {
-  NOTREACHED();
-}
-
 void RenderWidgetHostViewChildFrame::TransformPointToRootSurface(
     gfx::PointF* point) {
   // This function is called by RenderWidgetHostInputEventRouter only for
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
index b1aed43..103ddb8 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -57,17 +57,6 @@
 
   void SetFrameConnectorDelegate(FrameConnectorDelegate* frame_connector);
 
-  // This functions registers single-use callbacks that want to be notified when
-  // the next frame is swapped. The callback is triggered by
-  // SubmitCompositorFrame, which is the appropriate time to request pixel
-  // readback for the frame that is about to be drawn. Once called, the callback
-  // pointer is released.
-  // TODO(crbug.com/787941): This should be removed because it doesn't work when
-  // VIZ display compositing is enabled. The public CopyFromSurface() API does
-  // not make guarantees that it will succeed before the first frame is
-  // composited.
-  void RegisterFrameSwappedCallback(base::OnceClosure callback);
-
   // TouchSelectionControllerClientManager::Observer implementation.
   void OnManagerWillDestroy(
       TouchSelectionControllerClientManager* manager) override;
@@ -96,7 +85,6 @@
   gfx::NativeViewAccessible GetNativeViewAccessible() override;
   bool IsMouseLocked() override;
   void SetNeedsBeginFrames(bool needs_begin_frames) override {}
-  void SetWantsAnimateOnlyBeginFrames() override {}
   void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
 
   // RenderWidgetHostViewBase implementation.
@@ -113,11 +101,6 @@
   void SetTooltipText(const base::string16& tooltip_text) override;
   void GestureEventAck(const blink::WebGestureEvent& event,
                        InputEventAckState ack_result) override;
-  void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
-  void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
   // Since the URL of content rendered by this class is not displayed in
   // the URL bar, this method does not need an implementation.
   void ResetFallbackToFirstNavigationSurface() override {}
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 7875e19..9dccee3 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/surfaces/surface.h"
 #include "components/viz/service/surfaces/surface_manager.h"
@@ -36,7 +35,6 @@
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/mock_render_widget_host_delegate.h"
 #include "content/test/mock_widget_impl.h"
 #include "content/test/test_render_view_host.h"
@@ -181,19 +179,6 @@
   MockFrameConnectorDelegate* test_frame_connector_;
 };
 
-viz::CompositorFrame CreateDelegatedFrame(float scale_factor,
-                                          gfx::Size size,
-                                          const gfx::Rect& damage) {
-  viz::CompositorFrame frame;
-  frame.metadata.device_scale_factor = scale_factor;
-  frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
-
-  std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create();
-  pass->SetNew(1, gfx::Rect(size), damage, gfx::Transform());
-  frame.render_pass_list.push_back(std::move(pass));
-  return frame;
-}
-
 TEST_F(RenderWidgetHostViewChildFrameTest, VisibilityTest) {
   // Calling show and hide also needs to be propagated to child frame by the
   // |frame_connector_| which itself requires a |frame_proxy_in_parent_renderer|
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 3d5f4a73..b3cf7ca 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -116,7 +116,6 @@
   void SpeakSelection() override;
   void GetScreenInfo(ScreenInfo* screen_info) override;
   void SetNeedsBeginFrames(bool needs_begin_frames) override {}
-  void SetWantsAnimateOnlyBeginFrames() override {}
   void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
 
   // Implementation of RenderWidgetHostViewBase.
@@ -143,11 +142,6 @@
   void EnsureSurfaceSynchronizedForWebTest() override;
   void FocusedNodeChanged(bool is_editable_node,
                           const gfx::Rect& node_bounds_in_screen) override;
-  void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
-  void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
   void ResetFallbackToFirstNavigationSurface() override;
   bool RequestRepaintForTesting() override;
   BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index f1b2251d..e6e26f7 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1051,18 +1051,6 @@
   }
 }
 
-void RenderWidgetHostViewMac::SubmitCompositorFrame(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  NOTREACHED();
-}
-
-void RenderWidgetHostViewMac::OnDidNotProduceFrame(
-    const viz::BeginFrameAck& ack) {
-  NOTREACHED();
-}
-
 void RenderWidgetHostViewMac::ResetFallbackToFirstNavigationSurface() {
   browser_compositor_->GetDelegatedFrameHost()
       ->ResetFallbackToFirstNavigationSurface();
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc
index 5171535..dd2876a 100644
--- a/content/browser/renderer_host/render_widget_targeter.cc
+++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -106,7 +106,7 @@
     const ui::LatencyInfo& latency) {
   this->root_view = std::move(root_view);
   this->location = ComputeEventLocation(event);
-  this->event = ui::WebInputEventTraits::Clone(event);
+  this->event = event.Clone();
   this->latency = latency;
 }
 
diff --git a/content/browser/resources/indexed_db/indexeddb_internals.html b/content/browser/resources/indexed_db/indexeddb_internals.html
index 30e8a96d..22846a8 100644
--- a/content/browser/resources/indexed_db/indexeddb_internals.html
+++ b/content/browser/resources/indexed_db/indexeddb_internals.html
@@ -47,8 +47,6 @@
                        jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Force close</a>
                     <a href="#" class="download"
                        jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Download</a>
-                    <a href="#" class="force-schema-downgrade"
-                       jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Force schema downgrade</a>
                     <a href="https://crbug.com/829141"
                        target="_blank">?</a>
                     <span class="download-status" style="display: none">Loading...</span>
diff --git a/content/browser/resources/indexed_db/indexeddb_internals.js b/content/browser/resources/indexed_db/indexeddb_internals.js
index 98b00975..6fcf000 100644
--- a/content/browser/resources/indexed_db/indexeddb_internals.js
+++ b/content/browser/resources/indexed_db/indexeddb_internals.js
@@ -28,14 +28,6 @@
     return false;
   }
 
-  function forceSchemaDowngrade(event) {
-    const link = event.target;
-    progressNodeFor(link).style.display = 'inline';
-    chrome.send(
-        'forceSchemaDowngrade', [link.idb_partition_path, link.idb_origin_url]);
-    return false;
-  }
-
   function withNode(selector, partition_path, origin_url, callback) {
     const links = document.querySelectorAll(selector);
     for (let i = 0; i < links.length; ++i) {
@@ -66,17 +58,6 @@
     });
   }
 
-  function onForcedSchemaDowngrade(
-      partition_path, origin_url, connection_count) {
-    withNode(
-        'a.force-schema-downgrade', partition_path, origin_url, function(link) {
-          progressNodeFor(link).style.display = 'none';
-        });
-    withNode('.connection-count', partition_path, origin_url, function(span) {
-      span.innerText = connection_count;
-    });
-  }
-
   // Fired from the backend with a single partition's worth of
   // IndexedDB metadata.
   function onOriginsReady(origins, partition_path) {
@@ -95,18 +76,11 @@
     for (let i = 0; i < forceCloseLinks.length; ++i) {
       forceCloseLinks[i].addEventListener('click', forceClose, false);
     }
-    const forceSchemaDowngradeLinks =
-        container.querySelectorAll('a.force-schema-downgrade');
-    for (let i = 0; i < forceSchemaDowngradeLinks.length; ++i) {
-      forceSchemaDowngradeLinks[i].addEventListener(
-          'click', forceSchemaDowngrade, false);
-    }
   }
 
   return {
     initialize: initialize,
     onForcedClose: onForcedClose,
-    onForcedSchemaDowngrade: onForcedSchemaDowngrade,
     onOriginDownloadReady: onOriginDownloadReady,
     onOriginsReady: onOriginsReady,
   };
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 677cd52..764cd1d 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -462,13 +462,15 @@
     const std::string& client_id,
     scoped_refptr<ServiceWorkerVersion> version,
     base::OnceClosure prepare_callback,
-    FetchCallback fetch_callback)
+    FetchCallback fetch_callback,
+    bool is_offline_capability_check)
     : request_(std::move(request)),
       client_id_(client_id),
       version_(std::move(version)),
       resource_type_(resource_type),
       prepare_callback_(std::move(prepare_callback)),
-      fetch_callback_(std::move(fetch_callback)) {
+      fetch_callback_(std::move(fetch_callback)),
+      is_offline_capability_check_(is_offline_capability_check) {
   DCHECK(!request_->blob);
   TRACE_EVENT_WITH_FLOW1(
       "ServiceWorker",
@@ -596,7 +598,18 @@
   auto params = blink::mojom::DispatchFetchEventParams::New();
   params->request = std::move(request_);
   params->client_id = client_id_;
-  params->preload_handle = std::move(preload_handle_);
+  if (is_offline_capability_check_) {
+    // TODO(crbug.com/1031950): We have to set up |preload_handle_| correctly so
+    // that event.preloadResponse is valid one if navigation preload is enabled.
+
+    // At present, an offline-capability-check fetch event is not calling
+    // MayStartNavigationPreload() so |preload_handle_| is null here.
+    DCHECK(!preload_handle_);
+  } else {
+    params->preload_handle = std::move(preload_handle_);
+  }
+  params->is_offline_capability_check = is_offline_capability_check_;
+
   // TODO(https://crbug.com/900700): Make the remote connected to a receiver
   // which is passed to blink::PerformanceResourceTiming.
   params->worker_timing_remote = mojo::NullRemote();
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h
index 551d67b..b5f774e 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -57,7 +57,8 @@
                                const std::string& client_id,
                                scoped_refptr<ServiceWorkerVersion> version,
                                base::OnceClosure prepare_callback,
-                               FetchCallback fetch_callback);
+                               FetchCallback fetch_callback,
+                               bool is_offline_capability_check);
   ~ServiceWorkerFetchDispatcher();
 
   // If appropriate, starts the navigation preload request and creates
@@ -122,6 +123,9 @@
   // service worker along with the fetch event.
   blink::mojom::FetchEventPreloadHandlePtr preload_handle_;
 
+  // Whether to dispatch an offline-capability-check fetch event.
+  const bool is_offline_capability_check_ = false;
+
   base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFetchDispatcher);
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index addf968c..6b1888a 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -170,7 +170,8 @@
                      weak_factory_.GetWeakPtr(), active_worker,
                      active_worker->running_status()),
       base::BindOnce(&ServiceWorkerNavigationLoader::DidDispatchFetchEvent,
-                     weak_factory_.GetWeakPtr()));
+                     weak_factory_.GetWeakPtr()),
+      /*is_offline_capability_check=*/false);
   did_navigation_preload_ = fetch_dispatcher_->MaybeStartNavigationPreload(
       resource_request_, url_loader_factory_getter_.get(), std::move(context),
       container_host_->frame_tree_node_id());
diff --git a/content/browser/service_worker/service_worker_offline_capability_check_browsertest.cc b/content/browser/service_worker/service_worker_offline_capability_check_browsertest.cc
new file mode 100644
index 0000000..0bf613c2
--- /dev/null
+++ b/content/browser/service_worker/service_worker_offline_capability_check_browsertest.cc
@@ -0,0 +1,585 @@
+// Copyright 2019 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 "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/guid.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/test/bind_test_util.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+struct FetchResult {
+  blink::ServiceWorkerStatusCode status;
+  ServiceWorkerFetchDispatcher::FetchEventResult result;
+  blink::mojom::FetchAPIResponsePtr response;
+};
+
+class FetchEventTestHelper {
+ public:
+  struct FetchEventDispatchParam {
+    std::string path;
+    bool is_offline_capability_check;
+  };
+
+  struct ExpectedResult {
+    blink::ServiceWorkerStatusCode status;
+    ServiceWorkerFetchDispatcher::FetchEventResult result;
+    network::mojom::FetchResponseSource response_source;
+    uint16_t response_status_code;
+  };
+
+  struct FetchEventDispatchParamAndExpectedResult {
+    FetchEventDispatchParam param;
+    ExpectedResult expected_result;
+  };
+
+  FetchEventTestHelper(
+      const std::vector<FetchEventDispatchParamAndExpectedResult>&
+          test_inputs) {
+    for (const FetchEventDispatchParamAndExpectedResult&
+             param_and_expected_result : test_inputs) {
+      fetch_event_dispatches_.push_back(
+          FetchEventDispatch{param_and_expected_result, base::nullopt});
+    }
+  }
+
+  void DispatchFetchEventsOnCoreThread(
+      // |done_barrier_closure| is called on the UI thread each time a fetch
+      // event is dispatched.
+      base::RepeatingClosure done_barrier_closure_on_ui,
+      net::EmbeddedTestServer* embedded_test_server,
+      scoped_refptr<ServiceWorkerVersion> version) {
+    ASSERT_TRUE(
+        BrowserThread::CurrentlyOn(ServiceWorkerContext::GetCoreThreadId()));
+    ASSERT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
+
+    for (FetchEventDispatch& fetch_event_dispatch : fetch_event_dispatches_) {
+      FetchOnCoreThread(done_barrier_closure_on_ui, embedded_test_server,
+                        version, &fetch_event_dispatch);
+    }
+  }
+
+  void CheckResult() {
+    for (FetchEventDispatch& dispatch : fetch_event_dispatches_) {
+      ASSERT_FALSE(dispatch.fetch_dispatcher);
+      ExpectedResult& expected =
+          dispatch.param_and_expected_result.expected_result;
+      ASSERT_TRUE(dispatch.fetch_result.has_value());
+      FetchResult& result = *dispatch.fetch_result;
+
+      EXPECT_EQ(expected.status, result.status);
+      EXPECT_EQ(expected.result, result.result);
+      EXPECT_EQ(expected.response_source, result.response->response_source);
+      EXPECT_EQ(expected.response_status_code, result.response->status_code);
+    }
+  }
+
+ private:
+  struct FetchEventDispatch {
+    FetchEventDispatchParamAndExpectedResult param_and_expected_result;
+    base::Optional<FetchResult> fetch_result;
+    std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher;
+  };
+
+  void FetchCallbackOnCoreThread(
+      base::RepeatingClosure done_barrier_closure_on_ui,
+      FetchEventDispatch* fetch_event_dispatch,
+      blink::ServiceWorkerStatusCode actual_status,
+      ServiceWorkerFetchDispatcher::FetchEventResult actual_result,
+      blink::mojom::FetchAPIResponsePtr actual_response,
+      blink::mojom::ServiceWorkerStreamHandlePtr /* stream */,
+      blink::mojom::ServiceWorkerFetchEventTimingPtr /* timing */,
+      scoped_refptr<ServiceWorkerVersion> /* worker */) {
+    ASSERT_TRUE(
+        BrowserThread::CurrentlyOn(ServiceWorkerContext::GetCoreThreadId()));
+    ASSERT_FALSE(fetch_event_dispatch->fetch_result.has_value());
+    fetch_event_dispatch->fetch_result = FetchResult{
+        actual_status,
+        std::move(actual_result),
+        std::move(actual_response),
+    };
+
+    // FetchEventDispatch's |fetch_dispatcher| should be released on
+    // the core thread.  If we don't release |fetch_dispatcher|
+    // here, |fetch_dispatcher| would be wrongly released at the
+    // FetchEventTestHelper's destructor on the UI thread, which
+    // would cause a decrement of a ref count on the wrong thread.
+    fetch_event_dispatch->fetch_dispatcher.reset();
+    RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI,
+                          std::move(done_barrier_closure_on_ui));
+  }
+
+  void FetchOnCoreThread(base::RepeatingClosure done_barrier_closure_on_ui,
+                         net::EmbeddedTestServer* embedded_test_server,
+                         scoped_refptr<ServiceWorkerVersion> version,
+                         FetchEventDispatch* fetch_event_dispatch) {
+    ASSERT_TRUE(
+        BrowserThread::CurrentlyOn(ServiceWorkerContext::GetCoreThreadId()));
+
+    ServiceWorkerFetchDispatcher::FetchCallback fetch_callback =
+        base::BindOnce(&FetchEventTestHelper::FetchCallbackOnCoreThread,
+                       base::Unretained(this), done_barrier_closure_on_ui,
+                       fetch_event_dispatch);
+
+    auto request = blink::mojom::FetchAPIRequest::New();
+    request->url = embedded_test_server->GetURL(
+        fetch_event_dispatch->param_and_expected_result.param.path);
+    request->method = "GET";
+    request->is_main_resource_load = true;
+
+    fetch_event_dispatch->fetch_dispatcher =
+        std::make_unique<ServiceWorkerFetchDispatcher>(
+            std::move(request), ResourceType::kMainFrame,
+            base::GenerateGUID() /* client_id */, std::move(version),
+            base::DoNothing() /* prepare callback */, std::move(fetch_callback),
+            fetch_event_dispatch->param_and_expected_result.param
+                .is_offline_capability_check);
+    fetch_event_dispatch->fetch_dispatcher->Run();
+  }
+
+  std::vector<FetchEventDispatch> fetch_event_dispatches_;
+};
+
+void RunOnCoreThread(base::OnceClosure closure) {
+  base::RunLoop run_loop;
+  RunOrPostTaskOnThread(FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
+                        base::BindLambdaForTesting([&]() {
+                          std::move(closure).Run();
+                          run_loop.Quit();
+                        }));
+  run_loop.Run();
+}
+
+}  // namespace
+
+class ServiceWorkerOfflineCapabilityCheckBrowserTest
+    : public ContentBrowserTest {
+ public:
+  ServiceWorkerOfflineCapabilityCheckBrowserTest() = default;
+
+  ServiceWorkerOfflineCapabilityCheckBrowserTest(
+      const ServiceWorkerOfflineCapabilityCheckBrowserTest&) = delete;
+  ServiceWorkerOfflineCapabilityCheckBrowserTest& operator=(
+      const ServiceWorkerOfflineCapabilityCheckBrowserTest&) = delete;
+
+  void SetUp() override { ContentBrowserTest::SetUp(); }
+
+  void TearDownOnMainThread() override {
+    RunOnCoreThread(base::BindOnce(
+        &ServiceWorkerOfflineCapabilityCheckBrowserTest::TearDownOnCoreThread,
+        base::Unretained(this)));
+  }
+
+  void TearDownOnCoreThread() {
+    // |version_| must be released on the core thread.
+    DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+    version_ = nullptr;
+  }
+
+  void SetUpOnMainThread() override {
+    ASSERT_TRUE(embedded_test_server()->Start());
+
+    StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
+        shell()->web_contents()->GetBrowserContext());
+    wrapper_ = static_cast<ServiceWorkerContextWrapper*>(
+        partition->GetServiceWorkerContext());
+  }
+
+  ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
+
+  void SetupFetchEventDispatchTargetVersion() {
+    DCHECK(!version_);
+    base::RunLoop run_loop;
+    RunOrPostTaskOnThread(
+        FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
+        base::BindOnce(&ServiceWorkerOfflineCapabilityCheckBrowserTest::
+                           SetupFetchEventDispatchTargetVersionOnCoreThread,
+                       base::Unretained(this), run_loop.QuitClosure()));
+    run_loop.Run();
+    DCHECK(version_);
+  }
+
+  void SetupFetchEventDispatchTargetVersionOnCoreThread(
+      base::OnceClosure done) {
+    DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+    wrapper()->context()->storage()->FindRegistrationForScope(
+        embedded_test_server()->GetURL("/service_worker/"),
+        base::BindOnce(&ServiceWorkerOfflineCapabilityCheckBrowserTest::
+                           DidFindRegistration,
+                       base::Unretained(this), std::move(done)));
+  }
+
+  void DidFindRegistration(
+      base::OnceClosure done,
+      blink::ServiceWorkerStatusCode status,
+      scoped_refptr<ServiceWorkerRegistration> registration) {
+    DCHECK_EQ(status, blink::ServiceWorkerStatusCode::kOk);
+    DCHECK(!registration->waiting_version());
+    version_ = registration->active_version();
+    std::move(done).Run();
+  }
+
+  void RunFetchEventDispatchTest(
+      std::vector<
+          FetchEventTestHelper::FetchEventDispatchParamAndExpectedResult>
+          fetch_event_dispatches) {
+    base::RunLoop fetch_run_loop;
+
+    // Use BarrierClosure to wait for all fetch event dispatches to finish.
+    auto barrier_closure = base::BarrierClosure(fetch_event_dispatches.size(),
+                                                fetch_run_loop.QuitClosure());
+
+    FetchEventTestHelper test_helper(fetch_event_dispatches);
+    RunOrPostTaskOnThread(
+        FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
+        base::BindLambdaForTesting([&]() {
+          test_helper.DispatchFetchEventsOnCoreThread(
+              barrier_closure, embedded_test_server(),
+              // |version_| must be accessed from the core thread
+              version_);
+        }));
+    fetch_run_loop.Run();
+    test_helper.CheckResult();
+  }
+
+ protected:
+  // Expected results which are used in the tests.
+  const FetchEventTestHelper::ExpectedResult kNetworkCompleted =
+      FetchEventTestHelper::ExpectedResult{
+          blink::ServiceWorkerStatusCode::kOk,
+          ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
+          network::mojom::FetchResponseSource::kNetwork,
+          200,
+      };
+
+  const FetchEventTestHelper::ExpectedResult kOfflineCompleted =
+      FetchEventTestHelper::ExpectedResult{
+          blink::ServiceWorkerStatusCode::kOk,
+          ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
+          network::mojom::FetchResponseSource::kUnspecified,
+          200,
+      };
+
+  const FetchEventTestHelper::ExpectedResult kFailed =
+      FetchEventTestHelper::ExpectedResult{
+          blink::ServiceWorkerStatusCode::kOk,
+          ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
+          network::mojom::FetchResponseSource::kUnspecified,
+          0,
+      };
+
+  const FetchEventTestHelper::ExpectedResult kNotFound =
+      FetchEventTestHelper::ExpectedResult{
+          blink::ServiceWorkerStatusCode::kOk,
+          ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
+          network::mojom::FetchResponseSource::kNetwork,
+          404,
+      };
+
+  const FetchEventTestHelper::ExpectedResult kShouldFallback =
+      FetchEventTestHelper::ExpectedResult{
+          blink::ServiceWorkerStatusCode::kOk,
+          ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback,
+          network::mojom::FetchResponseSource::kUnspecified,
+          0,
+      };
+
+ private:
+  scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
+  scoped_refptr<ServiceWorkerVersion> version_;
+};
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerOfflineCapabilityCheckBrowserTest,
+                       DispatchOfflineCapabilityCheckFetchEvent) {
+  ASSERT_TRUE(NavigateToURL(shell(),
+                            embedded_test_server()->GetURL(
+                                "/service_worker/create_service_worker.html")));
+  EXPECT_EQ("DONE", EvalJs(shell(), "register('maybe_offline_support.js');"));
+  SetupFetchEventDispatchTargetVersion();
+
+  // For a better readability in this test.
+  bool normal = false;
+  bool is_offline_capability_check = true;
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html",
+          normal,
+      },
+      kShouldFallback,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html",
+          is_offline_capability_check,
+      },
+      kShouldFallback,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?fetch",
+          normal,
+      },
+      kNetworkCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?fetch",
+          is_offline_capability_check,
+      },
+      kFailed,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/not-found.html?fetch",
+          normal,
+      },
+      kNotFound,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/not-found.html?fetch",
+          is_offline_capability_check,
+      },
+      kFailed,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?offline",
+          normal,
+      },
+      kOfflineCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?offline",
+          is_offline_capability_check,
+      },
+      kOfflineCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?fetch_or_offline",
+          normal,
+      },
+      kNetworkCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?fetch_or_offline",
+          is_offline_capability_check,
+      },
+      kOfflineCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?sleep_then_offline",
+          normal,
+      },
+      kOfflineCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?sleep_then_offline",
+          is_offline_capability_check,
+      },
+      kOfflineCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?sleep_then_fetch",
+          normal,
+      },
+      kNetworkCompleted,
+  }});
+
+  RunFetchEventDispatchTest({{
+      {
+          "/service_worker/empty.html?sleep_then_fetch",
+          is_offline_capability_check,
+      },
+      kFailed,
+  }});
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerOfflineCapabilityCheckBrowserTest,
+                       DispatchOfflineCapabilityCheckFetchEventMoreThanOnce) {
+  EXPECT_TRUE(NavigateToURL(shell(),
+                            embedded_test_server()->GetURL(
+                                "/service_worker/create_service_worker.html")));
+  EXPECT_EQ("DONE", EvalJs(shell(), "register('maybe_offline_support.js');"));
+  SetupFetchEventDispatchTargetVersion();
+
+  // For a better readability in this test.
+  bool normal = false;
+  bool is_offline_capability_check = true;
+
+  // 1. normal -> 2. normal test case.
+  RunFetchEventDispatchTest({{
+                                 {
+                                     "/service_worker/empty.html?fetch",
+                                     normal,
+                                 },
+                                 kNetworkCompleted,
+                             },
+                             {
+                                 {
+                                     "/service_worker/empty.html?fetch",
+                                     normal,
+                                 },
+                                 kNetworkCompleted,
+                             }});
+
+  // // 1. offline -> 2. normal test cases.
+  RunFetchEventDispatchTest({{
+                                 {
+                                     "/service_worker/empty.html?fetch",
+                                     is_offline_capability_check,
+                                 },
+                                 kFailed,
+                             },
+                             {
+                                 {
+                                     "/service_worker/empty.html?fetch",
+                                     normal,
+                                 },
+                                 kNetworkCompleted,
+                             }});
+
+  // TODO(hayato): Find a reliable way to control the order of
+  // the execution. Currently, maybe_support_offline.js uses setTimeout so that
+  // 1st fetch event is still running when 2nd fetch event comes.
+  RunFetchEventDispatchTest(
+      {{
+           {
+               "/service_worker/empty.html?sleep_then_fetch",
+               is_offline_capability_check,
+           },
+           kFailed,
+       },
+       {
+           {
+               "/service_worker/empty.html?fetch",
+               normal,
+           },
+           // This fetch event should be enqueued before 1st fetch event
+           // finishes.
+           kNetworkCompleted,
+       }});
+
+  // 1. normal -> 2. offline test cases.
+  RunFetchEventDispatchTest({{
+                                 {
+                                     "/service_worker/empty.html?fetch",
+                                     normal,
+                                 },
+                                 kNetworkCompleted,
+                             },
+                             {
+                                 {
+                                     "/service_worker/empty.html?fetch",
+                                     is_offline_capability_check,
+                                 },
+                                 kFailed,
+                             }});
+
+  RunFetchEventDispatchTest(
+      {{
+           {
+               "/service_worker/empty.html?sleep_then_fetch",
+               normal,
+           },
+           kNetworkCompleted,
+       },
+       {
+           {
+               "/service_worker/empty.html?fetch",
+               is_offline_capability_check,
+           },
+           kFailed,
+       }});
+
+  // 1. offline -> 2. offline test cases
+  RunFetchEventDispatchTest({{
+                                 {
+                                     "/service_worker/empty.html?offline",
+                                     is_offline_capability_check,
+                                 },
+                                 kOfflineCompleted,
+                             },
+                             {
+                                 {
+                                     "/service_worker/empty.html?offline",
+                                     is_offline_capability_check,
+                                 },
+                                 kOfflineCompleted,
+                             }});
+
+  RunFetchEventDispatchTest(
+      {{
+           {
+               "/service_worker/empty.html?sleep_then_offline",
+               is_offline_capability_check,
+           },
+           kOfflineCompleted,
+       },
+       {{
+            "/service_worker/empty.html?offline",
+            is_offline_capability_check,
+        },
+        kOfflineCompleted}});
+
+  // 1. normal -> 2. offline -> 3. normal
+  RunFetchEventDispatchTest(
+      {{
+           {"/service_worker/empty.html?sleep_then_fetch", normal},
+           kNetworkCompleted,
+       },
+       {
+           {
+               "/service_worker/empty.html?sleep_then_fetch",
+               is_offline_capability_check,
+           },
+           kFailed,
+       },
+       {{
+            "/service_worker/empty.html?fetch",
+            normal,
+        },
+        kNetworkCompleted}});
+}
+
+}  // namespace content
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index 073f003a..405ecad 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -880,7 +880,8 @@
 
     if (registration()->newest_installed_version()) {
       context_->storage()->UpdateLastUpdateCheckTime(
-          registration(),
+          registration()->id(), registration()->scope().GetOrigin(),
+          registration()->last_update_check(),
           base::BindOnce([](blink::ServiceWorkerStatusCode status) {
             // Ignore errors; bumping the update check time is just best-effort.
           }));
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index b4b875c..7dcda4aa 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -637,7 +637,8 @@
   // "Run the Update State algorithm passing registration's active worker and
   // 'activated' as the arguments."
   activating_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
-  context_->storage()->UpdateToActiveState(this, base::DoNothing());
+  context_->storage()->UpdateToActiveState(id(), scope().GetOrigin(),
+                                           base::DoNothing());
 }
 
 void ServiceWorkerRegistration::OnDeleteFinished(
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index a6d63f0..f2cc310 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -476,11 +476,9 @@
                                     std::move(callback), data)));
 }
 
-void ServiceWorkerStorage::UpdateToActiveState(
-    ServiceWorkerRegistration* registration,
-    StatusCallback callback) {
-  DCHECK(registration);
-
+void ServiceWorkerStorage::UpdateToActiveState(int64_t registration_id,
+                                               const GURL& origin,
+                                               StatusCallback callback) {
   DCHECK(state_ == STORAGE_STATE_INITIALIZED ||
          state_ == STORAGE_STATE_DISABLED)
       << state_;
@@ -494,16 +492,17 @@
   base::PostTaskAndReplyWithResult(
       database_task_runner_.get(), FROM_HERE,
       base::BindOnce(&ServiceWorkerDatabase::UpdateVersionToActive,
-                     base::Unretained(database_.get()), registration->id(),
-                     registration->scope().GetOrigin()),
+                     base::Unretained(database_.get()), registration_id,
+                     origin),
       base::BindOnce(&ServiceWorkerStorage::DidUpdateToActiveState,
                      weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
-    ServiceWorkerRegistration* registration,
+    int64_t registration_id,
+    const GURL& origin,
+    base::Time last_update_check_time,
     StatusCallback callback) {
-  DCHECK(registration);
   DCHECK(state_ == STORAGE_STATE_INITIALIZED ||
          state_ == STORAGE_STATE_DISABLED)
       << state_;
@@ -517,9 +516,8 @@
   base::PostTaskAndReplyWithResult(
       database_task_runner_.get(), FROM_HERE,
       base::BindOnce(&ServiceWorkerDatabase::UpdateLastCheckTime,
-                     base::Unretained(database_.get()), registration->id(),
-                     registration->scope().GetOrigin(),
-                     registration->last_update_check()),
+                     base::Unretained(database_.get()), registration_id, origin,
+                     last_update_check_time),
       base::BindOnce(
           [](StatusCallback callback, ServiceWorkerDatabase::Status status) {
             std::move(callback).Run(DatabaseStatusToStatusCode(status));
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index 7e965b1..efc79cf 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -147,12 +147,15 @@
                          StatusCallback callback);
 
   // Updates the state of the registration's stored version to active.
-  void UpdateToActiveState(ServiceWorkerRegistration* registration,
+  void UpdateToActiveState(int64_t registration_id,
+                           const GURL& origin,
                            StatusCallback callback);
 
   // Updates the stored time to match the value of
   // registration->last_update_check().
-  void UpdateLastUpdateCheckTime(ServiceWorkerRegistration* registration,
+  void UpdateLastUpdateCheckTime(int64_t registration_id,
+                                 const GURL& origin,
+                                 base::Time last_update_check_time,
                                  StatusCallback callback);
 
   // Updates the specified registration's navigation preload state in storage.
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc
index 6e6e4cc..e8ff91c5 100644
--- a/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -453,7 +453,7 @@
     base::RunLoop loop;
     base::Optional<blink::ServiceWorkerStatusCode> result;
     storage()->UpdateToActiveState(
-        registration.get(),
+        registration->id(), registration->scope().GetOrigin(),
         base::BindOnce(&StatusCallback, loop.QuitClosure(), &result));
     EXPECT_FALSE(result.has_value());  // always async
     loop.Run();
@@ -465,7 +465,8 @@
     base::RunLoop loop;
     base::Optional<blink::ServiceWorkerStatusCode> result;
     storage()->UpdateLastUpdateCheckTime(
-        registration.get(),
+        registration->id(), registration->scope().GetOrigin(),
+        registration->last_update_check(),
         base::BindOnce(&StatusCallback, loop.QuitClosure(), &result));
     loop.Run();
     return result.value();
@@ -1403,7 +1404,9 @@
   // Promote the worker to active and add a controllee.
   registration_->SetActiveVersion(registration_->waiting_version());
   registration_->active_version()->SetStatus(ServiceWorkerVersion::ACTIVATED);
-  storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
+  storage()->UpdateToActiveState(registration_->id(),
+                                 registration_->scope().GetOrigin(),
+                                 base::DoNothing());
   ServiceWorkerRemoteProviderEndpoint remote_endpoint;
   base::WeakPtr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
       33 /* dummy render process id */, true /* is_parent_frame_secure */,
@@ -1437,7 +1440,9 @@
   registration_->SetActiveVersion(registration_->waiting_version());
   registration_->active_version()->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration_->SetWaitingVersion(nullptr);
-  storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
+  storage()->UpdateToActiveState(registration_->id(),
+                                 registration_->scope().GetOrigin(),
+                                 base::DoNothing());
   ServiceWorkerRemoteProviderEndpoint remote_endpoint;
   base::WeakPtr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
       33 /* dummy render process id */, true /* is_parent_frame_secure */,
@@ -1570,7 +1575,9 @@
   // Promote the worker to active worker and add a controllee.
   registration_->SetActiveVersion(registration_->waiting_version());
   registration_->active_version()->SetStatus(ServiceWorkerVersion::ACTIVATED);
-  storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
+  storage()->UpdateToActiveState(registration_->id(),
+                                 registration_->scope().GetOrigin(),
+                                 base::DoNothing());
   ServiceWorkerRemoteProviderEndpoint remote_endpoint;
   base::WeakPtr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
       33 /* dummy render process id */, true /* is_parent_frame_secure */,
@@ -1620,7 +1627,9 @@
 TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration_NoLiveVersion) {
   // Promote the worker to active worker and add a controllee.
   registration_->SetActiveVersion(registration_->waiting_version());
-  storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
+  storage()->UpdateToActiveState(registration_->id(),
+                                 registration_->scope().GetOrigin(),
+                                 base::DoNothing());
 
   // Make an updated registration.
   scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 5263964..74c1215 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -458,7 +458,11 @@
 
   switch (running_status()) {
     case EmbeddedWorkerStatus::STARTING:
-    case EmbeddedWorkerStatus::RUNNING:
+    case EmbeddedWorkerStatus::RUNNING: {
+      // EmbeddedWorkerInstance::Stop() may synchronously call
+      // ServiceWorkerVersion::OnStopped() and destroy |this|. This protection
+      // avoids it.
+      scoped_refptr<ServiceWorkerVersion> protect = this;
       embedded_worker_->Stop();
       if (running_status() == EmbeddedWorkerStatus::STOPPED) {
         RunSoon(std::move(callback));
@@ -466,6 +470,7 @@
       }
       stop_callbacks_.push_back(std::move(callback));
       return;
+    }
     case EmbeddedWorkerStatus::STOPPING:
       stop_callbacks_.push_back(std::move(callback));
       return;
diff --git a/content/browser/service_worker/service_worker_version_browsertest.cc b/content/browser/service_worker/service_worker_version_browsertest.cc
index 42b6e6c..f140770 100644
--- a/content/browser/service_worker/service_worker_version_browsertest.cc
+++ b/content/browser/service_worker/service_worker_version_browsertest.cc
@@ -718,7 +718,8 @@
     request->method = "GET";
     fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
         std::move(request), resource_type, std::string() /* client_id */,
-        version_, std::move(prepare_callback), std::move(fetch_callback));
+        version_, std::move(prepare_callback), std::move(fetch_callback),
+        /*is_offline_cpability_check=*/false);
     fetch_dispatcher_->Run();
   }
 
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 228c8cb..48cb1eb 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -95,7 +95,7 @@
 
   void OnInputEvent(const blink::WebInputEvent& event) override {
     events_received_.push_back(event.GetType());
-    event_ = ui::WebInputEventTraits::Clone(event);
+    event_ = event.Clone();
   }
 
   const std::vector<InputEventAckSource>& events_acked() {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 3eac125..7074ec7 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4637,7 +4637,7 @@
   if (source->did_first_visually_non_empty_paint() &&
       last_sent_theme_color_ != source->theme_color()) {
     for (auto& observer : observers_)
-      observer.DidChangeThemeColor(source->theme_color());
+      observer.DidChangeThemeColor();
     last_sent_theme_color_ = source->theme_color();
   }
 }
@@ -5139,7 +5139,7 @@
   if (source->theme_color() != last_sent_theme_color_) {
     // Theme color should have updated by now if there was one.
     for (auto& observer : observers_)
-      observer.DidChangeThemeColor(source->theme_color());
+      observer.DidChangeThemeColor();
     last_sent_theme_color_ = source->theme_color();
   }
 }
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 2413acc..ef7d790 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -324,9 +324,7 @@
     EXPECT_TRUE(web_contents()->CompletedFirstVisuallyNonEmptyPaint());
   }
 
-  void DidChangeThemeColor(base::Optional<SkColor> theme_color) override {
-    last_theme_color_ = theme_color;
-  }
+  void DidChangeThemeColor() override { ++theme_color_change_calls_; }
 
   void DidChangeVerticalScrollDirection(
       viz::VerticalScrollDirection scroll_direction) override {
@@ -340,7 +338,7 @@
   }
 
   const GURL& last_url() const { return last_url_; }
-  base::Optional<SkColor> last_theme_color() const { return last_theme_color_; }
+  int theme_color_change_calls() const { return theme_color_change_calls_; }
   base::Optional<viz::VerticalScrollDirection> last_vertical_scroll_direction()
       const {
     return last_vertical_scroll_direction_;
@@ -357,7 +355,7 @@
 
  private:
   GURL last_url_;
-  base::Optional<SkColor> last_theme_color_;
+  int theme_color_change_calls_ = 0;
   base::Optional<viz::VerticalScrollDirection> last_vertical_scroll_direction_;
   bool observed_did_first_visually_non_empty_paint_ = false;
   int num_is_connected_to_bluetooth_device_changed_ = 0;
@@ -3359,27 +3357,27 @@
   rfh->InitializeRenderFrameIfNeeded();
 
   EXPECT_EQ(base::nullopt, contents()->GetThemeColor());
-  EXPECT_EQ(base::nullopt, observer.last_theme_color());
+  EXPECT_EQ(0, observer.theme_color_change_calls());
 
   // Theme color changes should not propagate past the WebContentsImpl before
   // the first visually non-empty paint has occurred.
   rfh->DidChangeThemeColor(SK_ColorRED);
 
   EXPECT_EQ(SK_ColorRED, contents()->GetThemeColor());
-  EXPECT_EQ(base::nullopt, observer.last_theme_color());
+  EXPECT_EQ(0, observer.theme_color_change_calls());
 
   // Simulate that the first visually non-empty paint has occurred. This will
   // propagate the current theme color to the delegates.
   RenderViewHostTester::SimulateFirstPaint(test_rvh());
 
   EXPECT_EQ(SK_ColorRED, contents()->GetThemeColor());
-  EXPECT_EQ(SK_ColorRED, observer.last_theme_color());
+  EXPECT_EQ(1, observer.theme_color_change_calls());
 
   // Additional changes made by the web contents should propagate as well.
   rfh->DidChangeThemeColor(SK_ColorGREEN);
 
   EXPECT_EQ(SK_ColorGREEN, contents()->GetThemeColor());
-  EXPECT_EQ(SK_ColorGREEN, observer.last_theme_color());
+  EXPECT_EQ(2, observer.theme_color_change_calls());
 }
 
 TEST_F(WebContentsImplTest, ParseDownloadHeaders) {
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index ac8c4e2..e8b431a 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -3162,7 +3162,7 @@
         FROM_HERE, base::BindOnce(std::move(provide_pin_cb), std::move(pin)));
   }
 
-  void FinishCollectPIN() override {}
+  void FinishCollectToken() override {}
 
   bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
     *failure_reason_ = reason;
@@ -3230,21 +3230,22 @@
         // No support.
         config.pin_support = false;
         virtual_device_factory_->mutable_state()->pin = "";
-        virtual_device_factory_->mutable_state()->retries = 0;
+        virtual_device_factory_->mutable_state()->pin_retries = 0;
         break;
 
       case 1:
         // PIN supported, but no PIN set.
         config.pin_support = true;
         virtual_device_factory_->mutable_state()->pin = "";
-        virtual_device_factory_->mutable_state()->retries = 0;
+        virtual_device_factory_->mutable_state()->pin_retries = 0;
         break;
 
       case 2:
         // PIN set.
         config.pin_support = true;
         virtual_device_factory_->mutable_state()->pin = kTestPIN;
-        virtual_device_factory_->mutable_state()->retries = 8;
+        virtual_device_factory_->mutable_state()->pin_retries =
+            device::kMaxPinRetries;
         break;
 
       default:
@@ -3374,7 +3375,8 @@
 
 TEST_F(PINAuthenticatorImplTest, MakeCredentialSoftLock) {
   virtual_device_factory_->mutable_state()->pin = kTestPIN;
-  virtual_device_factory_->mutable_state()->retries = 8;
+  virtual_device_factory_->mutable_state()->pin_retries =
+      device::kMaxPinRetries;
 
   test_client_.expected = {{8, "wrong"}, {7, "wrong"}, {6, "wrong"}};
   mojo::Remote<blink::mojom::Authenticator> authenticator =
@@ -3384,7 +3386,7 @@
                                 callback_receiver.callback());
   callback_receiver.WaitForCallback();
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->retries);
+  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->pin_retries);
   EXPECT_TRUE(virtual_device_factory_->mutable_state()->soft_locked);
   ASSERT_TRUE(test_client_.failure_reason.has_value());
   EXPECT_EQ(InterestingFailureReason::kSoftPINBlock,
@@ -3393,7 +3395,7 @@
 
 TEST_F(PINAuthenticatorImplTest, MakeCredentialHardLock) {
   virtual_device_factory_->mutable_state()->pin = kTestPIN;
-  virtual_device_factory_->mutable_state()->retries = 1;
+  virtual_device_factory_->mutable_state()->pin_retries = 1;
 
   test_client_.expected = {{1, "wrong"}};
   mojo::Remote<blink::mojom::Authenticator> authenticator =
@@ -3403,7 +3405,7 @@
                                 callback_receiver.callback());
   callback_receiver.WaitForCallback();
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-  EXPECT_EQ(0, virtual_device_factory_->mutable_state()->retries);
+  EXPECT_EQ(0, virtual_device_factory_->mutable_state()->pin_retries);
   ASSERT_TRUE(test_client_.failure_reason.has_value());
   EXPECT_EQ(InterestingFailureReason::kHardPINBlock,
             *test_client_.failure_reason);
@@ -3500,7 +3502,8 @@
 
 TEST_F(PINAuthenticatorImplTest, GetAssertionSoftLock) {
   virtual_device_factory_->mutable_state()->pin = kTestPIN;
-  virtual_device_factory_->mutable_state()->retries = 8;
+  virtual_device_factory_->mutable_state()->pin_retries =
+      device::kMaxPinRetries;
 
   PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
   ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
@@ -3513,7 +3516,7 @@
   authenticator->GetAssertion(std::move(options), callback_receiver.callback());
   callback_receiver.WaitForCallback();
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->retries);
+  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->pin_retries);
   EXPECT_TRUE(virtual_device_factory_->mutable_state()->soft_locked);
   ASSERT_TRUE(test_client_.failure_reason.has_value());
   EXPECT_EQ(InterestingFailureReason::kSoftPINBlock,
@@ -3522,7 +3525,7 @@
 
 TEST_F(PINAuthenticatorImplTest, GetAssertionHardLock) {
   virtual_device_factory_->mutable_state()->pin = kTestPIN;
-  virtual_device_factory_->mutable_state()->retries = 1;
+  virtual_device_factory_->mutable_state()->pin_retries = 1;
 
   PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
   ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
@@ -3535,7 +3538,7 @@
   authenticator->GetAssertion(std::move(options), callback_receiver.callback());
   callback_receiver.WaitForCallback();
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-  EXPECT_EQ(0, virtual_device_factory_->mutable_state()->retries);
+  EXPECT_EQ(0, virtual_device_factory_->mutable_state()->pin_retries);
   ASSERT_TRUE(test_client_.failure_reason.has_value());
   EXPECT_EQ(InterestingFailureReason::kHardPINBlock,
             *test_client_.failure_reason);
@@ -3698,6 +3701,117 @@
   }
 }
 
+class UVTokenTestAuthenticatorClientDelegate
+    : public AuthenticatorRequestClientDelegate {
+ public:
+  void FinishCollectToken() override {}
+};
+
+class UVTokenTestAuthenticatorContentBrowserClient
+    : public ContentBrowserClient {
+ public:
+  std::unique_ptr<AuthenticatorRequestClientDelegate>
+  GetWebAuthenticationRequestDelegate(
+      RenderFrameHost* render_frame_host,
+      const std::string& relying_party_id) override {
+    return std::make_unique<UVTokenTestAuthenticatorClientDelegate>();
+  }
+};
+
+class UVTokenAuthenticatorImplTest : public UVAuthenticatorImplTest {
+ public:
+  UVTokenAuthenticatorImplTest() = default;
+  UVTokenAuthenticatorImplTest(const UVTokenAuthenticatorImplTest&) = delete;
+
+  void SetUp() override {
+    UVAuthenticatorImplTest::SetUp();
+    old_client_ = SetBrowserClientForTesting(&test_client_);
+    device::VirtualCtap2Device::Config config;
+    config.internal_uv_support = true;
+    config.uv_token_support = true;
+    virtual_device_factory_->SetCtap2Config(config);
+    NavigateAndCommit(GURL(kTestOrigin1));
+  }
+
+  void TearDown() override {
+    SetBrowserClientForTesting(old_client_);
+    AuthenticatorImplTest::TearDown();
+  }
+
+ protected:
+  UVTokenTestAuthenticatorContentBrowserClient test_client_;
+
+ private:
+  ContentBrowserClient* old_client_ = nullptr;
+};
+
+TEST_F(UVTokenAuthenticatorImplTest, GetAssertionUVToken) {
+  mojo::Remote<blink::mojom::Authenticator> authenticator =
+      ConnectToAuthenticator();
+  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
+      get_credential_options()->allow_credentials[0].id(),
+      kTestRelyingPartyId));
+
+  for (const auto fingerprints_enrolled : {false, true}) {
+    SCOPED_TRACE(::testing::Message()
+                 << "fingerprints_enrolled=" << fingerprints_enrolled);
+    virtual_device_factory_->mutable_state()->fingerprints_enrolled =
+        fingerprints_enrolled;
+
+    for (auto uv : {device::UserVerificationRequirement::kDiscouraged,
+                    device::UserVerificationRequirement::kPreferred,
+                    device::UserVerificationRequirement::kRequired}) {
+      SCOPED_TRACE(UVToString(uv));
+
+      auto options = get_credential_options(uv);
+      // Without a fingerprint enrolled we assume that a UV=required request
+      // cannot be satisfied by an authenticator that cannot do UV. It is
+      // possible for a credential to be created without UV and then later
+      // asserted with UV=required, but that would be bizarre behaviour from
+      // an RP and we currently don't worry about it.
+      const bool should_be_unrecognized =
+          !fingerprints_enrolled &&
+          uv == device::UserVerificationRequirement::kRequired;
+
+      TestGetAssertionCallback callback_receiver;
+      authenticator->GetAssertion(std::move(options),
+                                  callback_receiver.callback());
+      callback_receiver.WaitForCallback();
+
+      if (should_be_unrecognized) {
+        EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
+                  callback_receiver.status());
+      } else {
+        EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+        EXPECT_EQ(fingerprints_enrolled &&
+                      uv != device::UserVerificationRequirement::kDiscouraged,
+                  HasUV(callback_receiver));
+      }
+    }
+  }
+}
+
+TEST_F(UVTokenAuthenticatorImplTest, UvTokenRequestUvFails) {
+  mojo::Remote<blink::mojom::Authenticator> authenticator =
+      ConnectToAuthenticator();
+  device::VirtualCtap2Device::Config config;
+  config.internal_uv_support = true;
+  config.uv_token_support = true;
+  config.user_verification_succeeds = false;
+  virtual_device_factory_->SetCtap2Config(config);
+  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
+  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
+      get_credential_options()->allow_credentials[0].id(),
+      kTestRelyingPartyId));
+
+  auto options = get_credential_options();
+  TestGetAssertionCallback callback_receiver;
+  authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+  callback_receiver.WaitForCallback();
+
+  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+}
+
 // ResidentKeyTestAuthenticatorRequestDelegate is a delegate that:
 //   a) always returns |kTestPIN| when asked for a PIN.
 //   b) sorts potential resident-key accounts by user ID, maps them to a string
@@ -3726,7 +3840,7 @@
         FROM_HERE, base::BindOnce(std::move(provide_pin_cb), kTestPIN));
   }
 
-  void FinishCollectPIN() override {}
+  void FinishCollectToken() override {}
 
   bool SupportsResidentKeys() override { return true; }
 
@@ -3812,7 +3926,8 @@
     config.resident_key_support = true;
     virtual_device_factory_->SetCtap2Config(config);
     virtual_device_factory_->mutable_state()->pin = kTestPIN;
-    virtual_device_factory_->mutable_state()->retries = 8;
+    virtual_device_factory_->mutable_state()->pin_retries =
+        device::kMaxPinRetries;
     NavigateAndCommit(GURL(kTestOrigin1));
   }
 
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc
index 64bdcea..69fe841b 100644
--- a/content/browser/webui/shared_resources_data_source.cc
+++ b/content/browser/webui/shared_resources_data_source.cc
@@ -127,6 +127,10 @@
          "mojo/mojo/public/mojom/base/string16.mojom.html"},
         {IDR_MOJO_STRING16_MOJOM_LITE_JS,
          "mojo/mojo/public/mojom/base/string16.mojom-lite.js"},
+        {IDR_MOJO_TEXT_DIRECTION_MOJOM_HTML,
+         "mojo/mojo/public/mojom/base/text_direction.mojom.html"},
+        {IDR_MOJO_TEXT_DIRECTION_MOJOM_LITE_JS,
+         "mojo/mojo/public/mojom/base/text_direction.mojom-lite.js"},
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
         {IDR_MOJO_TIME_MOJOM_HTML,
          "mojo/mojo/public/mojom/base/time.mojom.html"},
diff --git a/content/common/input/event_with_latency_info.h b/content/common/input/event_with_latency_info.h
index e61aa65..58e8b8ca 100644
--- a/content/common/input/event_with_latency_info.h
+++ b/content/common/input/event_with_latency_info.h
@@ -41,9 +41,6 @@
     if (other.event.GetType() != event.GetType())
       return false;
 
-    DCHECK_EQ(sizeof(T), event.size());
-    DCHECK_EQ(sizeof(T), other.event.size());
-
     return ui::CanCoalesce(other.event, event);
   }
 
diff --git a/content/common/input/input_event.cc b/content/common/input/input_event.cc
index 5204dde..4e11e69a 100644
--- a/content/common/input/input_event.cc
+++ b/content/common/input/input_event.cc
@@ -16,8 +16,7 @@
 
 InputEvent::InputEvent(const blink::WebInputEvent& web_event,
                        const ui::LatencyInfo& latency_info)
-    : web_event(ui::WebInputEventTraits::Clone(web_event)),
-      latency_info(latency_info) {}
+    : web_event(web_event.Clone()), latency_info(latency_info) {}
 
 InputEvent::~InputEvent() {}
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
index c26722a..b068979 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -43,6 +43,7 @@
 import org.chromium.content_public.browser.AccessibilitySnapshotNode;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsAccessibility;
+import org.chromium.ui.base.WindowAndroid;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -215,6 +216,17 @@
         mCaptioningController.startListening();
     }
 
+    @Override
+    public void onWindowAndroidChanged(WindowAndroid windowAndroid) {
+        // Delete this object when switching between WindowAndroids/Activities.
+        WindowEventObserverManager.from(mWebContents).removeObserver(this);
+        mWebContents.removeUserData(WebContentsAccessibilityImpl.class);
+        if (mNativeObj != 0) {
+            WebContentsAccessibilityImplJni.get().deleteEarly(mNativeObj);
+            assert mNativeObj == 0;
+        }
+    }
+
     /**
      * Refresh a11y state with that of {@link AccessibilityManager}.
      */
@@ -1533,6 +1545,7 @@
     @NativeMethods
     interface Natives {
         long init(WebContentsAccessibilityImpl caller, WebContents webContents);
+        void deleteEarly(long nativeWebContentsAccessibilityAndroid);
         void onAutofillPopupDisplayed(
                 long nativeWebContentsAccessibilityAndroid, WebContentsAccessibilityImpl caller);
         void onAutofillPopupDismissed(
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
index 88f42a3..25cc907 100644
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -17,6 +17,7 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.os.Build;
+import android.os.Handler;
 import android.provider.Browser;
 import android.text.Spanned;
 import android.text.TextUtils;
@@ -110,6 +111,7 @@
                 SelectionPopupControllerImpl::new;
     }
 
+    private final Handler mHandler;
     private Context mContext;
     private WindowAndroid mWindowAndroid;
     private WebContentsImpl mWebContents;
@@ -128,6 +130,8 @@
     // required because ActionMode only exposes a temporary hide routine.
     private Runnable mRepeatingHideRunnable;
 
+    // Can be null temporarily when switching between WindowAndroid.
+    @Nullable
     private View mView;
     private ActionMode mActionMode;
 
@@ -236,6 +240,7 @@
 
     private SelectionPopupControllerImpl(
             WebContents webContents, PopupController popupController, boolean initializeNative) {
+        mHandler = new Handler();
         mWebContents = (WebContentsImpl) webContents;
         mPopupController = popupController;
         mContext = mWebContents.getContext();
@@ -254,7 +259,7 @@
                 assert mHidden;
                 final long hideDuration = getDefaultHideDuration();
                 // Ensure the next hide call occurs before the ActionMode reappears.
-                mView.postDelayed(mRepeatingHideRunnable, hideDuration - 1);
+                mHandler.postDelayed(mRepeatingHideRunnable, hideDuration - 1);
                 hideActionModeTemporarily(hideDuration);
             }
         };
@@ -287,14 +292,12 @@
 
     @Override
     public void onUpdateContainerView(ViewGroup view) {
-        assert view != null;
-
         // Cleans up action mode before switching to a new container view.
         if (isActionModeValid()) finishActionMode();
         mUnselectAllOnDismiss = true;
         destroyPastePopup();
 
-        view.setClickable(true);
+        if (view != null) view.setClickable(true);
         mView = view;
         initHandleObserver();
     }
@@ -411,7 +414,7 @@
      * <p> If the action mode cannot be created the selection is cleared.
      */
     public void showActionModeOrClearOnFailure() {
-        if (!isActionModeSupported() || !hasSelection()) return;
+        if (!isActionModeSupported() || !hasSelection() || mView == null) return;
 
         // Just refresh non-floating action mode if it already exists to avoid blinking.
         if (isActionModeValid() && !isFloatingActionMode()) {
@@ -442,6 +445,7 @@
     }
 
     private ActionMode startFloatingActionMode() {
+        assert mView != null;
         assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
         ActionMode actionMode = ContentApiHelperForM.startActionMode(mView, this, mCallback);
         return actionMode;
@@ -460,7 +464,7 @@
     }
 
     private void createAndShowPastePopup() {
-        if (mView.getParent() == null || mView.getVisibility() != View.VISIBLE) {
+        if (mView == null || mView.getParent() == null || mView.getVisibility() != View.VISIBLE) {
             return;
         }
 
@@ -595,6 +599,7 @@
     @Override
     public void onWindowAndroidChanged(WindowAndroid newWindowAndroid) {
         mWindowAndroid = newWindowAndroid;
+        mContext = mWebContents.getContext();
         initHandleObserver();
         destroyPastePopup();
     }
@@ -653,7 +658,7 @@
         if (mHidden) {
             mRepeatingHideRunnable.run();
         } else {
-            mView.removeCallbacks(mRepeatingHideRunnable);
+            mHandler.removeCallbacks(mRepeatingHideRunnable);
             // To show the action mode that is being hidden call hide() again with a short delay.
             hideActionModeTemporarily(SHOW_DELAY_MS);
         }
@@ -880,6 +885,8 @@
 
     @Override
     public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+        // Actions should only happen when there is a WindowAndroid so mView should not be null.
+        assert mView != null;
         if (!isActionModeValid()) return true;
 
         int id = item.getItemId();
@@ -1001,6 +1008,7 @@
      */
     @VisibleForTesting
     void doAssistAction() {
+        assert mView != null;
         if (mClassificationResult == null || !mClassificationResult.hasNamedAction()) return;
 
         assert mClassificationResult.onClickListener != null
@@ -1379,7 +1387,7 @@
 
     @VisibleForTesting
     /* package */ void performHapticFeedback() {
-        if (BuildInfo.isAtLeastQ()) {
+        if (BuildInfo.isAtLeastQ() && mView != null) {
             mView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE);
         }
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index 579d34b..be6087b28 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -922,6 +922,12 @@
         return key.cast(data);
     }
 
+    public <T extends UserData> void removeUserData(Class<T> key) {
+        UserDataHost userDataHost = getUserDataHost();
+        if (userDataHost == null) return;
+        userDataHost.removeUserData(key);
+    }
+
     /**
      * @return {@code UserDataHost} that contains internal user data. {@code null} if
      *         it is already gc'ed.
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
index 292e217..e7a4a8e 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
@@ -241,9 +241,9 @@
 
     @Override
     @CalledByNative
-    public void didChangeThemeColor(int color) {
+    public void didChangeThemeColor() {
         for (mObserversIterator.rewind(); mObserversIterator.hasNext();) {
-            mObserversIterator.next().didChangeThemeColor(color);
+            mObserversIterator.next().didChangeThemeColor();
         }
     }
 
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java
index d86fbbde..792563f 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java
@@ -163,9 +163,8 @@
 
     /**
      * Called when the theme color was changed.
-     * @param color the new color in ARGB format
      */
-    public void didChangeThemeColor(int color) {}
+    public void didChangeThemeColor() {}
 
     /**
      * Called when the Web Contents leaves or enters fullscreen mode.
diff --git a/content/public/browser/authenticator_request_client_delegate.cc b/content/public/browser/authenticator_request_client_delegate.cc
index fcc4e50..1778053 100644
--- a/content/public/browser/authenticator_request_client_delegate.cc
+++ b/content/public/browser/authenticator_request_client_delegate.cc
@@ -166,7 +166,7 @@
   NOTREACHED();
 }
 
-void AuthenticatorRequestClientDelegate::FinishCollectPIN() {
+void AuthenticatorRequestClientDelegate::FinishCollectToken() {
   NOTREACHED();
 }
 
diff --git a/content/public/browser/authenticator_request_client_delegate.h b/content/public/browser/authenticator_request_client_delegate.h
index f11f12129..7afae3e7 100644
--- a/content/public/browser/authenticator_request_client_delegate.h
+++ b/content/public/browser/authenticator_request_client_delegate.h
@@ -228,7 +228,7 @@
   void CollectPIN(
       base::Optional<int> attempts,
       base::OnceCallback<void(std::string)> provide_pin_cb) override;
-  void FinishCollectPIN() override;
+  void FinishCollectToken() override;
 
  protected:
   // CustomizeDiscoveryFactory may be overridden in order to configure
diff --git a/content/public/browser/file_url_loader.h b/content/public/browser/file_url_loader.h
index 8f25e0cc..de9c6e72 100644
--- a/content/public/browser/file_url_loader.h
+++ b/content/public/browser/file_url_loader.h
@@ -50,7 +50,7 @@
 // The URLLoader created by this function does *not* automatically follow
 // filesytem links (e.g. Windows shortcuts) or support directory listing.
 // A directory path will always yield a FILE_NOT_FOUND network error.
-CONTENT_EXPORT void CreateFileURLLoader(
+CONTENT_EXPORT void CreateFileURLLoaderBypassingSecurityChecks(
     const network::ResourceRequest& request,
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
diff --git a/content/public/browser/native_web_keyboard_event.h b/content/public/browser/native_web_keyboard_event.h
index 7b10a74..8498d45 100644
--- a/content/public/browser/native_web_keyboard_event.h
+++ b/content/public/browser/native_web_keyboard_event.h
@@ -57,7 +57,7 @@
 #endif
 
   NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event);
-  ~NativeWebKeyboardEvent();
+  ~NativeWebKeyboardEvent() override;
 
   NativeWebKeyboardEvent& operator=(const NativeWebKeyboardEvent& event);
 
diff --git a/content/public/browser/render_widget_host_view.h b/content/public/browser/render_widget_host_view.h
index d3033cc..8fe90d1 100644
--- a/content/public/browser/render_widget_host_view.h
+++ b/content/public/browser/render_widget_host_view.h
@@ -232,11 +232,6 @@
   // wants to have BeginFrame messages sent to it.  This should only be called
   // when the value has changed.  Views must initially default to false.
   virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0;
-
-  // Informs the view that its associated render widget also wants to receive
-  // animate_only BeginFrames.
-  virtual void SetWantsAnimateOnlyBeginFrames() = 0;
-
   // This method returns the ScreenInfo used by the view to render. If the
   // information is not knowable (e.g, because the view is not attached to a
   // screen yet), then a default best-guess will be used.
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h
index 1cfbc996..ea45fb5 100644
--- a/content/public/browser/web_contents_observer.h
+++ b/content/public/browser/web_contents_observer.h
@@ -508,8 +508,8 @@
   virtual void AccessibilityLocationChangesReceived(
       const std::vector<AXLocationChangeNotificationDetails>& details) {}
 
-  // Invoked when theme color is changed to |theme_color|.
-  virtual void DidChangeThemeColor(base::Optional<SkColor> theme_color) {}
+  // Invoked when theme color is changed.
+  virtual void DidChangeThemeColor() {}
 
   // Called when a message is added to the console of the WebContents. This is
   // invoked before forwarding the message to the WebContents' delegate.
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 87d66b8f..a19ec85 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -124,6 +124,8 @@
     "loader/code_cache_loader_impl.h",
     "loader/frame_request_blocker.cc",
     "loader/frame_request_blocker.h",
+    "loader/internet_disconnected_web_url_loader.cc",
+    "loader/internet_disconnected_web_url_loader.h",
     "loader/navigation_body_loader.cc",
     "loader/navigation_body_loader.h",
     "loader/navigation_response_override_parameters.cc",
diff --git a/content/renderer/input/input_event_prediction.cc b/content/renderer/input/input_event_prediction.cc
index bd43bcb..b8a7947 100644
--- a/content/renderer/input/input_event_prediction.cc
+++ b/content/renderer/input/input_event_prediction.cc
@@ -168,8 +168,7 @@
       last_event_timestamp_ + mouse_predictor_->MaxPredictionTime();
   bool success = true;
   while (success) {
-    ui::WebScopedInputEvent predicted_event =
-        ui::WebInputEventTraits::Clone(coalesced_event.Event());
+    ui::WebScopedInputEvent predicted_event = coalesced_event.Event().Clone();
     success = false;
     if (predicted_event->GetType() == WebInputEvent::kTouchMove) {
       WebTouchEvent& touch_event =
diff --git a/content/renderer/input/main_thread_event_queue_unittest.cc b/content/renderer/input/main_thread_event_queue_unittest.cc
index 35a467c..299833e0 100644
--- a/content/renderer/input/main_thread_event_queue_unittest.cc
+++ b/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 
 #include <new>
+#include <tuple>
 #include <utility>
 #include <vector>
 
@@ -197,8 +198,8 @@
   void HandleEvent(WebInputEvent& event, InputEventAckState ack_result) {
     base::AutoReset<bool> in_handle_event(&handler_callback_->handling_event_,
                                           true);
-    queue_->HandleEvent(ui::WebInputEventTraits::Clone(event),
-                        ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING, ack_result,
+    queue_->HandleEvent(event.Clone(), ui::LatencyInfo(),
+                        DISPATCH_TYPE_BLOCKING, ack_result,
                         handler_callback_->GetCallback());
   }
 
@@ -354,8 +355,6 @@
   }
 
   {
-    EXPECT_EQ(kEvents[0].size(),
-              handled_tasks_.at(0)->taskAsEvent()->Event().size());
     EXPECT_EQ(kEvents[0].GetType(),
               handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
     const WebMouseWheelEvent* last_wheel_event =
@@ -446,8 +445,6 @@
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(3u, handled_tasks_.size());
 
-  EXPECT_EQ(kEvents[0].size(),
-            handled_tasks_.at(0)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents[0].GetType(),
             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
   const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
@@ -464,8 +461,6 @@
     EXPECT_TRUE(Equal(kEvents[0], *coalesced_touch_event));
   }
 
-  EXPECT_EQ(kEvents[1].size(),
-            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents[1].GetType(),
             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
   last_touch_event = static_cast<const WebTouchEvent*>(
@@ -482,8 +477,6 @@
     EXPECT_TRUE(Equal(kEvents[1], *coalesced_touch_event));
   }
 
-  EXPECT_EQ(kEvents[2].size(),
-            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents[2].GetType(),
             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
   last_touch_event = static_cast<const WebTouchEvent*>(
@@ -602,8 +595,6 @@
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(2u, handled_tasks_.size());
   {
-    EXPECT_EQ(kWheelEvents[0].size(),
-              handled_tasks_.at(0)->taskAsEvent()->Event().size());
     EXPECT_EQ(kWheelEvents[0].GetType(),
               handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
     const WebMouseWheelEvent* last_wheel_event =
@@ -618,8 +609,6 @@
     EXPECT_TRUE(Equal(coalesced_event, *last_wheel_event));
   }
   {
-    EXPECT_EQ(kTouchEvents[0].size(),
-              handled_tasks_.at(1)->taskAsEvent()->Event().size());
     EXPECT_EQ(kTouchEvents[0].GetType(),
               handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
     const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
@@ -999,8 +988,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(1u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(0)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
   EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
@@ -1020,8 +1007,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(2u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
   EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
@@ -1040,8 +1025,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(3u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(2)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1058,8 +1041,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(4u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(3)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1086,8 +1067,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(1u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(0)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1105,8 +1084,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(2u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(1)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1124,8 +1101,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(3u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(2)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
@@ -1143,8 +1118,6 @@
   EXPECT_FALSE(main_task_runner_->HasPendingTask());
   EXPECT_EQ(0u, event_queue().size());
   EXPECT_EQ(4u, handled_tasks_.size());
-  EXPECT_EQ(kEvents.size(),
-            handled_tasks_.at(3)->taskAsEvent()->Event().size());
   EXPECT_EQ(kEvents.GetType(),
             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::kBlocking);
diff --git a/content/renderer/input/widget_input_handler_manager.cc b/content/renderer/input/widget_input_handler_manager.cc
index 21a11e3..eafde289 100644
--- a/content/renderer/input/widget_input_handler_manager.cc
+++ b/content/renderer/input/widget_input_handler_manager.cc
@@ -258,8 +258,7 @@
   blink::WebGestureEvent scroll_begin =
       ui::ScrollBeginFromScrollUpdate(update_event);
 
-  DispatchNonBlockingEventToMainThread(
-      ui::WebInputEventTraits::Clone(scroll_begin), ui::LatencyInfo());
+  DispatchNonBlockingEventToMainThread(scroll_begin.Clone(), ui::LatencyInfo());
 }
 
 void WidgetInputHandlerManager::SetWhiteListedTouchAction(
diff --git a/content/renderer/loader/internet_disconnected_web_url_loader.cc b/content/renderer/loader/internet_disconnected_web_url_loader.cc
new file mode 100644
index 0000000..3f727d1
--- /dev/null
+++ b/content/renderer/loader/internet_disconnected_web_url_loader.cc
@@ -0,0 +1,81 @@
+// Copyright 2019 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/loader/internet_disconnected_web_url_loader.h"
+
+#include "base/bind.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_loader_client.h"
+#include "third_party/blink/public/platform/web_url_request.h"
+
+namespace content {
+
+std::unique_ptr<blink::WebURLLoader>
+InternetDisconnectedWebURLLoaderFactory::CreateURLLoader(
+    const blink::WebURLRequest&,
+    std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+        task_runner_handle) {
+  DCHECK(task_runner_handle);
+  return std::make_unique<InternetDisconnectedWebURLLoader>(
+      std::move(task_runner_handle));
+}
+
+InternetDisconnectedWebURLLoader::InternetDisconnectedWebURLLoader(
+    std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+        task_runner_handle)
+    : task_runner_handle_(std::move(task_runner_handle)) {}
+
+InternetDisconnectedWebURLLoader::~InternetDisconnectedWebURLLoader() = default;
+
+void InternetDisconnectedWebURLLoader::LoadSynchronously(
+    const blink::WebURLRequest&,
+    blink::WebURLLoaderClient*,
+    blink::WebURLResponse&,
+    base::Optional<blink::WebURLError>&,
+    blink::WebData&,
+    int64_t& encoded_data_length,
+    int64_t& encoded_body_length,
+    blink::WebBlobInfo& downloaded_blob) {
+  NOTREACHED();
+}
+
+void InternetDisconnectedWebURLLoader::LoadAsynchronously(
+    const blink::WebURLRequest& request,
+    blink::WebURLLoaderClient* client) {
+  DCHECK(task_runner_handle_);
+  task_runner_handle_->GetTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &InternetDisconnectedWebURLLoader::DidFail,
+          weak_factory_.GetWeakPtr(),
+          // It is safe to use Unretained(client), because |client| is a
+          // ResourceLoader which owns |this|, and we are binding with weak ptr
+          // of |this| here.
+          base::Unretained(client),
+          blink::WebURLError(net::ERR_INTERNET_DISCONNECTED, request.Url())));
+}
+
+void InternetDisconnectedWebURLLoader::SetDefersLoading(bool defers) {}
+
+void InternetDisconnectedWebURLLoader::DidChangePriority(
+    blink::WebURLRequest::Priority,
+    int) {}
+
+void InternetDisconnectedWebURLLoader::DidFail(
+    blink::WebURLLoaderClient* client,
+    const blink::WebURLError& error) {
+  DCHECK(client);
+  client->DidFail(error, 0 /* total_encoded_data_length */,
+                  0 /* total_encoded_body_length */,
+                  0 /* total_decoded_body_length */);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+InternetDisconnectedWebURLLoader::GetTaskRunner() {
+  return task_runner_handle_->GetTaskRunner();
+}
+
+}  // namespace content
diff --git a/content/renderer/loader/internet_disconnected_web_url_loader.h b/content/renderer/loader/internet_disconnected_web_url_loader.h
new file mode 100644
index 0000000..19b85db
--- /dev/null
+++ b/content/renderer/loader/internet_disconnected_web_url_loader.h
@@ -0,0 +1,62 @@
+// Copyright 2019 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_LOADER_INTERNET_DISCONNECTED_WEB_URL_LOADER_H_
+#define CONTENT_RENDERER_LOADER_INTERNET_DISCONNECTED_WEB_URL_LOADER_H_
+
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+#include "third_party/blink/public/platform/web_url_loader.h"
+#include "third_party/blink/public/platform/web_url_loader_factory.h"
+
+namespace content {
+
+// WebURLLoaderFactory for InternetDisconnectedWebURLLoader.
+class InternetDisconnectedWebURLLoaderFactory final
+    : public blink::WebURLLoaderFactory {
+ public:
+  std::unique_ptr<blink::WebURLLoader> CreateURLLoader(
+      const blink::WebURLRequest&,
+      std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+          task_runner_handle) override;
+};
+
+// WebURLLoader which always returns an internet disconnected error. At present,
+// this is used for ServiceWorker's offline-capability-check fetch event.
+class InternetDisconnectedWebURLLoader final : public blink::WebURLLoader {
+ public:
+  explicit InternetDisconnectedWebURLLoader(
+      std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+          task_runner_handle);
+  ~InternetDisconnectedWebURLLoader() override;
+
+  // WebURLLoader implementation:
+  void LoadSynchronously(const blink::WebURLRequest&,
+                         blink::WebURLLoaderClient*,
+                         blink::WebURLResponse&,
+                         base::Optional<blink::WebURLError>&,
+                         blink::WebData&,
+                         int64_t& encoded_data_length,
+                         int64_t& encoded_body_length,
+                         blink::WebBlobInfo& downloaded_blob) override;
+  void LoadAsynchronously(const blink::WebURLRequest& request,
+                          blink::WebURLLoaderClient* client) override;
+  void SetDefersLoading(bool defers) override;
+  void DidChangePriority(blink::WebURLRequest::Priority, int) override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
+
+ private:
+  void DidFail(blink::WebURLLoaderClient* client,
+               const blink::WebURLError& error);
+
+  std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+      task_runner_handle_;
+  base::WeakPtrFactory<InternetDisconnectedWebURLLoader> weak_factory_{this};
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_LOADER_INTERNET_DISCONNECTED_WEB_URL_LOADER_H_
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc
index 776a03e..3e64cd8 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.cc
+++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -544,6 +544,11 @@
   return receiver.PassPipe();
 }
 
+void WebWorkerFetchContextImpl::SetIsOfflineMode(bool is_offline_mode) {
+  // Worker doesn't support offline mode. There should be no callers.
+  NOTREACHED();
+}
+
 void WebWorkerFetchContextImpl::set_controller_service_worker_mode(
     blink::mojom::ControllerServiceWorkerMode mode) {
   controller_service_worker_mode_ = mode;
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.h b/content/renderer/loader/web_worker_fetch_context_impl.h
index 898d090e..e174b5d74 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.h
+++ b/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -131,6 +131,7 @@
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
   mojo::ScopedMessagePipeHandle TakePendingWorkerTimingReceiver(
       int request_id) override;
+  void SetIsOfflineMode(bool is_offline_mode) override;
 
   // blink::mojom::ServiceWorkerWorkerClient implementation:
   void OnControllerChanged(blink::mojom::ControllerServiceWorkerMode) override;
diff --git a/content/renderer/pepper/pepper_video_capture_host.cc b/content/renderer/pepper/pepper_video_capture_host.cc
index 6fbea83..6794414 100644
--- a/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/content/renderer/pepper/pepper_video_capture_host.cc
@@ -21,6 +21,7 @@
 #include "ppapi/thunk/enter.h"
 #include "ppapi/thunk/ppb_buffer_api.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
+#include "third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h"
 
 using ppapi::HostResource;
 using ppapi::TrackedCallback;
@@ -136,9 +137,9 @@
 
   for (uint32_t i = 0; i < buffers_.size(); ++i) {
     if (!buffers_[i].in_use) {
-      DCHECK_EQ(frame.format(), media::PIXEL_FORMAT_I420);
       if (buffers_[i].buffer->size() <
-          media::VideoFrame::AllocationSize(frame.format(), alloc_size_)) {
+          media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
+                                            alloc_size_)) {
         // TODO(ihf): handle size mismatches gracefully here.
         return;
       }
@@ -146,17 +147,70 @@
       static_assert(media::VideoFrame::kYPlane == 0, "y plane should be 0");
       static_assert(media::VideoFrame::kUPlane == 1, "u plane should be 1");
       static_assert(media::VideoFrame::kVPlane == 2, "v plane should be 2");
-      for (size_t j = 0; j < media::VideoFrame::NumPlanes(frame.format());
-           ++j) {
-        const uint8_t* src = frame.visible_data(j);
-        const size_t row_bytes = frame.row_bytes(j);
-        const size_t src_stride = frame.stride(j);
-        for (int k = 0; k < frame.rows(j); ++k) {
-          memcpy(dst, src, row_bytes);
-          dst += row_bytes;
-          src += src_stride;
+
+      if (frame.storage_type() ==
+          media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+        // NV12 is the only supported GMB pixel format at the moment.
+        DCHECK_EQ(frame.format(), media::PIXEL_FORMAT_NV12);
+        auto* gmb = frame.GetGpuMemoryBuffer();
+        if (!gmb->Map()) {
+          DLOG(ERROR) << "Error mapping GpuMemoryBuffer video frame";
+          return;
+        }
+
+        const size_t src_y_stride = gmb->stride(0);
+        const size_t src_uv_stride = gmb->stride(1);
+        const uint8_t* src_y_plane =
+            (static_cast<uint8_t*>(gmb->memory(0)) + frame.visible_rect().x() +
+             (frame.visible_rect().y() * src_y_stride));
+        // UV plane of NV12 has 2-byte pixel width, with half chroma subsampling
+        // both horizontally and vertically.
+        const uint8_t* src_uv_plane =
+            (static_cast<uint8_t*>(gmb->memory(1)) +
+             ((frame.visible_rect().x() * 2) / 2) +
+             ((frame.visible_rect().y() / 2) * src_uv_stride));
+
+        const size_t dst_width = frame.natural_size().width();
+        const gfx::Size dst_size = frame.natural_size();
+        const size_t dst_y_stride = media::VideoFrame::RowBytes(
+            media::VideoFrame::kYPlane, media::PIXEL_FORMAT_I420, dst_width);
+        const size_t dst_u_stride = media::VideoFrame::RowBytes(
+            media::VideoFrame::kUPlane, media::PIXEL_FORMAT_I420, dst_width);
+        const size_t dst_v_stride = media::VideoFrame::RowBytes(
+            media::VideoFrame::kVPlane, media::PIXEL_FORMAT_I420, dst_width);
+        const size_t dst_y_plane_area =
+            media::VideoFrame::PlaneSize(media::PIXEL_FORMAT_I420,
+                                         media::VideoFrame::kYPlane, dst_size)
+                .GetArea();
+        const size_t dst_u_plane_area =
+            media::VideoFrame::PlaneSize(media::PIXEL_FORMAT_I420,
+                                         media::VideoFrame::kUPlane, dst_size)
+                .GetArea();
+
+        webrtc::NV12ToI420Scaler scaler;
+        scaler.NV12ToI420Scale(
+            src_y_plane, src_y_stride, src_uv_plane, src_uv_stride,
+            frame.coded_size().width(), frame.coded_size().height(), dst,
+            dst_y_stride, dst + dst_y_plane_area, dst_u_stride,
+            dst + dst_y_plane_area + dst_u_plane_area, dst_v_stride,
+            frame.natural_size().width(), frame.natural_size().height());
+
+        gmb->Unmap();
+      } else {
+        DCHECK_EQ(frame.format(), media::PIXEL_FORMAT_I420);
+        for (size_t j = 0; j < media::VideoFrame::NumPlanes(frame.format());
+             ++j) {
+          const uint8_t* src = frame.visible_data(j);
+          const size_t row_bytes = frame.row_bytes(j);
+          const size_t src_stride = frame.stride(j);
+          for (int k = 0; k < frame.rows(j); ++k) {
+            memcpy(dst, src, row_bytes);
+            dst += row_bytes;
+            src += src_stride;
+          }
         }
       }
+
       buffers_[i].in_use = true;
       host()->SendUnsolicitedReply(
           pp_resource(), PpapiPluginMsg_VideoCapture_OnBufferReady(i));
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index bb1f6c7..9bb3d8d 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -10,6 +10,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/renderer/url_loader_throttle_provider.h"
 #include "content/public/renderer/websocket_handshake_throttle_provider.h"
+#include "content/renderer/loader/internet_disconnected_web_url_loader.h"
 #include "content/renderer/loader/request_extra_data.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/web_url_loader_impl.h"
@@ -73,6 +74,9 @@
       network::SharedURLLoaderFactory::Create(
           std::move(pending_url_loader_factory_)));
 
+  internet_disconnected_web_url_loader_factory_ =
+      std::make_unique<InternetDisconnectedWebURLLoaderFactory>();
+
   if (pending_script_loader_factory_) {
     web_script_loader_factory_ =
         std::make_unique<content::WebURLLoaderFactoryImpl>(
@@ -86,6 +90,8 @@
 
 blink::WebURLLoaderFactory*
 ServiceWorkerFetchContextImpl::GetURLLoaderFactory() {
+  if (is_offline_mode_)
+    return internet_disconnected_web_url_loader_factory_.get();
   return web_url_loader_factory_.get();
 }
 
@@ -198,4 +204,8 @@
   return {};
 }
 
+void ServiceWorkerFetchContextImpl::SetIsOfflineMode(bool is_offline_mode) {
+  is_offline_mode_ = is_offline_mode;
+}
+
 }  // namespace content
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h
index 1b1191d..98b874e 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -17,6 +17,7 @@
 #include "url/gurl.h"
 
 namespace content {
+class InternetDisconnectedWebURLLoaderFactory;
 class ResourceDispatcher;
 class URLLoaderThrottleProvider;
 class WebSocketHandshakeThrottleProvider;
@@ -72,6 +73,7 @@
   blink::WebString GetAcceptLanguages() const override;
   mojo::ScopedMessagePipeHandle TakePendingWorkerTimingReceiver(
       int request_id) override;
+  void SetIsOfflineMode(bool) override;
 
  private:
   ~ServiceWorkerFetchContextImpl() override;
@@ -103,6 +105,10 @@
 
   // Responsible for regular loads from the service worker (i.e., Fetch API).
   std::unique_ptr<blink::WebURLLoaderFactory> web_url_loader_factory_;
+  // Responsible for loads which always fail as INTERNET_DISCONNECTED
+  // error, which is used in offline mode.
+  std::unique_ptr<InternetDisconnectedWebURLLoaderFactory>
+      internet_disconnected_web_url_loader_factory_;
   // Responsible for script loads from the service worker (i.e., the
   // classic/module main script, module imported scripts, or importScripts()).
   std::unique_ptr<blink::WebURLLoaderFactory> web_script_loader_factory_;
@@ -129,6 +135,7 @@
   blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr;
 
   int32_t service_worker_route_id_;
+  bool is_offline_mode_ = false;
 };
 
 }  // namespace content
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 79879df..d83b964 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -987,6 +987,7 @@
     "../browser/service_worker/service_worker_clients_api_browsertest.cc",
     "../browser/service_worker/service_worker_file_upload_browsertest.cc",
     "../browser/service_worker/service_worker_no_best_effort_tasks_browsertest.cc",
+    "../browser/service_worker/service_worker_offline_capability_check_browsertest.cc",
     "../browser/service_worker/service_worker_process_browsertest.cc",
     "../browser/service_worker/service_worker_version_browsertest.cc",
     "../browser/session_history_browsertest.cc",
diff --git a/content/test/data/accessibility/event/text-selection-changed-expected-uia-win.txt b/content/test/data/accessibility/event/text-selection-changed-expected-uia-win.txt
index 9a5505b..c5b6e58f 100644
--- a/content/test/data/accessibility/event/text-selection-changed-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/text-selection-changed-expected-uia-win.txt
@@ -1,5 +1,7 @@
 Text_TextSelectionChanged on role=document
 === Start Continuation ===
+Text_TextSelectionChanged on role=document
 Text_TextSelectionChanged on role=textbox, name=input
 === Start Continuation ===
+Text_TextSelectionChanged on role=document
 Text_TextSelectionChanged on role=textbox, name=textarea
diff --git a/content/test/data/service_worker/maybe_offline_support.js b/content/test/data/service_worker/maybe_offline_support.js
new file mode 100644
index 0000000..ec825ee1
--- /dev/null
+++ b/content/test/data/service_worker/maybe_offline_support.js
@@ -0,0 +1,41 @@
+// Copyright 2019 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.
+
+function sleep(delay) {
+  return new Promise(resolve => {
+    setTimeout(() => {
+      resolve();
+    }, delay);
+  });
+}
+
+self.addEventListener("fetch", event => {
+  const param = new URL(event.request.url).searchParams;
+
+  if (param.has("fetch")) {
+    event.respondWith(fetch(event.request.url));
+  } else if (param.has("offline")) {
+    event.respondWith(new Response("Hello Offline page"));
+  } else if (param.has("fetch_or_offline")) {
+    event.respondWith(
+      fetch(event.request).catch(error => {
+        return new Response("Hello Offline page");
+      })
+    );
+  } else if (param.has("sleep_then_fetch")) {
+    event.respondWith(
+      sleep(param.get("sleep") || 0, event.request.url).then(() => {
+        return fetch(event.request.url);
+      })
+    );
+  } else if (param.has("sleep_then_offline")) {
+    event.respondWith(
+      sleep(param.get("sleep") || 0, event.request.url).then(() => {
+        return new Response("Hello Offline page");
+      })
+    );
+  } else {
+    // fallback case: do nothing.
+  }
+});
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 6541f996..15b0226 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -555,6 +555,7 @@
 crbug.com/658930 [ mac intel ] conformance2/textures/misc/integer-cubemap-texture-sampling.html [ Failure ]
 crbug.com/731877 [ mac intel-0xa2e no-passthrough ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ]
 crbug.com/782317 [ mac intel ] conformance/rendering/rendering-stencil-large-viewport.html [ Failure ]
+crbug.com/1039465 [ mac intel ] conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ RetryOnFailure ]
 
 # Mac Passthrough
 crbug.com/982294 [ mac passthrough ] conformance/rendering/negative-one-index.html [ Failure ]
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index a4714db..f10cdeb 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -61,10 +61,7 @@
 }
 
 TestRenderWidgetHostView::TestRenderWidgetHostView(RenderWidgetHost* rwh)
-    : RenderWidgetHostViewBase(rwh),
-      is_showing_(false),
-      is_occluded_(false),
-      did_swap_compositor_frame_(false) {
+    : RenderWidgetHostViewBase(rwh), is_showing_(false), is_occluded_(false) {
 #if defined(OS_ANDROID)
   frame_sink_id_ = AllocateFrameSinkId();
   GetHostFrameSinkManager()->RegisterFrameSinkId(
@@ -169,15 +166,6 @@
   return gfx::Rect();
 }
 
-void TestRenderWidgetHostView::SubmitCompositorFrame(
-    const viz::LocalSurfaceId& local_surface_id,
-    viz::CompositorFrame frame,
-    base::Optional<viz::HitTestRegionList> hit_test_region_list) {
-  did_swap_compositor_frame_ = true;
-  if (frame.metadata.send_frame_token_to_embedder)
-    OnFrameTokenChanged(frame.metadata.frame_token);
-}
-
 void TestRenderWidgetHostView::TakeFallbackContentFrom(
     RenderWidgetHostView* view) {
   base::Optional<SkColor> color = view->GetBackgroundColor();
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index 50a242d..8e6f815 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -86,10 +86,6 @@
   void ShowDefinitionForSelection() override {}
   void SpeakSelection() override;
 #endif  // defined(OS_MACOSX)
-  void SubmitCompositorFrame(
-      const viz::LocalSurfaceId& local_surface_id,
-      viz::CompositorFrame frame,
-      base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
 
   // Advances the fallback surface to the first surface after navigation. This
   // ensures that stale surfaces are not presented to the user for an indefinite
@@ -97,7 +93,6 @@
   void ResetFallbackToFirstNavigationSurface() override {}
 
   void SetNeedsBeginFrames(bool needs_begin_frames) override {}
-  void SetWantsAnimateOnlyBeginFrames() override {}
   void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
   void EnsureSurfaceSynchronizedForWebTest() override {}
 
@@ -123,8 +118,6 @@
 
   bool is_showing() const { return is_showing_; }
   bool is_occluded() const { return is_occluded_; }
-  bool did_swap_compositor_frame() const { return did_swap_compositor_frame_; }
-  void reset_did_swap_compositor_frame() { did_swap_compositor_frame_ = false; }
 
   // viz::HostFrameSinkClient implementation.
   void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
@@ -139,7 +132,6 @@
  private:
   bool is_showing_;
   bool is_occluded_;
-  bool did_swap_compositor_frame_;
   ui::DummyTextInputClient text_input_client_;
 
 #if defined(USE_AURA)
diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc
index fd73612..da4369d 100644
--- a/courgette/assembly_program.cc
+++ b/courgette/assembly_program.cc
@@ -67,20 +67,6 @@
                                        RvaVisitor* rel32_visitor) {
   abs32_label_manager_.Read(abs32_visitor);
   rel32_label_manager_.Read(rel32_visitor);
-  // TrimLabels() should be called here if used. Previously this was used only
-  // for ARM binaries, but ARM support has been deprecated.
-}
-
-// Chosen empirically to give the best reduction in payload size for
-// an update from daisy_3701.98.0 to daisy_4206.0.0.
-const int AssemblyProgram::kLabelLowerLimit = 5;
-
-void AssemblyProgram::TrimLabels() {
-  int lower_limit = kLabelLowerLimit;
-
-  VLOG(1) << "TrimLabels: threshold " << lower_limit;
-
-  rel32_label_manager_.RemoveUnderusedLabels(lower_limit);
 }
 
 void AssemblyProgram::UnassignIndexes() {
diff --git a/courgette/assembly_program.h b/courgette/assembly_program.h
index 9ec944a..fe4b045 100644
--- a/courgette/assembly_program.h
+++ b/courgette/assembly_program.h
@@ -55,10 +55,6 @@
   // Traverses RVAs in |abs32_visitor| and |rel32_visitor| to precompute Labels.
   void PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor);
 
-  // Removes underused Labels. Thresholds used (0 = no trimming) is
-  // architecture-dependent.
-  void TrimLabels();
-
   void UnassignIndexes();
   void DefaultAssignIndexes();
   void AssignRemainingIndexes();
diff --git a/courgette/label_manager.cc b/courgette/label_manager.cc
index a22a36c..3fadd9c 100644
--- a/courgette/label_manager.cc
+++ b/courgette/label_manager.cc
@@ -113,17 +113,6 @@
   return it == labels_.end() || it->rva_ != rva ? nullptr : &(*it);
 }
 
-void LabelManager::RemoveUnderusedLabels(int32_t count_threshold) {
-  if (count_threshold <= 0)
-    return;
-  labels_.erase(std::remove_if(labels_.begin(), labels_.end(),
-                               [count_threshold](const Label& label) {
-                                 return label.count_ < count_threshold;
-                               }),
-                labels_.end());
-  // Not shrinking |labels_|, since this may cause reallocation.
-}
-
 void LabelManager::UnassignIndexes() {
   for (Label& label : labels_)
     label.index_ = Label::kNoIndex;
diff --git a/courgette/label_manager_unittest.cc b/courgette/label_manager_unittest.cc
index 037958b..7b84e5f 100644
--- a/courgette/label_manager_unittest.cc
+++ b/courgette/label_manager_unittest.cc
@@ -155,14 +155,6 @@
   EXPECT_EQ(nullptr, label_manager.Find(RVA(0x5F3759DF)));
   EXPECT_EQ(nullptr, label_manager.Find(RVA(0xFEEDFFF0)));
   EXPECT_EQ(nullptr, label_manager.Find(RVA(0xFFFFFFFF)));
-
-  // Remove Labels with |count_| < 2.
-  label_manager.RemoveUnderusedLabels(2);
-  static const std::pair<RVA, int32_t> kExpected2Raw[] = {
-      {0x04000010, 3}, {0x04000030, 2}, {0xFEEDF00D, 2}};
-  std::map<RVA, int32_t> expected2(std::begin(kExpected2Raw),
-                                   std::end(kExpected2Raw));
-  CheckLabelManagerContent(&label_manager, expected2);
 }
 
 TEST(LabelManagerTest, Single) {
@@ -324,8 +316,8 @@
     {"....AC", "BDEFAC"},
     {"ED...C...B....A", "EDFGHCIJKBLMNOA"},
     // Forward fill and infill.
-    {"E..", "EBA"},  // Forward: "A"; in: "B".
-    {"Z....", "ZDABC"},  // Forward: "ABC"; in: "D".
+    {"E..", "EBA"},          // Forward: "A"; in: "B".
+    {"Z....", "ZDABC"},      // Forward: "ABC"; in: "D".
     {".E.....", "AEFGBCD"},  // Forward: "A", "FG"; in: "BCD".
     {"....C..", "ABFGCDE"},  // Forward: "AB", "DE"; in: "FG".
     {"...Z...", "ABCZDEF"},  // Forward: "ABC"; in: "DEF".
@@ -337,7 +329,7 @@
     {"ANM..Z....L...T", "ANMXYZHIJKLQRST"},
     {"....G..Z...LAH", "CDEFGXYZIJKLAH"},
     // Forward fill and backward fill.
-    {"..ZA..", "XYZABC"},  // Forward: "BC"; backward: "XY".
+    {"..ZA..", "XYZABC"},    // Forward: "BC"; backward: "XY".
     {".....ZD", "ABCXYZD"},  // Forward: "ABC"; backward: "XY".
     {"DA.....", "DABCEFG"},  // Forward: "BC"; backward: "EFG".
     // Backward fill and infill.
@@ -346,7 +338,7 @@
     // All.
     {".....ZED.", "ABCXYZEDF"},  // Forward: "ABC"; backward: "XY"; in: "F".
     {".....GD.", "ABCHFGDE"},  // Forward: "ABC", "E"; backward: "F"; in: "H".
-    {"..FE..GD..", "ABFECHGDIJ"}, // Forward: "AB"; backward: "IJ"; in: "CH".
+    {"..FE..GD..", "ABFECHGDIJ"},  // Forward: "AB"; backward: "IJ"; in: "CH".
   };
   for (const auto& test_case : kTestCases) {
     TestLabelManager label_manager;
diff --git a/device/fido/authenticator_supported_options.cc b/device/fido/authenticator_supported_options.cc
index 0656016..006b17cf 100644
--- a/device/fido/authenticator_supported_options.cc
+++ b/device/fido/authenticator_supported_options.cc
@@ -83,6 +83,10 @@
       break;
   }
 
+  if (options.supports_uv_token) {
+    option_map.emplace(kUvTokenMapKey, true);
+  }
+
   return cbor::Value(std::move(option_map));
 }
 
diff --git a/device/fido/authenticator_supported_options.h b/device/fido/authenticator_supported_options.h
index 04d721f..c0f2938 100644
--- a/device/fido/authenticator_supported_options.h
+++ b/device/fido/authenticator_supported_options.h
@@ -82,6 +82,9 @@
   // authenticator.
   ClientPinAvailability client_pin_availability =
       ClientPinAvailability::kNotSupported;
+  // Indicates whether the authenticator is capable of handling built in user
+  // verification based tokens.
+  bool supports_uv_token = false;
 };
 
 COMPONENT_EXPORT(DEVICE_FIDO)
diff --git a/device/fido/bio/enrollment_handler_unittest.cc b/device/fido/bio/enrollment_handler_unittest.cc
index ad890f1..75c424f 100644
--- a/device/fido/bio/enrollment_handler_unittest.cc
+++ b/device/fido/bio/enrollment_handler_unittest.cc
@@ -24,7 +24,8 @@
   void SetUp() override {
     virtual_device_factory_.SetSupportedProtocol(ProtocolVersion::kCtap2);
     virtual_device_factory_.mutable_state()->pin = kPIN;
-    virtual_device_factory_.mutable_state()->retries = 8;
+    virtual_device_factory_.mutable_state()->pin_retries =
+        device::kMaxPinRetries;
   }
 
  public:
diff --git a/device/fido/ble_adapter_manager_unittest.cc b/device/fido/ble_adapter_manager_unittest.cc
index 78ec221..c717f65 100644
--- a/device/fido/ble_adapter_manager_unittest.cc
+++ b/device/fido/ble_adapter_manager_unittest.cc
@@ -57,7 +57,7 @@
   MOCK_METHOD2(CollectPIN,
                void(base::Optional<int>,
                     base::OnceCallback<void(std::string)>));
-  MOCK_METHOD0(FinishCollectPIN, void());
+  MOCK_METHOD0(FinishCollectToken, void());
   MOCK_METHOD1(SetMightCreateResidentCredential, void(bool));
 
  private:
diff --git a/device/fido/credential_management_handler_unittest.cc b/device/fido/credential_management_handler_unittest.cc
index 1e89144..9833040 100644
--- a/device/fido/credential_management_handler_unittest.cc
+++ b/device/fido/credential_management_handler_unittest.cc
@@ -72,7 +72,7 @@
   virtual_device_factory_.SetCtap2Config(ctap_config);
   virtual_device_factory_.SetSupportedProtocol(device::ProtocolVersion::kCtap2);
   virtual_device_factory_.mutable_state()->pin = kPIN;
-  virtual_device_factory_.mutable_state()->retries = 8;
+  virtual_device_factory_.mutable_state()->pin_retries = device::kMaxPinRetries;
 
   PublicKeyCredentialRpEntity rp(kRPID, kRPName,
                                  /*icon_url=*/base::nullopt);
@@ -130,7 +130,7 @@
   virtual_device_factory_.SetCtap2Config(ctap_config);
   virtual_device_factory_.SetSupportedProtocol(device::ProtocolVersion::kCtap2);
   virtual_device_factory_.mutable_state()->pin = kPIN;
-  virtual_device_factory_.mutable_state()->retries = 8;
+  virtual_device_factory_.mutable_state()->pin_retries = device::kMaxPinRetries;
 
   const std::string rp_name = base::StrCat({std::string(57, 'a'), "💣"});
   const std::string user_name = base::StrCat({std::string(57, 'b'), "💣"});
diff --git a/device/fido/device_response_converter.cc b/device/fido/device_response_converter.cc
index 3ac311c..1362b13 100644
--- a/device/fido/device_response_converter.cc
+++ b/device/fido/device_response_converter.cc
@@ -338,6 +338,14 @@
               : Availability::kSupportedButUnprovisioned;
     }
 
+    option_map_it = option_map.find(CBOR(kUvTokenMapKey));
+    if (option_map_it != option_map.end()) {
+      if (!option_map_it->second.is_bool()) {
+        return base::nullopt;
+      }
+      options.supports_uv_token = option_map_it->second.GetBool();
+    }
+
     response.options = std::move(options);
   }
 
diff --git a/device/fido/fido_authenticator.cc b/device/fido/fido_authenticator.cc
index 2d6208e..79924886 100644
--- a/device/fido/fido_authenticator.cc
+++ b/device/fido/fido_authenticator.cc
@@ -26,7 +26,12 @@
 
 void FidoAuthenticator::GetPINToken(
     std::string pin,
-    FidoAuthenticator::GetPINTokenCallback callback) {
+    FidoAuthenticator::GetTokenCallback callback) {
+  NOTREACHED();
+}
+
+void FidoAuthenticator::GetUvToken(
+    FidoAuthenticator::GetTokenCallback callback) {
   NOTREACHED();
 }
 
diff --git a/device/fido/fido_authenticator.h b/device/fido/fido_authenticator.h
index 96de5c5..ac09c14 100644
--- a/device/fido/fido_authenticator.h
+++ b/device/fido/fido_authenticator.h
@@ -47,7 +47,7 @@
   using GetRetriesCallback =
       base::OnceCallback<void(CtapDeviceResponseCode,
                               base::Optional<pin::RetriesResponse>)>;
-  using GetPINTokenCallback =
+  using GetTokenCallback =
       base::OnceCallback<void(CtapDeviceResponseCode,
                               base::Optional<pin::TokenResponse>)>;
   using SetPINCallback =
@@ -89,10 +89,14 @@
   // authenticator locks. It is only valid to call this method if |Options|
   // indicates that the authenticator supports PINs.
   virtual void GetRetries(GetRetriesCallback callback);
-  // GetPINToken uses the given PIN to request a PIN-token from an
+  // GetPINToken uses the given PIN to request a PinUvAuthToken from an
   // authenticator. It is only valid to call this method if |Options| indicates
   // that the authenticator supports PINs.
-  virtual void GetPINToken(std::string pin, GetPINTokenCallback callback);
+  virtual void GetPINToken(std::string pin, GetTokenCallback callback);
+  // GetUvToken uses internal user verification to request a PinUvAuthToken from
+  // an authenticator. It is only valid to call this method if |Options|
+  // indicates that the authenticator supports UV tokens.
+  virtual void GetUvToken(GetTokenCallback callback);
   // SetPIN sets a new PIN on a device that does not currently have one. The
   // length of |pin| must respect |pin::kMinLength| and |pin::kMaxLength|. It is
   // only valid to call this method if |Options| indicates that the
diff --git a/device/fido/fido_constants.cc b/device/fido/fido_constants.cc
index 3a2ae67..cd002f50 100644
--- a/device/fido/fido_constants.cc
+++ b/device/fido/fido_constants.cc
@@ -31,6 +31,7 @@
 const char kCredentialManagementPreviewMapKey[] = "credentialMgmtPreview";
 const char kBioEnrollmentMapKey[] = "bioEnroll";
 const char kBioEnrollmentPreviewMapKey[] = "userVerificationMgmtPreview";
+const char kUvTokenMapKey[] = "uvToken";
 
 const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(20);
 const base::TimeDelta kU2fRetryDelay = base::TimeDelta::FromMilliseconds(200);
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h
index 7bc723f3..e87db48 100644
--- a/device/fido/fido_constants.h
+++ b/device/fido/fido_constants.h
@@ -108,6 +108,7 @@
   kCtap2ErrPinPolicyViolation = 0x37,
   kCtap2ErrPinTokenExpired = 0x38,
   kCtap2ErrRequestTooLarge = 0x39,
+  kCtap2ErrUvBlocked = 0x3C,
   kCtap2ErrOther = 0x7F,
   kCtap2ErrSpecLast = 0xDF,
   kCtap2ErrExtensionFirst = 0xE0,
@@ -280,6 +281,7 @@
 extern const char kCredentialManagementPreviewMapKey[];
 COMPONENT_EXPORT(DEVICE_FIDO) extern const char kBioEnrollmentMapKey[];
 COMPONENT_EXPORT(DEVICE_FIDO) extern const char kBioEnrollmentPreviewMapKey[];
+COMPONENT_EXPORT(DEVICE_FIDO) extern const char kUvTokenMapKey[];
 
 // HID transport specific constants.
 constexpr uint32_t kHidBroadcastChannel = 0xffffffff;
diff --git a/device/fido/fido_device_authenticator.cc b/device/fido/fido_device_authenticator.cc
index ea7ac3127..52c203cd 100644
--- a/device/fido/fido_device_authenticator.cc
+++ b/device/fido/fido_device_authenticator.cc
@@ -110,17 +110,18 @@
 void FidoDeviceAuthenticator::GetEphemeralKey(
     GetEphemeralKeyCallback callback) {
   DCHECK(Options());
-  DCHECK(Options()->client_pin_availability !=
-         AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported);
+  DCHECK(
+      Options()->client_pin_availability !=
+          AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported ||
+      Options()->supports_uv_token);
 
   RunOperation<pin::KeyAgreementRequest, pin::KeyAgreementResponse>(
       pin::KeyAgreementRequest(), std::move(callback),
       base::BindOnce(&pin::KeyAgreementResponse::Parse));
 }
 
-void FidoDeviceAuthenticator::GetPINToken(
-    std::string pin,
-    GetPINTokenCallback callback) {
+void FidoDeviceAuthenticator::GetPINToken(std::string pin,
+                                          GetTokenCallback callback) {
   DCHECK(Options());
   DCHECK(Options()->client_pin_availability !=
          AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported);
@@ -132,16 +133,16 @@
 
 void FidoDeviceAuthenticator::OnHaveEphemeralKeyForGetPINToken(
     std::string pin,
-    GetPINTokenCallback callback,
+    GetTokenCallback callback,
     CtapDeviceResponseCode status,
     base::Optional<pin::KeyAgreementResponse> key) {
   if (status != CtapDeviceResponseCode::kSuccess) {
     std::move(callback).Run(status, base::nullopt);
     return;
   }
-  pin::TokenRequest request(pin, *key);
+  pin::PinTokenRequest request(pin, *key);
   std::array<uint8_t, 32> shared_key = request.shared_key();
-  RunOperation<pin::TokenRequest, pin::TokenResponse>(
+  RunOperation<pin::PinTokenRequest, pin::TokenResponse>(
       std::move(request), std::move(callback),
       base::BindOnce(&pin::TokenResponse::Parse, std::move(shared_key)));
 }
@@ -678,6 +679,30 @@
   task_ = std::move(task);
 }
 
+void FidoDeviceAuthenticator::GetUvToken(GetTokenCallback callback) {
+  GetEphemeralKey(
+      base::BindOnce(&FidoDeviceAuthenticator::OnHaveEphemeralKeyForUvToken,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void FidoDeviceAuthenticator::OnHaveEphemeralKeyForUvToken(
+    GetTokenCallback callback,
+    CtapDeviceResponseCode status,
+    base::Optional<pin::KeyAgreementResponse> key) {
+  if (status != CtapDeviceResponseCode::kSuccess) {
+    std::move(callback).Run(status, base::nullopt);
+    return;
+  }
+
+  DCHECK(key);
+
+  pin::UvTokenRequest request(*key);
+  std::array<uint8_t, 32> shared_key = request.shared_key();
+  RunOperation<pin::UvTokenRequest, pin::TokenResponse>(
+      std::move(request), std::move(callback),
+      base::BindOnce(&pin::TokenResponse::Parse, std::move(shared_key)));
+}
+
 base::WeakPtr<FidoAuthenticator> FidoDeviceAuthenticator::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
diff --git a/device/fido/fido_device_authenticator.h b/device/fido/fido_device_authenticator.h
index d554188..75ecb56 100644
--- a/device/fido/fido_device_authenticator.h
+++ b/device/fido/fido_device_authenticator.h
@@ -50,8 +50,8 @@
   void GetNextAssertion(GetAssertionCallback callback) override;
   void GetTouch(base::OnceCallback<void()> callback) override;
   void GetRetries(GetRetriesCallback callback) override;
-  void GetPINToken(std::string pin,
-                   GetPINTokenCallback callback) override;
+  void GetPINToken(std::string pin, GetTokenCallback callback) override;
+  void GetUvToken(GetTokenCallback callback) override;
   void SetPIN(const std::string& pin,
               SetPINCallback callback) override;
   void ChangePIN(const std::string& old_pin,
@@ -128,7 +128,7 @@
   void GetEphemeralKey(GetEphemeralKeyCallback callback);
   void OnHaveEphemeralKeyForGetPINToken(
       std::string pin,
-      GetPINTokenCallback callback,
+      GetTokenCallback callback,
       CtapDeviceResponseCode status,
       base::Optional<pin::KeyAgreementResponse> key);
   void OnHaveEphemeralKeyForSetPIN(
@@ -142,6 +142,10 @@
       SetPINCallback callback,
       CtapDeviceResponseCode status,
       base::Optional<pin::KeyAgreementResponse> key);
+  void OnHaveEphemeralKeyForUvToken(
+      GetTokenCallback callback,
+      CtapDeviceResponseCode status,
+      base::Optional<pin::KeyAgreementResponse> key);
 
   template <typename... Args>
   void TaskClearProxy(base::OnceCallback<void(Args...)> callback, Args... args);
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h
index 8cfce3a..17105fe 100644
--- a/device/fido/fido_request_handler_base.h
+++ b/device/fido/fido_request_handler_base.h
@@ -142,8 +142,7 @@
         base::Optional<int> attempts,
         base::OnceCallback<void(std::string)> provide_pin_cb) = 0;
 
-    // CollectClientPin is guaranteed to have been called previously.
-    virtual void FinishCollectPIN() = 0;
+    virtual void FinishCollectToken() = 0;
 
     // SetMightCreateResidentCredential indicates whether the activation of an
     // authenticator may cause a resident credential to be created. A resident
diff --git a/device/fido/fido_request_handler_unittest.cc b/device/fido/fido_request_handler_unittest.cc
index 55d29d8..ff481558 100644
--- a/device/fido/fido_request_handler_unittest.cc
+++ b/device/fido/fido_request_handler_unittest.cc
@@ -159,7 +159,7 @@
 
   void SetMightCreateResidentCredential(bool v) override {}
 
-  void FinishCollectPIN() override { NOTREACHED(); }
+  void FinishCollectToken() override { NOTREACHED(); }
 
  private:
   TransportAvailabilityNotificationReceiver
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc
index acf6c08..90373f2 100644
--- a/device/fido/get_assertion_handler_unittest.cc
+++ b/device/fido/get_assertion_handler_unittest.cc
@@ -800,7 +800,7 @@
       base::OnceCallback<void(std::string)> provide_pin_cb) override {
     NOTREACHED();
   }
-  void FinishCollectPIN() override { NOTREACHED(); }
+  void FinishCollectToken() override { NOTREACHED(); }
   void SetMightCreateResidentCredential(bool v) override {}
 
   bool controls_dispatch_ = false;
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc
index 10e72a05..c1355c8 100644
--- a/device/fido/get_assertion_request_handler.cc
+++ b/device/fido/get_assertion_request_handler.cc
@@ -297,6 +297,14 @@
                 kSupportedAndConfigured &&
         request_.user_verification !=
             UserVerificationRequirement::kDiscouraged) {
+      if (authenticator->Options()->supports_uv_token) {
+        FIDO_LOG(DEBUG) << "Getting UV token from "
+                        << authenticator->GetDisplayName();
+        authenticator->GetUvToken(
+            base::BindOnce(&GetAssertionRequestHandler::OnHaveUvToken,
+                           weak_factory_.GetWeakPtr(), authenticator));
+        return;
+      }
       request.user_verification = UserVerificationRequirement::kRequired;
     } else {
       request.user_verification = UserVerificationRequirement::kDiscouraged;
@@ -598,7 +606,7 @@
     return;
   }
 
-  observer()->FinishCollectPIN();
+  observer()->FinishCollectToken();
   state_ = State::kWaitingForSecondTouch;
   CtapGetAssertionRequest request(request_);
   request.pin_auth = response->PinAuth(request.client_data_hash);
@@ -615,4 +623,51 @@
                      weak_factory_.GetWeakPtr(), authenticator_));
 }
 
+void GetAssertionRequestHandler::OnHaveUvToken(
+    FidoAuthenticator* authenticator,
+    CtapDeviceResponseCode status,
+    base::Optional<pin::TokenResponse> response) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+  if (state_ != State::kWaitingForTouch) {
+    FIDO_LOG(DEBUG) << "Ignoring uv token response from "
+                    << authenticator->GetDisplayName()
+                    << " because no longer waiting for touch";
+    return;
+  }
+  if (status != CtapDeviceResponseCode::kSuccess) {
+    // TODO(nsatragno): implement PIN fallback and UV retries.
+    if (status == CtapDeviceResponseCode::kCtap2ErrPinInvalid ||
+        status == CtapDeviceResponseCode::kCtap2ErrOperationDenied) {
+      FIDO_LOG(ERROR) << "Failing assertion request due to status "
+                      << static_cast<int>(status) << " from "
+                      << authenticator->GetDisplayName()
+                      << " on uv token response";
+      CancelActiveAuthenticators(authenticator->GetId());
+      std::move(completion_callback_)
+          .Run(GetAssertionStatus::kUserConsentDenied, base::nullopt, nullptr);
+      return;
+    }
+    FIDO_LOG(ERROR) << "Ignoring status " << static_cast<int>(status)
+                    << " from " << authenticator->GetDisplayName();
+    return;
+  }
+
+  CancelActiveAuthenticators(authenticator->GetId());
+  observer()->FinishCollectToken();
+  authenticator_ = authenticator;
+  state_ = State::kWaitingForSecondTouch;
+  CtapGetAssertionRequest request(request_);
+  request.pin_auth = response->PinAuth(request.client_data_hash);
+  request.pin_protocol = pin::kProtocolVersion;
+  // Do not do internal UV again.
+  request.user_verification = UserVerificationRequirement::kDiscouraged;
+
+  ReportGetAssertionRequestTransport(authenticator_);
+
+  authenticator_->GetAssertion(
+      std::move(request),
+      base::BindOnce(&GetAssertionRequestHandler::HandleResponse,
+                     weak_factory_.GetWeakPtr(), authenticator_));
+}
+
 }  // namespace device
diff --git a/device/fido/get_assertion_request_handler.h b/device/fido/get_assertion_request_handler.h
index f02b7c5..c26a236 100644
--- a/device/fido/get_assertion_request_handler.h
+++ b/device/fido/get_assertion_request_handler.h
@@ -95,6 +95,9 @@
   void OnHavePIN(std::string pin);
   void OnHavePINToken(CtapDeviceResponseCode status,
                       base::Optional<pin::TokenResponse> response);
+  void OnHaveUvToken(FidoAuthenticator* authenticator,
+                     CtapDeviceResponseCode status,
+                     base::Optional<pin::TokenResponse> response);
 
   CompletionCallback completion_callback_;
   State state_ = State::kWaitingForTouch;
diff --git a/device/fido/mac/authenticator.h b/device/fido/mac/authenticator.h
index 0438976c..59b713a 100644
--- a/device/fido/mac/authenticator.h
+++ b/device/fido/mac/authenticator.h
@@ -16,6 +16,7 @@
 #include "base/strings/string_piece_forward.h"
 #include "device/fido/fido_authenticator.h"
 #include "device/fido/fido_transport_protocol.h"
+#include "device/fido/mac/credential_store.h"
 #include "device/fido/mac/operation.h"
 
 namespace device {
@@ -72,15 +73,7 @@
   TouchIdAuthenticator(std::string keychain_access_group,
                        std::string metadata_secret);
 
-  // The keychain access group under which credentials are stored in the macOS
-  // keychain for access control. The set of all access groups that the
-  // application belongs to is stored in the entitlements file that gets
-  // embedded into the application during code signing. For more information
-  // see
-  // https://developer.apple.com/documentation/security/ksecattraccessgroup?language=objc.
-  std::string keychain_access_group_;
-
-  std::string metadata_secret_;
+  TouchIdCredentialStore credential_store_;
 
   std::unique_ptr<Operation> operation_;
 
diff --git a/device/fido/mac/authenticator.mm b/device/fido/mac/authenticator.mm
index 5a47065..46d9733 100644
--- a/device/fido/mac/authenticator.mm
+++ b/device/fido/mac/authenticator.mm
@@ -16,6 +16,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "components/device_event_log/device_event_log.h"
 #include "device/base/features.h"
 #include "device/fido/authenticator_supported_options.h"
 #include "device/fido/ctap_get_assertion_request.h"
@@ -53,24 +54,23 @@
     const CtapGetAssertionRequest& request) {
   if (__builtin_available(macOS 10.12.2, *)) {
     if (request.allow_list.empty()) {
-      return !FindResidentCredentialsInKeychain(keychain_access_group_,
-                                                metadata_secret_, request.rp_id,
-                                                nullptr /* LAContext */)
-                  .empty();
+      base::Optional<std::list<Credential>> resident_credentials =
+          credential_store_.FindResidentCredentials(request.rp_id);
+      if (!resident_credentials) {
+        FIDO_LOG(ERROR) << "FindResidentCredentials() failed";
+        return false;
+      }
+      return !resident_credentials->empty();
     }
 
-    std::set<std::vector<uint8_t>> allowed_credential_ids =
-        FilterInapplicableEntriesFromAllowList(request);
-    if (allowed_credential_ids.empty()) {
-      // The allow list does not have applicable entries, but is not empty.
-      // We must not mistake this for a request for resident credentials and
-      // account choser UI.
+    base::Optional<std::list<Credential>> credentials =
+        credential_store_.FindCredentialsFromCredentialDescriptorList(
+            request.rp_id, request.allow_list);
+    if (!credentials) {
+      FIDO_LOG(ERROR) << "FindCredentialsFromCredentialDescriptorList() failed";
       return false;
     }
-    return !FindCredentialsInKeychain(keychain_access_group_, metadata_secret_,
-                                      request.rp_id, allowed_credential_ids,
-                                      nullptr /* LAContext */)
-                .empty();
+    return !credentials->empty();
   }
   NOTREACHED();
   return false;
@@ -86,8 +86,7 @@
   if (__builtin_available(macOS 10.12.2, *)) {
     DCHECK(!operation_);
     operation_ = std::make_unique<MakeCredentialOperation>(
-        std::move(request), metadata_secret_, keychain_access_group_,
-        std::move(callback));
+        std::move(request), &credential_store_, std::move(callback));
     operation_->Run();
     return;
   }
@@ -99,8 +98,7 @@
   if (__builtin_available(macOS 10.12.2, *)) {
     DCHECK(!operation_);
     operation_ = std::make_unique<GetAssertionOperation>(
-        std::move(request), metadata_secret_, keychain_access_group_,
-        std::move(callback));
+        std::move(request), &credential_store_, std::move(callback));
     operation_->Run();
     return;
   }
@@ -186,8 +184,8 @@
 
 TouchIdAuthenticator::TouchIdAuthenticator(std::string keychain_access_group,
                                            std::string metadata_secret)
-    : keychain_access_group_(std::move(keychain_access_group)),
-      metadata_secret_(std::move(metadata_secret)),
+    : credential_store_(
+          {std::move(keychain_access_group), std::move(metadata_secret)}),
       weak_factory_(this) {}
 
 }  // namespace mac
diff --git a/device/fido/mac/credential_store.h b/device/fido/mac/credential_store.h
index 441b2fb..76e77744 100644
--- a/device/fido/mac/credential_store.h
+++ b/device/fido/mac/credential_store.h
@@ -5,20 +5,110 @@
 #ifndef DEVICE_FIDO_MAC_CREDENTIAL_STORE_H_
 #define DEVICE_FIDO_MAC_CREDENTIAL_STORE_H_
 
+#include <list>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
 #include "base/component_export.h"
+#include "base/mac/availability.h"
+#include "base/mac/foundation_util.h"
+#include "base/optional.h"
 #include "device/fido/mac/authenticator_config.h"
+#include "device/fido/mac/credential_metadata.h"
 #include "device/fido/platform_credential_store.h"
+#include "device/fido/public_key_credential_descriptor.h"
+#include "device/fido/public_key_credential_user_entity.h"
 
 namespace device {
 namespace fido {
 namespace mac {
 
+class LAContext;
+
+// Credential represents a WebAuthn credential from the keychain.
+struct COMPONENT_EXPORT(FIDO) Credential {
+  Credential(base::ScopedCFTypeRef<SecKeyRef> private_key,
+             std::vector<uint8_t> credential_id);
+  ~Credential();
+  Credential(Credential&& other);
+  Credential& operator=(Credential&& other);
+
+  // An opaque reference to the private key that can be used for signing.
+  base::ScopedCFTypeRef<SecKeyRef> private_key;
+
+  // The credential ID is a handle to the key that gets passed to the RP. This
+  // ID is opaque to the RP, but is obtained by encrypting the credential
+  // metadata with a profile-specific metadata secret. See |CredentialMetadata|
+  // for more information.
+  std::vector<uint8_t> credential_id;
+
+ private:
+  Credential(const Credential&) = delete;
+  Credential& operator=(const Credential&) = delete;
+};
+
+// TouchIdCredentialStore allows operations on Touch ID platform authenticator
+// credentials stored in the macOS keychain.
 class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdCredentialStore
     : public ::device::fido::PlatformCredentialStore {
  public:
-  TouchIdCredentialStore(AuthenticatorConfig config);
+  explicit TouchIdCredentialStore(AuthenticatorConfig config);
   ~TouchIdCredentialStore() override;
 
+  // An LAContext that has been successfully evaluated using |TouchIdContext|
+  // may be passed in |authenticaton_context|, in order to authorize
+  // credentials returned by the other instance methods for signing without
+  // triggering a Touch ID prompt.
+  void set_authentication_context(LAContext* authentication_context) {
+    authentication_context_ = authentication_context;
+  }
+
+  // CreateCredential inserts a new credential into the keychain. It returns
+  // the new credential and its public key, or base::nullopt if an error
+  // occurred.
+  API_AVAILABLE(macosx(10.12.2))
+  base::Optional<std::pair<Credential, base::ScopedCFTypeRef<SecKeyRef>>>
+  CreateCredential(const std::string& rp_id,
+                   const PublicKeyCredentialUserEntity& user,
+                   bool is_resident,
+                   SecAccessControlRef access_control) const;
+
+  // FindCredentialsFromCredentialDescriptorList returns all credentials that
+  // match one of the given |descriptors| and belong to |rp_id|. A descriptor
+  // matches a credential if its transports() set is either empty or contains
+  // FidoTransportProtocol::kInternal, and if its id() is the credential ID.
+  // The returned credentials may be resident or non-resident. If any
+  // unexpected keychain API error occurs, base::nullopt is returned instead.
+  API_AVAILABLE(macosx(10.12.2))
+  base::Optional<std::list<Credential>>
+  FindCredentialsFromCredentialDescriptorList(
+      const std::string& rp_id,
+      const std::vector<PublicKeyCredentialDescriptor>& descriptors) const;
+
+  // FindResidentCredentials returns the resident credentials for the given
+  // |rp_id|, or base::nulltopt if an error occurred.
+  API_AVAILABLE(macosx(10.12.2))
+  base::Optional<std::list<Credential>> FindResidentCredentials(
+      const std::string& rp_id) const;
+
+  // UnsealMetadata returns the CredentialMetadata for the given credential's
+  // ID if it was encoded for the given RP ID, or base::nullopt otherwise.
+  API_AVAILABLE(macosx(10.12.2))
+  base::Optional<CredentialMetadata> UnsealMetadata(
+      const std::string& rp_id,
+      const Credential& credential) const;
+
+  // DeleteCredentialsForUserId deletes all (resident or non-resident)
+  // credentials for the given RP and user ID. Returns true if deleting
+  // succeeded or no matching credential exists, and false otherwise.
+  API_AVAILABLE(macosx(10.12.2))
+  bool DeleteCredentialsForUserId(const std::string& rp_id,
+                                  base::span<const uint8_t> user_id) const;
+
+  // PlatformCredentialStore:
+
   // DeleteCredentials deletes Touch ID authenticator credentials from
   // the macOS keychain that were created within the given time interval and
   // with the given metadata secret (which is tied to a browser profile). The
@@ -41,7 +131,13 @@
                           base::Time created_not_after) override;
 
  private:
+  API_AVAILABLE(macosx(10.12.2))
+  base::Optional<std::list<Credential>> FindCredentialsImpl(
+      const std::string& rp_id,
+      const std::set<std::vector<uint8_t>>& credential_ids) const;
+
   AuthenticatorConfig config_;
+  LAContext* authentication_context_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(TouchIdCredentialStore);
 };
diff --git a/device/fido/mac/credential_store.mm b/device/fido/mac/credential_store.mm
index 8f5337e..8ab3007 100644
--- a/device/fido/mac/credential_store.mm
+++ b/device/fido/mac/credential_store.mm
@@ -4,8 +4,6 @@
 
 #include "device/fido/mac/credential_store.h"
 
-#include <string>
-
 #import <Foundation/Foundation.h>
 #import <Security/Security.h>
 
@@ -17,7 +15,7 @@
 #include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/strings/sys_string_conversions.h"
-#include "device/base/features.h"
+#include "components/device_event_log/device_event_log.h"
 #include "device/fido/mac/credential_metadata.h"
 #include "device/fido/mac/keychain.h"
 
@@ -27,6 +25,24 @@
 
 namespace {
 
+// DefaultKeychainQuery returns a default keychain query dictionary that has
+// the keychain item class, keychain access group and RP ID filled out (but
+// not the credential ID). More fields can be set on the return value to
+// refine the query.
+base::ScopedCFTypeRef<CFMutableDictionaryRef> DefaultKeychainQuery(
+    const AuthenticatorConfig& config,
+    const std::string& rp_id) {
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> query(
+      CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr));
+  CFDictionarySetValue(query, kSecClass, kSecClassKey);
+  CFDictionarySetValue(query, kSecAttrAccessGroup,
+                       base::SysUTF8ToNSString(config.keychain_access_group));
+  CFDictionarySetValue(
+      query, kSecAttrLabel,
+      base::SysUTF8ToNSString(EncodeRpId(config.metadata_secret, rp_id)));
+  return query;
+}
+
 // Erase all keychain items with a creation date that is not within [not_before,
 // not_after).
 void FilterKeychainItemsByCreationDate(
@@ -49,6 +65,7 @@
         return creation_date < not_before || creation_date >= not_after;
       });
 }
+
 base::Optional<std::vector<base::ScopedCFTypeRef<CFDictionaryRef>>>
 QueryKeychainItemsForProfile(const std::string& keychain_access_group,
                              const std::string& metadata_secret,
@@ -192,10 +209,138 @@
 }
 }  // namespace
 
+Credential::Credential(base::ScopedCFTypeRef<SecKeyRef> private_key_,
+                       std::vector<uint8_t> credential_id_)
+    : private_key(std::move(private_key_)),
+      credential_id(std::move(credential_id_)) {}
+Credential::~Credential() = default;
+Credential::Credential(Credential&& other) = default;
+Credential& Credential::operator=(Credential&& other) = default;
+
 TouchIdCredentialStore::TouchIdCredentialStore(AuthenticatorConfig config)
     : config_(std::move(config)) {}
 TouchIdCredentialStore::~TouchIdCredentialStore() = default;
 
+base::Optional<std::pair<Credential, base::ScopedCFTypeRef<SecKeyRef>>>
+TouchIdCredentialStore::CreateCredential(
+    const std::string& rp_id,
+    const PublicKeyCredentialUserEntity& user,
+    bool is_resident,
+    SecAccessControlRef access_control) const {
+  std::vector<uint8_t> credential_id = SealCredentialId(
+      config_.metadata_secret, rp_id,
+      CredentialMetadata::FromPublicKeyCredentialUserEntity(user, is_resident));
+
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> params(
+      CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr));
+  CFDictionarySetValue(params, kSecAttrKeyType,
+                       kSecAttrKeyTypeECSECPrimeRandom);
+  CFDictionarySetValue(params, kSecAttrKeySizeInBits, @256);
+  CFDictionarySetValue(params, kSecAttrSynchronizable, @NO);
+  CFDictionarySetValue(params, kSecAttrTokenID, kSecAttrTokenIDSecureEnclave);
+
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> private_key_params =
+      DefaultKeychainQuery(config_, rp_id);
+  CFDictionarySetValue(params, kSecPrivateKeyAttrs, private_key_params);
+  CFDictionarySetValue(private_key_params, kSecAttrIsPermanent, @YES);
+  CFDictionarySetValue(private_key_params, kSecAttrAccessControl,
+                       access_control);
+  if (authentication_context_) {
+    CFDictionarySetValue(private_key_params, kSecUseAuthenticationContext,
+                         authentication_context_);
+  }
+  CFDictionarySetValue(private_key_params, kSecAttrApplicationTag,
+                       base::SysUTF8ToNSString(EncodeRpIdAndUserId(
+                           config_.metadata_secret, rp_id, user.id)));
+  CFDictionarySetValue(private_key_params, kSecAttrApplicationLabel,
+                       [NSData dataWithBytes:credential_id.data()
+                                      length:credential_id.size()]);
+
+  base::ScopedCFTypeRef<CFErrorRef> cferr;
+  base::ScopedCFTypeRef<SecKeyRef> private_key(
+      Keychain::GetInstance().KeyCreateRandomKey(params,
+                                                 cferr.InitializeInto()));
+  if (!private_key) {
+    FIDO_LOG(ERROR) << "SecKeyCreateRandomKey failed: " << cferr;
+    return base::nullopt;
+  }
+  base::ScopedCFTypeRef<SecKeyRef> public_key(
+      Keychain::GetInstance().KeyCopyPublicKey(private_key));
+  if (!public_key) {
+    FIDO_LOG(ERROR) << "SecKeyCopyPublicKey failed";
+    return base::nullopt;
+  }
+
+  return std::make_pair(
+      Credential(std::move(private_key), std::move(credential_id)),
+      std::move(public_key));
+}
+
+base::Optional<std::list<Credential>>
+TouchIdCredentialStore::FindCredentialsFromCredentialDescriptorList(
+    const std::string& rp_id,
+    const std::vector<PublicKeyCredentialDescriptor>& descriptors) const {
+  std::set<std::vector<uint8_t>> credential_ids;
+  for (const auto& descriptor : descriptors) {
+    if (descriptor.credential_type() == CredentialType::kPublicKey &&
+        (descriptor.transports().empty() ||
+         base::Contains(descriptor.transports(),
+                        FidoTransportProtocol::kInternal))) {
+      credential_ids.insert(descriptor.id());
+    }
+  }
+  if (credential_ids.empty()) {
+    // Don't call FindCredentialsImpl(). Given an empty |credential_ids|, it
+    // returns *all* credentials for |rp_id|.
+    return {};
+  }
+  return FindCredentialsImpl(rp_id, credential_ids);
+}
+
+base::Optional<std::list<Credential>>
+TouchIdCredentialStore::FindResidentCredentials(
+    const std::string& rp_id) const {
+  base::Optional<std::list<Credential>> credentials =
+      FindCredentialsImpl(rp_id, /*credential_ids=*/{});
+  if (!credentials) {
+    return base::nullopt;
+  }
+  credentials->remove_if([this, &rp_id](const Credential& credential) {
+    auto opt_metadata = UnsealCredentialId(config_.metadata_secret, rp_id,
+                                           credential.credential_id);
+    if (!opt_metadata) {
+      FIDO_LOG(ERROR) << "UnsealCredentialId() failed";
+      return true;
+    }
+    return !opt_metadata->is_resident;
+  });
+  return credentials;
+}
+
+base::Optional<CredentialMetadata> TouchIdCredentialStore::UnsealMetadata(
+    const std::string& rp_id,
+    const Credential& credential) const {
+  return UnsealCredentialId(config_.metadata_secret, rp_id,
+                            credential.credential_id);
+}
+
+bool TouchIdCredentialStore::DeleteCredentialsForUserId(
+    const std::string& rp_id,
+    base::span<const uint8_t> user_id) const {
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> query =
+      DefaultKeychainQuery(config_, rp_id);
+  CFDictionarySetValue(query, kSecAttrApplicationTag,
+                       base::SysUTF8ToNSString(EncodeRpIdAndUserId(
+                           config_.metadata_secret, rp_id, user_id)));
+
+  OSStatus status = Keychain::GetInstance().ItemDelete(query);
+  if (status != errSecSuccess && status != errSecItemNotFound) {
+    OSSTATUS_DLOG(ERROR, status) << "SecItemDelete failed";
+    return false;
+  }
+  return true;
+}
+
 bool TouchIdCredentialStore::DeleteCredentials(base::Time created_not_before,
                                                base::Time created_not_after) {
   // Touch ID uses macOS APIs available in 10.12.2 or newer. No need to check
@@ -218,6 +363,66 @@
   return 0;
 }
 
+API_AVAILABLE(macosx(10.12.2))
+base::Optional<std::list<Credential>>
+TouchIdCredentialStore::FindCredentialsImpl(
+    const std::string& rp_id,
+    const std::set<std::vector<uint8_t>>& credential_ids) const {
+  base::ScopedCFTypeRef<CFMutableDictionaryRef> query =
+      DefaultKeychainQuery(config_, rp_id);
+  if (authentication_context_) {
+    CFDictionarySetValue(query, kSecUseAuthenticationContext,
+                         authentication_context_);
+  }
+  CFDictionarySetValue(query, kSecReturnRef, @YES);
+  CFDictionarySetValue(query, kSecReturnAttributes, @YES);
+  CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
+
+  base::ScopedCFTypeRef<CFArrayRef> keychain_items;
+  OSStatus status = Keychain::GetInstance().ItemCopyMatching(
+      query, reinterpret_cast<CFTypeRef*>(keychain_items.InitializeInto()));
+  if (status == errSecItemNotFound) {
+    return std::list<Credential>();
+  }
+  if (status != errSecSuccess) {
+    FIDO_LOG(ERROR) << "SecItemCopyMatching failed: "
+                    << logging::DescriptionFromOSStatus(status);
+    return base::nullopt;
+  }
+
+  // Filter credentials for the RP down to |credential_ids|, unless it's
+  // empty in which case all credentials should be returned.
+  std::list<Credential> credentials;
+  for (CFIndex i = 0; i < CFArrayGetCount(keychain_items); ++i) {
+    CFDictionaryRef attributes = base::mac::CFCast<CFDictionaryRef>(
+        CFArrayGetValueAtIndex(keychain_items, i));
+    CFDataRef application_label = base::mac::GetValueFromDictionary<CFDataRef>(
+        attributes, kSecAttrApplicationLabel);
+    if (!application_label) {
+      FIDO_LOG(ERROR) << "credential with missing application label";
+      return base::nullopt;
+    }
+    SecKeyRef key =
+        base::mac::GetValueFromDictionary<SecKeyRef>(attributes, kSecValueRef);
+    if (!key) {
+      FIDO_LOG(ERROR) << "credential with missing value ref";
+      return base::nullopt;
+    }
+    std::vector<uint8_t> credential_id(CFDataGetBytePtr(application_label),
+                                       CFDataGetBytePtr(application_label) +
+                                           CFDataGetLength(application_label));
+    if (!credential_ids.empty() &&
+        !base::Contains(credential_ids, credential_id)) {
+      continue;
+    }
+    base::ScopedCFTypeRef<SecKeyRef> private_key(key,
+                                                 base::scoped_policy::RETAIN);
+    credentials.emplace_back(
+        Credential{std::move(private_key), std::move(credential_id)});
+  }
+  return std::move(credentials);
+}
+
 }  // namespace mac
 }  // namespace fido
 }  // namespace device
diff --git a/device/fido/mac/get_assertion_operation.h b/device/fido/mac/get_assertion_operation.h
index c05260e..00a31a6f 100644
--- a/device/fido/mac/get_assertion_operation.h
+++ b/device/fido/mac/get_assertion_operation.h
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/ctap_get_assertion_request.h"
-#include "device/fido/mac/keychain.h"
+#include "device/fido/mac/credential_store.h"
 #include "device/fido/mac/operation.h"
 #include "device/fido/mac/touch_id_context.h"
 
@@ -36,8 +36,7 @@
       base::Optional<AuthenticatorGetAssertionResponse>)>;
 
   GetAssertionOperation(CtapGetAssertionRequest request,
-                        std::string metadata_secret,
-                        std::string keychain_access_group,
+                        TouchIdCredentialStore* credential_store,
                         Callback callback);
   ~GetAssertionOperation() override;
 
@@ -53,26 +52,17 @@
   base::Optional<AuthenticatorGetAssertionResponse> ResponseForCredential(
       const Credential& credential);
 
-  // The secret parameter passed to |CredentialMetadata| operations to encrypt
-  // or encode credential metadata for storage in the macOS keychain.
-  const std::string metadata_secret_;
-  const std::string keychain_access_group_;
-
   const std::unique_ptr<TouchIdContext> touch_id_context_ =
       TouchIdContext::Create();
 
   const CtapGetAssertionRequest request_;
+  TouchIdCredentialStore* const credential_store_;
   Callback callback_;
   std::list<Credential> matching_credentials_;
 
   DISALLOW_COPY_AND_ASSIGN(GetAssertionOperation);
 };
 
-// Returns request.allow_list without entries that have an in inapplicable
-// |transports| field or a |type| other than "public-key".
-std::set<std::vector<uint8_t>> FilterInapplicableEntriesFromAllowList(
-    const CtapGetAssertionRequest& request);
-
 }  // namespace mac
 }  // namespace fido
 }  // namespace device
diff --git a/device/fido/mac/get_assertion_operation.mm b/device/fido/mac/get_assertion_operation.mm
index 4cd7758..a7c01d15 100644
--- a/device/fido/mac/get_assertion_operation.mm
+++ b/device/fido/mac/get_assertion_operation.mm
@@ -19,7 +19,6 @@
 #include "components/device_event_log/device_event_log.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/mac/credential_metadata.h"
-#include "device/fido/mac/keychain.h"
 #include "device/fido/mac/util.h"
 #include "device/fido/public_key_credential_descriptor.h"
 #include "device/fido/public_key_credential_user_entity.h"
@@ -32,14 +31,14 @@
 
 using base::ScopedCFTypeRef;
 
-GetAssertionOperation::GetAssertionOperation(CtapGetAssertionRequest request,
-                                             std::string metadata_secret,
-                                             std::string keychain_access_group,
-                                             Callback callback)
-    : metadata_secret_(std::move(metadata_secret)),
-      keychain_access_group_(std::move(keychain_access_group)),
-      request_(std::move(request)),
+GetAssertionOperation::GetAssertionOperation(
+    CtapGetAssertionRequest request,
+    TouchIdCredentialStore* credential_store,
+    Callback callback)
+    : request_(std::move(request)),
+      credential_store_(credential_store),
       callback_(std::move(callback)) {}
+
 GetAssertionOperation::~GetAssertionOperation() = default;
 
 void GetAssertionOperation::Run() {
@@ -57,30 +56,28 @@
                              base::nullopt);
     return;
   }
-  std::set<std::vector<uint8_t>> allowed_credential_ids =
-      FilterInapplicableEntriesFromAllowList(request_);
-  if (allowed_credential_ids.empty() && !request_.allow_list.empty()) {
-    // The caller checking
-    // TouchIdAuthenticator::HasCredentialForGetAssertionRequest() should have
-    // caught this.
-    NOTREACHED();
-    std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials,
+
+  // Setting an authentication context authorizes credentials returned from the
+  // credential store for signing without triggering yet another Touch ID
+  // prompt.
+  credential_store_->set_authentication_context(
+      touch_id_context_->authentication_context());
+
+  const bool empty_allow_list = request_.allow_list.empty();
+  base::Optional<std::list<Credential>> credentials =
+      empty_allow_list
+          ? credential_store_->FindResidentCredentials(request_.rp_id)
+          : credential_store_->FindCredentialsFromCredentialDescriptorList(
+                request_.rp_id, request_.allow_list);
+
+  if (!credentials) {
+    FIDO_LOG(ERROR) << "FindCredentialsFromCredentialDescriptorList() failed";
+    std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
                              base::nullopt);
     return;
   }
-  const bool empty_allow_list = request_.allow_list.empty();
 
-  std::list<Credential> credentials =
-      empty_allow_list
-          ? FindResidentCredentialsInKeychain(
-                keychain_access_group_, metadata_secret_, request_.rp_id,
-                touch_id_context_->authentication_context())
-          : FindCredentialsInKeychain(
-                keychain_access_group_, metadata_secret_, request_.rp_id,
-                allowed_credential_ids,
-                touch_id_context_->authentication_context());
-
-  if (credentials.empty()) {
+  if (credentials->empty()) {
     // TouchIdAuthenticator::HasCredentialForGetAssertionRequest() is
     // invoked first to ensure this doesn't occur.
     NOTREACHED();
@@ -90,7 +87,7 @@
   }
 
   base::Optional<AuthenticatorGetAssertionResponse> response =
-      ResponseForCredential(credentials.front());
+      ResponseForCredential(credentials->front());
   if (!response) {
     std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials,
                              base::nullopt);
@@ -98,9 +95,9 @@
   }
 
   if (empty_allow_list) {
-    response->SetNumCredentials(credentials.size());
-    credentials.pop_front();
-    matching_credentials_ = std::move(credentials);
+    response->SetNumCredentials(credentials->size());
+    credentials->pop_front();
+    matching_credentials_ = std::move(*credentials);
   }
 
   std::move(callback_).Run(CtapDeviceResponseCode::kSuccess,
@@ -124,13 +121,13 @@
 
 base::Optional<AuthenticatorGetAssertionResponse>
 GetAssertionOperation::ResponseForCredential(const Credential& credential) {
-  base::Optional<CredentialMetadata> metadata = UnsealCredentialId(
-      metadata_secret_, request_.rp_id, credential.credential_id);
+  base::Optional<CredentialMetadata> metadata =
+      credential_store_->UnsealMetadata(request_.rp_id, credential);
   if (!metadata) {
     // The keychain query already filtered for the RP ID encoded under this
     // operation's metadata secret, so the credential id really should have
     // been decryptable.
-    FIDO_LOG(ERROR) << "UnsealCredentialId failed";
+    FIDO_LOG(ERROR) << "UnsealMetadata failed";
     return base::nullopt;
   }
 
@@ -150,20 +147,6 @@
   return response;
 }
 
-std::set<std::vector<uint8_t>> FilterInapplicableEntriesFromAllowList(
-    const CtapGetAssertionRequest& request) {
-  std::set<std::vector<uint8_t>> allowed_credential_ids;
-  for (const auto& credential_descriptor : request.allow_list) {
-    if (credential_descriptor.credential_type() == CredentialType::kPublicKey &&
-        (credential_descriptor.transports().empty() ||
-         base::Contains(credential_descriptor.transports(),
-                        FidoTransportProtocol::kInternal))) {
-      allowed_credential_ids.insert(credential_descriptor.id());
-    }
-  }
-  return allowed_credential_ids;
-}
-
 }  // namespace mac
 }  // namespace fido
 }  // namespace device
diff --git a/device/fido/mac/get_assertion_operation_unittest_mac.mm b/device/fido/mac/get_assertion_operation_unittest_mac.mm
index cebbde3..b6af4c75 100644
--- a/device/fido/mac/get_assertion_operation_unittest_mac.mm
+++ b/device/fido/mac/get_assertion_operation_unittest_mac.mm
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/mac/get_assertion_operation.h"
-
 #include <array>
 
 #include <Foundation/Foundation.h>
@@ -14,6 +12,9 @@
 #include "base/test/task_environment.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_test_data.h"
+#include "device/fido/mac/authenticator_config.h"
+#include "device/fido/mac/credential_store.h"
+#include "device/fido/mac/get_assertion_operation.h"
 #include "device/fido/mac/make_credential_operation.h"
 #include "device/fido/test_callback_receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -45,7 +46,9 @@
       PublicKeyCredentialParams(
           {{PublicKeyCredentialParams::
                 CredentialInfo() /* defaults to ES-256 */}}));
-  MakeCredentialOperation op(request, "test-profile", kKeychainAccessGroup,
+  TouchIdCredentialStore credential_store(
+      AuthenticatorConfig{"test-profile", kKeychainAccessGroup});
+  MakeCredentialOperation op(request, &credential_store,
                              callback_receiver.callback());
 
   op.Run();
@@ -68,7 +71,9 @@
                        base::Optional<AuthenticatorGetAssertionResponse>>
       callback_receiver;
   auto request = MakeTestRequest();
-  GetAssertionOperation op(request, "test-profile", kKeychainAccessGroup,
+  TouchIdCredentialStore credential_store(
+      AuthenticatorConfig{"test-profile", kKeychainAccessGroup});
+  GetAssertionOperation op(request, &credential_store,
                            callback_receiver.callback());
 
   op.Run();
diff --git a/device/fido/mac/keychain.h b/device/fido/mac/keychain.h
index c661ca4a..245917e 100644
--- a/device/fido/mac/keychain.h
+++ b/device/fido/mac/keychain.h
@@ -5,12 +5,6 @@
 #ifndef DEVICE_FIDO_MAC_KEYCHAIN_H_
 #define DEVICE_FIDO_MAC_KEYCHAIN_H_
 
-#include <stdint.h>
-#include <list>
-#include <set>
-#include <string>
-#include <vector>
-
 #import <Foundation/Foundation.h>
 #import <LocalAuthentication/LocalAuthentication.h>
 #import <Security/Security.h>
@@ -19,7 +13,6 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/macros.h"
 #include "base/no_destructor.h"
-#include "base/optional.h"
 
 namespace device {
 namespace fido {
@@ -71,57 +64,6 @@
 
   DISALLOW_COPY_AND_ASSIGN(Keychain);
 };
-
-// Credential represents a WebAuthn credential from the keychain.
-struct COMPONENT_EXPORT(FIDO) Credential {
-  Credential(base::ScopedCFTypeRef<SecKeyRef> private_key,
-             std::vector<uint8_t> credential_id);
-  ~Credential();
-  Credential(Credential&& other);
-  Credential& operator=(Credential&& other);
-
-  // An opaque reference to the private key that can be used for signing.
-  base::ScopedCFTypeRef<SecKeyRef> private_key;
-
-  // The credential ID is a handle to the key that gets passed to the RP. This
-  // ID is opaque to the RP, but is obtained by encrypting the credential
-  // metadata with a profile-specific metadata secret. See |CredentialMetadata|
-  // for more information.
-  std::vector<uint8_t> credential_id;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Credential);
-};
-
-// FindCredentialsInKeychain returns a list of credentials for the given
-// |rp_id| with credential IDs matching those from |allowed_credential_ids|,
-// which may not be empty. The returned credentials may be resident or
-// non-resident.
-//
-// An LAContext that has been successfully evaluated using |TouchIdContext| may
-// be passed in |authenticaton_context|, in order to authorize the credential's
-// private key for signing. The authentication may also be null if the caller
-// only wants to check for existence of a key, but does not intend to create a
-// signature from it. (I.e., the credential's SecKeyRef should not be passed to
-// |KeyCreateSignature| if no authentication context was provided, since that
-// would trigger a Touch ID prompt dialog).
-COMPONENT_EXPORT(FIDO)
-std::list<Credential> FindCredentialsInKeychain(
-    const std::string& keychain_access_group,
-    const std::string& metadata_secret,
-    const std::string& rp_id,
-    const std::set<std::vector<uint8_t>>& allowed_credential_ids,
-    LAContext* authentication_context) API_AVAILABLE(macosx(10.12.2));
-
-// FindResidentCredentialsInKeychain returns a list of resident credentials for
-// the given |rp_id|.
-COMPONENT_EXPORT(FIDO)
-std::list<Credential> FindResidentCredentialsInKeychain(
-    const std::string& keychain_access_group,
-    const std::string& metadata_secret,
-    const std::string& rp_id,
-    LAContext* authentication_context) API_AVAILABLE(macosx(10.12.2));
-
 }  // namespace mac
 }  // namespace fido
 }  // namespace device
diff --git a/device/fido/mac/keychain.mm b/device/fido/mac/keychain.mm
index 4832676..5ed91cf6 100644
--- a/device/fido/mac/keychain.mm
+++ b/device/fido/mac/keychain.mm
@@ -4,15 +4,6 @@
 
 #include "device/fido/mac/keychain.h"
 
-#import <Foundation/Foundation.h>
-
-#include "base/mac/foundation_util.h"
-#include "base/mac/mac_logging.h"
-#include "base/stl_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "components/device_event_log/device_event_log.h"
-#include "device/fido/mac/credential_metadata.h"
-
 namespace device {
 namespace fido {
 namespace mac {
@@ -71,115 +62,6 @@
   return SecItemDelete(query);
 }
 
-Credential::Credential(base::ScopedCFTypeRef<SecKeyRef> private_key_,
-                       std::vector<uint8_t> credential_id_)
-    : private_key(std::move(private_key_)),
-      credential_id(std::move(credential_id_)) {}
-Credential::~Credential() = default;
-Credential::Credential(Credential&& other) = default;
-Credential& Credential::operator=(Credential&& other) = default;
-
-// Like FindCredentialsInKeychain(), but empty |allowed_credential_ids| allows
-// any credential to match.
-static std::list<Credential> FindCredentialsImpl(
-    const std::string& keychain_access_group,
-    const std::string& metadata_secret,
-    const std::string& rp_id,
-    const std::set<std::vector<uint8_t>>& allowed_credential_ids,
-    LAContext* authentication_context) API_AVAILABLE(macosx(10.12.2)) {
-  base::ScopedCFTypeRef<CFMutableDictionaryRef> query(
-      CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr));
-  CFDictionarySetValue(query, kSecClass, kSecClassKey);
-  CFDictionarySetValue(query, kSecAttrAccessGroup,
-                       base::SysUTF8ToNSString(keychain_access_group));
-  CFDictionarySetValue(
-      query, kSecAttrLabel,
-      base::SysUTF8ToNSString(EncodeRpId(metadata_secret, rp_id)));
-  if (authentication_context) {
-    CFDictionarySetValue(query, kSecUseAuthenticationContext,
-                         authentication_context);
-  }
-  CFDictionarySetValue(query, kSecReturnRef, @YES);
-  CFDictionarySetValue(query, kSecReturnAttributes, @YES);
-  CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
-
-  base::ScopedCFTypeRef<CFArrayRef> keychain_items;
-  OSStatus status = Keychain::GetInstance().ItemCopyMatching(
-      query, reinterpret_cast<CFTypeRef*>(keychain_items.InitializeInto()));
-  if (status == errSecItemNotFound) {
-    // No credentials for the RP.
-    return {};
-  }
-  if (status != errSecSuccess) {
-    OSSTATUS_DLOG(ERROR, status) << "SecItemCopyMatching failed";
-    return {};
-  }
-
-  // Filter credentials for the RP down to |allowed_credential_ids|, unless it's
-  // empty in which case all credentials should be returned.
-  std::list<Credential> result;
-  for (CFIndex i = 0; i < CFArrayGetCount(keychain_items); ++i) {
-    CFDictionaryRef attributes = base::mac::CFCast<CFDictionaryRef>(
-        CFArrayGetValueAtIndex(keychain_items, i));
-    CFDataRef application_label = base::mac::GetValueFromDictionary<CFDataRef>(
-        attributes, kSecAttrApplicationLabel);
-    SecKeyRef key =
-        base::mac::GetValueFromDictionary<SecKeyRef>(attributes, kSecValueRef);
-    if (!application_label || !key) {
-      // Corrupted keychain?
-      DLOG(ERROR) << "could not find application label or key ref: "
-                  << attributes;
-      continue;
-    }
-    std::vector<uint8_t> credential_id(CFDataGetBytePtr(application_label),
-                                       CFDataGetBytePtr(application_label) +
-                                           CFDataGetLength(application_label));
-    if (!allowed_credential_ids.empty() &&
-        !base::Contains(allowed_credential_ids, credential_id)) {
-      continue;
-    }
-    base::ScopedCFTypeRef<SecKeyRef> private_key(key,
-                                                 base::scoped_policy::RETAIN);
-    result.emplace_back(
-        Credential(std::move(private_key), std::move(credential_id)));
-  }
-  return result;
-}
-
-std::list<Credential> FindCredentialsInKeychain(
-    const std::string& keychain_access_group,
-    const std::string& metadata_secret,
-    const std::string& rp_id,
-    const std::set<std::vector<uint8_t>>& allowed_credential_ids,
-    LAContext* authentication_context) {
-  if (allowed_credential_ids.empty()) {
-    NOTREACHED();
-    return {};
-  }
-  return FindCredentialsImpl(keychain_access_group, metadata_secret, rp_id,
-                             allowed_credential_ids, authentication_context);
-}
-
-std::list<Credential> FindResidentCredentialsInKeychain(
-    const std::string& keychain_access_group,
-    const std::string& metadata_secret,
-    const std::string& rp_id,
-    LAContext* authentication_context) {
-  std::list<Credential> result = FindCredentialsImpl(
-      keychain_access_group, metadata_secret, rp_id,
-      /*allowed_credential_ids=*/{}, authentication_context);
-  result.remove_if([&metadata_secret, &rp_id](const Credential& credential) {
-    auto opt_metadata =
-        UnsealCredentialId(metadata_secret, rp_id, credential.credential_id);
-    if (!opt_metadata) {
-      FIDO_LOG(ERROR) << "UnsealCredentialId() failed";
-      return true;
-    }
-    return !opt_metadata->is_resident;
-  });
-  return result;
-}
-
 }  // namespace mac
 }  // namespace fido
 }  // namespace device
diff --git a/device/fido/mac/make_credential_operation.h b/device/fido/mac/make_credential_operation.h
index 5495b6371..6ef4c020 100644
--- a/device/fido/mac/make_credential_operation.h
+++ b/device/fido/mac/make_credential_operation.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/mac/credential_store.h"
 #include "device/fido/mac/operation.h"
 #include "device/fido/mac/touch_id_context.h"
 
@@ -52,8 +53,7 @@
       base::Optional<AuthenticatorMakeCredentialResponse>)>;
 
   MakeCredentialOperation(CtapMakeCredentialRequest request,
-                          std::string profile_id,
-                          std::string keychain_access_group,
+                          TouchIdCredentialStore* credential_store,
                           Callback callback);
   ~MakeCredentialOperation() override;
 
@@ -63,21 +63,11 @@
  private:
   void PromptTouchIdDone(bool success);
 
-  // DefaultKeychainQuery returns a default keychain query dictionary that has
-  // the keychain item class, keychain access group and RP ID filled out (but
-  // not the credential ID). More fields can be set on the return value to
-  // refine the query.
-  base::ScopedCFTypeRef<CFMutableDictionaryRef> DefaultKeychainQuery() const;
-
-  // The secret parameter passed to |CredentialMetadata| operations to encrypt
-  // or encode credential metadata for storage in the macOS keychain.
-  const std::string metadata_secret_;
-  const std::string keychain_access_group_;
-
   const std::unique_ptr<TouchIdContext> touch_id_context_ =
       TouchIdContext::Create();
 
   const CtapMakeCredentialRequest request_;
+  TouchIdCredentialStore* const credential_store_;
   Callback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(MakeCredentialOperation);
diff --git a/device/fido/mac/make_credential_operation.mm b/device/fido/mac/make_credential_operation.mm
index 0e2ead1..03fc0c85 100644
--- a/device/fido/mac/make_credential_operation.mm
+++ b/device/fido/mac/make_credential_operation.mm
@@ -22,7 +22,7 @@
 #include "device/fido/fido_parsing_utils.h"
 #include "device/fido/fido_transport_protocol.h"
 #include "device/fido/mac/credential_metadata.h"
-#include "device/fido/mac/keychain.h"
+#include "device/fido/mac/credential_store.h"
 #include "device/fido/mac/util.h"
 #include "device/fido/strings/grit/fido_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -31,17 +31,14 @@
 namespace fido {
 namespace mac {
 
-using base::ScopedCFTypeRef;
-
 MakeCredentialOperation::MakeCredentialOperation(
     CtapMakeCredentialRequest request,
-    std::string metadata_secret,
-    std::string keychain_access_group,
+    TouchIdCredentialStore* credential_store,
     Callback callback)
-    : metadata_secret_(std::move(metadata_secret)),
-      keychain_access_group_(std::move(keychain_access_group)),
-      request_(std::move(request)),
+    : request_(std::move(request)),
+      credential_store_(credential_store),
       callback_(std::move(callback)) {}
+
 MakeCredentialOperation::~MakeCredentialOperation() = default;
 
 void MakeCredentialOperation::Run() {
@@ -76,91 +73,47 @@
     return;
   }
 
-  // Evaluate that excludeList does not contain any credentials stored by this
-  // authenticator.
-  for (auto& credential : request_.exclude_list) {
-    ScopedCFTypeRef<CFMutableDictionaryRef> query = DefaultKeychainQuery();
-    CFDictionarySetValue(query, kSecAttrApplicationLabel,
-                         [NSData dataWithBytes:credential.id().data()
-                                        length:credential.id().size()]);
-    OSStatus status = SecItemCopyMatching(query, nullptr);
-    if (status == errSecSuccess) {
-      // Excluded item found.
-      DVLOG(1) << "credential from excludeList found";
-      std::move(callback_).Run(
-          CtapDeviceResponseCode::kCtap2ErrCredentialExcluded, base::nullopt);
-      return;
-    }
-    if (status != errSecItemNotFound) {
-      // Unexpected keychain error.
-      OSSTATUS_DLOG(ERROR, status) << "failed to check for excluded credential";
+  // Setting an authentication context authorizes credentials returned from the
+  // credential store for signing without triggering yet another Touch ID
+  // prompt.
+  credential_store_->set_authentication_context(
+      touch_id_context_->authentication_context());
+
+  if (!request_.exclude_list.empty()) {
+    base::Optional<std::list<Credential>> credentials =
+        credential_store_->FindCredentialsFromCredentialDescriptorList(
+            request_.rp.id, request_.exclude_list);
+    if (!credentials) {
+      FIDO_LOG(ERROR) << "Failed to check for excluded credentials";
       std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
                                base::nullopt);
       return;
     }
+    if (!credentials->empty()) {
+      std::move(callback_).Run(
+          CtapDeviceResponseCode::kCtap2ErrCredentialExcluded, base::nullopt);
+      return;
+    }
   }
 
   // Delete the key pair for this RP + user handle if one already exists.
   //
-  // Note that because the rk bit is not encoded here, a resident credential
-  // may overwrite a non-resident credential and vice versa.
-  const std::string encoded_rp_id_user_id =
-      EncodeRpIdAndUserId(metadata_secret_, request_.rp.id, request_.user.id);
-  {
-    ScopedCFTypeRef<CFMutableDictionaryRef> query = DefaultKeychainQuery();
-    CFDictionarySetValue(query, kSecAttrApplicationTag,
-                         base::SysUTF8ToNSString(encoded_rp_id_user_id));
-    OSStatus status = Keychain::GetInstance().ItemDelete(query);
-    if (status != errSecSuccess && status != errSecItemNotFound) {
-      OSSTATUS_DLOG(ERROR, status) << "SecItemDelete failed";
-      std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
-                               base::nullopt);
-      return;
-    }
-  }
-
-  // Generate the new key pair.
-  const std::vector<uint8_t> credential_id =
-      SealCredentialId(metadata_secret_, request_.rp.id,
-                       CredentialMetadata::FromPublicKeyCredentialUserEntity(
-                           request_.user, request_.resident_key_required));
-
-  ScopedCFTypeRef<CFMutableDictionaryRef> params(
-      CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr));
-  CFDictionarySetValue(params, kSecAttrKeyType,
-                       kSecAttrKeyTypeECSECPrimeRandom);
-  CFDictionarySetValue(params, kSecAttrKeySizeInBits, @256);
-  CFDictionarySetValue(params, kSecAttrSynchronizable, @NO);
-  CFDictionarySetValue(params, kSecAttrTokenID, kSecAttrTokenIDSecureEnclave);
-
-  ScopedCFTypeRef<CFMutableDictionaryRef> private_key_params =
-      DefaultKeychainQuery();
-  CFDictionarySetValue(params, kSecPrivateKeyAttrs, private_key_params);
-  CFDictionarySetValue(private_key_params, kSecAttrIsPermanent, @YES);
-  CFDictionarySetValue(private_key_params, kSecAttrAccessControl,
-                       touch_id_context_->access_control());
-  CFDictionarySetValue(private_key_params, kSecUseAuthenticationContext,
-                       touch_id_context_->authentication_context());
-  CFDictionarySetValue(private_key_params, kSecAttrApplicationTag,
-                       base::SysUTF8ToNSString(encoded_rp_id_user_id));
-  CFDictionarySetValue(private_key_params, kSecAttrApplicationLabel,
-                       [NSData dataWithBytes:credential_id.data()
-                                      length:credential_id.size()]);
-
-  ScopedCFTypeRef<CFErrorRef> cferr;
-  ScopedCFTypeRef<SecKeyRef> private_key(
-      Keychain::GetInstance().KeyCreateRandomKey(params,
-                                                 cferr.InitializeInto()));
-  if (!private_key) {
-    FIDO_LOG(ERROR) << "SecKeyCreateRandomKey failed: " << cferr;
+  // TODO(crbug/1025065): Decide whether we should evict non-resident
+  // credentials at all.
+  if (!credential_store_->DeleteCredentialsForUserId(request_.rp.id,
+                                                     request_.user.id)) {
     std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
                              base::nullopt);
     return;
   }
-  ScopedCFTypeRef<SecKeyRef> public_key(
-      Keychain::GetInstance().KeyCopyPublicKey(private_key));
-  if (!public_key) {
-    FIDO_LOG(ERROR) << "SecKeyCopyPublicKey failed";
+
+  // Generate the new key pair.
+  base::Optional<std::pair<Credential, base::ScopedCFTypeRef<SecKeyRef>>>
+      credential = credential_store_->CreateCredential(
+          request_.rp.id, request_.user, request_.resident_key_required,
+          touch_id_context_->access_control());
+  if (!credential) {
+    FIDO_LOG(ERROR) << "CreateCredential() failed";
     std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
                              base::nullopt);
     return;
@@ -169,8 +122,8 @@
   // Create attestation object. There is no separate attestation key pair, so
   // we perform self-attestation.
   base::Optional<AttestedCredentialData> attested_credential_data =
-      MakeAttestedCredentialData(credential_id,
-                                 SecKeyRefToECPublicKey(public_key));
+      MakeAttestedCredentialData(credential->first.credential_id,
+                                 SecKeyRefToECPublicKey(credential->second));
   if (!attested_credential_data) {
     FIDO_LOG(ERROR) << "MakeAttestedCredentialData failed";
     std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
@@ -179,8 +132,9 @@
   }
   AuthenticatorData authenticator_data = MakeAuthenticatorData(
       request_.rp.id, std::move(*attested_credential_data));
-  base::Optional<std::vector<uint8_t>> signature = GenerateSignature(
-      authenticator_data, request_.client_data_hash, private_key);
+  base::Optional<std::vector<uint8_t>> signature =
+      GenerateSignature(authenticator_data, request_.client_data_hash,
+                        credential->first.private_key);
   if (!signature) {
     FIDO_LOG(ERROR) << "MakeSignature failed";
     std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
@@ -198,18 +152,6 @@
                            std::move(response));
 }
 
-base::ScopedCFTypeRef<CFMutableDictionaryRef>
-MakeCredentialOperation::DefaultKeychainQuery() const {
-  base::ScopedCFTypeRef<CFMutableDictionaryRef> query(
-      CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr));
-  CFDictionarySetValue(query, kSecClass, kSecClassKey);
-  CFDictionarySetValue(query, kSecAttrAccessGroup,
-                       base::SysUTF8ToNSString(keychain_access_group_));
-  CFDictionarySetValue(
-      query, kSecAttrLabel,
-      base::SysUTF8ToNSString(EncodeRpId(metadata_secret_, request_.rp.id)));
-  return query;
-}
 }  // namespace mac
 }  // namespace fido
 }  // namespace device
diff --git a/device/fido/mac/make_credential_operation_unittest_mac.mm b/device/fido/mac/make_credential_operation_unittest_mac.mm
index efcd3e4..344e2af1 100644
--- a/device/fido/mac/make_credential_operation_unittest_mac.mm
+++ b/device/fido/mac/make_credential_operation_unittest_mac.mm
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/mac/make_credential_operation.h"
-
 #include <array>
 
 #include <Foundation/Foundation.h>
@@ -14,6 +12,9 @@
 #include "base/test/task_environment.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_test_data.h"
+#include "device/fido/mac/authenticator_config.h"
+#include "device/fido/mac/credential_store.h"
+#include "device/fido/mac/make_credential_operation.h"
 #include "device/fido/test_callback_receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -49,7 +50,9 @@
                        base::Optional<AuthenticatorMakeCredentialResponse>>
       callback_receiver;
   auto request = MakeTestRequest();
-  MakeCredentialOperation op(request, "test-profile", kKeychainAccessGroup,
+  TouchIdCredentialStore credential_store(
+      AuthenticatorConfig{"test-profile", kKeychainAccessGroup});
+  MakeCredentialOperation op(request, &credential_store,
                              callback_receiver.callback());
 
   op.Run();
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc
index 2dd59c4..bad5b658 100644
--- a/device/fido/make_credential_request_handler.cc
+++ b/device/fido/make_credential_request_handler.cc
@@ -620,7 +620,7 @@
     return;
   }
 
-  observer()->FinishCollectPIN();
+  observer()->FinishCollectToken();
   state_ = State::kWaitingForSecondTouch;
   CtapMakeCredentialRequest request(request_);
   request.pin_auth = response->PinAuth(request.client_data_hash);
diff --git a/device/fido/pin.cc b/device/fido/pin.cc
index ff212fc..895054d 100644
--- a/device/fido/pin.cc
+++ b/device/fido/pin.cc
@@ -445,13 +445,9 @@
   return std::make_pair(CtapRequestCommand::kAuthenticatorReset, base::nullopt);
 }
 
-TokenRequest::TokenRequest(const std::string& pin,
-                           const KeyAgreementResponse& peer_key)
+TokenRequest::TokenRequest(const KeyAgreementResponse& peer_key)
     : cose_key_(GenerateSharedKey(peer_key, shared_key_.data())) {
   DCHECK_EQ(static_cast<size_t>(SHA256_DIGEST_LENGTH), shared_key_.size());
-  uint8_t digest[SHA256_DIGEST_LENGTH];
-  SHA256(reinterpret_cast<const uint8_t*>(pin.data()), pin.size(), digest);
-  memcpy(pin_hash_, digest, sizeof(pin_hash_));
 }
 
 TokenRequest::~TokenRequest() = default;
@@ -462,9 +458,21 @@
   return shared_key_;
 }
 
+PinTokenRequest::PinTokenRequest(const std::string& pin,
+                                 const KeyAgreementResponse& peer_key)
+    : TokenRequest(peer_key) {
+  uint8_t digest[SHA256_DIGEST_LENGTH];
+  SHA256(reinterpret_cast<const uint8_t*>(pin.data()), pin.size(), digest);
+  memcpy(pin_hash_, digest, sizeof(pin_hash_));
+}
+
+PinTokenRequest::~PinTokenRequest() = default;
+
+PinTokenRequest::PinTokenRequest(PinTokenRequest&& other) = default;
+
 // static
 std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
-AsCTAPRequestValuePair(const TokenRequest& request) {
+AsCTAPRequestValuePair(const PinTokenRequest& request) {
   static_assert((sizeof(request.pin_hash_) % AES_BLOCK_SIZE) == 0,
                 "pin_hash_ is not a multiple of the AES block size");
   uint8_t encrypted_pin[sizeof(request.pin_hash_)];
@@ -481,6 +489,22 @@
       });
 }
 
+UvTokenRequest::UvTokenRequest(const KeyAgreementResponse& peer_key)
+    : TokenRequest(peer_key) {}
+
+UvTokenRequest::~UvTokenRequest() = default;
+
+UvTokenRequest::UvTokenRequest(UvTokenRequest&& other) = default;
+
+std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
+AsCTAPRequestValuePair(const UvTokenRequest& request) {
+  return EncodePINCommand(
+      Subcommand::kGetUvToken, [&request](cbor::Value::MapValue* map) {
+        map->emplace(static_cast<int>(RequestKey::kKeyAgreement),
+                     std::move(request.cose_key_));
+      });
+}
+
 }  // namespace pin
 
 }  // namespace device
diff --git a/device/fido/pin.h b/device/fido/pin.h
index c4aec16..f07cd59 100644
--- a/device/fido/pin.h
+++ b/device/fido/pin.h
@@ -130,24 +130,45 @@
 // assertion.
 class TokenRequest {
  public:
-  TokenRequest(const std::string& pin, const KeyAgreementResponse& peer_key);
-  ~TokenRequest();
-  TokenRequest(TokenRequest&&);
   TokenRequest(const TokenRequest&) = delete;
 
   // shared_key returns the shared ECDH key that was used to encrypt the PIN.
   // This is needed to decrypt the response.
   const std::array<uint8_t, 32>& shared_key() const;
 
-  friend std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
-  AsCTAPRequestValuePair(const TokenRequest&);
-
- private:
+ protected:
+  TokenRequest(TokenRequest&&);
+  explicit TokenRequest(const KeyAgreementResponse& peer_key);
+  ~TokenRequest();
   std::array<uint8_t, 32> shared_key_;
   cbor::Value::MapValue cose_key_;
+};
+
+class PinTokenRequest : public TokenRequest {
+ public:
+  PinTokenRequest(const std::string& pin, const KeyAgreementResponse& peer_key);
+  PinTokenRequest(PinTokenRequest&&);
+  PinTokenRequest(const PinTokenRequest&) = delete;
+  virtual ~PinTokenRequest();
+
+  friend std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
+  AsCTAPRequestValuePair(const PinTokenRequest&);
+
+ private:
   uint8_t pin_hash_[16];
 };
 
+class UvTokenRequest : public TokenRequest {
+ public:
+  explicit UvTokenRequest(const KeyAgreementResponse& peer_key);
+  UvTokenRequest(UvTokenRequest&&);
+  UvTokenRequest(const UvTokenRequest&) = delete;
+  virtual ~UvTokenRequest();
+
+  friend std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
+  AsCTAPRequestValuePair(const UvTokenRequest&);
+};
+
 // TokenResponse represents the response to a pin-token request. In order to
 // decrypt a response, the shared key from the request is needed. Once a pin-
 // token has been decrypted, it can be used to calculate the pinAuth parameters
diff --git a/device/fido/pin_internal.h b/device/fido/pin_internal.h
index 105b85df..2102966 100644
--- a/device/fido/pin_internal.h
+++ b/device/fido/pin_internal.h
@@ -28,6 +28,7 @@
   kSetPIN = 0x03,
   kChangePIN = 0x04,
   kGetPINToken = 0x05,
+  kGetUvToken = 0x06,
 };
 
 // RequestKey enumerates the keys in the top-level CBOR map for all PIN
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index 79293233..a0351b8 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -166,9 +166,10 @@
       }
     }
 
-    if (pin_auth && options.client_pin_availability ==
-                        AuthenticatorSupportedOptions::ClientPinAvailability::
-                            kSupportedAndPinSet) {
+    if (pin_auth && (options.client_pin_availability ==
+                         AuthenticatorSupportedOptions::ClientPinAvailability::
+                             kSupportedAndPinSet ||
+                     options.supports_uv_token)) {
       DCHECK(pin_protocol && *pin_protocol == 1);
       if (CheckPINToken(pin_token, *pin_auth, client_data_hash)) {
         uv = true;
@@ -320,15 +321,15 @@
     VirtualCtap2Device::State* state,
     const uint8_t shared_key[SHA256_DIGEST_LENGTH],
     const std::vector<uint8_t>& encrypted_pin_hash) {
-  if (state->retries == 0) {
+  if (state->pin_retries == 0) {
     return CtapDeviceResponseCode::kCtap2ErrPinBlocked;
   }
   if (state->soft_locked) {
     return CtapDeviceResponseCode::kCtap2ErrPinAuthBlocked;
   }
 
-  state->retries--;
-  state->retries_since_insertion++;
+  state->pin_retries--;
+  state->pin_retries_since_insertion++;
 
   DCHECK((encrypted_pin_hash.size() % AES_BLOCK_SIZE) == 0);
   uint8_t pin_hash[AES_BLOCK_SIZE];
@@ -340,18 +341,18 @@
 
   if (state->pin.empty() ||
       CRYPTO_memcmp(pin_hash, calculated_pin_hash, sizeof(pin_hash)) != 0) {
-    if (state->retries == 0) {
+    if (state->pin_retries == 0) {
       return CtapDeviceResponseCode::kCtap2ErrPinBlocked;
     }
-    if (state->retries_since_insertion == 3) {
+    if (state->pin_retries_since_insertion == 3) {
       state->soft_locked = true;
       return CtapDeviceResponseCode::kCtap2ErrPinAuthBlocked;
     }
     return CtapDeviceResponseCode::kCtap2ErrPinInvalid;
   }
 
-  state->retries = 8;
-  state->retries_since_insertion = 0;
+  state->pin_retries = kMaxPinRetries;
+  state->pin_retries_since_insertion = 0;
 
   return CtapDeviceResponseCode::kSuccess;
 }
@@ -400,7 +401,8 @@
 
   state->pin = std::string(reinterpret_cast<const char*>(plaintext_pin.data()),
                            plaintext_pin.size());
-  state->retries = 8;
+  state->pin_retries = kMaxPinRetries;
+  state->uv_retries = kMaxUvRetries;
 
   return CtapDeviceResponseCode::kSuccess;
 }
@@ -507,6 +509,15 @@
   return WriteCBOR(cbor::Value(std::move(response_map)), allow_invalid_utf8);
 }
 
+std::array<uint8_t, 32> GenerateAndEncryptToken(
+    base::span<const uint8_t, SHA256_DIGEST_LENGTH> shared_key,
+    base::span<uint8_t, 32> pin_token) {
+  RAND_bytes(pin_token.data(), pin_token.size());
+  std::array<uint8_t, pin_token.size()> encrypted_pin_token;
+  pin::Encrypt(shared_key.data(), pin_token, encrypted_pin_token.data());
+  return encrypted_pin_token;
+}
+
 }  // namespace
 
 VirtualCtap2Device::Config::Config() = default;
@@ -554,6 +565,7 @@
       options.user_verification_availability = AuthenticatorSupportedOptions::
           UserVerificationAvailability::kSupportedButNotConfigured;
     }
+    options.supports_uv_token = config.uv_token_support;
   }
 
   if (config.resident_key_support) {
@@ -1103,7 +1115,8 @@
     base::span<const uint8_t> request_bytes,
     std::vector<uint8_t>* response) {
   if (device_info_->options.client_pin_availability ==
-      AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported) {
+          AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported &&
+      !config_.uv_token_support) {
     return CtapDeviceResponseCode::kCtap1ErrInvalidCommand;
   }
 
@@ -1134,7 +1147,7 @@
   switch (subcommand) {
     case static_cast<int>(device::pin::Subcommand::kGetRetries):
       response_map.emplace(static_cast<int>(pin::ResponseKey::kRetries),
-                           mutable_state()->retries);
+                           mutable_state()->pin_retries);
       break;
 
     case static_cast<int>(device::pin::Subcommand::kGetKeyAgreement): {
@@ -1253,12 +1266,51 @@
         return err;
       };
 
-      RAND_bytes(mutable_state()->pin_token,
-                 sizeof(mutable_state()->pin_token));
-      uint8_t encrypted_pin_token[sizeof(mutable_state()->pin_token)];
-      pin::Encrypt(shared_key, mutable_state()->pin_token, encrypted_pin_token);
-      response_map.emplace(static_cast<int>(pin::ResponseKey::kPINToken),
-                           base::span<const uint8_t>(encrypted_pin_token));
+      response_map.emplace(
+          static_cast<int>(pin::ResponseKey::kPINToken),
+          GenerateAndEncryptToken(shared_key, mutable_state()->pin_token));
+      break;
+    }
+
+    case static_cast<int>(device::pin::Subcommand::kGetUvToken): {
+      const auto peer_key =
+          GetPINKey(request_map, pin::RequestKey::kKeyAgreement);
+      if (!peer_key) {
+        return CtapDeviceResponseCode::kCtap2ErrMissingParameter;
+      }
+
+      if (device_info_->options.user_verification_availability ==
+          AuthenticatorSupportedOptions::UserVerificationAvailability::
+              kSupportedButNotConfigured) {
+        return CtapDeviceResponseCode::kCtap2ErrNotAllowed;
+      }
+
+      if (mutable_state()->uv_retries <= 0) {
+        return CtapDeviceResponseCode::kCtap2ErrUvBlocked;
+      }
+
+      uint8_t shared_key[SHA256_DIGEST_LENGTH];
+      if (!mutable_state()->ecdh_key) {
+        // kGetKeyAgreement should have been called first.
+        NOTREACHED();
+        return CtapDeviceResponseCode::kCtap2ErrPinTokenExpired;
+      }
+      pin::CalculateSharedKey(mutable_state()->ecdh_key.get(), peer_key->get(),
+                              shared_key);
+
+      --mutable_state()->uv_retries;
+
+      // Simulate internal UV.
+      if (!config_.user_verification_succeeds) {
+        return CtapDeviceResponseCode::kCtap2ErrPinInvalid;
+      }
+
+      mutable_state()->pin_retries = kMaxPinRetries;
+      mutable_state()->uv_retries = kMaxUvRetries;
+
+      response_map.emplace(
+          static_cast<int>(pin::ResponseKey::kPINToken),
+          GenerateAndEncryptToken(shared_key, mutable_state()->pin_token));
       break;
     }
 
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h
index 716456d..07f4dc9d 100644
--- a/device/fido/virtual_ctap2_device.h
+++ b/device/fido/virtual_ctap2_device.h
@@ -43,6 +43,8 @@
     bool pin_support = false;
     bool is_platform_authenticator = false;
     bool internal_uv_support = false;
+    // Ignored if |internal_uv_support| is false.
+    bool uv_token_support = false;
     bool resident_key_support = false;
     bool credential_management_support = false;
     bool bio_enrollment_support = false;
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
index 563f612..acecba1 100644
--- a/device/fido/virtual_fido_device.h
+++ b/device/fido/virtual_fido_device.h
@@ -33,6 +33,10 @@
 
 namespace device {
 
+constexpr size_t kMaxPinRetries = 8;
+
+constexpr size_t kMaxUvRetries = 5;
+
 class COMPONENT_EXPORT(DEVICE_FIDO) VirtualFidoDevice : public FidoDevice {
  public:
   // Encapsulates information corresponding to one registered key on the virtual
@@ -106,9 +110,9 @@
     bool non_zero_aaguid_with_self_attestation = false;
 
     // Number of PIN retries remaining.
-    int retries = 8;
+    int pin_retries = kMaxPinRetries;
     // The number of failed PIN attempts since the token was "inserted".
-    int retries_since_insertion = 0;
+    int pin_retries_since_insertion = 0;
     // True if the token is soft-locked due to too many failed PIN attempts
     // since "insertion".
     bool soft_locked = false;
@@ -120,6 +124,9 @@
     // itself.
     uint8_t pin_token[32];
 
+    // Number of internal UV retries remaining.
+    int uv_retries = kMaxUvRetries;
+
     // Whether a device with internal-UV support has fingerprints enrolled.
     bool fingerprints_enrolled = false;
 
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index 281ad76..dc438e2 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -227,6 +227,7 @@
         "openxr/openxr_api_wrapper.h",
         "openxr/openxr_controller.cc",
         "openxr/openxr_controller.h",
+        "openxr/openxr_defs.h",
         "openxr/openxr_device.cc",
         "openxr/openxr_device.h",
         "openxr/openxr_input_helper.cc",
@@ -353,6 +354,7 @@
     include_dirs = [ "//third_party/openxr/src/include" ]
 
     sources = [
+      "openxr/openxr_defs.h",
       "openxr/openxr_util.cc",
       "openxr/openxr_util.h",
       "openxr/test/fake_openxr_impl_api.cc",
diff --git a/device/vr/openxr/openxr_defs.h b/device/vr/openxr/openxr_defs.h
new file mode 100644
index 0000000..0ca8d86a
--- /dev/null
+++ b/device/vr/openxr/openxr_defs.h
@@ -0,0 +1,14 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_VR_OPENXR_OPENXR_DEFS_H_
+#define DEVICE_VR_OPENXR_OPENXR_DEFS_H_
+
+namespace device {
+constexpr char kWin32AppcontainerCompatibleExtensionName[] =
+    "XR_EXT_win32_appcontainer_compatible";
+
+}  // namespace device
+
+#endif  // DEVICE_VR_OPENXR_OPENXR_DEFS_H_
diff --git a/device/vr/openxr/openxr_interaction_profiles.h b/device/vr/openxr/openxr_interaction_profiles.h
index 0d463168..8220865 100644
--- a/device/vr/openxr/openxr_interaction_profiles.h
+++ b/device/vr/openxr/openxr_interaction_profiles.h
@@ -23,7 +23,8 @@
   kMicrosoftMotion = 0,
   kKHRSimple = 1,
   kOculusTouch = 2,
-  kCount = 3,
+  kValveIndex = 3,
+  kCount = 4,
 };
 
 enum class OpenXrButtonType {
@@ -85,6 +86,7 @@
 // Microsoft motion controller.
 // Khronos simple controller.
 // Oculus touch controller.
+// Valve index controller.
 // Declare OpenXR input profile bindings for other runtimes when they become
 // available.
 constexpr const char* kMicrosoftMotionInputProfiles[] = {
@@ -95,6 +97,9 @@
 constexpr const char* kOculusTouchInputProfiles[] = {
     "oculus-touch", "generic-trigger-squeeze-thumbstick"};
 
+constexpr const char* kValveIndexInputProfiles[] = {
+    "valve-index", "generic-trigger-squeeze-touchpad-thumbstick"};
+
 constexpr OpenXrButtonPathMap kMicrosoftMotionControllerButtonPathMaps[] = {
     {OpenXrButtonType::kTrigger,
      {
@@ -173,6 +178,35 @@
      2},
 };
 
+constexpr OpenXrButtonPathMap kValveIndexControllerButtonPathMaps[] = {
+    {OpenXrButtonType::kTrigger,
+     {{OpenXrButtonActionType::kPress, "/input/trigger/click"},
+      {OpenXrButtonActionType::kValue, "/input/trigger/value"},
+      {OpenXrButtonActionType::kTouch, "/input/trigger/touch"}},
+     3},
+    {OpenXrButtonType::kSqueeze,
+     {{OpenXrButtonActionType::kPress, "/input/squeeze/value"},
+      {OpenXrButtonActionType::kValue, "/input/squeeze/value"},
+      {OpenXrButtonActionType::kValue, "/input/squeeze/force"}},
+     3},
+    {OpenXrButtonType::kThumbstick,
+     {{OpenXrButtonActionType::kPress, "/input/thumbstick/click"},
+      {OpenXrButtonActionType::kTouch, "/input/thumbstick/touch"}},
+     2},
+    {OpenXrButtonType::kTrackpad,
+     {{OpenXrButtonActionType::kTouch, "/input/trackpad/touch"},
+      {OpenXrButtonActionType::kValue, "/input/trackpad/force"}},
+     2},
+    {OpenXrButtonType::kButton1,
+     {{OpenXrButtonActionType::kPress, "/input/a/click"},
+      {OpenXrButtonActionType::kTouch, "/input/a/touch"}},
+     2},
+    {OpenXrButtonType::kButton2,
+     {{OpenXrButtonActionType::kPress, "/input/b/click"},
+      {OpenXrButtonActionType::kTouch, "/input/b/touch"}},
+     2},
+};  // namespace device
+
 constexpr OpenXrAxisPathMap kMicrosoftMotionControllerAxisPathMaps[] = {
     {OpenXrAxisType::kTrackpad, "/input/trackpad"},
     {OpenXrAxisType::kThumbstick, "/input/thumbstick"},
@@ -182,6 +216,11 @@
     {OpenXrAxisType::kThumbstick, "/input/thumbstick"},
 };
 
+constexpr OpenXrAxisPathMap kValveIndexControllerAxisPathMaps[] = {
+    {OpenXrAxisType::kTrackpad, "/input/trackpad"},
+    {OpenXrAxisType::kThumbstick, "/input/thumbstick"},
+};
+
 constexpr OpenXrControllerInteractionProfile
     kMicrosoftMotionInteractionProfile = {
         OpenXrInteractionProfileType::kMicrosoftMotion,
@@ -222,10 +261,23 @@
     kOculusTouchControllerAxisPathMaps,
     base::size(kOculusTouchControllerAxisPathMaps)};
 
+constexpr OpenXrControllerInteractionProfile kValveIndexInteractionProfile = {
+    OpenXrInteractionProfileType::kValveIndex,
+    "/interaction_profiles/valve/index_controller",
+    GamepadMapping::kXrStandard,
+    kValveIndexInputProfiles,
+    base::size(kValveIndexInputProfiles),
+    kValveIndexControllerButtonPathMaps,
+    base::size(kValveIndexControllerButtonPathMaps),
+    kValveIndexControllerButtonPathMaps,
+    base::size(kValveIndexControllerButtonPathMaps),
+    kValveIndexControllerAxisPathMaps,
+    base::size(kValveIndexControllerAxisPathMaps)};
+
 constexpr OpenXrControllerInteractionProfile
     kOpenXrControllerInteractionProfiles[] = {
         kMicrosoftMotionInteractionProfile, kKHRSimpleInteractionProfile,
-        kOculusTouchInteractionProfile};
+        kOculusTouchInteractionProfile, kValveIndexInteractionProfile};
 
 }  // namespace device
 
diff --git a/device/vr/openxr/openxr_util.cc b/device/vr/openxr/openxr_util.cc
index 60fbafc..85ac22d 100644
--- a/device/vr/openxr/openxr_util.cc
+++ b/device/vr/openxr/openxr_util.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "device/vr/openxr/openxr_util.h"
+#include "device/vr/openxr/openxr_defs.h"
 
 #include <d3d11.h>
 #include <string>
@@ -10,6 +11,8 @@
 
 #include "base/stl_util.h"
 #include "base/version.h"
+#include "base/win/scoped_handle.h"
+#include "build/build_config.h"
 #include "components/version_info/version_info.h"
 #include "third_party/openxr/src/include/openxr/openxr_platform.h"
 
@@ -27,6 +30,31 @@
   return xrGetSystem(instance, &system_info, system);
 }
 
+#if defined(OS_WIN)
+bool IsRunningInWin32AppContainer() {
+  base::win::ScopedHandle scopedProcessToken;
+  HANDLE processToken;
+  if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &processToken)) {
+    return false;
+  }
+
+  scopedProcessToken.Set(processToken);
+
+  BOOL isAppContainer;
+  DWORD dwSize = sizeof(BOOL);
+  if (!GetTokenInformation(scopedProcessToken.Get(), TokenIsAppContainer,
+                           &isAppContainer, dwSize, &dwSize)) {
+    return false;
+  }
+
+  return isAppContainer;
+}
+#else
+bool IsRunningInWin32AppContainer() {
+  return false;
+}
+#endif
+
 XrResult CreateInstance(XrInstance* instance,
                         OpenXRInstanceMetadata* metadata) {
   XrInstanceCreateInfo instance_create_info = {XR_TYPE_INSTANCE_CREATE_INFO};
@@ -72,6 +100,15 @@
   // the XR_KHR_D3D11_ENABLE_EXTENSION_NAME is required.
   std::vector<const char*> extensions{XR_KHR_D3D11_ENABLE_EXTENSION_NAME};
 
+  // If we are in an app container, we must require the app container extension
+  // to ensure robust execution of the OpenXR runtime
+  if (IsRunningInWin32AppContainer()) {
+    // Add the win32 app container compatible extension to our list of
+    // extensions. If this runtime does not support execution in an app
+    // container environment, one of xrCreateInstance or xrGetSystem will fail.
+    extensions.push_back(kWin32AppcontainerCompatibleExtensionName);
+  }
+
   // XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME, is required for optional
   // functionality (unbounded reference spaces) and thus only requested if it is
   // available.
diff --git a/device/vr/openxr/test/fake_openxr_impl_api.cc b/device/vr/openxr/test/fake_openxr_impl_api.cc
index 01a5071..a9da08c 100644
--- a/device/vr/openxr/test/fake_openxr_impl_api.cc
+++ b/device/vr/openxr/test/fake_openxr_impl_api.cc
@@ -790,6 +790,9 @@
               0 &&
           interaction_profile.compare(
               interaction_profile::kOculusTouchControllerInteractionProfile) !=
+              0 &&
+          interaction_profile.compare(
+              interaction_profile::kValveIndexControllerinteractionProfile) !=
               0,
       XR_ERROR_VALIDATION_FAILURE,
       "xrSetInteractionProfileSuggestedBindings invalid interaction_profile");
diff --git a/device/vr/openxr/test/openxr_test_helper.h b/device/vr/openxr/test/openxr_test_helper.h
index 29628c0..e3c5a9a 100644
--- a/device/vr/openxr/test/openxr_test_helper.h
+++ b/device/vr/openxr/test/openxr_test_helper.h
@@ -17,6 +17,7 @@
 #include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/synchronization/lock.h"
+#include "device/vr/openxr/openxr_defs.h"
 #include "device/vr/test/test_hook.h"
 #include "third_party/openxr/src/include/openxr/openxr.h"
 #include "third_party/openxr/src/include/openxr/openxr_platform.h"
@@ -34,6 +35,9 @@
 
 constexpr char kOculusTouchControllerInteractionProfile[] =
     "/interaction_profiles/oculus/touch_controller";
+
+constexpr char kValveIndexControllerinteractionProfile[] =
+    "/interaction_profiles/valve/index_controller";
 }  // namespace interaction_profile
 
 class OpenXrTestHelper : public device::ServiceTestHook {
@@ -127,7 +131,8 @@
 
   // Properties of the mock OpenXR runtime that do not change are created
   static constexpr const char* const kExtensions[] = {
-      XR_KHR_D3D11_ENABLE_EXTENSION_NAME};
+      XR_KHR_D3D11_ENABLE_EXTENSION_NAME,
+      device::kWin32AppcontainerCompatibleExtensionName};
   static constexpr uint32_t kDimension = 128;
   static constexpr uint32_t kSwapCount = 1;
   static constexpr uint32_t kMinSwapchainBuffering = 3;
diff --git a/docs/security/severity-guidelines.md b/docs/security/severity-guidelines.md
index d3c01d3..7e0d6fb 100644
--- a/docs/security/severity-guidelines.md
+++ b/docs/security/severity-guidelines.md
@@ -10,9 +10,15 @@
 
 Any significant mitigating factors, such as unusual or additional user
 interaction, or running Chrome with a specific command line flag or non-default
-feature enabled, may reduce an issue’s severity by one or more levels. Also note
-that most crashes do not indicate vulnerabilities. Chromium is designed to crash
-in a controlled manner (e.g., with a ```__debugBreak```) when memory is
+feature enabled, may reduce an issue’s severity by one or more levels.
+
+Conversely, we do not consider it a mitigating factor if a vulnerability applies
+only to a particular group of users. For instance, a Critical vulnerability is
+still considered Critical even if it applies only to Linux or to those users
+running with accessibility features enabled.
+
+Also note that most crashes do not indicate vulnerabilities. Chromium is designed
+to crash in a controlled manner (e.g., with a ```__debugBreak```) when memory is
 exhausted or in other exceptional circumstances.
 
 
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.cc b/extensions/browser/api/declarative_net_request/composite_matcher.cc
index 93ec25d..9db8fab 100644
--- a/extensions/browser/api/declarative_net_request/composite_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/composite_matcher.cc
@@ -9,7 +9,6 @@
 #include <utility>
 
 #include "base/metrics/histogram_macros.h"
-#include "extensions/browser/api/declarative_net_request/action_tracker.h"
 #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
 #include "extensions/browser/api/declarative_net_request/request_action.h"
 #include "extensions/browser/api/declarative_net_request/request_params.h"
@@ -19,7 +18,7 @@
 namespace declarative_net_request {
 namespace flat_rule = url_pattern_index::flat;
 using PageAccess = PermissionsData::PageAccess;
-using RedirectActionInfo = CompositeMatcher::RedirectActionInfo;
+using ActionInfo = CompositeMatcher::ActionInfo;
 
 namespace {
 
@@ -47,23 +46,18 @@
 
 }  // namespace
 
-RedirectActionInfo::RedirectActionInfo(base::Optional<RequestAction> action,
-                                       bool notify_request_withheld)
+ActionInfo::ActionInfo(base::Optional<RequestAction> action,
+                       bool notify_request_withheld)
     : action(std::move(action)),
-      notify_request_withheld(notify_request_withheld) {
-  if (action)
-    DCHECK_EQ(RequestAction::Type::REDIRECT, action->type);
-}
+      notify_request_withheld(notify_request_withheld) {}
 
-RedirectActionInfo::~RedirectActionInfo() = default;
+ActionInfo::~ActionInfo() = default;
 
-RedirectActionInfo::RedirectActionInfo(RedirectActionInfo&&) = default;
-RedirectActionInfo& RedirectActionInfo::operator=(RedirectActionInfo&& other) =
-    default;
+ActionInfo::ActionInfo(ActionInfo&&) = default;
+ActionInfo& ActionInfo::operator=(ActionInfo&& other) = default;
 
-CompositeMatcher::CompositeMatcher(MatcherList matchers,
-                                   ActionTracker* action_tracker)
-    : matchers_(std::move(matchers)), action_tracker_(action_tracker) {
+CompositeMatcher::CompositeMatcher(MatcherList matchers)
+    : matchers_(std::move(matchers)) {
   SortMatchersByPriority();
   DCHECK(AreIDsUnique(matchers_));
 }
@@ -95,66 +89,38 @@
   has_any_extra_headers_matcher_.reset();
 }
 
-base::Optional<RequestAction> CompositeMatcher::GetBlockOrCollapseAction(
-    const RequestParams& params) const {
-  // TODO(karandeepb): change this to report time in micro-seconds.
-  SCOPED_UMA_HISTOGRAM_TIMER(
-      "Extensions.DeclarativeNetRequest.ShouldBlockRequestTime."
-      "SingleExtension");
-
-  for (const auto& matcher : matchers_) {
-    if (HasAllowAction(*matcher, params))
-      return base::nullopt;
-
-    base::Optional<RequestAction> action =
-        matcher->GetBlockOrCollapseAction(params);
-    if (action)
-      return action;
-  }
-
-  return base::nullopt;
-}
-
-RedirectActionInfo CompositeMatcher::GetRedirectAction(
+ActionInfo CompositeMatcher::GetBeforeRequestAction(
     const RequestParams& params,
     PageAccess page_access) const {
   // TODO(karandeepb): change this to report time in micro-seconds.
   SCOPED_UMA_HISTOGRAM_TIMER(
-      "Extensions.DeclarativeNetRequest.ShouldRedirectRequestTime."
+      "Extensions.DeclarativeNetRequest.EvaluateBeforeRequestTime."
       "SingleExtension");
 
   bool notify_request_withheld = false;
   for (const auto& matcher : matchers_) {
-    if (HasAllowAction(*matcher, params)) {
-      return RedirectActionInfo(base::nullopt /* action */,
-                                false /* notify_request_withheld */);
+    base::Optional<RequestAction> action =
+        matcher->GetBeforeRequestAction(params);
+    params.allow_rule_cache[matcher.get()] =
+        action && action->type == RequestAction::Type::ALLOW;
+
+    if (action && action->type == RequestAction::Type::REDIRECT) {
+      // Redirecting requires host permissions.
+      // TODO(crbug.com/1033780): returning base::nullopt here results in
+      // counterintuitive behavior.
+      if (page_access == PageAccess::kDenied) {
+        action = base::nullopt;
+      } else if (page_access == PageAccess::kWithheld) {
+        action = base::nullopt;
+        notify_request_withheld = true;
+      }
     }
 
-    if (page_access == PageAccess::kAllowed) {
-      base::Optional<RequestAction> action =
-          matcher->GetRedirectOrUpgradeActionByPriority(params);
-      if (!action)
-        continue;
-
-      return RedirectActionInfo(std::move(action),
-                                false /* notify_request_withheld */);
-    }
-
-    // If the extension has no host permissions for the request, it can still
-    // upgrade the request.
-    base::Optional<RequestAction> upgrade_action =
-        matcher->GetUpgradeAction(params);
-    if (upgrade_action) {
-      return RedirectActionInfo(std::move(upgrade_action),
-                                false /* notify_request_withheld */);
-    }
-
-    notify_request_withheld |= (page_access == PageAccess::kWithheld &&
-                                matcher->GetRedirectAction(params));
+    if (action)
+      return ActionInfo(std::move(action), false);
   }
 
-  return RedirectActionInfo(base::nullopt /* action */,
-                            notify_request_withheld);
+  return ActionInfo(base::nullopt, notify_request_withheld);
 }
 
 uint8_t CompositeMatcher::GetRemoveHeadersMask(
@@ -163,9 +129,19 @@
     std::vector<RequestAction>* remove_headers_actions) const {
   uint8_t mask = 0;
   for (const auto& matcher : matchers_) {
-    // The allow rule will override lower priority remove header rules.
-    if (HasAllowAction(*matcher, params))
+    // An allow rule will override lower priority remove header rules.
+    if (!params.allow_rule_cache.contains(matcher.get())) {
+      // GetBeforeRequestAction is normally called before GetRemoveHeadersMask,
+      // so this should never happen in non-test builds. There are tests that
+      // call GetRemoveHeadersMask directly, though.
+      base::Optional<RequestAction> action =
+          matcher->GetBeforeRequestAction(params);
+      params.allow_rule_cache[matcher.get()] =
+          action && action->type == RequestAction::Type::ALLOW;
+    }
+    if (params.allow_rule_cache[matcher.get()])
       return mask;
+
     mask |= matcher->GetRemoveHeadersMask(
         params, mask | excluded_remove_headers_mask, remove_headers_actions);
   }
@@ -197,21 +173,5 @@
   DCHECK(AreSortedPrioritiesUnique(matchers_));
 }
 
-bool CompositeMatcher::HasAllowAction(const RulesetMatcher& matcher,
-                                      const RequestParams& params) const {
-  if (!params.allow_rule_cache.contains(&matcher)) {
-    base::Optional<RequestAction> allow_action = matcher.GetAllowAction(params);
-    params.allow_rule_cache[&matcher] = allow_action.has_value();
-
-    // OnRuleMatched is called only once, when the allow action is entered into
-    // the cache. This is done because an allow rule might override an action
-    // multiple times during a request and extraneous matches should be ignored.
-    if (allow_action && action_tracker_ && params.request_info)
-      action_tracker_->OnRuleMatched(*allow_action, *params.request_info);
-  }
-
-  return params.allow_rule_cache[&matcher];
-}
-
 }  // namespace declarative_net_request
 }  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.h b/extensions/browser/api/declarative_net_request/composite_matcher.h
index 053f46e..950897b0 100644
--- a/extensions/browser/api/declarative_net_request/composite_matcher.h
+++ b/extensions/browser/api/declarative_net_request/composite_matcher.h
@@ -18,51 +18,42 @@
 namespace extensions {
 namespace declarative_net_request {
 
-class ActionTracker;
 struct RequestAction;
 
 // Per extension instance which manages the different rulesets for an extension
 // while respecting their priorities.
 class CompositeMatcher {
  public:
-  struct RedirectActionInfo {
-    RedirectActionInfo(base::Optional<RequestAction> action, bool notify);
-    ~RedirectActionInfo();
-    RedirectActionInfo(RedirectActionInfo&& other);
-    RedirectActionInfo& operator=(RedirectActionInfo&& other);
+  struct ActionInfo {
+    ActionInfo(base::Optional<RequestAction> action, bool notify);
+    ~ActionInfo();
+    ActionInfo(ActionInfo&& other);
+    ActionInfo& operator=(ActionInfo&& other);
 
-    // The action to be taken for this request. If specified, the action type
-    // must be |REDIRECT|.
+    // The action to be taken for this request.
     base::Optional<RequestAction> action;
 
     // Whether the extension should be notified that the request was unable to
     // be redirected as the extension lacks the appropriate host permission for
-    // the request.
+    // the request. Can only be true for redirect actions.
     bool notify_request_withheld = false;
 
-    DISALLOW_COPY_AND_ASSIGN(RedirectActionInfo);
+    DISALLOW_COPY_AND_ASSIGN(ActionInfo);
   };
 
   using MatcherList = std::vector<std::unique_ptr<RulesetMatcher>>;
 
   // Each RulesetMatcher should have a distinct ID and priority.
-  explicit CompositeMatcher(MatcherList matchers,
-                            ActionTracker* action_tracker);
+  explicit CompositeMatcher(MatcherList matchers);
   ~CompositeMatcher();
 
   // Adds the |new_matcher| to the list of matchers. If a matcher with the
   // corresponding ID is already present, updates the matcher.
   void AddOrUpdateRuleset(std::unique_ptr<RulesetMatcher> new_matcher);
 
-  // Returns a RequestAction if the network request specified by |params| should
-  // be blocked.
-  base::Optional<RequestAction> GetBlockOrCollapseAction(
-      const RequestParams& params) const;
-
-  // Returns a RedirectActionInfo struct containing a RequestAction if the
-  // request is to be redirected, and whether the extension should be notified
-  // if its access to the request is withheld.
-  RedirectActionInfo GetRedirectAction(
+  // Returns a RequestAction for the network request specified by |params|, or
+  // base::nullopt if there is no matching rule.
+  ActionInfo GetBeforeRequestAction(
       const RequestParams& params,
       PermissionsData::PageAccess page_access) const;
 
@@ -85,11 +76,6 @@
   // Sorts |matchers_| in descending order of priority.
   void SortMatchersByPriority();
 
-  // Check if |matcher| has an allow action for |params| and tracks the action
-  // if needed.
-  bool HasAllowAction(const RulesetMatcher& matcher,
-                      const RequestParams& params) const;
-
   // Sorted by priority in descending order.
   MatcherList matchers_;
 
@@ -97,10 +83,6 @@
   // be taken to reset this as this object is modified.
   mutable base::Optional<bool> has_any_extra_headers_matcher_;
 
-  // Used to track when allow rules are matched; can be null during unit tests.
-  // Owned by RulesMonitorService.
-  ActionTracker* action_tracker_ = nullptr;
-
   DISALLOW_COPY_AND_ASSIGN(CompositeMatcher);
 };
 
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc b/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
index e06886a..5cd9a1b 100644
--- a/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/strings/stringprintf.h"
 #include "components/version_info/version_info.h"
 #include "extensions/browser/api/declarative_net_request/constants.h"
 #include "extensions/browser/api/declarative_net_request/request_action.h"
@@ -29,7 +30,7 @@
 namespace declarative_net_request {
 
 using PageAccess = PermissionsData::PageAccess;
-using RedirectActionInfo = CompositeMatcher::RedirectActionInfo;
+using ActionInfo = CompositeMatcher::ActionInfo;
 
 namespace dnr_api = api::declarative_net_request;
 
@@ -58,7 +59,8 @@
   redirect_rule_1.action->redirect->url = std::string("http://ruleset1.com");
   redirect_rule_1.id = kMinValidID + 1;
 
-  // Create the first ruleset matcher.
+  // Create the first ruleset matcher. It blocks google.com and redirects
+  // example.com to ruleset1.com.
   const size_t kSource1ID = 1;
   const size_t kSource1Priority = 1;
   std::unique_ptr<RulesetMatcher> matcher_1;
@@ -66,7 +68,8 @@
       {block_rule, redirect_rule_1},
       CreateTemporarySource(kSource1ID, kSource1Priority), &matcher_1));
 
-  // Now create a second ruleset matcher.
+  // Now create a second ruleset matcher. It allows google.com and redirects
+  // example.com to ruleset2.com.
   const size_t kSource2ID = 2;
   const size_t kSource2Priority = 2;
   TestRule allow_rule = block_rule;
@@ -83,8 +86,8 @@
   std::vector<std::unique_ptr<RulesetMatcher>> matchers;
   matchers.push_back(std::move(matcher_1));
   matchers.push_back(std::move(matcher_2));
-  auto composite_matcher = std::make_unique<CompositeMatcher>(
-      std::move(matchers), nullptr /* action_tracker */);
+  auto composite_matcher =
+      std::make_unique<CompositeMatcher>(std::move(matchers));
 
   GURL google_url = GURL("http://google.com");
   RequestParams google_params;
@@ -93,8 +96,10 @@
   google_params.is_third_party = false;
 
   // The second ruleset should get more priority.
-  EXPECT_FALSE(
-      composite_matcher->GetBlockOrCollapseAction(google_params).has_value());
+  ActionInfo action_info = composite_matcher->GetBeforeRequestAction(
+      google_params, PageAccess::kAllowed);
+  ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(action_info.action->type, RequestAction::Type::ALLOW);
 
   GURL example_url = GURL("http://example.com");
   RequestParams example_params;
@@ -103,9 +108,10 @@
       url_pattern_index::flat::ElementType_SUBDOCUMENT;
   example_params.is_third_party = false;
 
-  RedirectActionInfo action_info = composite_matcher->GetRedirectAction(
-      example_params, PageAccess::kAllowed);
+  action_info = composite_matcher->GetBeforeRequestAction(example_params,
+                                                          PageAccess::kAllowed);
   ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(action_info.action->type, RequestAction::Type::REDIRECT);
   EXPECT_EQ(GURL("http://ruleset2.com"), action_info.action->redirect_url);
   EXPECT_FALSE(action_info.notify_request_withheld);
 
@@ -122,20 +128,22 @@
       CreateTemporarySource(kSource2ID, kSource1Priority), &matcher_2));
   matchers.push_back(std::move(matcher_1));
   matchers.push_back(std::move(matcher_2));
-  composite_matcher = std::make_unique<CompositeMatcher>(
-      std::move(matchers), nullptr /* action_tracker */);
+  composite_matcher = std::make_unique<CompositeMatcher>(std::move(matchers));
 
   // Reusing request params means that their allow_rule_caches must be cleared.
   google_params.allow_rule_cache.clear();
   example_params.allow_rule_cache.clear();
 
   // The first ruleset should get more priority.
-  EXPECT_TRUE(
-      composite_matcher->GetBlockOrCollapseAction(google_params).has_value());
-
-  action_info = composite_matcher->GetRedirectAction(example_params,
-                                                     PageAccess::kAllowed);
+  action_info = composite_matcher->GetBeforeRequestAction(google_params,
+                                                          PageAccess::kAllowed);
   ASSERT_TRUE(action_info.action);
+  EXPECT_TRUE(action_info.action->IsBlockOrCollapse());
+
+  action_info = composite_matcher->GetBeforeRequestAction(example_params,
+                                                          PageAccess::kAllowed);
+  ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(action_info.action->type, RequestAction::Type::REDIRECT);
   EXPECT_EQ(GURL("http://ruleset1.com"), action_info.action->redirect_url);
   EXPECT_FALSE(action_info.notify_request_withheld);
 }
@@ -193,8 +201,8 @@
   std::vector<std::unique_ptr<RulesetMatcher>> matchers;
   matchers.push_back(std::move(matcher_1));
   matchers.push_back(std::move(matcher_2));
-  auto composite_matcher = std::make_unique<CompositeMatcher>(
-      std::move(matchers), nullptr /* action_tracker */);
+  auto composite_matcher =
+      std::make_unique<CompositeMatcher>(std::move(matchers));
 
   // Send a request to google.com which should be redirected.
   GURL google_url = GURL("http://google.com");
@@ -204,9 +212,10 @@
   google_params.is_third_party = false;
 
   // The second ruleset should get more priority.
-  RedirectActionInfo action_info =
-      composite_matcher->GetRedirectAction(google_params, PageAccess::kAllowed);
+  ActionInfo action_info = composite_matcher->GetBeforeRequestAction(
+      google_params, PageAccess::kAllowed);
   ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(action_info.action->type, RequestAction::Type::REDIRECT);
   EXPECT_EQ(GURL("http://ruleset2.com"), action_info.action->redirect_url);
   EXPECT_FALSE(action_info.notify_request_withheld);
 
@@ -244,8 +253,7 @@
       &matcher_2));
   matchers.push_back(std::move(matcher_1));
   matchers.push_back(std::move(matcher_2));
-  composite_matcher = std::make_unique<CompositeMatcher>(
-      std::move(matchers), nullptr /* action_tracker */);
+  composite_matcher = std::make_unique<CompositeMatcher>(std::move(matchers));
 
   // Reusing request params means that their allow_rule_caches must be cleared.
   google_params.allow_rule_cache.clear();
@@ -253,9 +261,10 @@
 
   // The first ruleset should get more priority and so the request to google.com
   // should not be redirected.
-  action_info =
-      composite_matcher->GetRedirectAction(google_params, PageAccess::kAllowed);
-  EXPECT_FALSE(action_info.action.has_value());
+  action_info = composite_matcher->GetBeforeRequestAction(google_params,
+                                                          PageAccess::kAllowed);
+  ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(action_info.action->type, RequestAction::Type::ALLOW);
   EXPECT_FALSE(action_info.notify_request_withheld);
 
   // The request to example.com should now have its headers removed.
@@ -328,8 +337,8 @@
   std::vector<std::unique_ptr<RulesetMatcher>> matchers;
   matchers.push_back(std::move(matcher_1));
   matchers.push_back(std::move(matcher_2));
-  auto composite_matcher = std::make_unique<CompositeMatcher>(
-      std::move(matchers), nullptr /* action_tracker */);
+  auto composite_matcher =
+      std::make_unique<CompositeMatcher>(std::move(matchers));
 
   GURL google_url = GURL("http://google.com");
   RequestParams google_params;
@@ -425,8 +434,8 @@
   // Create a composite matcher.
   std::vector<std::unique_ptr<RulesetMatcher>> matchers;
   matchers.push_back(std::move(matcher_1));
-  auto composite_matcher = std::make_unique<CompositeMatcher>(
-      std::move(matchers), nullptr /* action_tracker */);
+  auto composite_matcher =
+      std::make_unique<CompositeMatcher>(std::move(matchers));
 
   GURL google_url = GURL("http://google.com");
   GURL example_url = GURL("http://example.com");
@@ -464,13 +473,20 @@
   };
 
   for (const auto& test_case : test_cases) {
+    SCOPED_TRACE(base::StringPrintf(
+        "request_url=%s, access=%d, expected_final_url=%s, "
+        "should_notify_withheld=%d",
+        test_case.request_url.spec().c_str(), test_case.access,
+        test_case.expected_final_url.value_or(GURL()).spec().c_str(),
+        test_case.should_notify_withheld));
+
     RequestParams params;
     params.url = &test_case.request_url;
     params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
     params.is_third_party = false;
 
-    RedirectActionInfo redirect_action_info =
-        composite_matcher->GetRedirectAction(params, test_case.access);
+    ActionInfo redirect_action_info =
+        composite_matcher->GetBeforeRequestAction(params, test_case.access);
 
     EXPECT_EQ(test_case.should_notify_withheld,
               redirect_action_info.notify_request_withheld);
@@ -514,8 +530,8 @@
   // Create a composite matcher.
   std::vector<std::unique_ptr<RulesetMatcher>> matchers;
   matchers.push_back(std::move(matcher_1));
-  auto composite_matcher = std::make_unique<CompositeMatcher>(
-      std::move(matchers), nullptr /* action_tracker */);
+  auto composite_matcher =
+      std::make_unique<CompositeMatcher>(std::move(matchers));
 
   struct {
     GURL request_url;
@@ -534,23 +550,29 @@
       // the request should be redirected.
       {GURL("http://defghi.com"), GURL("http://example.com")},
 
-      // The request should be redirected as it does not match the upgrade rule
-      // because of its scheme.
-      {GURL("https://abcdef.com"), GURL("http://google.com")},
+      // The request will not be redirected as it matches the upgrade rule but
+      // is already https.
+      {GURL("https://abcdef.com"), base::nullopt},
+
       {GURL("http://xyz.com"), base::nullopt},
   };
 
   for (const auto& test_case : test_cases) {
+    SCOPED_TRACE(base::StringPrintf(
+        "Test redirect from %s to %s", test_case.request_url.spec().c_str(),
+        test_case.expected_final_url.value_or(GURL()).spec().c_str()));
+
     RequestParams params;
     params.url = &test_case.request_url;
     params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
     params.is_third_party = false;
 
-    RedirectActionInfo redirect_action_info =
-        composite_matcher->GetRedirectAction(params, PageAccess::kAllowed);
+    ActionInfo redirect_action_info =
+        composite_matcher->GetBeforeRequestAction(params, PageAccess::kAllowed);
 
     if (test_case.expected_final_url) {
       ASSERT_TRUE(redirect_action_info.action);
+      EXPECT_TRUE(redirect_action_info.action->IsRedirectOrUpgrade());
       EXPECT_EQ(test_case.expected_final_url,
                 redirect_action_info.action->redirect_url);
     } else {
diff --git a/extensions/browser/api/declarative_net_request/constants.cc b/extensions/browser/api/declarative_net_request/constants.cc
index 07c7799c..e0ba6bd6 100644
--- a/extensions/browser/api/declarative_net_request/constants.cc
+++ b/extensions/browser/api/declarative_net_request/constants.cc
@@ -16,15 +16,11 @@
 
 const char kErrorResourceTypeDuplicated[] =
     "Rule with id * includes and excludes the same resource.";
-const char kErrorEmptyRedirectRuleKey[] =
-    "Rule with id * does not specify the value for * key. This is required "
-    "for redirect rules.";
-const char kErrorEmptyUpgradeRulePriority[] =
-    "Rule with id * does not specify the value for priority key. This is "
-    "required for upgradeScheme rules.";
 const char kErrorInvalidRuleKey[] =
     "Rule with id * has an invalid value for * key. This should be greater "
     "than or equal to *.";
+const char kErrorEmptyRulePriority[] =
+    "Rule with id * does not specify the value for priority key.";
 const char kErrorNoApplicableResourceTypes[] =
     "Rule with id * is not applicable to any resource type.";
 const char kErrorEmptyList[] =
diff --git a/extensions/browser/api/declarative_net_request/constants.h b/extensions/browser/api/declarative_net_request/constants.h
index 752eac51..d99a3a4 100644
--- a/extensions/browser/api/declarative_net_request/constants.h
+++ b/extensions/browser/api/declarative_net_request/constants.h
@@ -18,11 +18,9 @@
 enum class ParseResult {
   SUCCESS,
   ERROR_RESOURCE_TYPE_DUPLICATED,
-  ERROR_EMPTY_REDIRECT_RULE_PRIORITY,
-  ERROR_EMPTY_UPGRADE_RULE_PRIORITY,
   ERROR_INVALID_RULE_ID,
-  ERROR_INVALID_REDIRECT_RULE_PRIORITY,
-  ERROR_INVALID_UPGRADE_RULE_PRIORITY,
+  ERROR_EMPTY_RULE_PRIORITY,
+  ERROR_INVALID_RULE_PRIORITY,
   ERROR_NO_APPLICABLE_RESOURCE_TYPES,
   ERROR_EMPTY_DOMAINS_LIST,
   ERROR_EMPTY_RESOURCE_TYPES_LIST,
@@ -83,9 +81,8 @@
 
 // Rule parsing errors.
 extern const char kErrorResourceTypeDuplicated[];
-extern const char kErrorEmptyRedirectRuleKey[];
-extern const char kErrorEmptyUpgradeRulePriority[];
 extern const char kErrorInvalidRuleKey[];
+extern const char kErrorEmptyRulePriority[];
 extern const char kErrorNoApplicableResourceTypes[];
 extern const char kErrorEmptyList[];
 extern const char kErrorEmptyKey[];
diff --git a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc
index c102ee3..f7686c8 100644
--- a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc
@@ -28,10 +28,10 @@
 std::vector<url_pattern_index::UrlPatternIndexMatcher> GetMatchers(
     const ExtensionUrlPatternIndexMatcher::UrlPatternIndexList* index_list) {
   DCHECK(index_list);
-  DCHECK_EQ(flat::ActionIndex_count, index_list->size());
+  DCHECK_EQ(flat::IndexType_count, index_list->size());
 
   std::vector<url_pattern_index::UrlPatternIndexMatcher> matchers;
-  matchers.reserve(flat::ActionIndex_count);
+  matchers.reserve(flat::IndexType_count);
   for (const flat_rule::UrlPatternIndex* index : *index_list)
     matchers.emplace_back(index);
   return matchers;
@@ -59,16 +59,16 @@
     const ExtensionUrlPatternIndexMatcher::UrlPatternIndexList* index_list) {
   // We only support removing a subset of extra headers currently. If that
   // changes, the implementation here should change as well.
-  static_assert(flat::ActionIndex_count == 7,
+  static_assert(flat::IndexType_count == 4,
                 "Modify this method to ensure IsExtraHeadersMatcherInternal is "
                 "updated as new actions are added.");
-  static const flat::ActionIndex extra_header_indices[] = {
-      flat::ActionIndex_remove_cookie_header,
-      flat::ActionIndex_remove_referer_header,
-      flat::ActionIndex_remove_set_cookie_header,
+  static const flat::IndexType extra_header_indices[] = {
+      flat::IndexType_remove_cookie_header,
+      flat::IndexType_remove_referer_header,
+      flat::IndexType_remove_set_cookie_header,
   };
 
-  for (flat::ActionIndex index : extra_header_indices) {
+  for (flat::IndexType index : extra_header_indices) {
     if (HasAnyRules(index_list->Get(index)))
       return true;
   }
@@ -91,49 +91,33 @@
 ExtensionUrlPatternIndexMatcher::~ExtensionUrlPatternIndexMatcher() = default;
 
 base::Optional<RequestAction>
-ExtensionUrlPatternIndexMatcher::GetBlockOrCollapseAction(
+ExtensionUrlPatternIndexMatcher::GetBeforeRequestAction(
     const RequestParams& params) const {
   const flat_rule::UrlRule* rule =
-      GetMatchingRule(params, flat::ActionIndex_block);
-  if (!rule)
-    return base::nullopt;
-
-  return CreateBlockOrCollapseRequestAction(params, *rule);
-}
-
-base::Optional<RequestAction> ExtensionUrlPatternIndexMatcher::GetAllowAction(
-    const RequestParams& params) const {
-  const flat_rule::UrlRule* rule =
-      GetMatchingRule(params, flat::ActionIndex_allow);
-  if (!rule)
-    return base::nullopt;
-
-  return CreateAllowAction(params, *rule);
-}
-
-base::Optional<RequestAction>
-ExtensionUrlPatternIndexMatcher::GetRedirectAction(
-    const RequestParams& params) const {
-  const flat_rule::UrlRule* redirect_rule = GetMatchingRule(
-      params, flat::ActionIndex_redirect, FindRuleStrategy::kHighestPriority);
-  if (!redirect_rule)
-    return base::nullopt;
-
-  return CreateRedirectActionFromMetadata(params, *redirect_rule,
-                                          *metadata_list_);
-}
-
-base::Optional<RequestAction> ExtensionUrlPatternIndexMatcher::GetUpgradeAction(
-    const RequestParams& params) const {
-  DCHECK(IsUpgradeableRequest(params));
-
-  const flat_rule::UrlRule* upgrade_rule =
-      GetMatchingRule(params, flat::ActionIndex_upgrade_scheme,
+      GetMatchingRule(params, flat::IndexType_before_request,
                       FindRuleStrategy::kHighestPriority);
-  if (!upgrade_rule)
+  if (!rule)
     return base::nullopt;
 
-  return CreateUpgradeAction(params, *upgrade_rule);
+  const flat::UrlRuleMetadata* metadata =
+      metadata_list_->LookupByKey(rule->id());
+  DCHECK(metadata);
+  DCHECK_EQ(metadata->id(), rule->id());
+  switch (metadata->action()) {
+    case flat::ActionType_block:
+      return CreateBlockOrCollapseRequestAction(params, *rule);
+    case flat::ActionType_allow:
+      return CreateAllowAction(params, *rule);
+    case flat::ActionType_redirect:
+      return CreateRedirectActionFromMetadata(params, *rule, *metadata_list_);
+    case flat::ActionType_upgrade_scheme:
+      return CreateUpgradeAction(params, *rule);
+    case flat::ActionType_remove_headers:
+    case flat::ActionType_count:
+      NOTREACHED();
+  }
+
+  return base::nullopt;
 }
 
 uint8_t ExtensionUrlPatternIndexMatcher::GetRemoveHeadersMask(
@@ -146,7 +130,7 @@
   base::flat_map<const flat_rule::UrlRule*, uint8_t> rule_to_mask_map;
   auto handle_remove_header_bit = [this, &params, excluded_remove_headers_mask,
                                    &rule_to_mask_map](uint8_t bit,
-                                                      flat::ActionIndex index) {
+                                                      flat::IndexType index) {
     if (excluded_remove_headers_mask & bit)
       return;
 
@@ -165,16 +149,15 @@
         break;
       case dnr_api::REMOVE_HEADER_TYPE_COOKIE:
         bit = flat::RemoveHeaderType_cookie;
-        handle_remove_header_bit(bit, flat::ActionIndex_remove_cookie_header);
+        handle_remove_header_bit(bit, flat::IndexType_remove_cookie_header);
         break;
       case dnr_api::REMOVE_HEADER_TYPE_REFERER:
         bit = flat::RemoveHeaderType_referer;
-        handle_remove_header_bit(bit, flat::ActionIndex_remove_referer_header);
+        handle_remove_header_bit(bit, flat::IndexType_remove_referer_header);
         break;
       case dnr_api::REMOVE_HEADER_TYPE_SETCOOKIE:
         bit = flat::RemoveHeaderType_set_cookie;
-        handle_remove_header_bit(bit,
-                                 flat::ActionIndex_remove_set_cookie_header);
+        handle_remove_header_bit(bit, flat::IndexType_remove_set_cookie_header);
         break;
     }
   }
@@ -195,9 +178,9 @@
 
 const flat_rule::UrlRule* ExtensionUrlPatternIndexMatcher::GetMatchingRule(
     const RequestParams& params,
-    flat::ActionIndex index,
+    flat::IndexType index,
     FindRuleStrategy strategy) const {
-  DCHECK_LT(index, flat::ActionIndex_count);
+  DCHECK_LT(index, flat::IndexType_count);
   DCHECK_GE(index, 0);
   DCHECK(params.url);
 
diff --git a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h
index cd221c5..a41222e 100644
--- a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h
+++ b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h
@@ -29,13 +29,7 @@
 
   // RulesetMatcherBase override:
   ~ExtensionUrlPatternIndexMatcher() override;
-  base::Optional<RequestAction> GetBlockOrCollapseAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetAllowAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetRedirectAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetUpgradeAction(
+  base::Optional<RequestAction> GetBeforeRequestAction(
       const RequestParams& params) const override;
   uint8_t GetRemoveHeadersMask(
       const RequestParams& params,
@@ -50,13 +44,13 @@
 
   const url_pattern_index::flat::UrlRule* GetMatchingRule(
       const RequestParams& params,
-      flat::ActionIndex index,
+      flat::IndexType index,
       UrlPatternIndexMatcher::FindRuleStrategy strategy =
           UrlPatternIndexMatcher::FindRuleStrategy::kAny) const;
 
   const ExtensionMetadataList* const metadata_list_;
 
-  // UrlPatternIndexMatchers corresponding to entries in flat::ActionIndex.
+  // UrlPatternIndexMatchers corresponding to entries in flat::IndexType.
   const std::vector<UrlPatternIndexMatcher> matchers_;
 
   const bool is_extra_headers_matcher_;
diff --git a/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc b/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc
index 648bc67..368f672 100644
--- a/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc
@@ -24,6 +24,7 @@
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/common/api/declarative_net_request.h"
+#include "extensions/common/api/declarative_net_request/constants.h"
 #include "extensions/common/api/declarative_net_request/test_utils.h"
 #include "extensions/common/features/feature_channel.h"
 #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
@@ -87,9 +88,9 @@
            base::Optional<std::string> expected_error, LoadRequestData data,
            base::Optional<std::string> error) {
           EXPECT_EQ(1u, data.rulesets.size());
+          EXPECT_EQ(expected_error, error) << error.value_or("no actual error");
           EXPECT_EQ(expected_did_load_successfully,
                     data.rulesets[0].did_load_successfully());
-          EXPECT_EQ(expected_error, error) << error.value_or("no actual error");
           run_loop->Quit();
         },
         &run_loop, expected_did_load_successfully, expected_error);
@@ -268,14 +269,14 @@
     rule.action->type = std::string("redirect");
     rule.action->redirect.emplace();
     rule.action->redirect->url = std::string("http://google.com");
+    rule.priority.reset();
     api_rules.clear();
     api_rules.push_back(GetAPIRule(rule));
     TestAddDynamicRules(
         source.Clone(), std::move(api_rules),
         ReadJSONRulesResult::Status::kSuccess,
         UpdateDynamicRulesStatus::kErrorInvalidRules,
-        ParseInfo(ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY,
-                  kMinValidID + 1)
+        ParseInfo(ParseResult::ERROR_EMPTY_RULE_PRIORITY, kMinValidID + 1)
             .GetErrorDescription(),
         false /* expected_did_load_successfully */);
   }
diff --git a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
index e00e034..40ca2d65 100644
--- a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
+++ b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
@@ -160,7 +160,7 @@
   }
 
   bool PopulatePriorirty() {
-    // Do nothing. Priority is optional and only relevant for redirect rules.
+    CHECK(json_rule_.SetKey(kPriorityKey, base::Value(kMinValidPriority)));
     return true;
   }
 
diff --git a/extensions/browser/api/declarative_net_request/filter_list_converter/converter_unittest.cc b/extensions/browser/api/declarative_net_request/filter_list_converter/converter_unittest.cc
index da23c756..2547951 100644
--- a/extensions/browser/api/declarative_net_request/filter_list_converter/converter_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/filter_list_converter/converter_unittest.cc
@@ -75,7 +75,8 @@
           "resourceTypes": [ "script", "image", "font" ],
           "urlFilter": "||example.com^|"
        },
-       "id": 1
+       "id": 1,
+       "priority": 1
     }, {
        "action": {
           "type": "allow"
@@ -86,7 +87,8 @@
           "isUrlFilterCaseSensitive": false,
           "urlFilter": "allowed.com"
        },
-       "id": 2
+       "id": 2,
+       "priority": 1
     }, {
        "action": {
           "type": "block"
@@ -98,7 +100,8 @@
           "urlFilter": "|https://*.abc.com|",
           "domainType": "thirdParty"
        },
-       "id": 3
+       "id": 3,
+       "priority": 1
     }, {
        "action": {
           "type": "block"
@@ -108,7 +111,8 @@
           "urlFilter": "abc.com",
           "domainType": "firstParty"
        },
-       "id": 4
+       "id": 4,
+       "priority": 1
     } ]
 
 )";
diff --git a/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs b/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs
index 6b3140d8..9fa756d 100644
--- a/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs
+++ b/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs
@@ -10,6 +10,18 @@
 
 namespace extensions.declarative_net_request.flat;
 
+/// The type of an action. Corresponds to
+/// extensions::api::declarative_net_request::RuleActionType.
+enum ActionType : ubyte {
+  block,
+  allow,
+  redirect,
+  upgrade_scheme,
+  remove_headers,
+  /// Number of actions. Must be the last entry.
+  count
+}
+
 table QueryKeyValue {
   key : string (required);
   value : string (required);
@@ -52,6 +64,9 @@
   /// ID of the UrlRule for which this metadata is stored.
   id : uint (key);
 
+  /// Action type for this rule.
+  action : ActionType;
+
   /// Redirect url for this rule. Should represent a valid GURL. At most one of
   /// |redirect_url| and |transform| should be specified for redirect rules.
   redirect_url : string;
@@ -60,30 +75,19 @@
   transform : UrlTransform;
 }
 
-/// This provides a mapping from an action to its index within the |index_list|
-/// vector.
-/// TODO(crbug.com/1017868): This should be unified with ActionType once generic
-/// priorities are implemented.
-enum ActionIndex : ubyte {
-  block = 0,
-  allow,
-  redirect,
-  upgrade_scheme,
+/// This provides a mapping from an index type to its index within
+/// the |index_list| vector.
+enum IndexType : ubyte {
+  /// Index for rules that are evaluated during the onBeforeRequest stage of a
+  /// request.
+  before_request = 0,
+
   remove_cookie_header,
   remove_referer_header,
   remove_set_cookie_header,
-  /// Number of actions. Must be the last entry.
-  count
-}
 
-/// The type of an action. Corresponds to
-/// extensions::api::declarative_net_request::RuleActionType.
-enum ActionType : ubyte {
-  block,
-  allow,
-  redirect,
-  upgrade_scheme,
-  remove_headers
+  /// Number of indices. Must be the last entry.
+  count
 }
 
 /// The type of header to remove. Corresponds to
@@ -100,6 +104,9 @@
   url_rule: url_pattern_index.flat.UrlRule;
 
   /// The action to take.
+  // TODO(tbodt): this is duplicated in the UrlRuleMetadata. We should either
+  // use the action type in the metadata or not use UrlRuleMetadata at all for
+  // regex rules.
   action_type: ActionType;
 
   /// The headers to be removed. Mask of RemoveHeaderType.
@@ -112,8 +119,8 @@
 /// The top-level data structure used to store extensions URL rules for the
 /// Declarative Net Request API.
 table ExtensionIndexedRuleset {
-  /// Vector of UrlPatternIndex for different action types. This will consist
-  /// of ActionIndex_count indices.
+  /// Vector of UrlPatternIndex. This will consist of IndexType_count
+  /// indices.
   index_list : [url_pattern_index.flat.UrlPatternIndex];
 
   // Regex rules are not matched by UrlPatternIndex and so we don't build an
@@ -121,7 +128,6 @@
   regex_rules: [RegexRule];
 
   /// Extension related metadata. Sorted by id, to support fast lookup.
-  /// Currently this is only used for redirect rules.
   extension_metadata : [UrlRuleMetadata];
 }
 
diff --git a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc
index eb7024c..509447cd 100644
--- a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc
+++ b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "extensions/browser/api/declarative_net_request/indexed_rule.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
 #include "net/base/escape.h"
 
 namespace extensions {
@@ -48,8 +49,8 @@
 std::vector<std::unique_ptr<url_pattern_index::UrlPatternIndexBuilder>>
 CreateIndexBuilders(flatbuffers::FlatBufferBuilder* builder) {
   std::vector<std::unique_ptr<url_pattern_index::UrlPatternIndexBuilder>>
-      result(flat::ActionIndex_count);
-  for (size_t i = 0; i < flat::ActionIndex_count; ++i) {
+      result(flat::IndexType_count);
+  for (size_t i = 0; i < flat::IndexType_count; ++i) {
     result[i] =
         std::make_unique<url_pattern_index::UrlPatternIndexBuilder>(builder);
   }
@@ -191,30 +192,24 @@
             ? builder_.CreateSharedString(*indexed_rule.regex_substitution)
             : FlatStringOffset();
     regex_rules_.push_back(flat::CreateRegexRule(
-        builder_, offset, GetActionType(indexed_rule),
+        builder_, offset, ConvertToFlatActionType(indexed_rule.action_type),
         GetRemoveHeadersMask(indexed_rule), regex_substitution_offset));
   }
 
-  // Store additional metadata required for a redirect rule.
-  if (indexed_rule.action_type == dnr_api::RULE_ACTION_TYPE_REDIRECT) {
-    if (indexed_rule.redirect_url) {
-      DCHECK(!indexed_rule.redirect_url->empty());
-      FlatStringOffset redirect_url_offset =
-          builder_.CreateSharedString(*indexed_rule.redirect_url);
-      metadata_.push_back(flat::CreateUrlRuleMetadata(
-          builder_, indexed_rule.id, redirect_url_offset,
-          FlatOffset<flat::UrlTransform>()));
-    } else if (indexed_rule.url_transform) {
-      FlatOffset<flat::UrlTransform> transform_offset =
-          BuildTransformOffset(&builder_, *indexed_rule.url_transform);
-      metadata_.push_back(flat::CreateUrlRuleMetadata(
-          builder_, indexed_rule.id, FlatStringOffset() /* redirect_url */,
-          transform_offset));
-    } else {
-      // This was already indexed as part of |regex_rules_|.
-      DCHECK(indexed_rule.regex_substitution);
-    }
+  FlatStringOffset redirect_url_offset;
+  FlatOffset<flat::UrlTransform> transform_offset;
+  if (indexed_rule.redirect_url) {
+    DCHECK(!indexed_rule.redirect_url->empty());
+    redirect_url_offset =
+        builder_.CreateSharedString(*indexed_rule.redirect_url);
+  } else if (indexed_rule.url_transform) {
+    transform_offset =
+        BuildTransformOffset(&builder_, *indexed_rule.url_transform);
   }
+  metadata_.push_back(flat::CreateUrlRuleMetadata(
+      builder_, indexed_rule.id,
+      ConvertToFlatActionType(indexed_rule.action_type), redirect_url_offset,
+      transform_offset));
 }
 
 void FlatRulesetIndexer::Finish() {
@@ -249,26 +244,6 @@
   return base::make_span(builder_.GetBufferPointer(), builder_.GetSize());
 }
 
-flat::ActionType FlatRulesetIndexer::GetActionType(
-    const IndexedRule& indexed_rule) const {
-  switch (indexed_rule.action_type) {
-    case dnr_api::RULE_ACTION_TYPE_BLOCK:
-      return flat::ActionType_block;
-    case dnr_api::RULE_ACTION_TYPE_ALLOW:
-      return flat::ActionType_allow;
-    case dnr_api::RULE_ACTION_TYPE_REDIRECT:
-      return flat::ActionType_redirect;
-    case dnr_api::RULE_ACTION_TYPE_REMOVEHEADERS:
-      return flat::ActionType_remove_headers;
-    case dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME:
-      return flat::ActionType_upgrade_scheme;
-    case dnr_api::RULE_ACTION_TYPE_NONE:
-      break;
-  }
-  NOTREACHED();
-  return flat::ActionType_block;
-}
-
 uint8_t FlatRulesetIndexer::GetRemoveHeadersMask(
     const IndexedRule& indexed_rule) const {
   uint8_t mask = 0;
@@ -295,15 +270,12 @@
 FlatRulesetIndexer::GetBuilders(const IndexedRule& indexed_rule) {
   switch (indexed_rule.action_type) {
     case dnr_api::RULE_ACTION_TYPE_BLOCK:
-      return {index_builders_[flat::ActionIndex_block].get()};
     case dnr_api::RULE_ACTION_TYPE_ALLOW:
-      return {index_builders_[flat::ActionIndex_allow].get()};
     case dnr_api::RULE_ACTION_TYPE_REDIRECT:
-      return {index_builders_[flat::ActionIndex_redirect].get()};
+    case dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME:
+      return {index_builders_[flat::IndexType_before_request].get()};
     case dnr_api::RULE_ACTION_TYPE_REMOVEHEADERS:
       return GetRemoveHeaderBuilders(indexed_rule.remove_headers_set);
-    case dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME:
-      return {index_builders_[flat::ActionIndex_upgrade_scheme].get()};
     case dnr_api::RULE_ACTION_TYPE_NONE:
       break;
   }
@@ -325,15 +297,15 @@
         break;
       case dnr_api::REMOVE_HEADER_TYPE_COOKIE:
         result.push_back(
-            index_builders_[flat::ActionIndex_remove_cookie_header].get());
+            index_builders_[flat::IndexType_remove_cookie_header].get());
         break;
       case dnr_api::REMOVE_HEADER_TYPE_REFERER:
         result.push_back(
-            index_builders_[flat::ActionIndex_remove_referer_header].get());
+            index_builders_[flat::IndexType_remove_referer_header].get());
         break;
       case dnr_api::REMOVE_HEADER_TYPE_SETCOOKIE:
         result.push_back(
-            index_builders_[flat::ActionIndex_remove_set_cookie_header].get());
+            index_builders_[flat::IndexType_remove_set_cookie_header].get());
         break;
     }
   }
diff --git a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.h b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.h
index 7a617ff..5b480dc 100644
--- a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.h
+++ b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.h
@@ -45,7 +45,6 @@
  private:
   using UrlPatternIndexBuilder = url_pattern_index::UrlPatternIndexBuilder;
 
-  flat::ActionType GetActionType(const IndexedRule& indexed_rule) const;
   uint8_t GetRemoveHeadersMask(const IndexedRule& indexed_rule) const;
   std::vector<UrlPatternIndexBuilder*> GetBuilders(
       const IndexedRule& indexed_rule);
@@ -54,7 +53,7 @@
 
   flatbuffers::FlatBufferBuilder builder_;
 
-  // This will consist of |flat::ActionIndex_count| builders. We use unique_ptr
+  // This will consist of |flat::IndexType_count| builders. We use unique_ptr
   // since UrlPatternIndexBuilder is a non-copyable and non-movable type.
   const std::vector<std::unique_ptr<UrlPatternIndexBuilder>> index_builders_;
 
diff --git a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
index 074789c..0711789 100644
--- a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
@@ -15,6 +15,7 @@
 #include "extensions/browser/api/declarative_net_request/constants.h"
 #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
 #include "extensions/browser/api/declarative_net_request/indexed_rule.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
@@ -220,9 +221,9 @@
 }
 
 // Verifies that |extension_metadata| is sorted by ID and corresponds to rules
-// in |redirect_rules|.
+// in |rules|.
 void VerifyExtensionMetadata(
-    const std::vector<const IndexedRule*>& redirect_rules,
+    const std::vector<const IndexedRule*>& rules,
     const ::flatbuffers::Vector<flatbuffers::Offset<flat::UrlRuleMetadata>>*
         extension_metdata) {
   struct MetadataPair {
@@ -233,8 +234,11 @@
   // Build a map from IDs to MetadataPair(s).
   std::map<uint32_t, MetadataPair> map;
 
-  for (const auto* rule : redirect_rules) {
-    EXPECT_EQ(nullptr, map[rule->id].indexed_rule);
+  for (const auto* rule : rules) {
+    // It is possible for a rule to be present in multiple indices, such as a
+    // remove headers rule that removes more than one header.
+    EXPECT_TRUE(map[rule->id].indexed_rule == nullptr ||
+                map[rule->id].indexed_rule == rule);
     map[rule->id].indexed_rule = rule;
   }
 
@@ -252,7 +256,15 @@
 
   // Returns whether the metadata for the given rule was correctly indexed.
   auto is_metadata_correct = [](const MetadataPair& pair) {
-    CHECK(pair.indexed_rule->redirect_url || pair.indexed_rule->url_transform);
+    EXPECT_TRUE(pair.indexed_rule);
+
+    if (ConvertToFlatActionType(pair.indexed_rule->action_type) !=
+        pair.metadata->action()) {
+      return false;
+    }
+
+    EXPECT_FALSE(pair.indexed_rule->redirect_url &&
+                 pair.indexed_rule->url_transform);
 
     if (pair.indexed_rule->redirect_url) {
       if (!pair.metadata->redirect_url())
@@ -261,11 +273,16 @@
              ToString(pair.metadata->redirect_url());
     }
 
-    return pair.metadata->transform() &&
-           VerifyUrlTransform(*pair.metadata->transform());
+    if (pair.indexed_rule->url_transform) {
+      if (!pair.metadata->transform())
+        return false;
+      return VerifyUrlTransform(*pair.metadata->transform());
+    }
+
+    return true;
   };
 
-  // Iterate over the map and verify equality of the redirect rules.
+  // Iterate over the map and verify correctness of the metadata.
   for (const auto& elem : map) {
     EXPECT_TRUE(is_metadata_correct(elem.second)) << base::StringPrintf(
         "Redirect rule with id %u was incorrectly indexed", elem.first);
@@ -296,26 +313,30 @@
 // ExtensionIndexedRuleset.
 void AddRulesAndVerifyIndex(const std::vector<IndexedRule>& rules_to_index,
                             const std::vector<const IndexedRule*>
-                                expected_index_lists[flat::ActionIndex_count]) {
+                                expected_index_lists[flat::IndexType_count]) {
   FlatRulesetIndexer indexer;
   const flat::ExtensionIndexedRuleset* ruleset =
       AddRuleAndGetRuleset(rules_to_index, &indexer);
   ASSERT_TRUE(ruleset);
 
-  for (size_t i = 0; i < flat::ActionIndex_count; ++i) {
+  for (size_t i = 0; i < flat::IndexType_count; ++i) {
     SCOPED_TRACE(base::StringPrintf("Testing index %" PRIuS, i));
     VerifyIndexEquality(expected_index_lists[i], ruleset->index_list()->Get(i));
   }
 
   {
     SCOPED_TRACE("Testing extension metadata");
-    VerifyExtensionMetadata(expected_index_lists[flat::ActionIndex_redirect],
-                            ruleset->extension_metadata());
+    std::vector<const IndexedRule*> all_rules;
+    for (size_t i = 0; i < flat::IndexType_count; i++) {
+      all_rules.insert(all_rules.end(), expected_index_lists[i].begin(),
+                       expected_index_lists[i].end());
+    }
+    VerifyExtensionMetadata(all_rules, ruleset->extension_metadata());
   }
 }
 
 TEST_F(FlatRulesetIndexerTest, TestEmptyIndex) {
-  std::vector<const IndexedRule*> expected_index_lists[flat::ActionIndex_count];
+  std::vector<const IndexedRule*> expected_index_lists[flat::IndexType_count];
   AddRulesAndVerifyIndex({}, expected_index_lists);
 }
 
@@ -410,19 +431,16 @@
   // vector can resize/reallocate invalidating the existing pointers/iterators.
   // Hence we build |expected_index_lists| once the vector |rules_to_index| is
   // finalized.
-  std::vector<const IndexedRule*> expected_index_lists[flat::ActionIndex_count];
-  expected_index_lists[flat::ActionIndex_block] = {&rules_to_index[0],
-                                                   &rules_to_index[1]};
-  expected_index_lists[flat::ActionIndex_redirect] = {
-      &rules_to_index[2], &rules_to_index[3], &rules_to_index[4],
-      &rules_to_index[5]};
-  expected_index_lists[flat::ActionIndex_allow] = {&rules_to_index[6],
-                                                   &rules_to_index[7]};
-  expected_index_lists[flat::ActionIndex_remove_cookie_header] = {
+  std::vector<const IndexedRule*> expected_index_lists[flat::IndexType_count];
+  expected_index_lists[flat::IndexType_before_request] = {
+      &rules_to_index[0], &rules_to_index[1], &rules_to_index[2],
+      &rules_to_index[3], &rules_to_index[4], &rules_to_index[5],
+      &rules_to_index[6], &rules_to_index[7]};
+  expected_index_lists[flat::IndexType_remove_cookie_header] = {
       &rules_to_index[8], &rules_to_index[9]};
-  expected_index_lists[flat::ActionIndex_remove_referer_header] = {
+  expected_index_lists[flat::IndexType_remove_referer_header] = {
       &rules_to_index[9]};
-  expected_index_lists[flat::ActionIndex_remove_set_cookie_header] = {
+  expected_index_lists[flat::IndexType_remove_set_cookie_header] = {
       &rules_to_index[8], &rules_to_index[9]};
 
   AddRulesAndVerifyIndex(rules_to_index, expected_index_lists);
@@ -473,16 +491,17 @@
   ASSERT_TRUE(ruleset);
 
   // All the indices should be empty, since we only have regex rules.
-  for (size_t i = 0; i < flat::ActionIndex_count; ++i) {
+  for (size_t i = 0; i < flat::IndexType_count; ++i) {
     SCOPED_TRACE(base::StringPrintf("Testing index %" PRIuS, i));
     VerifyIndexEquality({}, ruleset->index_list()->Get(i));
   }
 
-  // We should have metadata for the redirect rule.
   {
     SCOPED_TRACE("Testing extension metadata");
-    VerifyExtensionMetadata({&rules_to_index[1]},
-                            ruleset->extension_metadata());
+    std::vector<const IndexedRule*> all_rules;
+    for (IndexedRule& rule : rules_to_index)
+      all_rules.push_back(&rule);
+    VerifyExtensionMetadata(all_rules, ruleset->extension_metadata());
   }
 
   ASSERT_TRUE(ruleset->regex_rules());
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule.cc b/extensions/browser/api/declarative_net_request/indexed_rule.cc
index dde54c1..fc1c198 100644
--- a/extensions/browser/api/declarative_net_request/indexed_rule.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_rule.cc
@@ -384,20 +384,20 @@
   if (parsed_rule.id < kMinValidID)
     return ParseResult::ERROR_INVALID_RULE_ID;
 
+  const bool is_before_request_rule =
+      parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_BLOCK ||
+      parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_ALLOW ||
+      parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_REDIRECT ||
+      parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME;
+  if (is_before_request_rule) {
+    if (!parsed_rule.priority)
+      return ParseResult::ERROR_EMPTY_RULE_PRIORITY;
+    if (*parsed_rule.priority < kMinValidPriority)
+      return ParseResult::ERROR_INVALID_RULE_PRIORITY;
+  }
+
   const bool is_redirect_rule =
       parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_REDIRECT;
-  const bool is_upgrade_rule =
-      parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME;
-
-  if (is_redirect_rule || is_upgrade_rule) {
-    if (!parsed_rule.priority)
-      return is_redirect_rule ? ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY
-                              : ParseResult::ERROR_EMPTY_UPGRADE_RULE_PRIORITY;
-    if (*parsed_rule.priority < kMinValidPriority)
-      return is_redirect_rule
-                 ? ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY
-                 : ParseResult::ERROR_INVALID_UPGRADE_RULE_PRIORITY;
-  }
 
   if (is_redirect_rule) {
     if (!parsed_rule.action.redirect)
@@ -464,8 +464,7 @@
   indexed_rule->action_type = parsed_rule.action.type;
   indexed_rule->id = base::checked_cast<uint32_t>(parsed_rule.id);
   indexed_rule->priority = base::checked_cast<uint32_t>(
-      (is_redirect_rule || is_upgrade_rule) ? *parsed_rule.priority
-                                            : kDefaultPriority);
+      is_before_request_rule ? *parsed_rule.priority : kDefaultPriority);
   indexed_rule->options = GetOptionsMask(parsed_rule);
   indexed_rule->activation_types = GetActivationTypes(parsed_rule);
 
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
index fbc5260..8d2bfde3 100644
--- a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
@@ -18,6 +18,7 @@
 #include "extensions/browser/api/declarative_net_request/constants.h"
 #include "extensions/browser/api/declarative_net_request/test_utils.h"
 #include "extensions/common/api/declarative_net_request.h"
+#include "extensions/common/api/declarative_net_request/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/features/feature_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -43,6 +44,7 @@
 
 dnr_api::Rule CreateGenericParsedRule() {
   dnr_api::Rule rule;
+  rule.priority = std::make_unique<int>(kMinValidPriority);
   rule.id = kMinValidID;
   rule.condition.url_filter = std::make_unique<std::string>("filter");
   rule.action.type = dnr_api::RULE_ACTION_TYPE_BLOCK;
@@ -93,23 +95,27 @@
   } cases[] = {
       {dnr_api::RULE_ACTION_TYPE_REDIRECT,
        std::make_unique<int>(kMinValidPriority - 1),
-       ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY, kDefaultPriority},
+       ParseResult::ERROR_INVALID_RULE_PRIORITY, kDefaultPriority},
       {dnr_api::RULE_ACTION_TYPE_REDIRECT,
        std::make_unique<int>(kMinValidPriority), ParseResult::SUCCESS,
        kMinValidPriority},
+      {dnr_api::RULE_ACTION_TYPE_REDIRECT, nullptr,
+       ParseResult::ERROR_EMPTY_RULE_PRIORITY, kDefaultPriority},
       {dnr_api::RULE_ACTION_TYPE_REDIRECT,
        std::make_unique<int>(kMinValidPriority + 1), ParseResult::SUCCESS,
        kMinValidPriority + 1},
-      {dnr_api::RULE_ACTION_TYPE_REDIRECT, nullptr,
-       ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY, kDefaultPriority},
       {dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME,
        std::make_unique<int>(kMinValidPriority - 1),
-       ParseResult::ERROR_INVALID_UPGRADE_RULE_PRIORITY, kDefaultPriority},
+       ParseResult::ERROR_INVALID_RULE_PRIORITY, kDefaultPriority},
       {dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME,
        std::make_unique<int>(kMinValidPriority), ParseResult::SUCCESS,
        kMinValidPriority},
-      {dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME, nullptr,
-       ParseResult::ERROR_EMPTY_UPGRADE_RULE_PRIORITY, kDefaultPriority},
+      {dnr_api::RULE_ACTION_TYPE_BLOCK,
+       std::make_unique<int>(kMinValidPriority - 1),
+       ParseResult::ERROR_INVALID_RULE_PRIORITY, kDefaultPriority},
+      {dnr_api::RULE_ACTION_TYPE_BLOCK,
+       std::make_unique<int>(kMinValidPriority), ParseResult::SUCCESS,
+       kMinValidPriority},
   };
 
   for (size_t i = 0; i < base::size(cases); ++i) {
@@ -131,10 +137,15 @@
       EXPECT_EQ(cases[i].expected_priority, indexed_rule.priority);
   }
 
-  // Ensure priority is ignored for non-redirect rules.
+  // Ensure priority is ignored for non-before-request rules.
   {
     dnr_api::Rule rule = CreateGenericParsedRule();
+    rule.action.type = dnr_api::RULE_ACTION_TYPE_REMOVEHEADERS;
     rule.priority = std::make_unique<int>(5);
+    rule.action.remove_headers_list =
+        std::make_unique<std::vector<dnr_api::RemoveHeaderType>>(
+            std::vector<dnr_api::RemoveHeaderType>{
+                dnr_api::REMOVE_HEADER_TYPE_COOKIE});
     IndexedRule indexed_rule;
     ParseResult result = IndexedRule::CreateIndexedRule(
         std::move(rule), GetBaseURL(), &indexed_rule);
@@ -431,7 +442,6 @@
     dnr_api::Rule rule = CreateGenericParsedRule();
     rule.action.redirect = MakeRedirectUrl(cases[i].redirect_url);
     rule.action.type = dnr_api::RULE_ACTION_TYPE_REDIRECT;
-    rule.priority = std::make_unique<int>(kMinValidPriority);
 
     IndexedRule indexed_rule;
     ParseResult result = IndexedRule::CreateIndexedRule(
@@ -613,7 +623,6 @@
     SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i));
     dnr_api::Rule rule = CreateGenericParsedRule();
     rule.action.type = dnr_api::RULE_ACTION_TYPE_REDIRECT;
-    rule.priority = std::make_unique<int>(kMinValidPriority);
 
     base::Optional<base::Value> redirect_val =
         base::JSONReader::Read(cases[i].redirect_dictionary_json);
diff --git a/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc b/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
index 6a4bd11e..92b6de8 100644
--- a/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
@@ -20,6 +20,14 @@
 const char* kFlatbufferSchemaExpected = R"(
 include "components/url_pattern_index/flat/url_pattern_index.fbs";
 namespace extensions.declarative_net_request.flat;
+enum ActionType : ubyte {
+  block,
+  allow,
+  redirect,
+  upgrade_scheme,
+  remove_headers,
+  count
+}
 table QueryKeyValue {
   key : string (required);
   value : string (required);
@@ -42,26 +50,17 @@
 }
 table UrlRuleMetadata {
   id : uint (key);
+  action : ActionType;
   redirect_url : string;
   transform : UrlTransform;
 }
-enum ActionIndex : ubyte {
-  block = 0,
-  allow,
-  redirect,
-  upgrade_scheme,
+enum IndexType : ubyte {
+  before_request = 0,
   remove_cookie_header,
   remove_referer_header,
   remove_set_cookie_header,
   count
 }
-enum ActionType : ubyte {
-  block,
-  allow,
-  redirect,
-  upgrade_scheme,
-  remove_headers
-}
 enum RemoveHeaderType : ubyte (bit_flags) {
   cookie,
   referer,
@@ -144,7 +143,7 @@
   EXPECT_EQ(StripCommentsAndWhitespace(kFlatbufferSchemaExpected),
             StripCommentsAndWhitespace(flatbuffer_schema))
       << "Schema change detected; update this test and the schema version.";
-  EXPECT_EQ(13, GetIndexedRulesetFormatVersionForTesting())
+  EXPECT_EQ(14, GetIndexedRulesetFormatVersionForTesting())
       << "Update this test if you update the schema version.";
 }
 
diff --git a/extensions/browser/api/declarative_net_request/parse_info.cc b/extensions/browser/api/declarative_net_request/parse_info.cc
index 72c0133..eb08f6c 100644
--- a/extensions/browser/api/declarative_net_request/parse_info.cc
+++ b/extensions/browser/api/declarative_net_request/parse_info.cc
@@ -46,22 +46,16 @@
       error = ErrorUtils::FormatErrorMessage(kErrorResourceTypeDuplicated,
                                              base::NumberToString(*rule_id_));
       break;
-    case ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY:
-      error = ErrorUtils::FormatErrorMessage(kErrorEmptyRedirectRuleKey,
-                                             base::NumberToString(*rule_id_),
-                                             kPriorityKey);
-      break;
-    case ParseResult::ERROR_EMPTY_UPGRADE_RULE_PRIORITY:
-      error = ErrorUtils::FormatErrorMessage(kErrorEmptyUpgradeRulePriority,
-                                             base::NumberToString(*rule_id_));
-      break;
     case ParseResult::ERROR_INVALID_RULE_ID:
       error = ErrorUtils::FormatErrorMessage(
           kErrorInvalidRuleKey, base::NumberToString(*rule_id_), kIDKey,
           base::NumberToString(kMinValidID));
       break;
-    case ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY:
-    case ParseResult::ERROR_INVALID_UPGRADE_RULE_PRIORITY:
+    case ParseResult::ERROR_EMPTY_RULE_PRIORITY:
+      error = ErrorUtils::FormatErrorMessage(kErrorEmptyRulePriority,
+                                             base::NumberToString(*rule_id_));
+      break;
+    case ParseResult::ERROR_INVALID_RULE_PRIORITY:
       error = ErrorUtils::FormatErrorMessage(
           kErrorInvalidRuleKey, base::NumberToString(*rule_id_), kPriorityKey,
           base::NumberToString(kMinValidPriority));
diff --git a/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc b/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc
index 05c8907..efa29595 100644
--- a/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc
@@ -25,7 +25,7 @@
 
   // We only support removing a subset of extra headers currently. If that
   // changes, the implementation here should change as well.
-  static_assert(flat::ActionIndex_count == 7,
+  static_assert(flat::ActionType_count == 5,
                 "Modify this method to ensure IsExtraHeadersMatcherInternal is "
                 "updated as new actions are added.");
 
@@ -55,6 +55,21 @@
       params.first_party_origin, rule, false /* disable_generic_rules */);
 }
 
+bool IsBeforeRequestAction(flat::ActionType action_type) {
+  switch (action_type) {
+    case flat::ActionType_block:
+    case flat::ActionType_allow:
+    case flat::ActionType_redirect:
+    case flat::ActionType_upgrade_scheme:
+      return true;
+    case flat::ActionType_remove_headers:
+      return false;
+    case flat::ActionType_count:
+      NOTREACHED();
+  }
+  return false;
+}
+
 }  // namespace
 
 RegexRuleInfo::RegexRuleInfo(const flat::RegexRule* regex_rule,
@@ -80,85 +95,40 @@
 
 RegexRulesMatcher::~RegexRulesMatcher() = default;
 
-base::Optional<RequestAction> RegexRulesMatcher::GetBlockOrCollapseAction(
+base::Optional<RequestAction> RegexRulesMatcher::GetBeforeRequestAction(
     const RequestParams& params) const {
-  const RegexRuleInfo* info =
-      GetHighestPriorityMatchingRule(params, flat::ActionType_block);
-  if (!info)
+  const std::vector<RegexRuleInfo>& potential_matches =
+      GetPotentialMatches(params);
+  auto info = std::find_if(
+      potential_matches.begin(), potential_matches.end(),
+      [&params](const RegexRuleInfo& info) {
+        return IsBeforeRequestAction(info.regex_rule->action_type()) &&
+               re2::RE2::PartialMatch(params.url->spec(), *info.regex);
+      });
+  if (info == potential_matches.end())
     return base::nullopt;
 
-  return CreateBlockOrCollapseRequestAction(params,
-                                            *info->regex_rule->url_rule());
-}
-
-base::Optional<RequestAction> RegexRulesMatcher::GetAllowAction(
-    const RequestParams& params) const {
-  const RegexRuleInfo* info =
-      GetHighestPriorityMatchingRule(params, flat::ActionType_allow);
-  if (!info)
-    return base::nullopt;
-
-  return CreateAllowAction(params, *info->regex_rule->url_rule());
-}
-
-base::Optional<RequestAction> RegexRulesMatcher::GetRedirectAction(
-    const RequestParams& params) const {
-  const RegexRuleInfo* info =
-      GetHighestPriorityMatchingRule(params, flat::ActionType_redirect);
-  if (!info)
-    return base::nullopt;
-
-  // If this is a regex substitution rule, handle the substitution. Else create
-  // the redirect action from the information in |metadata_list_| below.
-  if (info->regex_rule->regex_substitution()) {
-    std::string redirect_str;
-
-    // We could have extracted the captured strings during the matching stage
-    // and directly used RE2::Rewrite here (which doesn't need to match the
-    // regex again). However we prefer to capture the strings only when
-    // necessary. Not capturing the strings should allow re2 to perform
-    // additional optimizations during the matching stage.
-    bool success =
-        RE2::Extract(params.url->spec(), *info->regex,
-                     ToRE2StringPiece(*info->regex_rule->regex_substitution()),
-                     &redirect_str);
-    if (!success) {
-      // This should generally not happen since we had already checked for a
-      // match and during indexing, had verified that the substitution pattern
-      // is not ill-formed. However, the re2 library implementation might have
-      // changed since indexing, causing this.
-      LOG(ERROR) << base::StringPrintf(
-          "Rewrite failed. Regex:%s Substitution:%s URL:%s\n",
-          info->regex->pattern().c_str(),
-          info->regex_rule->regex_substitution()->c_str(),
-          params.url->spec().c_str());
-      return base::nullopt;
-    }
-
-    GURL redirect_url(redirect_str);
-
-    // Redirects to JavaScript urls are not allowed.
-    if (redirect_url.SchemeIs(url::kJavaScriptScheme))
-      return base::nullopt;
-
-    return CreateRedirectAction(params, *info->regex_rule->url_rule(),
-                                std::move(redirect_url));
+  const flat_rule::UrlRule& rule = *info->regex_rule->url_rule();
+  switch (info->regex_rule->action_type()) {
+    case flat::ActionType_block:
+      return CreateBlockOrCollapseRequestAction(params, rule);
+    case flat::ActionType_allow:
+      return CreateAllowAction(params, rule);
+    case flat::ActionType_redirect:
+      // If this is a regex substitution rule, handle the substitution. Else
+      // create the redirect action from the information in |metadata_list_|
+      // below.
+      return info->regex_rule->regex_substitution()
+                 ? CreateRegexSubstitutionRedirectAction(params, *info)
+                 : CreateRedirectActionFromMetadata(params, rule,
+                                                    *metadata_list_);
+    case flat::ActionType_upgrade_scheme:
+      return CreateUpgradeAction(params, rule);
+    default:
+      NOTREACHED();
   }
 
-  return CreateRedirectActionFromMetadata(params, *info->regex_rule->url_rule(),
-                                          *metadata_list_);
-}
-
-base::Optional<RequestAction> RegexRulesMatcher::GetUpgradeAction(
-    const RequestParams& params) const {
-  DCHECK(IsUpgradeableRequest(params));
-
-  const RegexRuleInfo* info =
-      GetHighestPriorityMatchingRule(params, flat::ActionType_upgrade_scheme);
-  if (!info)
-    return base::nullopt;
-
-  return CreateUpgradeAction(params, *info->regex_rule->url_rule());
+  return base::nullopt;
 }
 
 uint8_t RegexRulesMatcher::GetRemoveHeadersMask(
@@ -259,23 +229,6 @@
   substring_matcher_.RegisterPatterns(patterns);
 }
 
-const RegexRuleInfo* RegexRulesMatcher::GetHighestPriorityMatchingRule(
-    const RequestParams& params,
-    flat::ActionType type) const {
-  const std::vector<RegexRuleInfo>& potential_matches =
-      GetPotentialMatches(params);
-  auto it = std::find_if(potential_matches.begin(), potential_matches.end(),
-                         [&params, type](const RegexRuleInfo& info) {
-                           return info.regex_rule->action_type() == type &&
-                                  re2::RE2::PartialMatch(params.url->spec(),
-                                                         *info.regex);
-                         });
-  if (it == potential_matches.end())
-    return nullptr;
-
-  return &(*it);
-}
-
 const std::vector<RegexRuleInfo>& RegexRulesMatcher::GetPotentialMatches(
     const RequestParams& params) const {
   auto iter = params.potential_regex_matches.find(this);
@@ -327,5 +280,43 @@
   return result.first->second;
 }
 
+base::Optional<RequestAction>
+RegexRulesMatcher::CreateRegexSubstitutionRedirectAction(
+    const RequestParams& params,
+    const RegexRuleInfo& info) const {
+  std::string redirect_str;
+
+  // We could have extracted the captured strings during the matching stage
+  // and directly used RE2::Rewrite here (which doesn't need to match the
+  // regex again). However we prefer to capture the strings only when
+  // necessary. Not capturing the strings should allow re2 to perform
+  // additional optimizations during the matching stage.
+  bool success = RE2::Extract(
+      params.url->spec(), *info.regex,
+      ToRE2StringPiece(*info.regex_rule->regex_substitution()), &redirect_str);
+  if (!success) {
+    // This should generally not happen since we had already checked for a
+    // match and during indexing, had verified that the substitution pattern
+    // is not ill-formed. However, the re2 library implementation might have
+    // changed since indexing, causing this.
+    LOG(ERROR) << base::StringPrintf(
+        "Rewrite failed. Regex:%s Substitution:%s URL:%s\n",
+        info.regex->pattern().c_str(),
+        info.regex_rule->regex_substitution()->c_str(),
+        params.url->spec().c_str());
+    return base::nullopt;
+  }
+
+  GURL redirect_url(redirect_str);
+
+  // Redirects to JavaScript urls are not allowed.
+  // TODO(crbug.com/1033780): this results in counterintuitive behavior.
+  if (redirect_url.SchemeIs(url::kJavaScriptScheme))
+    return base::nullopt;
+
+  return CreateRedirectAction(params, *info.regex_rule->url_rule(),
+                              std::move(redirect_url));
+}
+
 }  // namespace declarative_net_request
 }  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/regex_rules_matcher.h b/extensions/browser/api/declarative_net_request/regex_rules_matcher.h
index 4e6cffce..4abc8a2 100644
--- a/extensions/browser/api/declarative_net_request/regex_rules_matcher.h
+++ b/extensions/browser/api/declarative_net_request/regex_rules_matcher.h
@@ -56,13 +56,7 @@
 
   // RulesetMatcherBase override:
   ~RegexRulesMatcher() override;
-  base::Optional<RequestAction> GetBlockOrCollapseAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetAllowAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetRedirectAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetUpgradeAction(
+  base::Optional<RequestAction> GetBeforeRequestAction(
       const RequestParams& params) const override;
   uint8_t GetRemoveHeadersMask(
       const RequestParams& params,
@@ -76,12 +70,6 @@
   // Helper to build the necessary data structures for matching.
   void InitializeMatcher();
 
-  // Returns the highest priority matching rule for the given request |params|
-  // and action |type|, or null if no rules match.
-  const RegexRuleInfo* GetHighestPriorityMatchingRule(
-      const RequestParams& params,
-      flat::ActionType type) const;
-
   // Returns the potentially matching rules for the given request. A potentially
   // matching rule is one whose metadata matches the given request |params| and
   // which is not ruled out as a potential match by the |filtered_re2_| object.
@@ -89,6 +77,11 @@
   const std::vector<RegexRuleInfo>& GetPotentialMatches(
       const RequestParams& params) const;
 
+  // Returns a RequestAction for the the given regex substitution rule.
+  base::Optional<RequestAction> CreateRegexSubstitutionRedirectAction(
+      const RequestParams& params,
+      const RegexRuleInfo& info) const;
+
   // Pointers to flatbuffer indexed data. Guaranteed to be valid through the
   // lifetime of the object.
   const RegexRulesList* const regex_list_;
diff --git a/extensions/browser/api/declarative_net_request/request_action.h b/extensions/browser/api/declarative_net_request/request_action.h
index 8b98484..07352f1 100644
--- a/extensions/browser/api/declarative_net_request/request_action.h
+++ b/extensions/browser/api/declarative_net_request/request_action.h
@@ -26,10 +26,12 @@
     // Block the network request and collapse the corresponding DOM element.
     COLLAPSE,
     // Allow the network request, preventing it from being intercepted by other
-    // matching rules. Only used for tracking a matched allow rule.
+    // matching rules.
     ALLOW,
     // Redirect the network request.
     REDIRECT,
+    // Upgrade the scheme of the network request.
+    UPGRADE,
     // Remove request/response headers.
     REMOVE_HEADERS,
   };
@@ -45,14 +47,13 @@
 
   Type type = Type::BLOCK;
 
-  // Valid iff |type| is |REDIRECT|.
+  // Valid iff |IsRedirectOrUpgrade()| is true.
   base::Optional<GURL> redirect_url;
 
   // The ID of the matching rule for this action.
   uint32_t rule_id;
 
-  // The priority of the matching rule for this action. Only really valid for
-  // redirect actions.
+  // The priority of the matching rule for this action.
   uint32_t rule_priority;
 
   // The source type of the matching rule for this action.
@@ -71,6 +72,13 @@
   // ActionTracker.
   mutable bool tracked = false;
 
+  bool IsBlockOrCollapse() const {
+    return type == Type::BLOCK || type == Type::COLLAPSE;
+  }
+  bool IsRedirectOrUpgrade() const {
+    return type == Type::REDIRECT || type == Type::UPGRADE;
+  }
+
   DISALLOW_COPY_AND_ASSIGN(RequestAction);
 };
 
diff --git a/extensions/browser/api/declarative_net_request/request_params.h b/extensions/browser/api/declarative_net_request/request_params.h
index ba4bb64..8e43de8f 100644
--- a/extensions/browser/api/declarative_net_request/request_params.h
+++ b/extensions/browser/api/declarative_net_request/request_params.h
@@ -34,7 +34,7 @@
   bool is_third_party = false;
 
   // A map from RulesetMatchers to whether it has a matching allow rule. Used as
-  // a cache to prevent additional calls to GetAllowAction.
+  // a cache to prevent additional calls to GetBeforeRequestAction.
   mutable base::flat_map<const RulesetMatcher*, bool> allow_rule_cache;
 
   // Lower cased url, used for regex matching. Cached for performance.
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
index 90d59eca..d8c9a6a 100644
--- a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
+++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
@@ -304,10 +304,9 @@
     return;
 
   extensions_with_rulesets_.insert(load_data.extension_id);
-  LoadRuleset(
-      load_data.extension_id,
-      std::make_unique<CompositeMatcher>(std::move(matchers), &action_tracker_),
-      prefs_->GetDNRAllowedPages(load_data.extension_id));
+  LoadRuleset(load_data.extension_id,
+              std::make_unique<CompositeMatcher>(std::move(matchers)),
+              prefs_->GetDNRAllowedPages(load_data.extension_id));
 }
 
 void RulesMonitorService::OnDynamicRulesUpdated(
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
index d551b13..06b5a8b 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_manager.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
@@ -311,7 +311,7 @@
 
   // We only support removing a subset of extra headers currently. If that
   // changes, the implementation here should change as well.
-  static_assert(flat::ActionIndex_count == 7,
+  static_assert(flat::ActionType_count == 5,
                 "Modify this method to ensure HasExtraHeadersMatcherForRequest "
                 "is updated as new actions are added.");
 
@@ -351,19 +351,7 @@
          std::tie(other.extension_install_time, other.extension_id);
 }
 
-base::Optional<RequestAction> RulesetManager::GetBlockOrCollapseAction(
-    const std::vector<const ExtensionRulesetData*>& rulesets,
-    const RequestParams& params) const {
-  for (const ExtensionRulesetData* ruleset : rulesets) {
-    base::Optional<RequestAction> action =
-        ruleset->matcher->GetBlockOrCollapseAction(params);
-    if (action)
-      return action;
-  }
-  return base::nullopt;
-}
-
-base::Optional<RequestAction> RulesetManager::GetRedirectOrUpgradeAction(
+base::Optional<RequestAction> RulesetManager::GetBeforeRequestAction(
     const std::vector<const ExtensionRulesetData*>& rulesets,
     const WebRequestInfo& request,
     const int tab_id,
@@ -373,13 +361,31 @@
                         [](const ExtensionRulesetData* a,
                            const ExtensionRulesetData* b) { return *a < *b; }));
 
-  // Redirecting WebSocket handshake request is prohibited.
-  if (params.element_type == flat_rule::ElementType_WEBSOCKET)
-    return base::nullopt;
+  // The priorities of actions between different extensions is different from
+  // the priorities of actions within an extension.
+  const auto action_priority = [](const base::Optional<RequestAction>& action) {
+    if (!action.has_value())
+      return 0;
+    switch (action->type) {
+      case RequestAction::Type::BLOCK:
+      case RequestAction::Type::COLLAPSE:
+        return 3;
+      case RequestAction::Type::REDIRECT:
+      case RequestAction::Type::UPGRADE:
+        return 2;
+      case RequestAction::Type::ALLOW:
+        return 1;
+      case RequestAction::Type::REMOVE_HEADERS:
+        NOTREACHED();
+        return 0;
+    }
+  };
+
+  base::Optional<RequestAction> action;
 
   // This iterates in decreasing order of extension installation time. Hence
   // more recently installed extensions get higher priority in choosing the
-  // redirect url.
+  // action for the request.
   for (const ExtensionRulesetData* ruleset : rulesets) {
     PageAccess page_access = WebRequestPermissions::CanExtensionAccessURL(
         permission_helper_, ruleset->extension_id, request.url, tab_id,
@@ -387,23 +393,20 @@
         WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL_AND_INITIATOR,
         request.initiator, request.type);
 
-    CompositeMatcher::RedirectActionInfo redirect_action_info =
-        ruleset->matcher->GetRedirectAction(params, page_access);
+    CompositeMatcher::ActionInfo action_info =
+        ruleset->matcher->GetBeforeRequestAction(params, page_access);
 
-    DCHECK(!(redirect_action_info.action &&
-             redirect_action_info.notify_request_withheld));
-    if (redirect_action_info.notify_request_withheld) {
+    DCHECK(!(action_info.action && action_info.notify_request_withheld));
+    if (action_info.notify_request_withheld) {
       NotifyRequestWithheld(ruleset->extension_id, request);
       continue;
     }
 
-    if (!redirect_action_info.action)
-      continue;
-
-    return std::move(redirect_action_info.action);
+    if (action_priority(action_info.action) > action_priority(action))
+      action = std::move(action_info.action);
   }
 
-  return base::nullopt;
+  return action;
 }
 
 std::vector<RequestAction> RulesetManager::GetRemoveHeadersActions(
@@ -483,18 +486,10 @@
     rulesets_to_evaluate.push_back(&ruleset);
   }
 
-  // If the request is blocked, no further modifications can happen.
-  base::Optional<RequestAction> action =
-      GetBlockOrCollapseAction(rulesets_to_evaluate, params);
-  if (action) {
-    actions.push_back(std::move(std::move(*action)));
-    return actions;
-  }
-
-  // If the request is redirected, no further modifications can happen. A new
-  // request will be created and subsequently evaluated.
-  action = GetRedirectOrUpgradeAction(rulesets_to_evaluate, request, tab_id,
-                                      crosses_incognito, params);
+  // If the request is blocked/allowed/redirected, no further modifications can
+  // happen. A new request will be created and subsequently evaluated.
+  base::Optional<RequestAction> action = GetBeforeRequestAction(
+      rulesets_to_evaluate, request, tab_id, crosses_incognito, params);
   if (action) {
     actions.push_back(std::move(std::move(*action)));
     return actions;
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.h b/extensions/browser/api/declarative_net_request/ruleset_manager.h
index 2d7acb2..7f8e4f1 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_manager.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_manager.h
@@ -114,10 +114,7 @@
     DISALLOW_COPY_AND_ASSIGN(ExtensionRulesetData);
   };
 
-  base::Optional<RequestAction> GetBlockOrCollapseAction(
-      const std::vector<const ExtensionRulesetData*>& rulesets,
-      const RequestParams& params) const;
-  base::Optional<RequestAction> GetRedirectOrUpgradeAction(
+  base::Optional<RequestAction> GetBeforeRequestAction(
       const std::vector<const ExtensionRulesetData*>& rulesets,
       const WebRequestInfo& request,
       const int tab_id,
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
index 4f775a9..eafdbf0 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
@@ -78,39 +78,11 @@
 
 RulesetMatcher::~RulesetMatcher() = default;
 
-base::Optional<RequestAction> RulesetMatcher::GetBlockOrCollapseAction(
-    const RequestParams& params) const {
-  base::Optional<RequestAction> action =
-      url_pattern_index_matcher_.GetBlockOrCollapseAction(params);
-  if (!action)
-    action = regex_matcher_.GetBlockOrCollapseAction(params);
-  return action;
-}
-
-base::Optional<RequestAction> RulesetMatcher::GetAllowAction(
-    const RequestParams& params) const {
-  base::Optional<RequestAction> action =
-      url_pattern_index_matcher_.GetAllowAction(params);
-  if (!action)
-    action = regex_matcher_.GetAllowAction(params);
-  return action;
-}
-
-base::Optional<RequestAction> RulesetMatcher::GetRedirectAction(
+base::Optional<RequestAction> RulesetMatcher::GetBeforeRequestAction(
     const RequestParams& params) const {
   return GetMaxPriorityAction(
-      url_pattern_index_matcher_.GetRedirectAction(params),
-      regex_matcher_.GetRedirectAction(params));
-}
-
-base::Optional<RequestAction> RulesetMatcher::GetUpgradeAction(
-    const RequestParams& params) const {
-  if (!IsUpgradeableRequest(params))
-    return base::nullopt;
-
-  return GetMaxPriorityAction(
-      url_pattern_index_matcher_.GetUpgradeAction(params),
-      regex_matcher_.GetUpgradeAction(params));
+      url_pattern_index_matcher_.GetBeforeRequestAction(params),
+      regex_matcher_.GetBeforeRequestAction(params));
 }
 
 uint8_t RulesetMatcher::GetRemoveHeadersMask(
@@ -134,13 +106,6 @@
          regex_matcher_.IsExtraHeadersMatcher();
 }
 
-base::Optional<RequestAction>
-RulesetMatcher::GetRedirectOrUpgradeActionByPriority(
-    const RequestParams& params) const {
-  return GetMaxPriorityAction(GetRedirectAction(params),
-                              GetUpgradeAction(params));
-}
-
 RulesetMatcher::RulesetMatcher(
     std::string ruleset_data,
     size_t id,
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.h b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
index c7f657b3..a1e2b147 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
@@ -66,13 +66,8 @@
 
   // RulesetMatcherBase overrides:
   ~RulesetMatcher() override;
-  base::Optional<RequestAction> GetBlockOrCollapseAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetAllowAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetRedirectAction(
-      const RequestParams& params) const override;
-  base::Optional<RequestAction> GetUpgradeAction(
+
+  base::Optional<RequestAction> GetBeforeRequestAction(
       const RequestParams& params) const override;
   uint8_t GetRemoveHeadersMask(
       const RequestParams& params,
@@ -80,12 +75,6 @@
       std::vector<RequestAction>* remove_headers_actions) const override;
   bool IsExtraHeadersMatcher() const override;
 
-  // Returns a RequestAction constructed from the matching redirect or upgrade
-  // rule with the highest priority, or base::nullopt if no matching redirect or
-  // upgrade rules are found for this request.
-  base::Optional<RequestAction> GetRedirectOrUpgradeActionByPriority(
-      const RequestParams& params) const;
-
   // ID of the ruleset. Each extension can have multiple rulesets with
   // their own unique ids.
   size_t id() const { return id_; }
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc
index 6dd3083..fc29131 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc
@@ -29,8 +29,13 @@
          type == flat_rule::ElementType_SUBDOCUMENT;
 }
 
+bool IsUpgradeableUrl(const GURL& url) {
+  return url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kFtpScheme);
+}
+
 // Upgrades the url's scheme to HTTPS.
 GURL GetUpgradedUrl(const GURL& url) {
+  DCHECK(IsUpgradeableUrl(url));
   GURL::Replacements replacements;
   replacements.SetSchemeStr(url::kHttpsScheme);
   return url.ReplaceComponents(replacements);
@@ -195,36 +200,30 @@
     : extension_id_(extension_id), source_type_(source_type) {}
 RulesetMatcherBase::~RulesetMatcherBase() = default;
 
-// static
-bool RulesetMatcherBase::IsUpgradeableRequest(const RequestParams& params) {
-  return params.url->SchemeIs(url::kHttpScheme) ||
-         params.url->SchemeIs(url::kFtpScheme);
-}
-
 RequestAction RulesetMatcherBase::CreateBlockOrCollapseRequestAction(
     const RequestParams& params,
     const flat_rule::UrlRule& rule) const {
-  return ShouldCollapseResourceType(params.element_type)
-             ? RequestAction(RequestAction::Type::COLLAPSE, rule.id(),
-                             rule.priority(), source_type(), extension_id())
-             : RequestAction(RequestAction::Type::BLOCK, rule.id(),
-                             rule.priority(), source_type(), extension_id());
+  return CreateRequestAction(ShouldCollapseResourceType(params.element_type)
+                                 ? RequestAction::Type::COLLAPSE
+                                 : RequestAction::Type::BLOCK,
+                             rule);
 }
 
 RequestAction RulesetMatcherBase::CreateAllowAction(
     const RequestParams& params,
-    const url_pattern_index::flat::UrlRule& rule) const {
-  return RequestAction(RequestAction::Type::ALLOW, rule.id(), rule.priority(),
-                       source_type(), extension_id());
+    const flat_rule::UrlRule& rule) const {
+  return CreateRequestAction(RequestAction::Type::ALLOW, rule);
 }
 
-RequestAction RulesetMatcherBase::CreateUpgradeAction(
+base::Optional<RequestAction> RulesetMatcherBase::CreateUpgradeAction(
     const RequestParams& params,
     const url_pattern_index::flat::UrlRule& rule) const {
-  DCHECK(IsUpgradeableRequest(params));
-
-  RequestAction upgrade_action(RequestAction::Type::REDIRECT, rule.id(),
-                               rule.priority(), source_type(), extension_id());
+  if (!IsUpgradeableUrl(*params.url)) {
+    // TODO(crbug.com/1033780): this results in counterintuitive behavior.
+    return base::nullopt;
+  }
+  RequestAction upgrade_action =
+      CreateRequestAction(RequestAction::Type::UPGRADE, rule);
   upgrade_action.redirect_url = GetUpgradedUrl(*params.url);
   return upgrade_action;
 }
@@ -234,8 +233,6 @@
     const RequestParams& params,
     const url_pattern_index::flat::UrlRule& rule,
     const ExtensionMetadataList& metadata_list) const {
-  DCHECK_NE(flat_rule::ElementType_WEBSOCKET, params.element_type);
-
   // Find the UrlRuleMetadata corresponding to |rule|. Since |metadata_list| is
   // sorted by rule id, use LookupByKey which binary searches for fast lookup.
   const flat::UrlRuleMetadata* metadata = metadata_list.LookupByKey(rule.id());
@@ -264,12 +261,17 @@
     const RequestParams& params,
     const url_pattern_index::flat::UrlRule& rule,
     GURL redirect_url) const {
+  // Redirecting WebSocket handshake request is prohibited.
+  // TODO(crbug.com/1033780): this results in counterintuitive behavior.
+  if (params.element_type == flat_rule::ElementType_WEBSOCKET)
+    return base::nullopt;
+
   // Prevent a redirect loop where a URL continuously redirects to itself.
   if (!redirect_url.is_valid() || *params.url == redirect_url)
     return base::nullopt;
 
-  RequestAction redirect_action(RequestAction::Type::REDIRECT, rule.id(),
-                                rule.priority(), source_type(), extension_id());
+  RequestAction redirect_action =
+      CreateRequestAction(RequestAction::Type::REDIRECT, rule);
   redirect_action.redirect_url = std::move(redirect_url);
   return redirect_action;
 }
@@ -278,8 +280,8 @@
     const url_pattern_index::flat::UrlRule& rule,
     uint8_t mask) const {
   DCHECK(mask);
-  RequestAction action(RequestAction::Type::REMOVE_HEADERS, rule.id(),
-                       rule.priority(), source_type(), extension_id());
+  RequestAction action =
+      CreateRequestAction(RequestAction::Type::REMOVE_HEADERS, rule);
 
   for (int header = 0; header <= dnr_api::REMOVE_HEADER_TYPE_LAST; ++header) {
     switch (header) {
@@ -307,5 +309,12 @@
   return action;
 }
 
+RequestAction RulesetMatcherBase::CreateRequestAction(
+    RequestAction::Type type,
+    const flat_rule::UrlRule& rule) const {
+  return RequestAction(type, rule.id(), rule.priority(), source_type(),
+                       extension_id());
+}
+
 }  // namespace declarative_net_request
 }  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h
index ea26d1a..7a3928d 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h
@@ -9,6 +9,7 @@
 
 #include "base/optional.h"
 #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
+#include "extensions/browser/api/declarative_net_request/request_action.h"
 #include "extensions/common/api/declarative_net_request.h"
 #include "extensions/common/extension_id.h"
 
@@ -16,7 +17,6 @@
 namespace extensions {
 
 namespace declarative_net_request {
-struct RequestAction;
 struct RequestParams;
 
 // An abstract class for rule matchers. Overridden by different kinds of
@@ -28,26 +28,10 @@
 
   virtual ~RulesetMatcherBase();
 
-  // Returns any matching RequestAction with type |BLOCK| or |COLLAPSE|, or
-  // base::nullopt if the ruleset has no matching blocking rule.
-  virtual base::Optional<RequestAction> GetBlockOrCollapseAction(
-      const RequestParams& params) const = 0;
-
-  // Returns any matching RequestAction with type |ALLOW| or base::nullopt if
-  // the ruleset has no matching allow rule.
-  virtual base::Optional<RequestAction> GetAllowAction(
-      const RequestParams& params) const = 0;
-
-  // Returns a RequestAction constructed from the matching redirect rule with
-  // the highest priority, or base::nullopt if no matching redirect rules are
-  // found for this request.
-  virtual base::Optional<RequestAction> GetRedirectAction(
-      const RequestParams& params) const = 0;
-
-  // Returns a RequestAction constructed from the matching upgrade rule with the
-  // highest priority, or base::nullopt if no matching upgrade rules are found
-  // for this request.
-  virtual base::Optional<RequestAction> GetUpgradeAction(
+  // Returns the ruleset's highest priority matching RequestAction for the
+  // onBeforeRequest phase, or base::nullopt if the ruleset has no matching
+  // rule.
+  virtual base::Optional<RequestAction> GetBeforeRequestAction(
       const RequestParams& params) const = 0;
 
   // Returns the bitmask of headers to remove from the request. The bitmask
@@ -74,9 +58,6 @@
   using ExtensionMetadataList =
       ::flatbuffers::Vector<flatbuffers::Offset<flat::UrlRuleMetadata>>;
 
-  // Returns true if the given request can be upgraded.
-  static bool IsUpgradeableRequest(const RequestParams& params);
-
   // Helper to create a RequestAction of type |BLOCK| or |COLLAPSE|.
   RequestAction CreateBlockOrCollapseRequestAction(
       const RequestParams& params,
@@ -88,8 +69,8 @@
       const url_pattern_index::flat::UrlRule& rule) const;
 
   // Helper to create a RequestAction of type |REDIRECT| with the request
-  // upgraded.
-  RequestAction CreateUpgradeAction(
+  // upgraded. Returns base::nullopt if the request is not upgradeable.
+  base::Optional<RequestAction> CreateUpgradeAction(
       const RequestParams& params,
       const url_pattern_index::flat::UrlRule& rule) const;
 
@@ -112,6 +93,10 @@
       uint8_t mask) const;
 
  private:
+  RequestAction CreateRequestAction(
+      RequestAction::Type type,
+      const url_pattern_index::flat::UrlRule& rule) const;
+
   const ExtensionId extension_id_;
   const api::declarative_net_request::SourceType source_type_;
 
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
index b7b9d1a..c956400 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
@@ -54,8 +54,8 @@
   ASSERT_TRUE(CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
 
   auto should_block_request = [&matcher](const RequestParams& params) {
-    return !matcher->GetAllowAction(params) &&
-           matcher->GetBlockOrCollapseAction(params).has_value();
+    auto action = matcher->GetBeforeRequestAction(params);
+    return action.has_value() && action->IsBlockOrCollapse();
   };
 
   GURL google_url("http://google.com");
@@ -92,12 +92,13 @@
   params.is_third_party = true;
 
   base::Optional<RequestAction> redirect_action =
-      matcher->GetRedirectAction(params);
+      matcher->GetBeforeRequestAction(params);
   ASSERT_TRUE(redirect_action);
+  ASSERT_EQ(redirect_action->type, RequestAction::Type::REDIRECT);
   EXPECT_EQ(yahoo_url, redirect_action->redirect_url);
 
   params.url = &yahoo_url;
-  EXPECT_FALSE(matcher->GetRedirectAction(params));
+  EXPECT_FALSE(matcher->GetBeforeRequestAction(params));
 }
 
 // Test that a URL cannot redirect to itself, as filed in crbug.com/954646.
@@ -118,7 +119,7 @@
   params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
   params.is_third_party = true;
 
-  EXPECT_FALSE(matcher->GetRedirectAction(params));
+  EXPECT_FALSE(matcher->GetBeforeRequestAction(params));
 }
 
 // Tests a simple upgrade scheme rule.
@@ -132,7 +133,8 @@
   ASSERT_TRUE(CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
 
   auto should_upgrade_request = [&matcher](const RequestParams& params) {
-    return matcher->GetUpgradeAction(params).has_value();
+    auto action = matcher->GetBeforeRequestAction(params);
+    return action.has_value() && action->type == RequestAction::Type::UPGRADE;
   };
 
   GURL google_url("http://google.com");
@@ -329,9 +331,10 @@
   params.url = &example_url;
 
   base::Optional<RequestAction> redirect_action =
-      matcher->GetRedirectAction(params);
+      matcher->GetBeforeRequestAction(params);
 
   ASSERT_TRUE(redirect_action.has_value());
+  EXPECT_EQ(redirect_action->type, RequestAction::Type::REDIRECT);
   GURL expected_redirect_url(
       "chrome-extension://extensionid/path/newfile.js?query#fragment");
   EXPECT_EQ(expected_redirect_url, redirect_action->redirect_url);
@@ -354,9 +357,10 @@
   params.url = &example_url;
 
   base::Optional<RequestAction> redirect_action =
-      matcher->GetRedirectAction(params);
+      matcher->GetBeforeRequestAction(params);
 
   ASSERT_TRUE(redirect_action.has_value());
+  EXPECT_EQ(redirect_action->type, RequestAction::Type::REDIRECT);
   GURL expected_redirect_url("https://google.com");
   EXPECT_EQ(expected_redirect_url, redirect_action->redirect_url);
 }
@@ -487,13 +491,16 @@
     params.url = &url;
 
     base::Optional<RequestAction> redirect_action =
-        matcher->GetRedirectAction(params);
+        matcher->GetBeforeRequestAction(params);
 
     if (!test_case.expected_redirect_url) {
       EXPECT_FALSE(redirect_action) << redirect_action->redirect_url->spec();
       continue;
     }
 
+    ASSERT_TRUE(redirect_action.has_value());
+    EXPECT_EQ(redirect_action->type, RequestAction::Type::REDIRECT);
+
     ASSERT_TRUE(GURL(*test_case.expected_redirect_url).is_valid())
         << *test_case.expected_redirect_url;
 
@@ -551,10 +558,7 @@
 
   struct TestCase {
     const char* url = nullptr;
-    base::Optional<RequestAction> expected_block_or_collapse_action;
-    base::Optional<RequestAction> expected_allow_action;
-    base::Optional<RequestAction> expected_redirect_action;
-    base::Optional<RequestAction> expected_upgrade_action;
+    base::Optional<RequestAction> expected_action;
     uint8_t expected_remove_headers_mask = 0u;
     base::Optional<RequestAction> expected_remove_header_action;
   };
@@ -563,7 +567,7 @@
 
   {
     TestCase test_case = {"http://www.block.com/path"};
-    test_case.expected_block_or_collapse_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::BLOCK, *block_rule.id);
     test_cases.push_back(std::move(test_case));
   }
@@ -577,7 +581,7 @@
 
   {
     TestCase test_case = {"http://abc.xyz.allow.com/path"};
-    test_case.expected_allow_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::ALLOW, *allow_rule.id);
     test_cases.push_back(std::move(test_case));
   }
@@ -589,9 +593,9 @@
 
   {
     TestCase test_case = {"http://redirect.com?path=abc"};
-    test_case.expected_redirect_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::REDIRECT, *redirect_rule.id);
-    test_case.expected_redirect_action->redirect_url =
+    test_case.expected_action->redirect_url =
         GURL(*redirect_rule.action->redirect->url);
     test_cases.push_back(std::move(test_case));
   }
@@ -603,9 +607,9 @@
 
   {
     TestCase test_case = {"http://example.com/upgrade"};
-    test_case.expected_upgrade_action = CreateRequestActionForTesting(
-        RequestAction::Type::REDIRECT, *upgrade_rule.id);
-    test_case.expected_upgrade_action->redirect_url.emplace(
+    test_case.expected_action = CreateRequestActionForTesting(
+        RequestAction::Type::UPGRADE, *upgrade_rule.id);
+    test_case.expected_action->redirect_url.emplace(
         "https://example.com/upgrade");
     test_cases.push_back(std::move(test_case));
   }
@@ -638,14 +642,8 @@
     RequestParams params;
     params.url = &url;
 
-    EXPECT_EQ(test_case.expected_block_or_collapse_action,
-              matcher->GetBlockOrCollapseAction(params));
-    EXPECT_EQ(test_case.expected_allow_action, matcher->GetAllowAction(params));
-    EXPECT_EQ(test_case.expected_redirect_action,
-              matcher->GetRedirectAction(params));
-    EXPECT_EQ(test_case.expected_upgrade_action,
-              matcher->GetUpgradeAction(params));
-
+    EXPECT_EQ(test_case.expected_action,
+              matcher->GetBeforeRequestAction(params));
     std::vector<RequestAction> remove_header_actions;
     EXPECT_EQ(test_case.expected_remove_headers_mask,
               matcher->GetRemoveHeadersMask(
@@ -711,7 +709,7 @@
     url_pattern_index::flat::ElementType element_type =
         url_pattern_index::flat::ElementType_OTHER;
     bool is_third_party = false;
-    base::Optional<RequestAction> expected_block_or_collapse_action;
+    base::Optional<RequestAction> expected_action;
   };
   std::vector<TestCase> test_cases;
 
@@ -722,21 +720,21 @@
 
   {
     TestCase test_case = {"http://example.com/PATH/abc"};
-    test_case.expected_block_or_collapse_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::BLOCK, *path_rule.id);
     test_cases.push_back(std::move(test_case));
   }
 
   {
     TestCase test_case = {"http://example.com/xyz/abc"};
-    test_case.expected_block_or_collapse_action =
+    test_case.expected_action =
         CreateRequestActionForTesting(RequestAction::Type::BLOCK, *xyz_rule.id);
     test_cases.push_back(std::move(test_case));
   }
 
   {
     TestCase test_case = {"http://example.com/XYZ/abc"};
-    test_case.expected_block_or_collapse_action =
+    test_case.expected_action =
         CreateRequestActionForTesting(RequestAction::Type::BLOCK, *xyz_rule.id);
     test_cases.push_back(std::move(test_case));
   }
@@ -746,7 +744,7 @@
     test_case.first_party_origin =
         url::Origin::Create(GURL("http://a.example.com"));
     test_case.is_third_party = true;
-    test_case.expected_block_or_collapse_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::BLOCK, *google_rule.id);
     test_cases.push_back(std::move(test_case));
   }
@@ -767,7 +765,7 @@
   {
     TestCase test_case = {"http://abc.com"};
     test_case.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
-    test_case.expected_block_or_collapse_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::COLLAPSE, *sub_frame_rule.id);
     test_cases.push_back(std::move(test_case));
   }
@@ -775,7 +773,7 @@
   {
     TestCase test_case = {"http://243.com"};
     test_case.is_third_party = true;
-    test_case.expected_block_or_collapse_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::BLOCK, *third_party_rule.id);
     test_cases.push_back(std::move(test_case));
   }
@@ -798,8 +796,8 @@
     params.element_type = test_cases[i].element_type;
     params.is_third_party = test_cases[i].is_third_party;
 
-    EXPECT_EQ(test_cases[i].expected_block_or_collapse_action,
-              matcher->GetBlockOrCollapseAction(params));
+    EXPECT_EQ(test_cases[i].expected_action,
+              matcher->GetBeforeRequestAction(params));
   }
 }
 
@@ -850,44 +848,40 @@
 
   struct TestCase {
     const char* url = nullptr;
-    base::Optional<RequestAction> expected_redirect_action;
-    base::Optional<RequestAction> expected_upgrade_action;
+    base::Optional<RequestAction> expected_action;
   };
   std::vector<TestCase> test_cases;
 
   {
     TestCase test_case = {"http://filter.com"};
-    test_case.expected_redirect_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::REDIRECT, rule_info[0].id, rule_info[0].priority);
-    test_case.expected_redirect_action->redirect_url.emplace(
+    test_case.expected_action->redirect_url.emplace(
         "http://redirect_filter.com");
     test_cases.push_back(std::move(test_case));
   }
 
   {
     TestCase test_case = {"http://regex.com"};
-    test_case.expected_upgrade_action = CreateRequestActionForTesting(
-        RequestAction::Type::REDIRECT, rule_info[1].id, rule_info[1].priority);
-    test_case.expected_upgrade_action->redirect_url.emplace(
-        "https://regex.com");
+    test_case.expected_action = CreateRequestActionForTesting(
+        RequestAction::Type::UPGRADE, rule_info[1].id, rule_info[1].priority);
+    test_case.expected_action->redirect_url.emplace("https://regex.com");
     test_cases.push_back(std::move(test_case));
   }
 
   {
     TestCase test_case = {"http://common1.com"};
-    test_case.expected_redirect_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::REDIRECT, rule_info[3].id, rule_info[3].priority);
-    test_case.expected_redirect_action->redirect_url.emplace(
-        "http://common1_regex.com");
+    test_case.expected_action->redirect_url.emplace("http://common1_regex.com");
     test_cases.push_back(std::move(test_case));
   }
 
   {
     TestCase test_case = {"http://common2.com"};
-    test_case.expected_upgrade_action = CreateRequestActionForTesting(
-        RequestAction::Type::REDIRECT, rule_info[4].id, rule_info[4].priority);
-    test_case.expected_upgrade_action->redirect_url.emplace(
-        "https://common2.com");
+    test_case.expected_action = CreateRequestActionForTesting(
+        RequestAction::Type::UPGRADE, rule_info[4].id, rule_info[4].priority);
+    test_case.expected_action->redirect_url.emplace("https://common2.com");
     test_cases.push_back(std::move(test_case));
   }
 
@@ -904,19 +898,17 @@
 
   {
     TestCase test_case = {"http://abc.com"};
-    test_case.expected_redirect_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::REDIRECT, rule_info[6].id, rule_info[6].priority);
-    test_case.expected_redirect_action->redirect_url.emplace(
-        "http://example1.com");
+    test_case.expected_action->redirect_url.emplace("http://example1.com");
     test_cases.push_back(std::move(test_case));
   }
 
   {
     TestCase test_case = {"http://xyz.com/abc"};
-    test_case.expected_redirect_action = CreateRequestActionForTesting(
+    test_case.expected_action = CreateRequestActionForTesting(
         RequestAction::Type::REDIRECT, rule_info[7].id, rule_info[7].priority);
-    test_case.expected_redirect_action->redirect_url.emplace(
-        "http://example2.com");
+    test_case.expected_action->redirect_url.emplace("http://example2.com");
     test_cases.push_back(std::move(test_case));
   }
 
@@ -927,10 +919,8 @@
     RequestParams params;
     params.url = &url;
 
-    EXPECT_EQ(test_case.expected_redirect_action,
-              matcher->GetRedirectAction(params));
-    EXPECT_EQ(test_case.expected_upgrade_action,
-              matcher->GetUpgradeAction(params));
+    EXPECT_EQ(test_case.expected_action,
+              matcher->GetBeforeRequestAction(params));
   }
 }
 
@@ -1051,7 +1041,7 @@
 
   struct {
     std::string url;
-    base::Optional<RequestAction> expected_redirect_action;
+    base::Optional<RequestAction> expected_action;
   } test_cases[] = {
       {"http://google.com/path?query",
        create_redirect_action(
@@ -1074,8 +1064,8 @@
     RequestParams params;
     params.url = &url;
 
-    ASSERT_EQ(test_case.expected_redirect_action,
-              matcher->GetRedirectAction(params));
+    ASSERT_EQ(test_case.expected_action,
+              matcher->GetBeforeRequestAction(params));
   }
 }
 
diff --git a/extensions/browser/api/declarative_net_request/test_utils.cc b/extensions/browser/api/declarative_net_request/test_utils.cc
index 32f0e205..a33bc4f 100644
--- a/extensions/browser/api/declarative_net_request/test_utils.cc
+++ b/extensions/browser/api/declarative_net_request/test_utils.cc
@@ -37,7 +37,7 @@
 // with gtest. This reuses the logic used to test action equality in
 // TestRequestACtion in test_utils.h.
 bool operator==(const RequestAction& lhs, const RequestAction& rhs) {
-  static_assert(flat::ActionIndex_count == 7,
+  static_assert(flat::IndexType_count == 4,
                 "Modify this method to ensure it stays updated as new actions "
                 "are added.");
 
@@ -74,6 +74,9 @@
     case RequestAction::Type::REDIRECT:
       output << "REDIRECT";
       break;
+    case RequestAction::Type::UPGRADE:
+      output << "UPGRADE";
+      break;
     case RequestAction::Type::REMOVE_HEADERS:
       output << "REMOVE_HEADERS";
       break;
@@ -108,20 +111,14 @@
     case ParseResult::ERROR_RESOURCE_TYPE_DUPLICATED:
       output << "ERROR_RESOURCE_TYPE_DUPLICATED";
       break;
-    case ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY:
-      output << "ERROR_EMPTY_REDIRECT_RULE_PRIORITY";
-      break;
-    case ParseResult::ERROR_EMPTY_UPGRADE_RULE_PRIORITY:
-      output << "ERROR_EMPTY_UPGRADE_RULE_PRIORITY";
+    case ParseResult::ERROR_EMPTY_RULE_PRIORITY:
+      output << "ERROR_EMPTY_RULE_PRIORITY";
       break;
     case ParseResult::ERROR_INVALID_RULE_ID:
       output << "ERROR_INVALID_RULE_ID";
       break;
-    case ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY:
-      output << "ERROR_INVALID_REDIRECT_RULE_PRIORITY";
-      break;
-    case ParseResult::ERROR_INVALID_UPGRADE_RULE_PRIORITY:
-      output << "ERROR_INVALID_UPGRADE_RULE_PRIORITY";
+    case ParseResult::ERROR_INVALID_RULE_PRIORITY:
+      output << "ERROR_INVALID_RULE_PRIORITY";
       break;
     case ParseResult::ERROR_NO_APPLICABLE_RESOURCE_TYPES:
       output << "ERROR_NO_APPLICABLE_RESOURCE_TYPES";
diff --git a/extensions/browser/api/declarative_net_request/utils.cc b/extensions/browser/api/declarative_net_request/utils.cc
index 5256a59..cc6a7bb1 100644
--- a/extensions/browser/api/declarative_net_request/utils.cc
+++ b/extensions/browser/api/declarative_net_request/utils.cc
@@ -37,7 +37,7 @@
 // url_pattern_index.fbs. Whenever an extension with an indexed ruleset format
 // version different from the one currently used by Chrome is loaded, the
 // extension ruleset will be reindexed.
-constexpr int kIndexedRulesetFormatVersion = 13;
+constexpr int kIndexedRulesetFormatVersion = 14;
 
 // This static assert is meant to catch cases where
 // url_pattern_index::kUrlPatternIndexFormatVersion is incremented without
@@ -238,5 +238,24 @@
   return options;
 }
 
+flat::ActionType ConvertToFlatActionType(dnr_api::RuleActionType action_type) {
+  switch (action_type) {
+    case dnr_api::RULE_ACTION_TYPE_BLOCK:
+      return flat::ActionType_block;
+    case dnr_api::RULE_ACTION_TYPE_ALLOW:
+      return flat::ActionType_allow;
+    case dnr_api::RULE_ACTION_TYPE_REDIRECT:
+      return flat::ActionType_redirect;
+    case dnr_api::RULE_ACTION_TYPE_REMOVEHEADERS:
+      return flat::ActionType_remove_headers;
+    case dnr_api::RULE_ACTION_TYPE_UPGRADESCHEME:
+      return flat::ActionType_upgrade_scheme;
+    case dnr_api::RULE_ACTION_TYPE_NONE:
+      break;
+  }
+  NOTREACHED();
+  return flat::ActionType_block;
+}
+
 }  // namespace declarative_net_request
 }  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/utils.h b/extensions/browser/api/declarative_net_request/utils.h
index 3abbeec..6041877 100644
--- a/extensions/browser/api/declarative_net_request/utils.h
+++ b/extensions/browser/api/declarative_net_request/utils.h
@@ -14,6 +14,7 @@
 #include "base/containers/span.h"
 #include "base/macros.h"
 #include "base/optional.h"
+#include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_source.h"
 #include "extensions/common/api/declarative_net_request.h"
 #include "third_party/re2/src/re2/re2.h"
@@ -69,6 +70,10 @@
 re2::RE2::Options CreateRE2Options(bool is_case_sensitive,
                                    bool require_capturing);
 
+// Convert dnr_api::RuleActionType into flat::ActionType.
+flat::ActionType ConvertToFlatActionType(
+    api::declarative_net_request::RuleActionType action_type);
+
 }  // namespace declarative_net_request
 }  // namespace extensions
 
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index df41969..56e1012 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -1134,9 +1134,11 @@
         *should_collapse_initiator = true;
         return net::ERR_BLOCKED_BY_CLIENT;
       case DNRRequestAction::Type::ALLOW:
-        NOTREACHED();
+        DCHECK_EQ(1u, actions.size());
+        OnDNRActionMatched(browser_context, *request, action);
         break;
       case DNRRequestAction::Type::REDIRECT:
+      case DNRRequestAction::Type::UPGRADE:
         ClearPendingCallbacks(*request);
         DCHECK_EQ(1u, actions.size());
         DCHECK(action.redirect_url);
diff --git a/extensions/browser/extension_protocols.cc b/extensions/browser/extension_protocols.cc
index 6a516d2..6df6a3da 100644
--- a/extensions/browser/extension_protocols.cc
+++ b/extensions/browser/extension_protocols.cc
@@ -604,7 +604,7 @@
           resource.relative_path());
     }
 
-    content::CreateFileURLLoader(
+    content::CreateFileURLLoaderBypassingSecurityChecks(
         request, std::move(loader), std::move(client),
         std::make_unique<FileLoaderObserver>(std::move(verify_job)),
         /* allow_directory_listing */ false, std::move(response_headers));
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc
index 55a5cba..1783452a 100644
--- a/extensions/browser/extension_registrar.cc
+++ b/extensions/browser/extension_registrar.cc
@@ -431,8 +431,9 @@
   // ensure its URLRequestContexts appropriately discover the loaded extension.
   extension_system_->RegisterExtensionWithRequestContexts(
       extension,
-      base::Bind(&ExtensionRegistrar::OnExtensionRegisteredWithRequestContexts,
-                 weak_factory_.GetWeakPtr(), WrapRefCounted(extension)));
+      base::BindOnce(
+          &ExtensionRegistrar::OnExtensionRegisteredWithRequestContexts,
+          weak_factory_.GetWeakPtr(), WrapRefCounted(extension)));
 
   // Activate the extension before calling
   // RendererStartupHelper::OnExtensionLoaded() below, so that we have
diff --git a/extensions/browser/extension_registrar.h b/extensions/browser/extension_registrar.h
index a2c7a914..7195e39 100644
--- a/extensions/browser/extension_registrar.h
+++ b/extensions/browser/extension_registrar.h
@@ -11,6 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 
 namespace base {
 class FilePath;
diff --git a/extensions/browser/extension_registrar_unittest.cc b/extensions/browser/extension_registrar_unittest.cc
index 1fac72088..0f4c594 100644
--- a/extensions/browser/extension_registrar_unittest.cc
+++ b/extensions/browser/extension_registrar_unittest.cc
@@ -44,8 +44,9 @@
   // MockExtensionSystem:
   void RegisterExtensionWithRequestContexts(
       const Extension* extension,
-      const base::Closure& callback) override {
-    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+      base::OnceClosure callback) override {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                     std::move(callback));
   }
   RuntimeData* runtime_data() override { return &runtime_data_; }
 
diff --git a/extensions/browser/extension_system.h b/extensions/browser/extension_system.h
index 34728e1..77d8bfff 100644
--- a/extensions/browser/extension_system.h
+++ b/extensions/browser/extension_system.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/callback_forward.h"
+#include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "build/build_config.h"
@@ -114,7 +114,7 @@
   // asynchronously. |callback| is run on the calling thread once completed.
   virtual void RegisterExtensionWithRequestContexts(
       const Extension* extension,
-      const base::Closure& callback) {}
+      base::OnceClosure callback) {}
 
   // Called by the ExtensionService that lives in this system. Lets the
   // info map clean up its RequestContexts once all the listeners to the
diff --git a/extensions/browser/warning_service.h b/extensions/browser/warning_service.h
index 0e0d02bc..c2ee1d7a 100644
--- a/extensions/browser/warning_service.h
+++ b/extensions/browser/warning_service.h
@@ -16,6 +16,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/browser/warning_set.h"
+#include "extensions/common/extension_id.h"
 
 // TODO(battre) Remove the Extension prefix.
 
diff --git a/extensions/common/api/declarative_net_request/test_utils.cc b/extensions/common/api/declarative_net_request/test_utils.cc
index 8a75e42a..0da3046 100644
--- a/extensions/common/api/declarative_net_request/test_utils.cc
+++ b/extensions/common/api/declarative_net_request/test_utils.cc
@@ -175,6 +175,7 @@
   action.type = std::string("block");
   TestRule rule;
   rule.id = kMinValidID;
+  rule.priority = kMinValidPriority;
   rule.action = action;
   rule.condition = condition;
   return rule;
diff --git a/extensions/common/extension.h b/extensions/common/extension.h
index 56c7e5a..f04aee3 100644
--- a/extensions/common/extension.h
+++ b/extensions/common/extension.h
@@ -473,7 +473,6 @@
 };
 
 typedef std::vector<scoped_refptr<const Extension> > ExtensionList;
-typedef std::set<ExtensionId> ExtensionIdSet;
 
 // Handy struct to pass core extension info around.
 struct ExtensionInfo {
diff --git a/extensions/common/extension_id.h b/extensions/common/extension_id.h
index 7d8573e2..8ab0adba 100644
--- a/extensions/common/extension_id.h
+++ b/extensions/common/extension_id.h
@@ -5,6 +5,7 @@
 #ifndef EXTENSIONS_COMMON_EXTENSION_ID_H_
 #define EXTENSIONS_COMMON_EXTENSION_ID_H_
 
+#include <set>
 #include <string>
 #include <vector>
 
@@ -15,6 +16,7 @@
 using ExtensionId = std::string;
 
 using ExtensionIdList = std::vector<ExtensionId>;
+using ExtensionIdSet = std::set<ExtensionId>;
 
 }  // namespace extensions
 
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 6410d9c..12017bd 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -33,6 +33,7 @@
 #include "extensions/common/api/messaging/message.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/cors_util.h"
+#include "extensions/common/extension.h"
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/extension_urls.h"
diff --git a/extensions/renderer/dispatcher.h b/extensions/renderer/dispatcher.h
index 25814ba..22e2c75 100644
--- a/extensions/renderer/dispatcher.h
+++ b/extensions/renderer/dispatcher.h
@@ -21,7 +21,7 @@
 #include "components/version_info/version_info.h"
 #include "content/public/renderer/render_thread_observer.h"
 #include "extensions/common/event_filter.h"
-#include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/extensions_client.h"
 #include "extensions/common/features/feature.h"
 #include "extensions/common/features/feature_session_type.h"
@@ -60,6 +60,7 @@
 namespace extensions {
 class ContentWatcher;
 class DispatcherDelegate;
+class Extension;
 class NativeExtensionBindingsSystem;
 class IPCMessageSender;
 class ScriptContext;
diff --git a/extensions/renderer/gc_callback_unittest.cc b/extensions/renderer/gc_callback_unittest.cc
index 350ad6c..f5f72c4 100644
--- a/extensions/renderer/gc_callback_unittest.cc
+++ b/extensions/renderer/gc_callback_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/features/feature.h"
 #include "extensions/renderer/scoped_web_frame.h"
diff --git a/extensions/renderer/native_extension_bindings_system_test_base.h b/extensions/renderer/native_extension_bindings_system_test_base.h
index 29d096b7..be09f1bb 100644
--- a/extensions/renderer/native_extension_bindings_system_test_base.h
+++ b/extensions/renderer/native_extension_bindings_system_test_base.h
@@ -12,6 +12,7 @@
 #include "extensions/common/api/messaging/message.h"
 #include "extensions/common/api/messaging/port_id.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/features/feature.h"
 #include "extensions/renderer/bindings/api_binding_test.h"
 #include "extensions/renderer/bindings/api_binding_types.h"
diff --git a/extensions/renderer/script_context_set.h b/extensions/renderer/script_context_set.h
index 9cb60af..6756577 100644
--- a/extensions/renderer/script_context_set.h
+++ b/extensions/renderer/script_context_set.h
@@ -13,7 +13,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/features/feature.h"
 #include "extensions/renderer/renderer_extension_registry.h"
 #include "extensions/renderer/script_context_set_iterable.h"
@@ -32,6 +32,7 @@
 }
 
 namespace extensions {
+class Extension;
 class ScriptContext;
 
 // A container of ScriptContexts, responsible for both creating and managing
diff --git a/extensions/renderer/script_context_set_unittest.cc b/extensions/renderer/script_context_set_unittest.cc
index 0a46b00..b0b7f58 100644
--- a/extensions/renderer/script_context_set_unittest.cc
+++ b/extensions/renderer/script_context_set_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/features/feature.h"
 #include "extensions/renderer/scoped_web_frame.h"
diff --git a/extensions/shell/browser/shell_extension_system.cc b/extensions/shell/browser/shell_extension_system.cc
index ab2935e9..d594ae2 100644
--- a/extensions/shell/browser/shell_extension_system.cc
+++ b/extensions/shell/browser/shell_extension_system.cc
@@ -138,12 +138,12 @@
 
 void ShellExtensionSystem::RegisterExtensionWithRequestContexts(
     const Extension* extension,
-    const base::Closure& callback) {
-  base::PostTaskAndReply(
-      FROM_HERE, {BrowserThread::IO},
-      base::Bind(&InfoMap::AddExtension, info_map(),
-                 base::RetainedRef(extension), base::Time::Now(), false, false),
-      callback);
+    base::OnceClosure callback) {
+  base::PostTaskAndReply(FROM_HERE, {BrowserThread::IO},
+                         base::BindOnce(&InfoMap::AddExtension, info_map(),
+                                        base::RetainedRef(extension),
+                                        base::Time::Now(), false, false),
+                         std::move(callback));
 }
 
 void ShellExtensionSystem::UnregisterExtensionWithRequestContexts(
diff --git a/extensions/shell/browser/shell_extension_system.h b/extensions/shell/browser/shell_extension_system.h
index bb77897..5788f236 100644
--- a/extensions/shell/browser/shell_extension_system.h
+++ b/extensions/shell/browser/shell_extension_system.h
@@ -73,7 +73,7 @@
   AppSorting* app_sorting() override;
   void RegisterExtensionWithRequestContexts(
       const Extension* extension,
-      const base::Closure& callback) override;
+      base::OnceClosure callback) override;
   void UnregisterExtensionWithRequestContexts(
       const std::string& extension_id,
       const UnloadedExtensionReason reason) override;
diff --git a/google_apis/drive/base_requests.cc b/google_apis/drive/base_requests.cc
index 2b25752f..5cd0c8d 100644
--- a/google_apis/drive/base_requests.cc
+++ b/google_apis/drive/base_requests.cc
@@ -942,7 +942,7 @@
 void MultipartUploadRequestBase::NotifyResult(
     DriveApiErrorCode code,
     const std::string& body,
-    const base::Closure& notify_complete_callback) {
+    base::OnceClosure notify_complete_callback) {
   // The upload is successfully done. Parse the response which should be
   // the entry's metadata.
   if (code == HTTP_CREATED || code == HTTP_SUCCESS) {
@@ -950,10 +950,10 @@
         blocking_task_runner_.get(), body,
         base::BindOnce(&MultipartUploadRequestBase::OnDataParsed,
                        weak_ptr_factory_.GetWeakPtr(), code,
-                       notify_complete_callback));
+                       std::move(notify_complete_callback)));
   } else {
     NotifyError(MapJsonError(code, body));
-    notify_complete_callback.Run();
+    std::move(notify_complete_callback).Run();
   }
 }
 
@@ -969,14 +969,14 @@
 
 void MultipartUploadRequestBase::OnDataParsed(
     DriveApiErrorCode code,
-    const base::Closure& notify_complete_callback,
+    base::OnceClosure notify_complete_callback,
     std::unique_ptr<base::Value> value) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (value)
     callback_.Run(code, google_apis::FileResource::CreateFrom(*value));
   else
     NotifyError(DRIVE_PARSE_ERROR);
-  notify_complete_callback.Run();
+  std::move(notify_complete_callback).Run();
 }
 
 //============================ DownloadFileRequestBase =========================
diff --git a/google_apis/drive/base_requests.h b/google_apis/drive/base_requests.h
index aff05fda..9a53376 100644
--- a/google_apis/drive/base_requests.h
+++ b/google_apis/drive/base_requests.h
@@ -309,7 +309,7 @@
   // |callback|.
   virtual void NotifyResult(DriveApiErrorCode code,
                             const std::string& response_body,
-                            const base::Closure& callback) = 0;
+                            base::OnceClosure callback) = 0;
 
   // Notifies error. Unlike |NotifyResult|, it must report error
   // synchronously. The instance may be deleted just after calling
@@ -575,12 +575,12 @@
                       std::string* upload_content) override;
   void NotifyResult(DriveApiErrorCode code,
                     const std::string& body,
-                    const base::Closure& callback) override;
+                    base::OnceClosure callback) override;
   void NotifyError(DriveApiErrorCode code) override;
   void NotifyUploadProgress(int64_t current, int64_t total) override;
   // Parses the response value and invokes |callback_| with |FileResource|.
   void OnDataParsed(DriveApiErrorCode code,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     std::unique_ptr<base::Value> value);
 
  private:
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc
index 4d08fde..a6431a97 100644
--- a/google_apis/drive/drive_api_requests.cc
+++ b/google_apis/drive/drive_api_requests.cc
@@ -1144,7 +1144,7 @@
     std::string response_body) {
   delegate_->NotifyResult(
       GetErrorCode(), response_body,
-      base::Bind(
+      base::BindOnce(
           &SingleBatchableDelegateRequest::OnProcessURLFetchResultsComplete,
           weak_ptr_factory_.GetWeakPtr()));
 }
@@ -1347,9 +1347,10 @@
     BatchableDelegate* delegate = child_requests_[i]->request.get();
     // Pass ownership of |delegate| so that child_requests_.clear() won't
     // kill the delegate. It has to be deleted after the notification.
-    delegate->NotifyResult(parts[i].code, parts[i].body,
-                           base::Bind(&base::DeletePointer<BatchableDelegate>,
-                                      child_requests_[i]->request.release()));
+    delegate->NotifyResult(
+        parts[i].code, parts[i].body,
+        base::BindOnce(&base::DeletePointer<BatchableDelegate>,
+                       child_requests_[i]->request.release()));
   }
   child_requests_.clear();
 
diff --git a/google_apis/drive/drive_api_requests_unittest.cc b/google_apis/drive/drive_api_requests_unittest.cc
index 55f21f7..babc294c 100644
--- a/google_apis/drive/drive_api_requests_unittest.cc
+++ b/google_apis/drive/drive_api_requests_unittest.cc
@@ -100,9 +100,9 @@
   void NotifyError(DriveApiErrorCode code) override { callback_.Run(); }
   void NotifyResult(DriveApiErrorCode code,
                     const std::string& body,
-                    const base::Closure& closure) override {
+                    base::OnceClosure closure) override {
     callback_.Run();
-    closure.Run();
+    std::move(closure).Run();
   }
   void NotifyUploadProgress(int64_t current, int64_t total) override {
     progress_values_.push_back(current);
diff --git a/ios/chrome/app/strings/resources/ios_strings_eu.xtb b/ios/chrome/app/strings/resources/ios_strings_eu.xtb
index 855dc10..ed630be8 100644
--- a/ios/chrome/app/strings/resources/ios_strings_eu.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_eu.xtb
@@ -57,7 +57,7 @@
 <translation id="1608337082864370066">Bilatu kopiatu duzun irudia</translation>
 <translation id="1612730193129642006">Erakutsi fitxen sareta</translation>
 <translation id="1644574205037202324">Historia</translation>
-<translation id="1650222530560417226">Fitxa guztietako JavaScript kontsolaren erregistroak eta erroreak biltzeko, sakatu "Hasi partekatzen" botoia. Bildutako erregistroak memorian bakarrik gordeko dira, orria itxi arte edo "Utzi erregistratzeari" sakatu arte.</translation>
+<translation id="1650222530560417226">Fitxa guztietako JavaScript-en kontsolaren erregistroak eta erroreak biltzeko, sakatu "Hasi partekatzen" botoia. Bildutako erregistroak memorian bakarrik gordeko dira, orria itxi arte edo "Utzi erregistratzeari" sakatu arte.</translation>
 <translation id="1657011748321897393">Ezin izan da partekatu ez zaudelako Internetera konektatuta.</translation>
 <translation id="165877110639533037">Ez dago irekitako fitxarik</translation>
 <translation id="1674504678466460478"><ph name="SOURCE_LANGUAGE" /> - <ph name="TARGET_LANGUAGE" /></translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_fr.xtb b/ios/chrome/app/strings/resources/ios_strings_fr.xtb
index fa27b757..494f4e2 100644
--- a/ios/chrome/app/strings/resources/ios_strings_fr.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_fr.xtb
@@ -245,7 +245,7 @@
 <translation id="4276041135170112053">Corriger maintenant.</translation>
 <translation id="4281844954008187215">Conditions d'utilisation</translation>
 <translation id="430793432425771671">Tout synchroniser</translation>
-<translation id="430967081421617822">Toutes les périodes</translation>
+<translation id="430967081421617822">Toutes les données</translation>
 <translation id="4334428914252001502">1 article non lu.</translation>
 <translation id="4338650699862464074">Envoie à Google les URL des pages que vous consultez.</translation>
 <translation id="4359125752503270327">Cette page va s'ouvrir dans une autre application.</translation>
@@ -462,7 +462,7 @@
 <translation id="7133798577887235672">Nom complet</translation>
 <translation id="7136892417564438900">Appareil photo non disponible</translation>
 <translation id="7159472599653637159">Voir version mobile</translation>
-<translation id="7173114856073700355">Ouvrir les paramètres</translation>
+<translation id="7173114856073700355">Paramètres</translation>
 <translation id="7192050974311852563">Démarrer la journalisation</translation>
 <translation id="7203585745079012652">Énoncer les réponses</translation>
 <translation id="7265758999917665941">Jamais pour ce site</translation>
@@ -575,7 +575,7 @@
 <translation id="9037965129289936994">Afficher l'original</translation>
 <translation id="9039373489628511875">Bande passante</translation>
 <translation id="9055772144595778347">Connexion impossible</translation>
-<translation id="9065203028668620118">Édition</translation>
+<translation id="9065203028668620118">Modifier</translation>
 <translation id="9079935439869366234">Tout marquer comme non lu</translation>
 <translation id="9081058212938299310">Changer le mot de passe pour <ph name="USERNAME" /> ?</translation>
 <translation id="9083392325882095631">1 élément</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ko.xtb b/ios/chrome/app/strings/resources/ios_strings_ko.xtb
index 02d66ef..ea4bd30 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ko.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ko.xtb
@@ -47,7 +47,7 @@
 <translation id="145015347812617860">항목 <ph name="COUNT" />개</translation>
 <translation id="1491277525950327607">설정을 전환하려면 두 번 탭하세요.</translation>
 <translation id="1509486075633541495">웹사이트에 로그인</translation>
-<translation id="152234381334907219">저장되지 않음</translation>
+<translation id="152234381334907219">저장하지 않음</translation>
 <translation id="1540800554400757039">주소 1</translation>
 <translation id="1545749641540134597">QR 코드 스캔</translation>
 <translation id="1552525382687785070">관리자가 동기화를 사용 중지했습니다.</translation>
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/BUILD.gn b/ios/chrome/browser/crash_report/breadcrumbs/BUILD.gn
index 41529d3..105a6b98 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/BUILD.gn
+++ b/ios/chrome/browser/crash_report/breadcrumbs/BUILD.gn
@@ -27,6 +27,8 @@
   ]
 
   sources = [
+    "breadcrumb_manager.cc",
+    "breadcrumb_manager.h",
     "breadcrumb_manager_browser_agent.h",
     "breadcrumb_manager_browser_agent.mm",
     "breadcrumb_manager_keyed_service.cc",
@@ -73,6 +75,7 @@
     "breadcrumb_manager_observer_bridge_unittest.mm",
     "breadcrumb_manager_observer_unittest.mm",
     "breadcrumb_manager_tab_helper_unittest.mm",
+    "breadcrumb_manager_unittest.mm",
     "breadcrumb_persistent_storage_keyed_service_unittest.mm",
     "breadcrumb_persistent_storage_util_unittest.mm",
   ]
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.cc b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.cc
new file mode 100644
index 0000000..555eebe
--- /dev/null
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.cc
@@ -0,0 +1,99 @@
+// Copyright 2019 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 "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h"
+
+namespace {
+
+// The minimum number of event buckets to keep, even if they are expired.
+const int kMinEventsBuckets = 2;
+
+// Returns a Time used to bucket events for easier discarding of expired events.
+base::Time EventBucket(const base::Time& time) {
+  base::Time::Exploded exploded;
+  time.LocalExplode(&exploded);
+  exploded.millisecond = 0;
+  exploded.second = 0;
+
+  base::Time bucket_time;
+  bool converted = base::Time::FromLocalExploded(exploded, &bucket_time);
+  DCHECK(converted);
+  return bucket_time;
+}
+
+}  // namespace
+
+BreadcrumbManager::BreadcrumbManager() = default;
+BreadcrumbManager::~BreadcrumbManager() = default;
+
+const std::list<std::string> BreadcrumbManager::GetEvents(
+    size_t event_count_limit) {
+  DropOldEvents();
+
+  std::list<std::string> events;
+  for (auto it = event_buckets_.rbegin(); it != event_buckets_.rend(); ++it) {
+    std::list<std::string> bucket_events = it->second;
+    for (auto event_it = bucket_events.rbegin();
+         event_it != bucket_events.rend(); ++event_it) {
+      std::string event = *event_it;
+      events.push_front(event);
+      if (event_count_limit > 0 && events.size() >= event_count_limit) {
+        return events;
+      }
+    }
+  }
+  return events;
+}
+
+void BreadcrumbManager::AddEvent(const std::string& event) {
+  base::Time time = base::Time::Now();
+  base::Time bucket_time = EventBucket(time);
+
+  // If bucket exists, it will be at the end of the list.
+  if (event_buckets_.empty() || event_buckets_.back().first != bucket_time) {
+    std::pair<base::Time, std::list<std::string>> bucket(
+        bucket_time, std::list<std::string>());
+    event_buckets_.push_back(bucket);
+  }
+
+  base::Time::Exploded exploded;
+  time.UTCExplode(&exploded);
+  std::string timestamp = base::StringPrintf(
+      "%02d:%02d.%03d", exploded.minute, exploded.second, exploded.millisecond);
+  std::string event_log =
+      base::StringPrintf("%s %s", timestamp.c_str(), event.c_str());
+  event_buckets_.back().second.push_back(event_log);
+
+  DropOldEvents();
+
+  for (auto& observer : observers_) {
+    observer.EventAdded(this, event_log);
+  }
+}
+
+void BreadcrumbManager::DropOldEvents() {
+  static const base::TimeDelta kMessageExpirationTime =
+      base::TimeDelta::FromMinutes(20);
+
+  base::Time now = base::Time::Now();
+  while (event_buckets_.size() > kMinEventsBuckets) {
+    base::Time oldest_bucket_time = event_buckets_.front().first;
+    if (now - oldest_bucket_time < kMessageExpirationTime) {
+      break;
+    }
+    event_buckets_.pop_front();
+  }
+}
+
+void BreadcrumbManager::AddObserver(BreadcrumbManagerObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void BreadcrumbManager::RemoveObserver(BreadcrumbManagerObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h
new file mode 100644
index 0000000..15b59476
--- /dev/null
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h
@@ -0,0 +1,59 @@
+// Copyright 2019 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 IOS_CHROME_BROWSER_CRASH_REPORT_BREADCRUMBS_BREADCRUMB_MANAGER_H_
+#define IOS_CHROME_BROWSER_CRASH_REPORT_BREADCRUMBS_BREADCRUMB_MANAGER_H_
+
+#include <list>
+#include <memory>
+#include <string>
+
+#include "base/observer_list.h"
+#import "base/time/time.h"
+
+class BreadcrumbManagerObserver;
+
+// Stores events logged with |AddEvent| in memory which can later be retrieved
+// with |GetEvents|. Events will be silently dropped after a certain amount of
+// time has passed unless no more recent events are available. The internal
+// management of events aims to keep relevant events available while clearing
+// stale data.
+class BreadcrumbManager {
+ public:
+  // Returns a list of the collected breadcrumb events which are still relevant
+  // up to |event_count_limit|. Passing zero for |event_count_limit| signifies
+  // no limit. Events returned will have a timestamp prepended to the original
+  // |event| string representing when |AddEvent| was called.
+  const std::list<std::string> GetEvents(size_t event_count_limit);
+
+  // Logs a breadcrumb event with message data |event|.
+  // NOTE: |event| must not include newline characters as newlines are used by
+  // BreadcrumbPersistentStore as a deliminator.
+  void AddEvent(const std::string& event);
+
+  // Adds and removes observers.
+  void AddObserver(BreadcrumbManagerObserver* observer);
+  void RemoveObserver(BreadcrumbManagerObserver* observer);
+
+  BreadcrumbManager();
+  ~BreadcrumbManager();
+
+ private:
+  BreadcrumbManager(const BreadcrumbManager&) = delete;
+  BreadcrumbManager& operator=(const BreadcrumbManager&) = delete;
+
+  // Drops events which are considered stale. Note that stale events are not
+  // guaranteed to be removed. Explicitly, stale events will be retained while
+  // newer events are limited.
+  void DropOldEvents();
+
+  // List of events, paired with the time which they were logged to minute
+  // resolution. Newer events are at the end of the list.
+  std::list<std::pair<base::Time, std::list<std::string>>> event_buckets_;
+
+  base::ObserverList<BreadcrumbManagerObserver, /*check_empty=*/true>
+      observers_;
+};
+
+#endif  // IOS_CHROME_BROWSER_CRASH_REPORT_BREADCRUMBS_BREADCRUMB_MANAGER_H_
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_browser_agent_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_browser_agent_unittest.mm
index 944a81dd..5f9f08ca 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_browser_agent_unittest.mm
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_browser_agent_unittest.mm
@@ -30,7 +30,7 @@
     TestChromeBrowserState::Builder test_cbs_builder;
     browser_state_ = test_cbs_builder.Build();
 
-    breadcrumb_manager_ = static_cast<BreadcrumbManagerKeyedService*>(
+    breadcrumb_service_ = static_cast<BreadcrumbManagerKeyedService*>(
         BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
             browser_state_.get()));
   }
@@ -40,13 +40,13 @@
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   std::unique_ptr<TestChromeBrowserState> browser_state_;
   FakeWebStateListDelegate web_state_list_delegate_;
-  BreadcrumbManagerKeyedService* breadcrumb_manager_;
+  BreadcrumbManagerKeyedService* breadcrumb_service_;
 };
 
 // Tests that an event logged by the BrowserAgent is returned with events for
 // the associated |browser_state_|.
 TEST_F(BreadcrumbManagerBrowserAgentTest, LogEvent) {
-  ASSERT_EQ(0ul, breadcrumb_manager_->GetEvents(0).size());
+  ASSERT_EQ(0ul, breadcrumb_service_->GetEvents(0).size());
 
   // Create and setup Browser.
   WebStateList web_state_list(&web_state_list_delegate_);
@@ -63,14 +63,14 @@
       /*index=*/0, std::move(web_state),
       WebStateList::InsertionFlags::INSERT_NO_FLAGS, WebStateOpener());
 
-  EXPECT_EQ(1ul, breadcrumb_manager_->GetEvents(0).size());
+  EXPECT_EQ(1ul, breadcrumb_service_->GetEvents(0).size());
 }
 
 // Tests that events logged through BrowserAgents associated with different
 // Browser instances are returned with events for the associated
 // |browser_state_| and are uniquely identifiable.
 TEST_F(BreadcrumbManagerBrowserAgentTest, MultipleBrowsers) {
-  ASSERT_EQ(0ul, breadcrumb_manager_->GetEvents(0).size());
+  ASSERT_EQ(0ul, breadcrumb_service_->GetEvents(0).size());
 
   // Create and setup Browser.
   WebStateList web_state_list(&web_state_list_delegate_);
@@ -101,7 +101,7 @@
       /*index=*/0, std::move(web_state2),
       WebStateList::InsertionFlags::INSERT_NO_FLAGS, WebStateOpener());
 
-  std::list<std::string> events = breadcrumb_manager_->GetEvents(0);
+  std::list<std::string> events = breadcrumb_service_->GetEvents(0);
   EXPECT_EQ(2ul, events.size());
 
   // Seperately compare the start and end of the event strings to ensure
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.cc b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.cc
index 5d866aa..6bb655c7 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.cc
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.cc
@@ -5,103 +5,35 @@
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
 
 #include "base/strings/stringprintf.h"
-#include "base/time/time.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
 #include "ios/web/public/browser_state.h"
 
-namespace {
-
-// The minimum number of event buckets to keep, even if they are expired.
-const int kMinEventsBuckets = 2;
-
-// Returns a Time used to bucket events for easier discarding of expired events.
-base::Time EventBucket(const base::Time& time) {
-  base::Time::Exploded exploded;
-  time.LocalExplode(&exploded);
-  exploded.millisecond = 0;
-  exploded.second = 0;
-
-  base::Time bucket_time;
-  bool converted = base::Time::FromLocalExploded(exploded, &bucket_time);
-  DCHECK(converted);
-  return bucket_time;
-}
-
-}  // namespace
-
-std::list<std::string> BreadcrumbManagerKeyedService::GetEvents(
-    size_t event_count_limit) {
-  DropOldEvents();
-
-  std::list<std::string> events;
-  for (auto it = event_buckets_.rbegin(); it != event_buckets_.rend(); ++it) {
-    std::list<std::string> bucket_events = it->second;
-    for (auto event_it = bucket_events.rbegin();
-         event_it != bucket_events.rend(); ++event_it) {
-      std::string event = *event_it;
-      events.push_front(event);
-      if (event_count_limit > 0 && events.size() >= event_count_limit) {
-        return events;
-      }
-    }
-  }
-  return events;
-}
-
 void BreadcrumbManagerKeyedService::AddEvent(const std::string& event) {
-  base::Time time = base::Time::Now();
-  base::Time bucket_time = EventBucket(time);
-
-  // If bucket exists, it will be at the end of the list.
-  if (event_buckets_.empty() || event_buckets_.back().first != bucket_time) {
-    std::pair<base::Time, std::list<std::string>> bucket(
-        bucket_time, std::list<std::string>());
-    event_buckets_.push_back(bucket);
-  }
-
-  base::Time::Exploded exploded;
-  time.UTCExplode(&exploded);
-  std::string timestamp = base::StringPrintf(
-      "%02d:%02d.%03d", exploded.minute, exploded.second, exploded.millisecond);
-  std::string event_log = base::StringPrintf(
-      "%s %s %s", timestamp.c_str(), browsing_mode_.c_str(), event.c_str());
-  event_buckets_.back().second.push_back(event_log);
-
-  DropOldEvents();
-
-  for (auto& observer : observers_) {
-    observer.EventAdded(this, event_log);
-  }
+  std::string event_log =
+      base::StringPrintf("%s %s", browsing_mode_.c_str(), event.c_str());
+  breadcrumb_manager_->AddEvent(event_log);
 }
 
-void BreadcrumbManagerKeyedService::DropOldEvents() {
-  static const base::TimeDelta kMessageExpirationTime =
-      base::TimeDelta::FromMinutes(20);
+void BreadcrumbManagerKeyedService::AddObserver(
+    BreadcrumbManagerObserver* observer) {
+  breadcrumb_manager_->AddObserver(observer);
+}
 
-  base::Time now = base::Time::Now();
-  while (event_buckets_.size() > kMinEventsBuckets) {
-    base::Time oldest_bucket_time = event_buckets_.front().first;
-    if (now - oldest_bucket_time < kMessageExpirationTime) {
-      break;
-    }
-    event_buckets_.pop_front();
-  }
+void BreadcrumbManagerKeyedService::RemoveObserver(
+    BreadcrumbManagerObserver* observer) {
+  breadcrumb_manager_->RemoveObserver(observer);
+}
+
+const std::list<std::string> BreadcrumbManagerKeyedService::GetEvents(
+    size_t event_count_limit) {
+  return breadcrumb_manager_->GetEvents(event_count_limit);
 }
 
 BreadcrumbManagerKeyedService::BreadcrumbManagerKeyedService(
     web::BrowserState* browser_state)
     // Set "I" for Incognito (Chrome branded OffTheRecord implementation) and
     // "N" for Normal browsing mode.
-    : browsing_mode_(browser_state->IsOffTheRecord() ? "I" : "N") {}
+    : browsing_mode_(browser_state->IsOffTheRecord() ? "I" : "N"),
+      breadcrumb_manager_(std::make_unique<BreadcrumbManager>()) {}
 
 BreadcrumbManagerKeyedService::~BreadcrumbManagerKeyedService() = default;
-
-void BreadcrumbManagerKeyedService::AddObserver(
-    BreadcrumbManagerObserver* observer) {
-  observers_.AddObserver(observer);
-}
-
-void BreadcrumbManagerKeyedService::RemoveObserver(
-    BreadcrumbManagerObserver* observer) {
-  observers_.RemoveObserver(observer);
-}
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h
index 772eb40..aabb531 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h
@@ -6,62 +6,47 @@
 #define IOS_CHROME_BROWSER_CRASH_REPORT_BREADCRUMBS_BREADCRUMB_MANAGER_KEYED_SERVICE_H_
 
 #include <list>
-#include <map>
+#include <memory>
 #include <string>
 
-#include "base/observer_list.h"
-#import "base/time/time.h"
 #include "components/keyed_service/core/keyed_service.h"
 
+class BreadcrumbManager;
 class BreadcrumbManagerObserver;
 
 namespace web {
 class BrowserState;
 }
 
-// Stores events logged with |AddEvent| in memory which can later be retrieved
-// with |GetEvents|. Events will be silently dropped after a certain amount of
-// time has passed unless no more recent events are available. The internal
-// management of events aims to keep relevant events available while clearing
-// stale data.
+// Associates a BreadcrumbManager instance with a BrowserState.
 class BreadcrumbManagerKeyedService : public KeyedService {
  public:
-  // Returns a list of the collected breadcrumb events which are still relevant
-  // up to |event_count_limit|. Passing zero for |event_count_limit| signifies
-  // no limit. Events returned will have a timestamp prepended to the original
-  // |event| string representing when |AddEvent| was called.
-  std::list<std::string> GetEvents(size_t event_count_limit);
-
-  // Logs a breadcrumb event with message data |event|.
-  // NOTE: |event| must not include newline characters as newlines are used by
-  // BreadcrumbPersistentStore as a deliminator.
-  void AddEvent(const std::string& event);
-
-  // Adds and removes observers.
-  void AddObserver(BreadcrumbManagerObserver* observer);
-  void RemoveObserver(BreadcrumbManagerObserver* observer);
-
   explicit BreadcrumbManagerKeyedService(web::BrowserState* browser_state);
   ~BreadcrumbManagerKeyedService() override;
 
- private:
-  // Drops events which are considered stale. Note that stale events are not
-  // guaranteed to be removed. Explicitly, stale events will be retained while
-  // newer events are limited.
-  void DropOldEvents();
+  // Logs a breadcrumb |event| associated with the BrowserState passed in at
+  // initialization of this instance. Prepends the |browsing_mode_| identifier
+  // to the event before passing it to the |breadcrumb_manager_|.
+  void AddEvent(const std::string& event);
 
+  // Adds and removes observers to the underlying |breadcrumb_manager_|.
+  void AddObserver(BreadcrumbManagerObserver* observer);
+  void RemoveObserver(BreadcrumbManagerObserver* observer);
+
+  // Returns up to |event_count_limit| events from the underlying
+  // |breadcrumb_manager|. See |BreadcrumbManager::GetEvents| for returned event
+  // details.
+  const std::list<std::string> GetEvents(size_t event_count_limit);
+
+ private:
   // A short string identifying the browser state used to initialize the
   // receiver. For example, "N" for "N"ormal browsing mode. This value is
   // prepended to events sent to |AddEvent| in order to differentiate the
   // BrowserState associated with each event.
   std::string browsing_mode_;
 
-  // List of events, paired with the time which they were logged to minute
-  // resolution. Newer events are at the end of the list.
-  std::list<std::pair<base::Time, std::list<std::string>>> event_buckets_;
-
-  base::ObserverList<BreadcrumbManagerObserver, /*check_empty=*/true>
-      observers_;
+  // The associated BreadcrumbManager to store events added with |AddEvent|.
+  std::unique_ptr<BreadcrumbManager> breadcrumb_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(BreadcrumbManagerKeyedService);
 };
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_unittest.mm
index 1b81e91..5741bfd 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_unittest.mm
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_unittest.mm
@@ -7,6 +7,7 @@
 #include "base/time/time.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_factory.h"
 #include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h"
 #include "ios/web/public/test/web_task_environment.h"
@@ -39,7 +40,7 @@
         base::BindRepeating(&BuildBreadcrumbManagerKeyedService));
     chrome_browser_state_ = test_cbs_builder.Build();
 
-    breadcrumb_manager_ = static_cast<BreadcrumbManagerKeyedService*>(
+    breadcrumb_manager_service_ = static_cast<BreadcrumbManagerKeyedService*>(
         BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
             chrome_browser_state_.get()));
   }
@@ -49,92 +50,29 @@
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-  BreadcrumbManagerKeyedService* breadcrumb_manager_;
+  BreadcrumbManagerKeyedService* breadcrumb_manager_service_;
 };
 
-// Tests that an event is logged and returned.
-TEST_F(BreadcrumbManagerKeyedServiceTest, AddEvent) {
-  std::string event_message = "event";
-  breadcrumb_manager_->AddEvent(event_message);
-  std::list<std::string> events = breadcrumb_manager_->GetEvents(0);
-  ASSERT_EQ(1ul, events.size());
-  // Events returned from |GetEvents| will have a timestamp prepended.
-  EXPECT_NE(std::string::npos, events.front().find(event_message));
-}
-
-// Tests that returned events returned by |GetEvents| are limited by the
-// |event_count_limit| parameter.
-TEST_F(BreadcrumbManagerKeyedServiceTest, EventCountLimited) {
-  breadcrumb_manager_->AddEvent("event1");
-  breadcrumb_manager_->AddEvent("event2");
-  breadcrumb_manager_->AddEvent("event3");
-  breadcrumb_manager_->AddEvent("event4");
-
-  std::list<std::string> events = breadcrumb_manager_->GetEvents(2);
-  ASSERT_EQ(2ul, events.size());
-  EXPECT_NE(std::string::npos, events.front().find("event3"));
-  events.pop_front();
-  EXPECT_NE(std::string::npos, events.front().find("event4"));
-}
-
-// Tests that old events are dropped.
-TEST_F(BreadcrumbManagerKeyedServiceTest, OldEventsDropped) {
-  // Log an event from one and two hours ago.
-  breadcrumb_manager_->AddEvent("event1");
-  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
-  breadcrumb_manager_->AddEvent("event2");
-  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
-
-  // Log three events separated by three minutes to ensure they receive their
-  // own event bucket. Otherwise, some old events may be returned to ensure a
-  // minimum number of available events. See |MinimumEventsReturned| test below.
-  breadcrumb_manager_->AddEvent("event3");
-  task_env_.FastForwardBy(base::TimeDelta::FromMinutes(3));
-  breadcrumb_manager_->AddEvent("event4");
-  task_env_.FastForwardBy(base::TimeDelta::FromMinutes(3));
-  breadcrumb_manager_->AddEvent("event5");
-
-  std::list<std::string> events = breadcrumb_manager_->GetEvents(0);
-  ASSERT_EQ(3ul, events.size());
-  // Validate the three most recent events are the ones which were returned.
-  EXPECT_NE(std::string::npos, events.front().find("event3"));
-  events.pop_front();
-  EXPECT_NE(std::string::npos, events.front().find("event4"));
-  events.pop_front();
-  EXPECT_NE(std::string::npos, events.front().find("event5"));
-}
-
-// Tests that expired events are returned if not enough new events exist.
-TEST_F(BreadcrumbManagerKeyedServiceTest, MinimumEventsReturned) {
-  // Log an event from one and two hours ago.
-  breadcrumb_manager_->AddEvent("event1");
-  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
-  breadcrumb_manager_->AddEvent("event2");
-  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
-  breadcrumb_manager_->AddEvent("event3");
-
-  std::list<std::string> events = breadcrumb_manager_->GetEvents(0);
-  EXPECT_EQ(2ul, events.size());
-}
-
 // Tests that events logged to Normal and OffTheRecord BrowserStates are
 // seperately identifiable.
 TEST_F(BreadcrumbManagerKeyedServiceTest, EventsLabeledWithBrowserState) {
-  breadcrumb_manager_->AddEvent("event");
-  std::string event = breadcrumb_manager_->GetEvents(0).front();
+  breadcrumb_manager_service_->AddEvent("event");
+
+  std::string event = breadcrumb_manager_service_->GetEvents(0).front();
   // Event should indicate it was logged from a "Normal" browser state.
   EXPECT_NE(std::string::npos, event.find(" N "));
 
   ios::ChromeBrowserState* off_the_record_browser_state =
       chrome_browser_state_->GetOffTheRecordChromeBrowserState();
 
-  BreadcrumbManagerKeyedService* off_the_record_breadcrumb_manager =
+  BreadcrumbManagerKeyedService* otr_breadcrumb_manager_service =
       static_cast<BreadcrumbManagerKeyedService*>(
           BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
               off_the_record_browser_state));
-  off_the_record_breadcrumb_manager->AddEvent("event");
+  otr_breadcrumb_manager_service->AddEvent("event");
+
   std::string off_the_record_event =
-      off_the_record_breadcrumb_manager->GetEvents(0).front();
+      otr_breadcrumb_manager_service->GetEvents(0).front();
   // Event should indicate it was logged from an off the record "Incognito"
   // browser state.
   EXPECT_NE(std::string::npos, off_the_record_event.find(" I "));
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h
index 884911f..03e4c58 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h
@@ -10,15 +10,15 @@
 #include "base/macros.h"
 #include "base/observer_list_types.h"
 
-class BreadcrumbManagerKeyedService;
+class BreadcrumbManager;
 
 class BreadcrumbManagerObserver : public base::CheckedObserver {
  public:
   // Called when a new |event| has been added to |manager|. Similar to
-  // |BreadcrumbManagerKeyedService::GetEvents|, |event| will have the timestamp
-  // at which it was logged prepended to the string which was passed to
-  // |BreadcrumbManagerKeyedService::AddEvent|.
-  virtual void EventAdded(BreadcrumbManagerKeyedService* manager,
+  // |BreadcrumbManager::GetEvents|, |event| will have the timestamp at which it
+  // was logged prepended to the string which was passed to
+  // |BreadcrumbManager::AddEvent|.
+  virtual void EventAdded(BreadcrumbManager* manager,
                           const std::string& event) {}
 
  protected:
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.h b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.h
index b2ddc6a2..6369724 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.h
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.h
@@ -7,11 +7,12 @@
 
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h"
 
+class BreadcrumbManager;
 class BreadcrumbManagerKeyedService;
 
 // Protocol mirroring BreadcrumbManagerObserver
 @protocol BreadcrumbManagerObserving
-- (void)breadcrumbManager:(BreadcrumbManagerKeyedService*)manager
+- (void)breadcrumbManager:(BreadcrumbManager*)manager
               didAddEvent:(NSString*)string;
 @end
 
@@ -19,9 +20,17 @@
 // that observes the connection type.
 class BreadcrumbManagerObserverBridge : public BreadcrumbManagerObserver {
  public:
-  explicit BreadcrumbManagerObserverBridge(
-      BreadcrumbManagerKeyedService* breadcrumb_manager_keyed_service,
+  // Constructs a new bridge instance adding |observer| as an observer of
+  // |breadcrumb_manager|.
+  BreadcrumbManagerObserverBridge(BreadcrumbManager* breadcrumb_manager,
+                                  id<BreadcrumbManagerObserving> observer);
+
+  // Constructs a new bridge instance adding |observer| as an observer of
+  // |breadcrumb_manager_service|.
+  BreadcrumbManagerObserverBridge(
+      BreadcrumbManagerKeyedService* breadcrumb_manager_service,
       id<BreadcrumbManagerObserving> observer);
+
   ~BreadcrumbManagerObserverBridge() override;
 
  private:
@@ -31,10 +40,11 @@
       const BreadcrumbManagerObserverBridge&) = delete;
 
   // BreadcrumbManagerObserver implementation:
-  void EventAdded(BreadcrumbManagerKeyedService* manager,
+  void EventAdded(BreadcrumbManager* manager,
                   const std::string& event) override;
 
-  BreadcrumbManagerKeyedService* breadcrumb_manager_keyed_service_ = nullptr;
+  BreadcrumbManager* breadcrumb_manager_ = nullptr;
+  BreadcrumbManagerKeyedService* breadcrumb_manager_service_ = nullptr;
   __weak id<BreadcrumbManagerObserving> observer_ = nil;
 };
 
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.mm
index 75da0f12..e565d0bf 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.mm
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.mm
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/strings/sys_string_conversions.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -13,21 +14,33 @@
 #endif
 
 BreadcrumbManagerObserverBridge::BreadcrumbManagerObserverBridge(
-    BreadcrumbManagerKeyedService* breadcrumb_manager_keyed_service,
+    BreadcrumbManager* breadcrumb_manager,
     id<BreadcrumbManagerObserving> observer)
-    : breadcrumb_manager_keyed_service_(breadcrumb_manager_keyed_service),
+    : breadcrumb_manager_(breadcrumb_manager), observer_(observer) {
+  DCHECK(observer_);
+  breadcrumb_manager_->AddObserver(this);
+}
+
+BreadcrumbManagerObserverBridge::BreadcrumbManagerObserverBridge(
+    BreadcrumbManagerKeyedService* breadcrumb_manager_service,
+    id<BreadcrumbManagerObserving> observer)
+    : breadcrumb_manager_service_(breadcrumb_manager_service),
       observer_(observer) {
   DCHECK(observer_);
-  breadcrumb_manager_keyed_service_->AddObserver(this);
+  breadcrumb_manager_service_->AddObserver(this);
 }
 
 BreadcrumbManagerObserverBridge::~BreadcrumbManagerObserverBridge() {
-  breadcrumb_manager_keyed_service_->RemoveObserver(this);
+  if (breadcrumb_manager_) {
+    breadcrumb_manager_->RemoveObserver(this);
+  }
+  if (breadcrumb_manager_service_) {
+    breadcrumb_manager_service_->RemoveObserver(this);
+  }
 }
 
-void BreadcrumbManagerObserverBridge::EventAdded(
-    BreadcrumbManagerKeyedService* manager,
-    const std::string& event) {
+void BreadcrumbManagerObserverBridge::EventAdded(BreadcrumbManager* manager,
+                                                 const std::string& event) {
   [observer_ breadcrumbManager:manager
                    didAddEvent:base::SysUTF8ToNSString(event)];
 }
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge_unittest.mm
index b5b7f00..5e659ec 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge_unittest.mm
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge_unittest.mm
@@ -7,8 +7,7 @@
 #import "base/strings/sys_string_conversions.h"
 #include "base/test/task_environment.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_factory.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
@@ -23,21 +22,13 @@
 class BreadcrumbManagerObserverBridgeTest : public PlatformTest {
  protected:
   BreadcrumbManagerObserverBridgeTest() {
-    TestChromeBrowserState::Builder test_cbs_builder;
-    chrome_browser_state_ = test_cbs_builder.Build();
-
-    breadcrumb_service_ =
-        BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
-            chrome_browser_state_.get());
-
     mock_observer_ = OCMProtocolMock(@protocol(BreadcrumbManagerObserving));
     observer_bridge_ = std::make_unique<BreadcrumbManagerObserverBridge>(
-        breadcrumb_service_, mock_observer_);
+        &breadcrumb_manager_, mock_observer_);
   }
 
   base::test::TaskEnvironment task_environment_;
-  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-  BreadcrumbManagerKeyedService* breadcrumb_service_;
+  BreadcrumbManager breadcrumb_manager_;
   id mock_observer_;
   std::unique_ptr<BreadcrumbManagerObserverBridge> observer_bridge_;
 };
@@ -52,10 +43,10 @@
     return [value isKindOfClass:[NSString class]] &&
            [value hasSuffix:base::SysUTF8ToNSString(event)];
   }];
-  OCMExpect([mock_observer_ breadcrumbManager:breadcrumb_service_
+  OCMExpect([mock_observer_ breadcrumbManager:&breadcrumb_manager_
                                   didAddEvent:event_parameter_validator]);
 
-  breadcrumb_service_->AddEvent(event);
+  breadcrumb_manager_.AddEvent(event);
 
   [mock_observer_ verify];
 }
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_unittest.mm
index e4403f9..c907fb7 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_unittest.mm
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_unittest.mm
@@ -4,13 +4,7 @@
 
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h"
 
-#import "base/macros.h"
-#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_factory.h"
-#include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h"
-#include "ios/web/public/test/web_task_environment.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
 #include "testing/platform_test.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -23,52 +17,32 @@
   FakeBreadcrumbManagerObserver() {}
   ~FakeBreadcrumbManagerObserver() override = default;
 
+  FakeBreadcrumbManagerObserver(const FakeBreadcrumbManagerObserver&) = delete;
+  FakeBreadcrumbManagerObserver& operator=(
+      const FakeBreadcrumbManagerObserver&) = delete;
+
   // BreadcrumbManagerObserver
-  void EventAdded(BreadcrumbManagerKeyedService* manager,
+  void EventAdded(BreadcrumbManager* manager,
                   const std::string& event) override {
     last_received_manager_ = manager;
     last_received_event_ = event;
   }
 
-  BreadcrumbManagerKeyedService* last_received_manager_ = nullptr;
+  BreadcrumbManager* last_received_manager_ = nullptr;
   std::string last_received_event_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeBreadcrumbManagerObserver);
 };
 
-// Creates a new BreadcrumbManagerKeyedService for |browser_state|.
-std::unique_ptr<KeyedService> BuildBreadcrumbManagerKeyedService(
-    web::BrowserState* browser_state) {
-  return std::make_unique<BreadcrumbManagerKeyedService>(
-      ios::ChromeBrowserState::FromBrowserState(browser_state));
-}
 }
 
 class BreadcrumbManagerObserverTest : public PlatformTest {
  protected:
-  BreadcrumbManagerObserverTest()
-      : scoped_browser_state_manager_(
-            std::make_unique<TestChromeBrowserStateManager>(base::FilePath())) {
-    TestChromeBrowserState::Builder test_cbs_builder;
-    test_cbs_builder.AddTestingFactory(
-        BreadcrumbManagerKeyedServiceFactory::GetInstance(),
-        base::BindRepeating(&BuildBreadcrumbManagerKeyedService));
-    chrome_browser_state_ = test_cbs_builder.Build();
-
-    manager_ = static_cast<BreadcrumbManagerKeyedService*>(
-        BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
-            chrome_browser_state_.get()));
-    manager_->AddObserver(&observer_);
-  }
+  BreadcrumbManagerObserverTest() { manager_.AddObserver(&observer_); }
 
   ~BreadcrumbManagerObserverTest() override {
-    manager_->RemoveObserver(&observer_);
+    manager_.RemoveObserver(&observer_);
   }
 
-  web::WebTaskEnvironment task_environment_;
-  IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_;
-  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-  BreadcrumbManagerKeyedService* manager_;
+  BreadcrumbManager manager_;
   FakeBreadcrumbManagerObserver observer_;
 };
 
@@ -79,9 +53,9 @@
   ASSERT_TRUE(observer_.last_received_event_.empty());
 
   std::string event = "event";
-  manager_->AddEvent(event);
+  manager_.AddEvent(event);
 
-  EXPECT_EQ(manager_, observer_.last_received_manager_);
+  EXPECT_EQ(&manager_, observer_.last_received_manager_);
   // A timestamp will be prepended to the event passed to |AddEvent|.
   EXPECT_NE(std::string::npos, observer_.last_received_event_.find(event));
 }
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm
index baa145c..c2bd7bd 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm
@@ -28,7 +28,7 @@
     first_web_state_.SetBrowserState(chrome_browser_state_.get());
     second_web_state_.SetBrowserState(chrome_browser_state_.get());
 
-    breadcrumb_manager_ = static_cast<BreadcrumbManagerKeyedService*>(
+    breadcrumb_service_ = static_cast<BreadcrumbManagerKeyedService*>(
         BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
             chrome_browser_state_.get()));
   }
@@ -37,7 +37,7 @@
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
   web::TestWebState first_web_state_;
   web::TestWebState second_web_state_;
-  BreadcrumbManagerKeyedService* breadcrumb_manager_;
+  BreadcrumbManagerKeyedService* breadcrumb_service_;
 };
 
 // Tests that the identifier returned for a WebState is unique.
@@ -64,13 +64,13 @@
 TEST_F(BreadcrumbManagerTabHelperTest, EventsLogged) {
   BreadcrumbManagerTabHelper::CreateForWebState(&first_web_state_);
 
-  EXPECT_EQ(0ul, breadcrumb_manager_->GetEvents(0).size());
+  EXPECT_EQ(0ul, breadcrumb_service_->GetEvents(0).size());
   first_web_state_.SetLoading(true);
-  std::list<std::string> events = breadcrumb_manager_->GetEvents(0);
+  std::list<std::string> events = breadcrumb_service_->GetEvents(0);
   EXPECT_EQ(1ul, events.size());
   EXPECT_NE(std::string::npos, events.back().find("DidStartLoading"));
   first_web_state_.SetLoading(false);
-  events = breadcrumb_manager_->GetEvents(0);
+  events = breadcrumb_service_->GetEvents(0);
   EXPECT_EQ(2ul, events.size());
   EXPECT_NE(std::string::npos, events.back().find("DidStopLoading"));
 }
@@ -84,7 +84,7 @@
   BreadcrumbManagerTabHelper::CreateForWebState(&second_web_state_);
   second_web_state_.SetLoading(true);
 
-  std::list<std::string> events = breadcrumb_manager_->GetEvents(0);
+  std::list<std::string> events = breadcrumb_service_->GetEvents(0);
   EXPECT_EQ(2ul, events.size());
   EXPECT_STRNE(events.front().c_str(), events.back().c_str());
   EXPECT_NE(std::string::npos, events.front().find("DidStartLoading"));
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_unittest.mm
new file mode 100644
index 0000000..e4bf87a
--- /dev/null
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_unittest.mm
@@ -0,0 +1,88 @@
+// Copyright 2019 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.
+
+#import "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
+
+#import "ios/web/public/test/web_task_environment.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// Test fixture for testing BreadcrumbManager class.
+class BreadcrumbManagerTest : public PlatformTest {
+ protected:
+  BreadcrumbManagerTest() = default;
+
+  web::WebTaskEnvironment task_env_{
+      web::WebTaskEnvironment::Options::DEFAULT,
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  BreadcrumbManager breadcrumb_manager_;
+};
+
+// Tests that an event is logged and returned.
+TEST_F(BreadcrumbManagerTest, AddEvent) {
+  std::string event_message = "event";
+  breadcrumb_manager_.AddEvent(event_message);
+  std::list<std::string> events = breadcrumb_manager_.GetEvents(0);
+  ASSERT_EQ(1ul, events.size());
+  // Events returned from |GetEvents| will have a timestamp prepended.
+  EXPECT_NE(std::string::npos, events.front().find(event_message));
+}
+
+// Tests that returned events returned by |GetEvents| are limited by the
+// |event_count_limit| parameter.
+TEST_F(BreadcrumbManagerTest, EventCountLimited) {
+  breadcrumb_manager_.AddEvent("event1");
+  breadcrumb_manager_.AddEvent("event2");
+  breadcrumb_manager_.AddEvent("event3");
+  breadcrumb_manager_.AddEvent("event4");
+
+  std::list<std::string> events = breadcrumb_manager_.GetEvents(2);
+  ASSERT_EQ(2ul, events.size());
+  EXPECT_NE(std::string::npos, events.front().find("event3"));
+  events.pop_front();
+  EXPECT_NE(std::string::npos, events.front().find("event4"));
+}
+
+// Tests that old events are dropped.
+TEST_F(BreadcrumbManagerTest, OldEventsDropped) {
+  // Log an event from one and two hours ago.
+  breadcrumb_manager_.AddEvent("event1");
+  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+  breadcrumb_manager_.AddEvent("event2");
+  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+
+  // Log three events separated by three minutes to ensure they receive their
+  // own event bucket. Otherwise, some old events may be returned to ensure a
+  // minimum number of available events. See |MinimumEventsReturned| test below.
+  breadcrumb_manager_.AddEvent("event3");
+  task_env_.FastForwardBy(base::TimeDelta::FromMinutes(3));
+  breadcrumb_manager_.AddEvent("event4");
+  task_env_.FastForwardBy(base::TimeDelta::FromMinutes(3));
+  breadcrumb_manager_.AddEvent("event5");
+
+  std::list<std::string> events = breadcrumb_manager_.GetEvents(0);
+  ASSERT_EQ(3ul, events.size());
+  // Validate the three most recent events are the ones which were returned.
+  EXPECT_NE(std::string::npos, events.front().find("event3"));
+  events.pop_front();
+  EXPECT_NE(std::string::npos, events.front().find("event4"));
+  events.pop_front();
+  EXPECT_NE(std::string::npos, events.front().find("event5"));
+}
+
+// Tests that expired events are returned if not enough new events exist.
+TEST_F(BreadcrumbManagerTest, MinimumEventsReturned) {
+  // Log an event from one and two hours ago.
+  breadcrumb_manager_.AddEvent("event1");
+  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+  breadcrumb_manager_.AddEvent("event2");
+  task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+  breadcrumb_manager_.AddEvent("event3");
+
+  std::list<std::string> events = breadcrumb_manager_.GetEvents(0);
+  EXPECT_EQ(2ul, events.size());
+}
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.cc b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.cc
index 8051f8a..e2757e5 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.cc
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_util.h"
 
 namespace {
@@ -53,7 +53,7 @@
 }
 
 void BreadcrumbPersistentStorageKeyedService::ObserveBreadcrumbManager(
-    BreadcrumbManagerKeyedService* manager) {
+    BreadcrumbManager* manager) {
   if (observered_manager_) {
     observered_manager_->RemoveObserver(this);
   }
@@ -98,7 +98,7 @@
 }
 
 void BreadcrumbPersistentStorageKeyedService::EventAdded(
-    BreadcrumbManagerKeyedService* manager,
+    BreadcrumbManager* manager,
     const std::string& event) {
   WriteBreadcrumbEvent(event);
   persisted_events_file_->Flush();
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.h b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.h
index 8d6cb3d..7e45224 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.h
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service.h
@@ -15,7 +15,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer.h"
 
-class BreadcrumbManagerKeyedService;
+class BreadcrumbManager;
 
 namespace web {
 class BrowserState;
@@ -41,7 +41,7 @@
   // if null is passed for |manager|. As such, this can be used to ensure stale
   // data does not take up disk space. If manager is non-null, events will be
   // written whenever |manager| receives an event.
-  void ObserveBreadcrumbManager(BreadcrumbManagerKeyedService* manager);
+  void ObserveBreadcrumbManager(BreadcrumbManager* manager);
 
  private:
   // Writes |observered_manager_|'s events to disk, overwriting any existing
@@ -54,11 +54,11 @@
   void WriteBreadcrumbEvent(const std::string& event);
 
   // BreadcrumbManagerObserver
-  void EventAdded(BreadcrumbManagerKeyedService* manager,
+  void EventAdded(BreadcrumbManager* manager,
                   const std::string& event) override;
 
   // The breadcrumb manager currently being observed.
-  BreadcrumbManagerKeyedService* observered_manager_ = nullptr;
+  BreadcrumbManager* observered_manager_ = nullptr;
 
   // The path to the breadcrumbs file.
   base::FilePath breadcrumbs_file_path_;
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service_unittest.mm
index b79fc6f3..ff76d1bd 100644
--- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service_unittest.mm
+++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service_unittest.mm
@@ -8,8 +8,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
-#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_factory.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_keyed_service_factory.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_persistent_storage_util.h"
 #include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h"
@@ -24,13 +23,6 @@
     GetBreadcrumbPersistentStorageFilePath;
 
 namespace {
-// Creates a new BreadcrumbManagerKeyedService for |browser_state|.
-std::unique_ptr<KeyedService> BuildBreadcrumbManagerKeyedService(
-    web::BrowserState* browser_state) {
-  return std::make_unique<BreadcrumbManagerKeyedService>(
-      ios::ChromeBrowserState::FromBrowserState(browser_state));
-}
-
 // Creates a new BreadcrumbPersistentStorageKeyedService for |browser_state|.
 std::unique_ptr<KeyedService> BuildBreadcrumbPersistentStorageKeyedService(
     web::BrowserState* browser_state) {
@@ -50,16 +42,10 @@
     TestChromeBrowserState::Builder test_cbs_builder;
     test_cbs_builder.SetPath(directory_name);
     test_cbs_builder.AddTestingFactory(
-        BreadcrumbManagerKeyedServiceFactory::GetInstance(),
-        base::BindRepeating(&BuildBreadcrumbManagerKeyedService));
-    test_cbs_builder.AddTestingFactory(
         BreadcrumbPersistentStorageKeyedServiceFactory::GetInstance(),
         base::BindRepeating(&BuildBreadcrumbPersistentStorageKeyedService));
     chrome_browser_state_ = test_cbs_builder.Build();
 
-    breadcrumb_manager_ = static_cast<BreadcrumbManagerKeyedService*>(
-        BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
-            chrome_browser_state_.get()));
     persistent_storage_ = static_cast<BreadcrumbPersistentStorageKeyedService*>(
         BreadcrumbPersistentStorageKeyedServiceFactory::GetForBrowserState(
             chrome_browser_state_.get()));
@@ -75,15 +61,15 @@
   IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
   base::ScopedTempDir scoped_temp_directory_;
-  BreadcrumbManagerKeyedService* breadcrumb_manager_;
+  BreadcrumbManager breadcrumb_manager_;
   BreadcrumbPersistentStorageKeyedService* persistent_storage_;
 };
 
 // Ensures that events logged after a BreadcrumbManager is already being
 // observed are persisted.
 TEST_F(BreadcrumbPersistentStorageKeyedServiceTest, PersistMessages) {
-  persistent_storage_->ObserveBreadcrumbManager(breadcrumb_manager_);
-  breadcrumb_manager_->AddEvent("event");
+  persistent_storage_->ObserveBreadcrumbManager(&breadcrumb_manager_);
+  breadcrumb_manager_.AddEvent("event");
 
   auto events = persistent_storage_->GetStoredEvents();
   ASSERT_EQ(1ul, events.size());
@@ -93,8 +79,8 @@
 // Ensures that events logged before a BreadcrumbManager is being observed
 // are persisted.
 TEST_F(BreadcrumbPersistentStorageKeyedServiceTest, PersistExistingMessages) {
-  breadcrumb_manager_->AddEvent("event");
-  persistent_storage_->ObserveBreadcrumbManager(breadcrumb_manager_);
+  breadcrumb_manager_.AddEvent("event");
+  persistent_storage_->ObserveBreadcrumbManager(&breadcrumb_manager_);
 
   auto events = persistent_storage_->GetStoredEvents();
   ASSERT_EQ(1ul, events.size());
@@ -104,8 +90,8 @@
 // Tests that calling |ObserveBreadcrumbManager| with a null manager removes the
 // contents of the persistent storage file.
 TEST_F(BreadcrumbPersistentStorageKeyedServiceTest, DeletePersistentStorage) {
-  breadcrumb_manager_->AddEvent("event");
-  persistent_storage_->ObserveBreadcrumbManager(breadcrumb_manager_);
+  breadcrumb_manager_.AddEvent("event");
+  persistent_storage_->ObserveBreadcrumbManager(&breadcrumb_manager_);
   persistent_storage_->ObserveBreadcrumbManager(/*manager=*/nullptr);
 
   int64_t file_size = -1;
diff --git a/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer.mm b/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer.mm
index 2ec3d83..288556f 100644
--- a/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer.mm
+++ b/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer.mm
@@ -64,7 +64,7 @@
 
 #pragma mark - BreadcrumbManagerObserving protocol
 
-- (void)breadcrumbManager:(BreadcrumbManagerKeyedService*)manager
+- (void)breadcrumbManager:(BreadcrumbManager*)manager
               didAddEvent:(NSString*)event {
   NSString* eventWithSeperator = [NSString stringWithFormat:@"%@\n", event];
   [_breadcrumbsString insertString:eventWithSeperator atIndex:0];
diff --git a/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer_unittest.mm b/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer_unittest.mm
index 6326001..ae2ae76 100644
--- a/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer_unittest.mm
+++ b/ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer_unittest.mm
@@ -8,6 +8,7 @@
 #import "base/test/ios/wait_util.h"
 #include "base/test/task_environment.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_keyed_service_factory.h"
 #import "ios/chrome/browser/crash_report/breakpad_helper.h"
@@ -100,7 +101,7 @@
       observeBrowserState:chrome_browser_state_.get()];
 
   const std::string event = std::string("Breadcrumb Event");
-  BreadcrumbManagerKeyedService* breadcrumb_manager =
+  BreadcrumbManagerKeyedService* breadcrumb_service =
       BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
           chrome_browser_state_.get());
 
@@ -108,7 +109,7 @@
     if (![value isKindOfClass:[NSString class]]) {
       return NO;
     }
-    std::list<std::string> events = breadcrumb_manager->GetEvents(0);
+    std::list<std::string> events = breadcrumb_service->GetEvents(0);
     std::string expected_breadcrumbs;
     for (const auto& event : events) {
       expected_breadcrumbs += event + "\n";
@@ -120,7 +121,7 @@
       addUploadParameter:breadcrumbs_param_vaidation_block
                   forKey:@"browser_state_breadcrumbs"];
 
-  breadcrumb_manager->AddEvent(event);
+  breadcrumb_service->AddEvent(event);
   EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_);
 }
 
@@ -140,40 +141,43 @@
 
   [crash_reporter_breadcrumb_observer
       observeBrowserState:chrome_browser_state_.get()];
-  BreadcrumbManagerKeyedService* breadcrumb_manager =
+  BreadcrumbManagerKeyedService* breadcrumb_service =
       BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
           chrome_browser_state_.get());
+
   [[mock_breakpad_controller_ expect]
       addUploadParameter:StringParameterValidatorWithCountOfSubstring(
                              1, event_nsstring)
                   forKey:@"browser_state_breadcrumbs"];
-  breadcrumb_manager->AddEvent(event);
+  breadcrumb_service->AddEvent(event);
 
   ios::ChromeBrowserState* otr_browser_state =
       chrome_browser_state_->GetOffTheRecordChromeBrowserState();
   [crash_reporter_breadcrumb_observer observeBrowserState:otr_browser_state];
-  BreadcrumbManagerKeyedService* otr_breadcrumb_manager =
+  BreadcrumbManagerKeyedService* otr_breadcrumb_service =
       BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
           otr_browser_state);
+
   [[mock_breakpad_controller_ expect]
       addUploadParameter:StringParameterValidatorWithCountOfSubstring(
                              2, event_nsstring)
                   forKey:@"browser_state_breadcrumbs"];
-  otr_breadcrumb_manager->AddEvent(event);
+  otr_breadcrumb_service->AddEvent(event);
 
   TestChromeBrowserState::Builder test_cbs_builder;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_2 =
       test_cbs_builder.Build();
   [crash_reporter_breadcrumb_observer
       observeBrowserState:chrome_browser_state_2.get()];
-  BreadcrumbManagerKeyedService* breadcrumb_manager_2 =
+  BreadcrumbManagerKeyedService* breadcrumb_service_2 =
       BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
           chrome_browser_state_2.get());
+
   [[mock_breakpad_controller_ expect]
       addUploadParameter:StringParameterValidatorWithCountOfSubstring(
                              3, event_nsstring)
                   forKey:@"browser_state_breadcrumbs"];
-  breadcrumb_manager_2->AddEvent(event);
+  breadcrumb_service_2->AddEvent(event);
 
   EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_);
 
diff --git a/ios/chrome/browser/infobars/BUILD.gn b/ios/chrome/browser/infobars/BUILD.gn
index e1a60f5..520b8fb2 100644
--- a/ios/chrome/browser/infobars/BUILD.gn
+++ b/ios/chrome/browser/infobars/BUILD.gn
@@ -51,8 +51,6 @@
 source_set("badge") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
-    "infobar_badge_browser_agent.h",
-    "infobar_badge_browser_agent.mm",
     "infobar_badge_tab_helper.h",
     "infobar_badge_tab_helper.mm",
     "infobar_badge_tab_helper_delegate.h",
@@ -91,7 +89,6 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
-    "infobar_badge_browser_agent_unittest.mm",
     "infobar_badge_tab_helper_unittest.mm",
     "infobar_ios_unittest.mm",
   ]
@@ -105,9 +102,6 @@
     "//ios/chrome/browser/infobars/test",
     "//ios/chrome/browser/main",
     "//ios/chrome/browser/main:test_support",
-    "//ios/chrome/browser/overlays",
-    "//ios/chrome/browser/overlays/public/common/infobars",
-    "//ios/chrome/browser/overlays/test",
     "//ios/chrome/browser/ui/badges:public",
     "//ios/chrome/browser/ui/badges:util",
     "//ios/chrome/browser/ui/infobars:feature_flags",
diff --git a/ios/chrome/browser/infobars/infobar_badge_browser_agent.h b/ios/chrome/browser/infobars/infobar_badge_browser_agent.h
deleted file mode 100644
index 8295a3f6..0000000
--- a/ios/chrome/browser/infobars/infobar_badge_browser_agent.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2019 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 IOS_CHROME_BROWSER_INFOBARS_INFOBAR_BADGE_BROWSER_AGENT_H_
-#define IOS_CHROME_BROWSER_INFOBARS_INFOBAR_BADGE_BROWSER_AGENT_H_
-
-#include "base/scoped_observer.h"
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#include "ios/chrome/browser/main/browser_user_data.h"
-#include "ios/chrome/browser/overlays/public/overlay_presenter.h"
-#include "ios/chrome/browser/overlays/public/overlay_presenter_observer.h"
-
-class InfobarBadgeTabHelper;
-namespace web {
-class WebState;
-}
-
-// Browser agent that updates InfobarTabHelpers for observed infobar overlay
-// events.
-class InfobarBadgeBrowserAgent
-    : public BrowserUserData<InfobarBadgeBrowserAgent> {
- public:
-  ~InfobarBadgeBrowserAgent() override;
-
- private:
-  BROWSER_USER_DATA_KEY_DECL();
-  friend class BrowserUserData<InfobarBadgeBrowserAgent>;
-  explicit InfobarBadgeBrowserAgent(Browser* browser);
-
-  // Returns the badge tab helper for the active WebState.
-  InfobarBadgeTabHelper* GetBadgeCurrentTabHelper() const;
-
-  // Called when the banner UI for |request| was presented or dismissed.
-  void OnInfobarBannerPresented(OverlayRequest* request);
-  void OnInfobarBannerDismissed(OverlayRequest* request);
-
-  // Helper object that observes the presentation of infobar overlays.
-  class InfobarOverlayObserver : public OverlayPresenterObserver {
-   public:
-    InfobarOverlayObserver(InfobarBadgeBrowserAgent* browser_agent,
-                           Browser* browser);
-    ~InfobarOverlayObserver() override;
-
-   private:
-    // OverlayPresenterObserver:
-    void DidShowOverlay(OverlayPresenter* presenter,
-                        OverlayRequest* request) override;
-    void DidHideOverlay(OverlayPresenter* presenter,
-                        OverlayRequest* request) override;
-    void OverlayPresenterDestroyed(OverlayPresenter* presenter) override;
-
-   private:
-    ScopedObserver<OverlayPresenter, OverlayPresenterObserver> scoped_observer_;
-    InfobarBadgeBrowserAgent* browser_agent_;
-  };
-
-  InfobarOverlayObserver infobar_overlay_observer_;
-  WebStateList* web_state_list_ = nullptr;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_INFOBAR_BADGE_BROWSER_AGENT_H_
diff --git a/ios/chrome/browser/infobars/infobar_badge_browser_agent.mm b/ios/chrome/browser/infobars/infobar_badge_browser_agent.mm
deleted file mode 100644
index ef302b7..0000000
--- a/ios/chrome/browser/infobars/infobar_badge_browser_agent.mm
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2019 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.
-
-#import "ios/chrome/browser/infobars/infobar_badge_browser_agent.h"
-
-#include "base/logging.h"
-#include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h"
-#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
-#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
-#include "ios/chrome/browser/overlays/public/overlay_presenter.h"
-#include "ios/chrome/browser/overlays/public/overlay_request.h"
-#import "ios/chrome/browser/web_state_list/web_state_list.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-// Returns the InfobarType used to configure |request|.  |request| must be
-// configured with an InfobarOverlayRequestConfig.
-InfobarType GetInfobarType(OverlayRequest* request) {
-  return request->GetConfig<InfobarOverlayRequestConfig>()->infobar_type();
-}
-}  // namespace
-
-#pragma mark - InfobarBadgeBrowserAgent
-
-BROWSER_USER_DATA_KEY_IMPL(InfobarBadgeBrowserAgent)
-
-InfobarBadgeBrowserAgent::InfobarBadgeBrowserAgent(Browser* browser)
-    : infobar_overlay_observer_(this, browser),
-      web_state_list_(browser->GetWebStateList()) {
-  DCHECK(web_state_list_);
-}
-
-InfobarBadgeBrowserAgent::~InfobarBadgeBrowserAgent() = default;
-
-InfobarBadgeTabHelper* InfobarBadgeBrowserAgent::GetBadgeCurrentTabHelper()
-    const {
-  if (web_state_list_->active_index() == WebStateList::kInvalidIndex)
-    return nullptr;
-  return InfobarBadgeTabHelper::FromWebState(
-      web_state_list_->GetActiveWebState());
-}
-
-void InfobarBadgeBrowserAgent::OnInfobarBannerPresented(
-    OverlayRequest* request) {
-  InfobarBadgeTabHelper* tab_helper = GetBadgeCurrentTabHelper();
-  if (tab_helper)
-    tab_helper->UpdateBadgeForInfobarBannerPresented(GetInfobarType(request));
-}
-
-void InfobarBadgeBrowserAgent::OnInfobarBannerDismissed(
-    OverlayRequest* request) {
-  InfobarBadgeTabHelper* tab_helper = GetBadgeCurrentTabHelper();
-  if (tab_helper)
-    tab_helper->UpdateBadgeForInfobarBannerDismissed(GetInfobarType(request));
-}
-
-#pragma mark - InfobarBadgeBrowserAgent::InfobarOverlayObserver
-
-InfobarBadgeBrowserAgent::InfobarOverlayObserver::InfobarOverlayObserver(
-    InfobarBadgeBrowserAgent* browser_agent,
-    Browser* browser)
-    : scoped_observer_(this), browser_agent_(browser_agent) {
-  DCHECK(browser_agent_);
-  scoped_observer_.Add(
-      OverlayPresenter::FromBrowser(browser, OverlayModality::kInfobarBanner));
-  scoped_observer_.Add(
-      OverlayPresenter::FromBrowser(browser, OverlayModality::kInfobarModal));
-}
-
-InfobarBadgeBrowserAgent::InfobarOverlayObserver::~InfobarOverlayObserver() =
-    default;
-
-void InfobarBadgeBrowserAgent::InfobarOverlayObserver::DidShowOverlay(
-    OverlayPresenter* presenter,
-    OverlayRequest* request) {
-  browser_agent_->OnInfobarBannerPresented(request);
-}
-
-void InfobarBadgeBrowserAgent::InfobarOverlayObserver::DidHideOverlay(
-    OverlayPresenter* presenter,
-    OverlayRequest* request) {
-  browser_agent_->OnInfobarBannerDismissed(request);
-}
-
-void InfobarBadgeBrowserAgent::InfobarOverlayObserver::
-    OverlayPresenterDestroyed(OverlayPresenter* presenter) {
-  scoped_observer_.Remove(presenter);
-}
diff --git a/ios/chrome/browser/infobars/infobar_badge_browser_agent_unittest.mm b/ios/chrome/browser/infobars/infobar_badge_browser_agent_unittest.mm
deleted file mode 100644
index 34bdc09..0000000
--- a/ios/chrome/browser/infobars/infobar_badge_browser_agent_unittest.mm
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2019 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.
-
-#import "ios/chrome/browser/infobars/infobar_badge_browser_agent.h"
-
-#import <Foundation/Foundation.h>
-#include <map>
-
-#include "base/test/scoped_feature_list.h"
-#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h"
-#include "ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h"
-#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
-#import "ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.h"
-#import "ios/chrome/browser/infobars/test/fake_infobar_badge_tab_helper_delegate.h"
-#import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
-#import "ios/chrome/browser/main/test_browser.h"
-#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
-#include "ios/chrome/browser/overlays/public/overlay_request.h"
-#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
-#include "ios/chrome/browser/overlays/public/overlay_response.h"
-#include "ios/chrome/browser/overlays/test/fake_overlay_presentation_context.h"
-#import "ios/chrome/browser/ui/badges/badge_item.h"
-#import "ios/chrome/browser/ui/badges/badge_type.h"
-#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
-#import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h"
-#import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
-#import "ios/chrome/browser/web_state_list/web_state_list.h"
-#import "ios/chrome/browser/web_state_list/web_state_opener.h"
-#import "ios/web/public/test/fakes/test_navigation_manager.h"
-#import "ios/web/public/test/fakes/test_web_state.h"
-#include "ios/web/public/test/web_task_environment.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-using infobars::InfoBar;
-
-namespace {
-// The InfobarType to use for the test.
-const InfobarType kInfobarType = InfobarType::kInfobarTypePasswordSave;
-// The corresponding BadgeType for kInfobarType.
-const BadgeType kBadgeType = BadgeType::kBadgeTypePasswordSave;
-}  // namespace
-
-// Test fixture for InfobarBadgeBrowserAgent.
-class InfobarBadgeBrowserAgentTest : public PlatformTest {
- public:
-  InfobarBadgeBrowserAgentTest()
-      : web_state_list_(&web_state_list_delegate_),
-        tab_helper_delegate_([[FakeInfobarTabHelperDelegate alloc] init]) {
-    // Enable the UI reboot feature.
-    feature_list_.InitAndEnableFeature(kInfobarUIReboot);
-    // Create the Browser and set up the browser agent.
-    TestChromeBrowserState::Builder builder;
-    browser_state_ = builder.Build();
-    browser_ =
-        std::make_unique<TestBrowser>(browser_state_.get(), &web_state_list_);
-    InfobarBadgeBrowserAgent::CreateForBrowser(browser_.get());
-    // Create a WebState and add it to the Browser.
-    std::unique_ptr<web::TestWebState> passed_web_state =
-        std::make_unique<web::TestWebState>();
-    passed_web_state->SetNavigationManager(
-        std::make_unique<web::TestNavigationManager>());
-    web_state_ = passed_web_state.get();
-    web_state_list_.InsertWebState(0, std::move(passed_web_state),
-                                   WebStateList::INSERT_ACTIVATE,
-                                   WebStateOpener());
-    // Set up the WebState's InfoBarManager and InfobarBadgeTabHelper.
-    InfoBarManagerImpl::CreateForWebState(web_state_);
-    InfobarBadgeTabHelper::CreateForWebState(web_state_);
-    InfobarBadgeTabHelper::FromWebState(web_state_)
-        ->SetDelegate(tab_helper_delegate_);
-    // Set up the OverlayPresenter for OverlayModality::kInfobarBanner.
-    presenter()->SetPresentationContext(&presentation_context_);
-  }
-
-  ~InfobarBadgeBrowserAgentTest() override {
-    presenter()->SetPresentationContext(nullptr);
-  }
-
-  // Adds an InfoBar with |type| to the manager and returns the added infobar.
-  InfoBar* AddInfobar() {
-    std::unique_ptr<FakeInfobarIOS> passed_infobar =
-        std::make_unique<FakeInfobarIOS>();
-    InfoBar* infobar = passed_infobar.get();
-    passed_infobar->fake_ui_delegate().infobarType = kInfobarType;
-    passed_infobar->fake_ui_delegate().hasBadge = YES;
-    InfoBarManagerImpl::FromWebState(web_state_)
-        ->AddInfoBar(std::move(passed_infobar));
-    return infobar;
-  }
-
-  // Adds a fake banner OverlayRequest for |infobar|, adds it to queue(), and
-  // returns the added request.
-  OverlayRequest* AddOverlayRequest(InfoBar* infobar) {
-    FakeInfobarOverlayRequestFactory factory;
-    std::unique_ptr<OverlayRequest> passed_request =
-        factory.CreateInfobarRequest(infobar, InfobarOverlayType::kBanner);
-    OverlayRequest* request = passed_request.get();
-    queue()->AddRequest(std::move(passed_request));
-    return request;
-  }
-
-  OverlayPresenter* presenter() const {
-    return OverlayPresenter::FromBrowser(browser_.get(),
-                                         OverlayModality::kInfobarBanner);
-  }
-  OverlayRequestQueue* queue() const {
-    return OverlayRequestQueue::FromWebState(web_state_,
-                                             OverlayModality::kInfobarBanner);
-  }
-
- protected:
-  base::test::ScopedFeatureList feature_list_;
-  web::WebTaskEnvironment task_environment_;
-  std::unique_ptr<ios::ChromeBrowserState> browser_state_;
-  FakeWebStateListDelegate web_state_list_delegate_;
-  WebStateList web_state_list_;
-  web::WebState* web_state_ = nullptr;
-  std::unique_ptr<Browser> browser_;
-  FakeOverlayPresentationContext presentation_context_;
-  FakeInfobarTabHelperDelegate* tab_helper_delegate_ = nil;
-};
-
-// Tests that the browser agent correctly updates the badge state to presented.
-TEST_F(InfobarBadgeBrowserAgentTest, InfobarPresented) {
-  // Simulate the presentation of an infobar banner overlay and verify that the
-  // badge state gets updated to presented.
-  InfoBar* infobar = AddInfobar();
-  OverlayRequest* request = AddOverlayRequest(infobar);
-  id<BadgeItem> badge = [tab_helper_delegate_ itemForBadgeType:kBadgeType];
-  ASSERT_TRUE(badge);
-  ASSERT_EQ(FakeOverlayPresentationContext::PresentationState::kPresented,
-            presentation_context_.GetPresentationState(request));
-  EXPECT_TRUE(badge.badgeState & BadgeStatePresented);
-}
-
-// Tests that the browser agent correctly updates the badge state to dismissed.
-TEST_F(InfobarBadgeBrowserAgentTest, InfobarDismissed) {
-  InfoBar* infobar = AddInfobar();
-  OverlayRequest* request = AddOverlayRequest(infobar);
-  id<BadgeItem> badge = [tab_helper_delegate_ itemForBadgeType:kBadgeType];
-  ASSERT_TRUE(badge);
-  ASSERT_EQ(FakeOverlayPresentationContext::PresentationState::kPresented,
-            presentation_context_.GetPresentationState(request));
-  ASSERT_TRUE(badge.badgeState & BadgeStatePresented);
-
-  // Simulate the dismissal of the infobar banner overlay and verify that the
-  // badge state gets updated to dismissed.
-  presentation_context_.SimulateDismissalForRequest(
-      request, OverlayDismissalReason::kUserInteraction);
-  EXPECT_FALSE(badge.badgeState & BadgeStatePresented);
-}
-
-// TODO(crbug.com/1030357): Add tests for non-banners.
diff --git a/ios/chrome/browser/infobars/overlays/BUILD.gn b/ios/chrome/browser/infobars/overlays/BUILD.gn
index 7ae5cce..042427d 100644
--- a/ios/chrome/browser/infobars/overlays/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/BUILD.gn
@@ -30,6 +30,19 @@
   ]
 }
 
+source_set("browser_agent_util") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "infobar_overlay_browser_agent_util.cc",
+    "infobar_overlay_browser_agent_util.h",
+  ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser/main:public",
+    "//ios/chrome/browser/ui/infobars:feature_flags",
+  ]
+}
+
 source_set("test_support") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
diff --git a/ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.cc b/ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.cc
new file mode 100644
index 0000000..c82ab34
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.cc
@@ -0,0 +1,14 @@
+// Copyright 2019 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 "ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.h"
+
+#include "base/feature_list.h"
+#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
+
+void AttachInfobarOverlayBrowserAgents(Browser* browser) {
+  if (!base::FeatureList::IsEnabled(kInfobarOverlayUI))
+    return;
+  // TODO(crbug.com/1030357): Create browser agents.
+}
diff --git a/ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.h b/ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.h
new file mode 100644
index 0000000..60b440ac
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.h
@@ -0,0 +1,14 @@
+// Copyright 2019 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 IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_INFOBAR_OVERLAY_BROWSER_AGENT_UTIL_H_
+#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_INFOBAR_OVERLAY_BROWSER_AGENT_UTIL_H_
+
+class Browser;
+
+// Attaches browser agents to |browser| that manage the model changes for
+// infobar UI presented via OverlayPresenter.
+void AttachInfobarOverlayBrowserAgents(Browser* browser);
+
+#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_INFOBAR_OVERLAY_BROWSER_AGENT_UTIL_H_
diff --git a/ios/chrome/browser/main/BUILD.gn b/ios/chrome/browser/main/BUILD.gn
index e99d615..e58c0ea 100644
--- a/ios/chrome/browser/main/BUILD.gn
+++ b/ios/chrome/browser/main/BUILD.gn
@@ -33,7 +33,7 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/crash_report/breadcrumbs",
     "//ios/chrome/browser/crash_report/breadcrumbs:feature_flags",
-    "//ios/chrome/browser/infobars:badge",
+    "//ios/chrome/browser/infobars/overlays:browser_agent_util",
     "//ios/chrome/browser/sessions:serialisation",
     "//ios/chrome/browser/sessions:session_service",
     "//ios/chrome/browser/tabs",
diff --git a/ios/chrome/browser/main/browser_agent_util.mm b/ios/chrome/browser/main/browser_agent_util.mm
index 4eec336f..dc145ebd 100644
--- a/ios/chrome/browser/main/browser_agent_util.mm
+++ b/ios/chrome/browser/main/browser_agent_util.mm
@@ -7,8 +7,7 @@
 #include "base/feature_list.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_browser_agent.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/features.h"
-#import "ios/chrome/browser/infobars/infobar_badge_browser_agent.h"
-#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
+#include "ios/chrome/browser/infobars/overlays/infobar_overlay_browser_agent_util.h"
 #import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 
@@ -21,10 +20,8 @@
     BreadcrumbManagerBrowserAgent::CreateForBrowser(browser);
   }
   TabInsertionBrowserAgent::CreateForBrowser(browser);
+  AttachInfobarOverlayBrowserAgents(browser);
 
-  if (base::FeatureList::IsEnabled(kInfobarOverlayUI)) {
-    InfobarBadgeBrowserAgent::CreateForBrowser(browser);
-  }
   // This needs to be called last in case any downstream browser agents need to
   // access upstream agents created earlier in this function.
   ios::GetChromeBrowserProvider()->AttachBrowserAgents(browser);
diff --git a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h
index be03640..e69e8fc 100644
--- a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h
+++ b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h
@@ -60,12 +60,12 @@
 
   // ConfirmInfoBarDelegate implementation.
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+  base::string16 GetLinkText() const override;
+  void InfoBarDismissed() override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
-  void InfoBarDismissed() override;
-  base::string16 GetLinkText() const override;
 
   // The credential that should be displayed in the infobar, and for which the
   // password will be updated.
diff --git a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm
index 35964c23..1524e98 100644
--- a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm
@@ -86,6 +86,15 @@
   return UPDATE_PASSWORD_INFOBAR_DELEGATE_MOBILE;
 }
 
+base::string16 IOSChromeUpdatePasswordInfoBarDelegate::GetLinkText() const {
+  return ShowMultipleAccounts() ? selected_account_ : base::string16();
+}
+
+void IOSChromeUpdatePasswordInfoBarDelegate::InfoBarDismissed() {
+  DCHECK(form_to_save());
+  set_infobar_response(password_manager::metrics_util::CLICKED_CANCEL);
+}
+
 base::string16 IOSChromeUpdatePasswordInfoBarDelegate::GetMessageText() const {
   return selected_account_.length() > 0
              ? l10n_util::GetStringFUTF16(
@@ -114,12 +123,3 @@
   set_infobar_response(password_manager::metrics_util::CLICKED_SAVE);
   return true;
 }
-
-void IOSChromeUpdatePasswordInfoBarDelegate::InfoBarDismissed() {
-  DCHECK(form_to_save());
-  set_infobar_response(password_manager::metrics_util::CLICKED_CANCEL);
-}
-
-base::string16 IOSChromeUpdatePasswordInfoBarDelegate::GetLinkText() const {
-  return ShowMultipleAccounts() ? selected_account_ : base::string16();
-}
diff --git a/ios/chrome/browser/ui/badges/BUILD.gn b/ios/chrome/browser/ui/badges/BUILD.gn
index 32d37628..1c0ff82 100644
--- a/ios/chrome/browser/ui/badges/BUILD.gn
+++ b/ios/chrome/browser/ui/badges/BUILD.gn
@@ -49,8 +49,10 @@
     "resources:wrench_badge",
     "//base:base",
     "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/infobars:badge",
     "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/elements",
@@ -112,6 +114,7 @@
     "//ios/chrome/browser/infobars:badge",
     "//ios/chrome/browser/infobars:badge_public",
     "//ios/chrome/browser/infobars/test",
+    "//ios/chrome/browser/main:test_support",
     "//ios/chrome/browser/ui/infobars:feature_flags",
     "//ios/chrome/browser/ui/infobars:test_support",
     "//ios/chrome/browser/web_state_list",
diff --git a/ios/chrome/browser/ui/badges/badge_mediator.h b/ios/chrome/browser/ui/badges/badge_mediator.h
index 81e8e67..26b3db45b 100644
--- a/ios/chrome/browser/ui/badges/badge_mediator.h
+++ b/ios/chrome/browser/ui/badges/badge_mediator.h
@@ -11,16 +11,14 @@
 
 @protocol BadgeConsumer;
 @protocol BadgeItem;
+class Browser;
 @protocol BrowserCoordinatorCommands;
 @protocol InfobarCommands;
-class WebStateList;
 
 // A mediator object that updates the consumer when the state of badges changes.
 @interface BadgeMediator : NSObject <BadgeDelegate>
 
-- (instancetype)initWithConsumer:(id<BadgeConsumer>)consumer
-                    webStateList:(WebStateList*)webStateList
-    NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithBrowser:(Browser*)browser NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 
 // Stops observing all objects.
@@ -30,6 +28,10 @@
 @property(nonatomic, weak) id<InfobarCommands, BrowserCoordinatorCommands>
     dispatcher;
 
+// The consumer being set up by this mediator.  Setting to a new value updates
+// the new consumer.
+@property(nonatomic, weak) id<BadgeConsumer> consumer;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_BADGES_BADGE_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/badges/badge_mediator.mm b/ios/chrome/browser/ui/badges/badge_mediator.mm
index ec3475c..8573d06 100644
--- a/ios/chrome/browser/ui/badges/badge_mediator.mm
+++ b/ios/chrome/browser/ui/badges/badge_mediator.mm
@@ -6,10 +6,12 @@
 
 #include "base/mac/foundation_util.h"
 #include "base/metrics/user_metrics.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h"
 #include "ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h"
 #include "ios/chrome/browser/infobars/infobar_metrics_recorder.h"
 #import "ios/chrome/browser/infobars/infobar_type.h"
+#include "ios/chrome/browser/main/browser.h"
 #import "ios/chrome/browser/ui/badges/badge_button.h"
 #import "ios/chrome/browser/ui/badges/badge_consumer.h"
 #import "ios/chrome/browser/ui/badges/badge_item.h"
@@ -20,7 +22,6 @@
 #import "ios/chrome/browser/ui/list_model/list_model.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
-#include "ios/web/public/browser_state.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -32,38 +33,45 @@
 // The minimum number of non-Fullscreen badges to display the overflow popup
 // menu.
 const int kMinimumNonFullScreenBadgesForOverflow = 2;
-}
+}  // namespace
 
 @interface BadgeMediator () <InfobarBadgeTabHelperDelegate,
                              WebStateListObserving> {
-  std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
+  std::unique_ptr<WebStateListObserver> _webStateListObserver;
 }
 
 // The WebStateList that this mediator listens for any changes on the active web
 // state.
-@property(nonatomic, assign) WebStateList* webStateList;
+@property(nonatomic, readonly) WebStateList* webStateList;
+
+// The WebStateList's active WebState.
+@property(nonatomic, assign) web::WebState* webState;
+
+// The active WebState's badge tab helper.
+@property(nonatomic, readonly) InfobarBadgeTabHelper* badgeTabHelper;
+
+// The incognito badge, or nil if the Browser is not off-the-record.
+@property(nonatomic, readonly) id<BadgeItem> offTheRecordBadge;
 
 // Array of all available badges.
 @property(nonatomic, strong) NSMutableArray<id<BadgeItem>>* badges;
 
-// The consumer of the mediator.
-@property(nonatomic, weak) id<BadgeConsumer> consumer;
-
 @end
 
 @implementation BadgeMediator
-@synthesize webStateList = _webStateList;
 
-- (instancetype)initWithConsumer:(id<BadgeConsumer>)consumer
-                    webStateList:(WebStateList*)webStateList {
+- (instancetype)initWithBrowser:(Browser*)browser {
   self = [super init];
   if (self) {
-    _consumer = consumer;
-    _webStateList = webStateList;
-    web::WebState* activeWebState = webStateList->GetActiveWebState();
-    if (activeWebState) {
-      [self updateNewWebState:activeWebState withWebStateList:webStateList];
+    DCHECK(browser);
+    // Create the incognito badge if |browser| is off-the-record.
+    if (browser->GetBrowserState()->IsOffTheRecord()) {
+      _offTheRecordBadge = [[BadgeStaticItem alloc]
+          initWithBadgeType:BadgeType::kBadgeTypeIncognito];
     }
+    // Set up the WebStateList and its observer.
+    _webStateList = browser->GetWebStateList();
+    _webState = _webStateList->GetActiveWebState();
     _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
     _webStateList->AddObserver(_webStateListObserver.get());
   }
@@ -71,45 +79,82 @@
 }
 
 - (void)dealloc {
-  [self disconnect];
+  // |-disconnect| must be called before deallocation.
+  DCHECK(!_webStateList);
 }
 
 - (void)disconnect {
   if (_webStateList) {
+    self.webState = nullptr;
     _webStateList->RemoveObserver(_webStateListObserver.get());
-    _webStateListObserver.reset();
+    _webStateListObserver = nullptr;
     _webStateList = nullptr;
   }
 }
 
-#pragma mark - InfobarBadgeTabHelperDelegate
+#pragma mark - Accessors
 
-- (void)addInfobarBadge:(id<BadgeItem>)badgeItem {
-  if (!self.badges) {
-    self.badges = [NSMutableArray array];
-  }
-  [self.badges addObject:badgeItem];
-  [self updateBadgesShown];
+- (void)setConsumer:(id<BadgeConsumer>)consumer {
+  if (_consumer == consumer)
+    return;
+  _consumer = consumer;
+  [self updateConsumer];
 }
 
-- (void)removeInfobarBadge:(id<BadgeItem>)badgeItem {
-  for (id<BadgeItem> item in self.badges) {
-    if (item.badgeType == badgeItem.badgeType) {
-      [self.badges removeObject:item];
-      [self updateBadgesShown];
-      return;
-    }
+- (void)setWebState:(web::WebState*)webState {
+  if (_webState == webState)
+    return;
+  if (_webState)
+    InfobarBadgeTabHelper::FromWebState(_webState)->SetDelegate(nil);
+  _webState = webState;
+  if (_webState)
+    InfobarBadgeTabHelper::FromWebState(_webState)->SetDelegate(self);
+  [self updateBadgesForActiveWebState];
+  [self updateConsumer];
+}
+
+- (InfobarBadgeTabHelper*)badgeTabHelper {
+  return self.webState ? InfobarBadgeTabHelper::FromWebState(self.webState)
+                       : nullptr;
+}
+
+#pragma mark - Accessor helpers
+
+- (void)updateBadgesForActiveWebState {
+  if (self.webState) {
+    self.badges = [self.badgeTabHelper->GetInfobarBadgeItems() mutableCopy];
+    if (self.offTheRecordBadge)
+      [self.badges addObject:self.offTheRecordBadge];
+  } else {
+    self.badges = [NSMutableArray<id<BadgeItem>> array];
   }
 }
 
-- (void)updateInfobarBadge:(id<BadgeItem>)badgeItem {
-  for (id<BadgeItem> item in self.badges) {
-    if (item.badgeType == badgeItem.badgeType) {
-      item.badgeState = badgeItem.badgeState;
-      [self updateBadgesShown];
-      return;
-    }
+// Updates the consumer for the current active WebState.
+- (void)updateConsumer {
+  if (!self.consumer)
+    return;
+
+  // Update the badges array if necessary.
+  if (!self.badges)
+    [self updateBadgesForActiveWebState];
+
+  // Show the overflow badge if there are multiple BadgeItems.  Otherwise, use
+  // the last badge.
+  NSUInteger fullscreenBadgeCount = self.offTheRecordBadge ? 1U : 0U;
+  BOOL shouldDisplayOverflowBadge =
+      self.badges.count - fullscreenBadgeCount > 1;
+  id<BadgeItem> displayedBadge = nil;
+  if (shouldDisplayOverflowBadge) {
+    displayedBadge = [[BadgeTappableItem alloc]
+        initWithBadgeType:BadgeType::kBadgeTypeOverflow];
+  } else {
+    id<BadgeItem> firstBadge = [self.badges firstObject];
+    displayedBadge = firstBadge.fullScreen ? nil : firstBadge;
   }
+  // Update the consumer with the new badge items.
+  [self.consumer setupWithDisplayedBadge:displayedBadge
+                         fullScreenBadge:self.offTheRecordBadge];
 }
 
 #pragma mark - BadgeDelegate
@@ -166,15 +211,42 @@
   // TODO(crbug.com/976901): Add metric for this action.
 }
 
+#pragma mark - InfobarBadgeTabHelperDelegate
+
+- (void)addInfobarBadge:(id<BadgeItem>)badgeItem {
+  [self.badges addObject:badgeItem];
+  [self updateBadgesShown];
+}
+
+- (void)removeInfobarBadge:(id<BadgeItem>)badgeItem {
+  for (id<BadgeItem> item in self.badges) {
+    if (item.badgeType == badgeItem.badgeType) {
+      [self.badges removeObject:item];
+      [self updateBadgesShown];
+      return;
+    }
+  }
+}
+
+- (void)updateInfobarBadge:(id<BadgeItem>)badgeItem {
+  for (id<BadgeItem> item in self.badges) {
+    if (item.badgeType == badgeItem.badgeType) {
+      item.badgeState = badgeItem.badgeState;
+      [self updateBadgesShown];
+      return;
+    }
+  }
+}
+
 #pragma mark - WebStateListObserver
 
 - (void)webStateList:(WebStateList*)webStateList
     didReplaceWebState:(web::WebState*)oldWebState
           withWebState:(web::WebState*)newWebState
                atIndex:(int)atIndex {
-  if (newWebState && newWebState == webStateList->GetActiveWebState()) {
-    [self updateNewWebState:newWebState withWebStateList:webStateList];
-  }
+  DCHECK_EQ(self.webStateList, webStateList);
+  if (atIndex == webStateList->active_index())
+    self.webState = newWebState;
 }
 
 - (void)webStateList:(WebStateList*)webStateList
@@ -182,11 +254,8 @@
                 oldWebState:(web::WebState*)oldWebState
                     atIndex:(int)atIndex
                      reason:(int)reason {
-  // Only attempt to retrieve badges if there is a new current web state, since
-  // |newWebState| can be null.
-  if (newWebState) {
-    [self updateNewWebState:newWebState withWebStateList:webStateList];
-  }
+  DCHECK_EQ(self.webStateList, webStateList);
+  self.webState = newWebState;
 }
 
 #pragma mark - Helpers
@@ -279,37 +348,4 @@
   [self updateConsumerReadStatus];
 }
 
-- (void)updateNewWebState:(web::WebState*)newWebState
-         withWebStateList:(WebStateList*)webStateList {
-  DCHECK_EQ(_webStateList, webStateList);
-  InfobarBadgeTabHelper* infobarBadgeTabHelper =
-      InfobarBadgeTabHelper::FromWebState(newWebState);
-  DCHECK(infobarBadgeTabHelper);
-  infobarBadgeTabHelper->SetDelegate(self);
-  // Whenever the WebState changes ask the corresponding
-  // InfobarBadgeTabHelper for all the badges for that WebState.
-  self.badges = [infobarBadgeTabHelper->GetInfobarBadgeItems() mutableCopy];
-
-  id<BadgeItem> displayedBadge;
-  if ([self.badges count] > 1) {
-    // Show the overflow menu badge when there are multiple badges.
-    displayedBadge = [[BadgeTappableItem alloc]
-        initWithBadgeType:BadgeType::kBadgeTypeOverflow];
-  } else if ([self.badges count] == 1) {
-    displayedBadge = [self.badges lastObject];
-  }
-  id<BadgeItem> fullScreenBadge;
-  if (newWebState->GetBrowserState()->IsOffTheRecord()) {
-    BadgeStaticItem* incognitoItem = [[BadgeStaticItem alloc]
-        initWithBadgeType:BadgeType::kBadgeTypeIncognito];
-    fullScreenBadge = incognitoItem;
-    // Keep track of presence of an incognito badge so that the mediator knows
-    // whether or not there is a fullscreen badge when calling
-    // updateDisplayedBadge:fullScreenBadge:.
-    [self.badges addObject:incognitoItem];
-  }
-  [self.consumer setupWithDisplayedBadge:displayedBadge
-                         fullScreenBadge:fullScreenBadge];
-}
-
 @end
diff --git a/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm b/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm
index 114b88c3..399b231d 100644
--- a/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm
@@ -13,6 +13,7 @@
 #include "ios/chrome/browser/infobars/infobar_ios.h"
 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
 #import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
+#import "ios/chrome/browser/main/test_browser.h"
 #import "ios/chrome/browser/ui/badges/badge_consumer.h"
 #import "ios/chrome/browser/ui/badges/badge_item.h"
 #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
@@ -24,7 +25,6 @@
 #import "ios/web/public/test/fakes/test_web_state.h"
 #import "ios/web/public/web_state_user_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -34,24 +34,29 @@
 // The two infobar types used in tests.  Both support badges.
 InfobarType kFirstInfobarType = InfobarType::kInfobarTypePasswordSave;
 InfobarType kSecondInfobarType = InfobarType::kInfobarTypePasswordUpdate;
+// Parameters used for BadgeMediator test fixtures.
+enum class TestParam {
+  kNormal,
+  kOffTheRecord,
+};
 }  // namespace
 
 // Fake of BadgeConsumer.
 @interface FakeBadgeConsumer : NSObject <BadgeConsumer>
 @property(nonatomic, strong) id<BadgeItem> displayedBadge;
-@property(nonatomic, assign) BOOL hasIncognitoBadge;
+@property(nonatomic, assign) BOOL hasFullscreenBadge;
 @property(nonatomic, assign) BOOL hasUnreadBadge;
 @end
 
 @implementation FakeBadgeConsumer
 - (void)setupWithDisplayedBadge:(id<BadgeItem>)displayedBadgeItem
                 fullScreenBadge:(id<BadgeItem>)fullscreenBadgeItem {
-  self.hasIncognitoBadge = fullscreenBadgeItem != nil;
+  self.hasFullscreenBadge = fullscreenBadgeItem != nil;
   self.displayedBadge = displayedBadgeItem;
 }
 - (void)updateDisplayedBadge:(id<BadgeItem>)displayedBadgeItem
              fullScreenBadge:(id<BadgeItem>)fullscreenBadgeItem {
-  self.hasIncognitoBadge = fullscreenBadgeItem != nil;
+  self.hasFullscreenBadge = fullscreenBadgeItem != nil;
   self.displayedBadge = displayedBadgeItem;
 }
 - (void)markDisplayedBadgeAsRead:(BOOL)read {
@@ -59,39 +64,31 @@
 }
 @end
 
-class BadgeMediatorTest : public PlatformTest {
+class BadgeMediatorTest : public testing::TestWithParam<TestParam> {
  protected:
   BadgeMediatorTest()
-      : browser_state_(TestChromeBrowserState::Builder().Build()),
-        web_state_list_(
-            std::make_unique<WebStateList>(&web_state_list_delegate_)) {
+      : badge_consumer_([[FakeBadgeConsumer alloc] init]),
+        browser_state_(TestChromeBrowserState::Builder().Build()),
+        web_state_list_(&web_state_list_delegate_) {
     feature_list_.InitAndEnableFeature(kInfobarUIReboot);
-    badge_consumer_ = [[FakeBadgeConsumer alloc] init];
-    badge_mediator_ =
-        [[BadgeMediator alloc] initWithConsumer:badge_consumer_
-                                   webStateList:web_state_list_.get()];
+    badge_mediator_ = [[BadgeMediator alloc] initWithBrowser:browser()];
+    badge_mediator_.consumer = badge_consumer_;
   }
 
   ~BadgeMediatorTest() override { [badge_mediator_ disconnect]; }
 
-  // Adds a new WebState to the WebStateList and activates it.
-  void AddAndActivateWebState(int index, bool incognito) {
+  // Inserts a new WebState to the WebStateList at |index| and activates it.
+  void InsertActivatedWebState(int index) {
     std::unique_ptr<web::TestWebState> web_state =
         std::make_unique<web::TestWebState>();
     web_state->SetNavigationManager(
         std::make_unique<web::TestNavigationManager>());
+    web_state->SetBrowserState(browser_state());
     InfoBarManagerImpl::CreateForWebState(web_state.get());
     InfobarBadgeTabHelper::CreateForWebState(web_state.get());
-    if (incognito) {
-      web_state->SetBrowserState(
-          browser_state_->GetOffTheRecordChromeBrowserState());
-    } else {
-      web_state->SetBrowserState(browser_state_.get());
-    }
-    web_state_list_->InsertWebState(index, std::move(web_state),
-                                    WebStateList::INSERT_NO_FLAGS,
-                                    WebStateOpener());
-    web_state_list_->ActivateWebStateAt(index);
+    web_state_list_.InsertWebState(index, std::move(web_state),
+                                   WebStateList::INSERT_ACTIVATE,
+                                   WebStateOpener());
   }
 
   // Adds an Infobar of |type| to the InfoBarManager and returns the infobar.
@@ -108,8 +105,26 @@
     infobar_manager()->RemoveInfoBar(infobar);
   }
 
+  // Returns whether the test fixture is for an incognito BrowserState.
+  bool is_off_the_record() const {
+    return GetParam() == TestParam::kOffTheRecord;
+  }
+  // Returns the BrowserState to use for the test fixture.
+  ios::ChromeBrowserState* browser_state() {
+    return is_off_the_record()
+               ? browser_state_->GetOffTheRecordChromeBrowserState()
+               : browser_state_.get();
+  }
+  // Returns the Browser to use for the test fixture.
+  Browser* browser() {
+    if (!browser_) {
+      browser_ =
+          std::make_unique<TestBrowser>(browser_state(), &web_state_list_);
+    }
+    return browser_.get();
+  }
   // Returns the active WebState.
-  web::WebState* web_state() { return web_state_list_->GetActiveWebState(); }
+  web::WebState* web_state() { return web_state_list_.GetActiveWebState(); }
   // Returns the active WebState's InfoBarManagerImpl.
   InfoBarManagerImpl* infobar_manager() {
     return InfoBarManagerImpl::FromWebState(web_state());
@@ -123,23 +138,24 @@
   base::test::TaskEnvironment environment_;
   FakeBadgeConsumer* badge_consumer_;
   std::unique_ptr<ios::ChromeBrowserState> browser_state_;
-  BadgeMediator* badge_mediator_;
-  std::unique_ptr<WebStateList> web_state_list_;
   FakeWebStateListDelegate web_state_list_delegate_;
+  WebStateList web_state_list_;
+  std::unique_ptr<Browser> browser_;
+  BadgeMediator* badge_mediator_ = nil;
 };
 
 // Test that the BadgeMediator responds with no displayed and fullscreen badge
 // when there are no Infobars added and the BrowserState is not OffTheRecord.
-TEST_F(BadgeMediatorTest, BadgeMediatorTestNoInfobar) {
-  AddAndActivateWebState(0, false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestNoInfobar) {
+  InsertActivatedWebState(/*index=*/0);
   EXPECT_FALSE(badge_consumer_.displayedBadge);
-  EXPECT_FALSE(badge_consumer_.hasIncognitoBadge);
+  EXPECT_EQ(is_off_the_record(), badge_consumer_.hasFullscreenBadge);
 }
 
 // Test that the BadgeMediator responds with one new badge when an infobar is
 // added
-TEST_F(BadgeMediatorTest, BadgeMediatorTestAddInfobar) {
-  AddAndActivateWebState(0, false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestAddInfobar) {
+  InsertActivatedWebState(/*index=*/0);
   AddInfobar(kFirstInfobarType);
   ASSERT_TRUE(badge_consumer_.displayedBadge);
   EXPECT_EQ(badge_consumer_.displayedBadge.badgeType,
@@ -148,8 +164,8 @@
 
 // Test that the BadgeMediator handled the removal of the correct badge when two
 // infobars are added and then one is removed.
-TEST_F(BadgeMediatorTest, BadgeMediatorTestRemoveInfobar) {
-  AddAndActivateWebState(0, false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestRemoveInfobar) {
+  InsertActivatedWebState(/*index=*/0);
   AddInfobar(kFirstInfobarType);
   InfoBarIOS* second_infobar = AddInfobar(kSecondInfobarType);
   EXPECT_EQ(badge_consumer_.displayedBadge.badgeType,
@@ -160,8 +176,8 @@
             BadgeType::kBadgeTypePasswordSave);
 }
 
-TEST_F(BadgeMediatorTest, BadgeMediatorTestMarkAsRead) {
-  AddAndActivateWebState(/*index=*/0, /*incognito=*/false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestMarkAsRead) {
+  InsertActivatedWebState(/*index=*/0);
   AddInfobar(kFirstInfobarType);
   // Since there is only one badge, it should be marked as read.
   EXPECT_FALSE(badge_consumer_.hasUnreadBadge);
@@ -178,19 +194,19 @@
 
 // Test that the BadgeMediator updates the current badges to none when switching
 // to a second WebState after an infobar is added to the first WebState.
-TEST_F(BadgeMediatorTest, BadgeMediatorTestSwitchWebState) {
-  AddAndActivateWebState(0, false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestSwitchWebState) {
+  InsertActivatedWebState(/*index=*/0);
   AddInfobar(kFirstInfobarType);
   ASSERT_TRUE(badge_consumer_.displayedBadge);
   EXPECT_EQ(badge_consumer_.displayedBadge.badgeType,
             BadgeType::kBadgeTypePasswordSave);
-  AddAndActivateWebState(1, false);
+  InsertActivatedWebState(/*index=*/1);
   EXPECT_FALSE(badge_consumer_.displayedBadge);
 }
 
 // Test that the BadgeMediator updates the badge when it is accepted.
-TEST_F(BadgeMediatorTest, BadgeMediatorTestAcceptedBadge) {
-  AddAndActivateWebState(0, false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestAcceptedBadge) {
+  InsertActivatedWebState(/*index=*/0);
   AddInfobar(kFirstInfobarType);
   ASSERT_TRUE(badge_consumer_.displayedBadge);
   EXPECT_FALSE(badge_consumer_.displayedBadge.badgeState &= BadgeStateAccepted);
@@ -199,29 +215,22 @@
   EXPECT_TRUE(badge_consumer_.displayedBadge.badgeState &= BadgeStateAccepted);
 }
 
-// Test that the BadgeMediator adds an incognito badge when the webstatelist
-// changes.
-TEST_F(BadgeMediatorTest, BadgeMediatorTestIncognito) {
-  AddAndActivateWebState(0, true);
-  EXPECT_TRUE(badge_consumer_.hasIncognitoBadge);
-}
-
 // Test that the BadgeMediator updates the current badges when the starting
 // active WebState already has a badge. This simulates an app launch after an
 // update when the WebStateList is preserved but the LocationBar (and therefore
 // the BadgeMediator) is restarted from scratch.
-TEST_F(BadgeMediatorTest, BadgeMediatorTestRestartWithInfobar) {
-  AddAndActivateWebState(0, false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestRestartWithInfobar) {
+  InsertActivatedWebState(/*index=*/0);
   AddInfobar(kFirstInfobarType);
 
   // Simulate reload of app, but preservation of WebStateList.
+  [badge_mediator_ disconnect];
   badge_mediator_ = nil;
   badge_consumer_ = nil;
 
   badge_consumer_ = [[FakeBadgeConsumer alloc] init];
-  badge_mediator_ =
-      [[BadgeMediator alloc] initWithConsumer:badge_consumer_
-                                 webStateList:web_state_list_.get()];
+  badge_mediator_ = [[BadgeMediator alloc] initWithBrowser:browser()];
+  badge_mediator_.consumer = badge_consumer_;
   ASSERT_TRUE(badge_consumer_.displayedBadge);
   EXPECT_EQ(badge_consumer_.displayedBadge.badgeType,
             BadgeType::kBadgeTypePasswordSave);
@@ -230,13 +239,18 @@
 // Test that the BadgeMediator clears its badges when the last WebState is
 // detached and a new WebState is added. This test also makes sure that closing
 // the last WebState doesn't break anything.
-TEST_F(BadgeMediatorTest, BadgeMediatorTestCloseLastTab) {
-  AddAndActivateWebState(0, false);
+TEST_P(BadgeMediatorTest, BadgeMediatorTestCloseLastTab) {
+  InsertActivatedWebState(/*index=*/0);
   AddInfobar(kFirstInfobarType);
   ASSERT_TRUE(badge_consumer_.displayedBadge);
   EXPECT_EQ(badge_consumer_.displayedBadge.badgeType,
             BadgeType::kBadgeTypePasswordSave);
-  web_state_list_->DetachWebStateAt(0);
-  AddAndActivateWebState(0, false);
+  web_state_list_.DetachWebStateAt(0);
+  InsertActivatedWebState(/*index=*/0);
   ASSERT_FALSE(badge_consumer_.displayedBadge);
 }
+
+INSTANTIATE_TEST_SUITE_P(/* No InstantiationName */,
+                         BadgeMediatorTest,
+                         testing::Values(TestParam::kNormal,
+                                         TestParam::kOffTheRecord));
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
index 6f2a2c84..74de6eb 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -183,9 +183,8 @@
   [self.viewController setBadgeView:self.badgeViewController.view];
   [self.badgeViewController didMoveToParentViewController:self.viewController];
   // Create BadgeMediator and set the viewController as its consumer.
-  self.badgeMediator =
-      [[BadgeMediator alloc] initWithConsumer:self.badgeViewController
-                                 webStateList:self.webStateList];
+  self.badgeMediator = [[BadgeMediator alloc] initWithBrowser:self.browser];
+  self.badgeMediator.consumer = self.badgeViewController;
   self.badgeMediator.dispatcher =
       static_cast<id<InfobarCommands, BrowserCoordinatorCommands>>(
           self.dispatcher);
@@ -218,6 +217,7 @@
   [self.omniboxPopupCoordinator stop];
   [self.omniboxCoordinator stop];
   [self.badgeMediator disconnect];
+  self.badgeMediator = nil;
   _editController.reset();
 
   self.viewController = nil;
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index af9cb759..8a0c600 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -1071,7 +1071,7 @@
     UnderlyingType value;
     if (!ReadParam(m, iter, &value))
       return false;
-    *r = param_type::StrongAlias(value);
+    *r = param_type(value);
     return true;
   }
   static void Log(const param_type& p, std::string* l) {
diff --git a/ipc/ipc_message_utils_unittest.cc b/ipc/ipc_message_utils_unittest.cc
index 8522d1b..92f31029 100644
--- a/ipc/ipc_message_utils_unittest.cc
+++ b/ipc/ipc_message_utils_unittest.cc
@@ -216,5 +216,19 @@
   EXPECT_EQ(input, output);
 }
 
+TEST(IPCMessageUtilsTest, StrongAlias) {
+  using TestType = util::StrongAlias<class Tag, int>;
+  TestType input(42);
+
+  base::Pickle pickle;
+  IPC::WriteParam(&pickle, input);
+
+  base::PickleIterator iter(pickle);
+  TestType output;
+  EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &output));
+
+  EXPECT_EQ(input, output);
+}
+
 }  // namespace
 }  // namespace IPC
diff --git a/media/base/android/media_crypto_context_impl.cc b/media/base/android/media_crypto_context_impl.cc
index 434c9425..4304fc2b 100644
--- a/media/base/android/media_crypto_context_impl.cc
+++ b/media/base/android/media_crypto_context_impl.cc
@@ -15,9 +15,11 @@
 
 MediaCryptoContextImpl::~MediaCryptoContextImpl() {}
 
-int MediaCryptoContextImpl::RegisterPlayer(const base::Closure& new_key_cb,
-                                           const base::Closure& cdm_unset_cb) {
-  return media_drm_bridge_->RegisterPlayer(new_key_cb, cdm_unset_cb);
+int MediaCryptoContextImpl::RegisterPlayer(
+    base::RepeatingClosure new_key_cb,
+    base::RepeatingClosure cdm_unset_cb) {
+  return media_drm_bridge_->RegisterPlayer(std::move(new_key_cb),
+                                           std::move(cdm_unset_cb));
 }
 
 void MediaCryptoContextImpl::UnregisterPlayer(int registration_id) {
diff --git a/media/base/android/media_crypto_context_impl.h b/media/base/android/media_crypto_context_impl.h
index 24a4ca1..3bc2d5f2 100644
--- a/media/base/android/media_crypto_context_impl.h
+++ b/media/base/android/media_crypto_context_impl.h
@@ -36,8 +36,8 @@
   //
   // Note: RegisterPlayer() must be called before SetMediaCryptoReadyCB() to
   // avoid missing any new key notifications.
-  int RegisterPlayer(const base::Closure& new_key_cb,
-                     const base::Closure& cdm_unset_cb) final;
+  int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                     base::RepeatingClosure cdm_unset_cb) final;
   void UnregisterPlayer(int registration_id) final;
 
   // MediaCryptoContext implementation.
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index d90fc4f7..2fd927cd 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -579,10 +579,11 @@
   return &media_crypto_context_;
 }
 
-int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb,
-                                   const base::Closure& cdm_unset_cb) {
+int MediaDrmBridge::RegisterPlayer(base::RepeatingClosure new_key_cb,
+                                   base::RepeatingClosure cdm_unset_cb) {
   // |player_tracker_| can be accessed from any thread.
-  return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb);
+  return player_tracker_.RegisterPlayer(std::move(new_key_cb),
+                                        std::move(cdm_unset_cb));
 }
 
 void MediaDrmBridge::UnregisterPlayer(int registration_id) {
diff --git a/media/base/android/media_drm_bridge.h b/media/base/android/media_drm_bridge.h
index dc08296..df15d031 100644
--- a/media/base/android/media_drm_bridge.h
+++ b/media/base/android/media_drm_bridge.h
@@ -147,8 +147,8 @@
   //
   // Note: RegisterPlayer() should be called before SetMediaCryptoReadyCB() to
   // avoid missing any new key notifications.
-  int RegisterPlayer(const base::Closure& new_key_cb,
-                     const base::Closure& cdm_unset_cb) override;
+  int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                     base::RepeatingClosure cdm_unset_cb) override;
   void UnregisterPlayer(int registration_id) override;
 
   // Helper function to determine whether a secure decoder is required for the
diff --git a/media/base/android/mock_media_crypto_context.cc b/media/base/android/mock_media_crypto_context.cc
index 0176772..e20d085c3 100644
--- a/media/base/android/mock_media_crypto_context.cc
+++ b/media/base/android/mock_media_crypto_context.cc
@@ -25,7 +25,7 @@
 
   // Provide some sane defaults.
   ON_CALL(*this, RegisterPlayer(_, _))
-      .WillByDefault(DoAll(SaveArg<0>(&new_key_cb), SaveArg<1>(&cdm_unset_cb),
+      .WillByDefault(DoAll(MoveArg<0>(&new_key_cb), MoveArg<1>(&cdm_unset_cb),
                            Return(kRegistrationId)));
   ON_CALL(*this, SetMediaCryptoReadyCB_(_))
       .WillByDefault(MoveArg<0>(&media_crypto_ready_cb));
diff --git a/media/base/android/mock_media_crypto_context.h b/media/base/android/mock_media_crypto_context.h
index 6630574..745019f 100644
--- a/media/base/android/mock_media_crypto_context.h
+++ b/media/base/android/mock_media_crypto_context.h
@@ -27,8 +27,8 @@
 
   // MediaCryptoContext implementation.
   MOCK_METHOD2(RegisterPlayer,
-               int(const base::Closure& new_key_cb,
-                   const base::Closure& cdm_unset_cb));
+               int(base::RepeatingClosure new_key_cb,
+                   base::RepeatingClosure cdm_unset_cb));
   MOCK_METHOD1(UnregisterPlayer, void(int registration_id));
   void SetMediaCryptoReadyCB(
       MediaCryptoReadyCB media_crypto_ready_cb) override {
@@ -39,8 +39,8 @@
 
   static constexpr int kRegistrationId = 1000;
 
-  base::Closure new_key_cb;
-  base::Closure cdm_unset_cb;
+  base::RepeatingClosure new_key_cb;
+  base::RepeatingClosure cdm_unset_cb;
   MediaCryptoReadyCB media_crypto_ready_cb;
   // To be set to true when |media_crypto_ready_cb| is consumed and run.
   bool ran_media_crypto_ready_cb = false;
diff --git a/media/base/audio_buffer.cc b/media/base/audio_buffer.cc
index 6de13f0..d0f34c5 100644
--- a/media/base/audio_buffer.cc
+++ b/media/base/audio_buffer.cc
@@ -82,6 +82,8 @@
   if (!create_buffer)
     return;
 
+  CHECK_NE(sample_format, kUnknownSampleFormat);
+
   int data_size_per_channel = frame_count * bytes_per_channel;
   if (IsPlanar(sample_format)) {
     DCHECK(!IsBitstreamFormat()) << sample_format_;
diff --git a/media/base/player_tracker.h b/media/base/player_tracker.h
index 57c59ab5..8c7bf35 100644
--- a/media/base/player_tracker.h
+++ b/media/base/player_tracker.h
@@ -22,8 +22,8 @@
   // - |cdm_unset_cb| is fired when the CDM is detached from the player. The
   //   player should stop using the CDM and release any ref-count to the CDM.
   // Returns a registration ID which can be used to unregister a player.
-  virtual int RegisterPlayer(const base::Closure& new_key_cb,
-                             const base::Closure& cdm_unset_cb) = 0;
+  virtual int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                             base::RepeatingClosure cdm_unset_cb) = 0;
 
   // Unregisters a previously registered player. This should be called when
   // the CDM is detached from the player (e.g. setMediaKeys(0)), or when the
diff --git a/media/cdm/player_tracker_impl.cc b/media/cdm/player_tracker_impl.cc
index 72c27974..a734a34 100644
--- a/media/cdm/player_tracker_impl.cc
+++ b/media/cdm/player_tracker_impl.cc
@@ -11,12 +11,16 @@
 namespace media {
 
 PlayerTrackerImpl::PlayerCallbacks::PlayerCallbacks(
-    const base::Closure& new_key_cb,
-    const base::Closure& cdm_unset_cb)
-    : new_key_cb(new_key_cb), cdm_unset_cb(cdm_unset_cb) {}
+    base::RepeatingClosure new_key_cb,
+    base::RepeatingClosure cdm_unset_cb)
+    : new_key_cb(std::move(new_key_cb)),
+      cdm_unset_cb(std::move(cdm_unset_cb)) {}
 
-PlayerTrackerImpl::PlayerCallbacks::PlayerCallbacks(
-    const PlayerCallbacks& other) = default;
+PlayerTrackerImpl::PlayerCallbacks::PlayerCallbacks(PlayerCallbacks&& other) =
+    default;
+
+PlayerTrackerImpl::PlayerCallbacks& PlayerTrackerImpl::PlayerCallbacks::
+operator=(PlayerCallbacks&&) = default;
 
 PlayerTrackerImpl::PlayerCallbacks::~PlayerCallbacks() = default;
 
@@ -25,13 +29,14 @@
 
 PlayerTrackerImpl::~PlayerTrackerImpl() = default;
 
-int PlayerTrackerImpl::RegisterPlayer(const base::Closure& new_key_cb,
-                                      const base::Closure& cdm_unset_cb) {
+int PlayerTrackerImpl::RegisterPlayer(base::RepeatingClosure new_key_cb,
+                                      base::RepeatingClosure cdm_unset_cb) {
   base::AutoLock lock(lock_);
   int registration_id = next_registration_id_++;
   DCHECK(!base::Contains(player_callbacks_map_, registration_id));
   player_callbacks_map_.insert(std::make_pair(
-      registration_id, PlayerCallbacks(new_key_cb, cdm_unset_cb)));
+      registration_id,
+      PlayerCallbacks(std::move(new_key_cb), std::move(cdm_unset_cb))));
   return registration_id;
 }
 
@@ -43,10 +48,11 @@
 }
 
 void PlayerTrackerImpl::NotifyNewKey() {
-  std::vector<base::Closure> new_key_callbacks;
+  std::vector<base::RepeatingClosure> new_key_callbacks;
 
   {
     base::AutoLock lock(lock_);
+    new_key_callbacks.reserve(player_callbacks_map_.size());
     for (const auto& entry : player_callbacks_map_)
       new_key_callbacks.push_back(entry.second.new_key_cb);
   }
@@ -56,10 +62,11 @@
 }
 
 void PlayerTrackerImpl::NotifyCdmUnset() {
-  std::vector<base::Closure> cdm_unset_callbacks;
+  std::vector<base::RepeatingClosure> cdm_unset_callbacks;
 
   {
     base::AutoLock lock(lock_);
+    cdm_unset_callbacks.reserve(player_callbacks_map_.size());
     for (const auto& entry : player_callbacks_map_)
       cdm_unset_callbacks.push_back(entry.second.cdm_unset_cb);
   }
diff --git a/media/cdm/player_tracker_impl.h b/media/cdm/player_tracker_impl.h
index 8d6bbe2..901c401 100644
--- a/media/cdm/player_tracker_impl.h
+++ b/media/cdm/player_tracker_impl.h
@@ -24,8 +24,8 @@
   ~PlayerTrackerImpl() override;
 
   // PlayerTracker implementation.
-  int RegisterPlayer(const base::Closure& new_key_cb,
-                     const base::Closure& cdm_unset_cb) override;
+  int RegisterPlayer(base::RepeatingClosure new_key_cb,
+                     base::RepeatingClosure cdm_unset_cb) override;
   void UnregisterPlayer(int registration_id) override;
 
   // Helpers methods to fire registered callbacks.
@@ -34,13 +34,14 @@
 
  private:
   struct PlayerCallbacks {
-    PlayerCallbacks(const base::Closure& new_key_cb,
-                    const base::Closure& cdm_unset_cb);
-    PlayerCallbacks(const PlayerCallbacks& other);
+    PlayerCallbacks(base::RepeatingClosure new_key_cb,
+                    base::RepeatingClosure cdm_unset_cb);
+    PlayerCallbacks(PlayerCallbacks&& other);
+    PlayerCallbacks& operator=(PlayerCallbacks&& other);
     ~PlayerCallbacks();
 
-    base::Closure new_key_cb;
-    base::Closure cdm_unset_cb;
+    base::RepeatingClosure new_key_cb;
+    base::RepeatingClosure cdm_unset_cb;
   };
 
   base::Lock lock_;
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc
index 4f594854..260f2b7 100644
--- a/media/filters/ffmpeg_audio_decoder.cc
+++ b/media/filters/ffmpeg_audio_decoder.cc
@@ -369,6 +369,11 @@
   AVSampleFormat format = static_cast<AVSampleFormat>(frame->format);
   SampleFormat sample_format =
       AVSampleFormatToSampleFormat(format, s->codec_id);
+  if (sample_format == kUnknownSampleFormat) {
+    DLOG(ERROR) << "Unknown sample format: " << format;
+    return AVERROR(EINVAL);
+  }
+
   int channels = DetermineChannels(frame);
   if (channels <= 0 || channels >= limits::kMaxChannels) {
     DLOG(ERROR) << "Requested number of channels (" << channels
diff --git a/media/gpu/chromeos/fourcc.cc b/media/gpu/chromeos/fourcc.cc
index 07ff7f9..dff77f7e 100644
--- a/media/gpu/chromeos/fourcc.cc
+++ b/media/gpu/chromeos/fourcc.cc
@@ -55,25 +55,25 @@
   if (single_planar) {
     switch (pixel_format) {
       case PIXEL_FORMAT_ARGB:
-        return Fourcc(Fourcc::AR24);
+        return Fourcc(AR24);
       case PIXEL_FORMAT_ABGR:
-        return Fourcc(Fourcc::AB24);
+        return Fourcc(AB24);
       case PIXEL_FORMAT_XRGB:
-        return Fourcc(Fourcc::XR24);
+        return Fourcc(XR24);
       case PIXEL_FORMAT_XBGR:
-        return Fourcc(Fourcc::XB24);
+        return Fourcc(XB24);
       case PIXEL_FORMAT_BGRA:
-        return Fourcc(Fourcc::RGB4);
+        return Fourcc(RGB4);
       case PIXEL_FORMAT_I420:
-        return Fourcc(Fourcc::YU12);
+        return Fourcc(YU12);
       case PIXEL_FORMAT_YV12:
-        return Fourcc(Fourcc::YV12);
+        return Fourcc(YV12);
       case PIXEL_FORMAT_YUY2:
-        return Fourcc(Fourcc::YUYV);
+        return Fourcc(YUYV);
       case PIXEL_FORMAT_NV12:
-        return Fourcc(Fourcc::NV12);
+        return Fourcc(NV12);
       case PIXEL_FORMAT_NV21:
-        return Fourcc(Fourcc::NV21);
+        return Fourcc(NV21);
       case PIXEL_FORMAT_I422:
       case PIXEL_FORMAT_I420A:
       case PIXEL_FORMAT_I444:
@@ -98,15 +98,15 @@
   } else {
     switch (pixel_format) {
       case PIXEL_FORMAT_I420:
-        return Fourcc(Fourcc::YM12);
+        return Fourcc(YM12);
       case PIXEL_FORMAT_YV12:
-        return Fourcc(Fourcc::YM21);
+        return Fourcc(YM21);
       case PIXEL_FORMAT_NV12:
-        return Fourcc(Fourcc::NM12);
+        return Fourcc(NM12);
       case PIXEL_FORMAT_I422:
-        return Fourcc(Fourcc::YM16);
+        return Fourcc(YM16);
       case PIXEL_FORMAT_NV21:
-        return Fourcc(Fourcc::NM21);
+        return Fourcc(NM21);
       case PIXEL_FORMAT_I420A:
       case PIXEL_FORMAT_I444:
       case PIXEL_FORMAT_YUY2:
@@ -141,31 +141,31 @@
 
 VideoPixelFormat Fourcc::ToVideoPixelFormat() const {
   switch (value_) {
-    case Fourcc::AR24:
+    case AR24:
       return PIXEL_FORMAT_ARGB;
-    case Fourcc::AB24:
+    case AB24:
       return PIXEL_FORMAT_ABGR;
-    case Fourcc::XR24:
+    case XR24:
       return PIXEL_FORMAT_XRGB;
-    case Fourcc::XB24:
+    case XB24:
       return PIXEL_FORMAT_XBGR;
-    case Fourcc::RGB4:
+    case RGB4:
       return PIXEL_FORMAT_BGRA;
-    case Fourcc::YU12:
-    case Fourcc::YM12:
+    case YU12:
+    case YM12:
       return PIXEL_FORMAT_I420;
-    case Fourcc::YV12:
-    case Fourcc::YM21:
+    case YV12:
+    case YM21:
       return PIXEL_FORMAT_YV12;
-    case Fourcc::YUYV:
+    case YUYV:
       return PIXEL_FORMAT_YUY2;
-    case Fourcc::NV12:
-    case Fourcc::NM12:
+    case NV12:
+    case NM12:
       return PIXEL_FORMAT_NV12;
-    case Fourcc::NV21:
-    case Fourcc::NM21:
+    case NV21:
+    case NM21:
       return PIXEL_FORMAT_NV21;
-    case Fourcc::YM16:
+    case YM16:
       return PIXEL_FORMAT_I422;
     // V4L2_PIX_FMT_MT21C is only used for MT8173 hardware video decoder output
     // and should be converted by MT8173 image processor for compositor to
@@ -174,11 +174,11 @@
     // VideoFrameLayout for the format to process the intermediate frame. Hence
     // we map V4L2_PIX_FMT_MT21C to PIXEL_FORMAT_NV12 as their layout are the
     // same.
-    case Fourcc::MT21:
+    case MT21:
     // V4L2_PIX_FMT_MM21 is used for MT8183 hardware video decoder. It is
     // similar to V4L2_PIX_FMT_MT21C but is not compressed ; thus it can also
     // be mapped to PIXEL_FORMAT_NV12.
-    case Fourcc::MM21:
+    case MM21:
       return PIXEL_FORMAT_NV12;
   }
   NOTREACHED() << "Unmapped Fourcc: " << ToString();
@@ -205,25 +205,25 @@
 base::Optional<Fourcc> Fourcc::FromVAFourCC(uint32_t va_fourcc) {
   switch (va_fourcc) {
     case VA_FOURCC_I420:
-      return Fourcc(Fourcc::YU12);
+      return Fourcc(YU12);
     case VA_FOURCC_NV12:
-      return Fourcc(Fourcc::NV12);
+      return Fourcc(NV12);
     case VA_FOURCC_NV21:
-      return Fourcc(Fourcc::NV21);
+      return Fourcc(NV21);
     case VA_FOURCC_YV12:
-      return Fourcc(Fourcc::YV12);
+      return Fourcc(YV12);
     case VA_FOURCC_YUY2:
-      return Fourcc(Fourcc::YUYV);
+      return Fourcc(YUYV);
     case VA_FOURCC_RGBA:
-      return Fourcc(Fourcc::AB24);
+      return Fourcc(AB24);
     case VA_FOURCC_RGBX:
-      return Fourcc(Fourcc::XB24);
+      return Fourcc(XB24);
     case VA_FOURCC_BGRA:
-      return Fourcc(Fourcc::AR24);
+      return Fourcc(AR24);
     case VA_FOURCC_BGRX:
-      return Fourcc(Fourcc::XR24);
+      return Fourcc(XR24);
     case VA_FOURCC_ARGB:
-      return Fourcc(Fourcc::RGB4);
+      return Fourcc(RGB4);
   }
   DVLOGF(3) << "Unmapped VAFourCC: " << FourccToString(va_fourcc);
   return base::nullopt;
@@ -231,33 +231,33 @@
 
 base::Optional<uint32_t> Fourcc::ToVAFourCC() const {
   switch (value_) {
-    case Fourcc::YU12:
+    case YU12:
       return VA_FOURCC_I420;
-    case Fourcc::NV12:
+    case NV12:
       return VA_FOURCC_NV12;
-    case Fourcc::NV21:
+    case NV21:
       return VA_FOURCC_NV21;
-    case Fourcc::YV12:
+    case YV12:
       return VA_FOURCC_YV12;
-    case Fourcc::YUYV:
+    case YUYV:
       return VA_FOURCC_YUY2;
-    case Fourcc::AB24:
+    case AB24:
       return VA_FOURCC_RGBA;
-    case Fourcc::XB24:
+    case XB24:
       return VA_FOURCC_RGBX;
-    case Fourcc::AR24:
+    case AR24:
       return VA_FOURCC_BGRA;
-    case Fourcc::XR24:
+    case XR24:
       return VA_FOURCC_BGRX;
-    case Fourcc::RGB4:
+    case RGB4:
       return VA_FOURCC_ARGB;
-    case Fourcc::YM12:
-    case Fourcc::YM21:
-    case Fourcc::NM12:
-    case Fourcc::NM21:
-    case Fourcc::YM16:
-    case Fourcc::MT21:
-    case Fourcc::MM21:
+    case YM12:
+    case YM21:
+    case NM12:
+    case NM21:
+    case YM16:
+    case MT21:
+    case MM21:
       // VAAPI does not know about these formats, so signal this by returning
       // nullopt.
       DVLOGF(3) << "Fourcc not convertible to VaFourCC: " << ToString();
diff --git a/media/gpu/chromeos/image_processor_test.cc b/media/gpu/chromeos/image_processor_test.cc
index 8c5553d..cce275e 100644
--- a/media/gpu/chromeos/image_processor_test.cc
+++ b/media/gpu/chromeos/image_processor_test.cc
@@ -69,8 +69,12 @@
     FILE_PATH_LITERAL("puppets-1280x720.nv12.yuv");
 const base::FilePath::CharType* kNV12Image360P =
     FILE_PATH_LITERAL("puppets-640x360.nv12.yuv");
+const base::FilePath::CharType* kNV12Image270P =
+    FILE_PATH_LITERAL("puppets-480x270.nv12.yuv");
 const base::FilePath::CharType* kNV12Image180P =
     FILE_PATH_LITERAL("puppets-320x180.nv12.yuv");
+const base::FilePath::CharType* kNV12Image360PIn480P =
+    FILE_PATH_LITERAL("puppets-640x360_in_640x480.nv12.yuv");
 
 class ImageProcessorParamTest
     : public ::testing::Test,
@@ -107,10 +111,10 @@
     LOG_ASSERT(input_layout && output_layout);
     ImageProcessor::PortConfig input_config(
         input_fourcc, input_image.Size(), input_layout->planes(),
-        gfx::Rect(input_image.Size()), input_storage_types);
+        input_image.VisibleRect(), input_storage_types);
     ImageProcessor::PortConfig output_config(
         output_fourcc, output_image->Size(), output_layout->planes(),
-        gfx::Rect(output_image->Size()), output_storage_types);
+        output_image->VisibleRect(), output_storage_types);
     // TODO(crbug.com/917951): Select more appropriate number of buffers.
     constexpr size_t kNumBuffers = 1;
     LOG_ASSERT(output_image->IsMetadataLoaded());
@@ -280,9 +284,22 @@
     NV12DownScaling,
     ImageProcessorParamTest,
     ::testing::Values(std::make_tuple(kNV12Image720P, kNV12Image360P),
+                      std::make_tuple(kNV12Image720P, kNV12Image270P),
                       std::make_tuple(kNV12Image720P, kNV12Image180P),
+                      std::make_tuple(kNV12Image360P, kNV12Image270P),
                       std::make_tuple(kNV12Image360P, kNV12Image180P)));
 
+// Crop 360P frame from 480P.
+INSTANTIATE_TEST_SUITE_P(NV12Cropping,
+                         ImageProcessorParamTest,
+                         ::testing::Values(std::make_tuple(kNV12Image360PIn480P,
+                                                           kNV12Image360P)));
+// Crop 360p frame from 480P and scale the area to 270P.
+INSTANTIATE_TEST_SUITE_P(NV12CroppingAndScaling,
+                         ImageProcessorParamTest,
+                         ::testing::Values(std::make_tuple(kNV12Image360PIn480P,
+                                                           kNV12Image270P)));
+
 #if defined(OS_CHROMEOS)
 // TODO(hiroh): Add more tests.
 // MEM->DMABUF (V4L2VideoEncodeAccelerator),
diff --git a/media/gpu/test/image.cc b/media/gpu/test/image.cc
index 3a8de93e..11fbb30 100644
--- a/media/gpu/test/image.cc
+++ b/media/gpu/test/image.cc
@@ -11,8 +11,7 @@
 #include "base/json/json_reader.h"
 #include "base/values.h"
 #include "media/base/test_data_util.h"
-
-#define VLOGF(level) VLOG(level) << __func__ << "(): "
+#include "media/gpu/macros.h"
 
 namespace media {
 namespace test {
@@ -145,6 +144,26 @@
   }
   size_ = gfx::Size(width->GetInt(), height->GetInt());
 
+  // Try to get the visible rectangle of the image from the json data.
+  // These values are not in json data if all the image data is in the visible
+  // area.
+  visible_rect_ = gfx::Rect(size_);
+  const base::Value* visible_rect_info =
+      metadata->FindKeyOfType("visible_rect", base::Value::Type::LIST);
+  if (visible_rect_info) {
+    base::Value::ConstListView values = visible_rect_info->GetList();
+    if (values.size() != 4) {
+      VLOGF(1) << "unexpected json format for visible rectangle";
+      return false;
+    }
+    int origin_x = values[0].GetInt();
+    int origin_y = values[1].GetInt();
+    int visible_width = values[2].GetInt();
+    int visible_height = values[3].GetInt();
+    visible_rect_ =
+        gfx::Rect(origin_x, origin_y, visible_width, visible_height);
+  }
+
   // Get the image checksum from the json data.
   const base::Value* checksum =
       metadata->FindKeyOfType("checksum", base::Value::Type::STRING);
@@ -177,6 +196,10 @@
   return size_;
 }
 
+const gfx::Rect& Image::VisibleRect() const {
+  return visible_rect_;
+}
+
 const char* Image::Checksum() const {
   return checksum_.data();
 }
diff --git a/media/gpu/test/image.h b/media/gpu/test/image.h
index 423592c..56d790f 100644
--- a/media/gpu/test/image.h
+++ b/media/gpu/test/image.h
@@ -10,6 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/files/memory_mapped_file.h"
 #include "media/base/video_types.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
@@ -42,6 +43,8 @@
   VideoPixelFormat PixelFormat() const;
   // Get the image size.
   const gfx::Size& Size() const;
+  // Get the visible rectangle of the image.
+  const gfx::Rect& VisibleRect() const;
   // Get the image checksum.
   const char* Checksum() const;
 
@@ -57,6 +60,8 @@
   VideoPixelFormat pixel_format_ = PIXEL_FORMAT_UNKNOWN;
   // The image size.
   gfx::Size size_;
+  // The visible rectangle of the image.
+  gfx::Rect visible_rect_;
   // The image md5 checksum.
   std::string checksum_;
 
diff --git a/media/gpu/test/video_frame_helpers.cc b/media/gpu/test/video_frame_helpers.cc
index 7472133..dfba32ca 100644
--- a/media/gpu/test/video_frame_helpers.cc
+++ b/media/gpu/test/video_frame_helpers.cc
@@ -318,14 +318,14 @@
 scoped_refptr<const VideoFrame> CreateVideoFrameFromImage(const Image& image) {
   DCHECK(image.IsLoaded());
   const auto format = image.PixelFormat();
-  const auto& visible_size = image.Size();
+  const auto& image_size = image.Size();
   // Loaded image data must be tight.
-  DCHECK_EQ(image.DataSize(), VideoFrame::AllocationSize(format, visible_size));
+  DCHECK_EQ(image.DataSize(), VideoFrame::AllocationSize(format, image_size));
 
   // Create planes for layout. We cannot use WrapExternalData() because it
   // calls GetDefaultLayout() and it supports only a few pixel formats.
   base::Optional<VideoFrameLayout> layout =
-      CreateVideoFrameLayout(format, visible_size);
+      CreateVideoFrameLayout(format, image_size);
   if (!layout) {
     LOG(ERROR) << "Failed to create VideoFrameLayout";
     return nullptr;
@@ -333,8 +333,8 @@
 
   scoped_refptr<const VideoFrame> video_frame =
       VideoFrame::WrapExternalDataWithLayout(
-          *layout, gfx::Rect(visible_size), visible_size, image.Data(),
-          image.DataSize(), base::TimeDelta());
+          *layout, image.VisibleRect(), image.VisibleRect().size(),
+          image.Data(), image.DataSize(), base::TimeDelta());
   if (!video_frame) {
     LOG(ERROR) << "Failed to create VideoFrame";
     return nullptr;
diff --git a/media/gpu/test/video_player/frame_renderer_thumbnail.cc b/media/gpu/test/video_player/frame_renderer_thumbnail.cc
index 69bf3db5..82edb9d 100644
--- a/media/gpu/test/video_player/frame_renderer_thumbnail.cc
+++ b/media/gpu/test/video_player/frame_renderer_thumbnail.cc
@@ -225,6 +225,9 @@
     uint32_t* texture_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(renderer_sequence_checker_);
 
+  // Make the GL context current in the case it's not currently yet.
+  AcquireGLContext();
+
   // Create a mailbox.
   gpu::Mailbox mailbox = gpu::Mailbox::Generate();
   gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes];
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 1e4989e..49ff3d8 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -569,6 +569,8 @@
   parser.SetStream(bitstream_data, bitstream_size);
   H264NALU nalu;
 
+  bool inserted_sps = false;
+  bool inserted_pps = false;
   while (parser.AdvanceToNextNALU(&nalu) == H264Parser::kOk) {
     // nalu.size is always without the start code, regardless of the NALU type.
     if (nalu.size + kH264StartCodeSize > remaining_dst_size) {
@@ -582,6 +584,7 @@
         memcpy(cached_sps_.data(), nalu.data, nalu.size);
         cached_h264_header_size_ =
             cached_sps_.size() + cached_pps_.size() + 2 * kH264StartCodeSize;
+        inserted_sps = true;
         break;
 
       case H264NALU::kPPS:
@@ -589,9 +592,14 @@
         memcpy(cached_pps_.data(), nalu.data, nalu.size);
         cached_h264_header_size_ =
             cached_sps_.size() + cached_pps_.size() + 2 * kH264StartCodeSize;
+        inserted_pps = true;
         break;
 
       case H264NALU::kIDRSlice:
+        if (inserted_sps && inserted_pps) {
+          // Already inserted SPS and PPS. No need to inject.
+          break;
+        }
         // Only inject if we have both headers cached, and enough space for both
         // the headers and the NALU itself.
         if (cached_sps_.empty() || cached_pps_.empty()) {
@@ -604,10 +612,14 @@
           break;
         }
 
-        CopyNALUPrependingStartCode(cached_sps_.data(), cached_sps_.size(),
-                                    &dst_ptr, &remaining_dst_size);
-        CopyNALUPrependingStartCode(cached_pps_.data(), cached_pps_.size(),
-                                    &dst_ptr, &remaining_dst_size);
+        if (!inserted_sps) {
+          CopyNALUPrependingStartCode(cached_sps_.data(), cached_sps_.size(),
+                                      &dst_ptr, &remaining_dst_size);
+        }
+        if (!inserted_pps) {
+          CopyNALUPrependingStartCode(cached_pps_.data(), cached_pps_.size(),
+                                      &dst_ptr, &remaining_dst_size);
+        }
         VLOGF(2) << "Stream header injected before IDR";
         break;
     }
diff --git a/mojo/public/js/mojo_bindings_resources.grd b/mojo/public/js/mojo_bindings_resources.grd
index 4f4db5fe..83da5be2 100644
--- a/mojo/public/js/mojo_bindings_resources.grd
+++ b/mojo/public/js/mojo_bindings_resources.grd
@@ -60,6 +60,16 @@
           use_base_dir="false"
           type="BINDATA"
           compress="gzip" />
+      <include name="IDR_MOJO_TEXT_DIRECTION_MOJOM_HTML"
+          file="${root_gen_dir}/mojo/public/mojom/base/text_direction.mojom.html"
+          use_base_dir="false"
+          type="BINDATA"
+          compress="gzip" />
+      <include name="IDR_MOJO_TEXT_DIRECTION_MOJOM_LITE_JS"
+          file="${root_gen_dir}/mojo/public/mojom/base/text_direction.mojom-lite.js"
+          use_base_dir="false"
+          type="BINDATA"
+          compress="gzip" />
       <if expr="is_win or is_macosx or is_linux">
         <include name="IDR_MOJO_TIME_MOJOM_HTML"
             file="${root_gen_dir}/mojo/public/mojom/base/time.mojom.html"
diff --git a/net/base/features.cc b/net/base/features.cc
index 3d70448..d4634ab 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "net/base/features.h"
+#include "build/build_config.h"
 
 namespace net {
 namespace features {
@@ -87,7 +88,7 @@
 #if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
 const base::Feature kCertVerifierBuiltinFeature {
   "CertVerifierBuiltin",
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
       base::FEATURE_ENABLED_BY_DEFAULT
 #else
       base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/net/base/net_errors.cc b/net/base/net_errors.cc
index ed6bc4514..7e7ee37ac 100644
--- a/net/base/net_errors.cc
+++ b/net/base/net_errors.cc
@@ -63,8 +63,8 @@
 }
 
 bool IsDnsError(int error) {
-  return (error == ERR_NAME_NOT_RESOLVED ||
-          error == ERR_NAME_RESOLUTION_FAILED);
+  DCHECK_NE(ERR_NAME_RESOLUTION_FAILED, error);
+  return error == ERR_NAME_NOT_RESOLVED;
 }
 
 Error FileErrorToNetError(base::File::Error file_error) {
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h
index 092ac6f..264ab583 100644
--- a/net/dns/host_resolver.h
+++ b/net/dns/host_resolver.h
@@ -66,12 +66,9 @@
     // On any other returned value, the request was handled synchronously and
     // |callback| will not be invoked.
     //
-    // Results in ERR_NAME_NOT_RESOLVED if the hostname is invalid, or if it is
-    // an incompatible IP literal (e.g. IPv6 is disabled and it is an IPv6
-    // literal).
-    //
-    // Results in ERR_DNS_CACHE_MISS if only fast local sources are to be
-    // queried and a cache lookup attempt fails.
+    // Results in ERR_NAME_NOT_RESOLVED if the hostname is not resolved. More
+    // detail about the underlying error can be retrieved using
+    // GetResolveErrorInfo().
     //
     // The parent HostResolver must still be alive when Start() is called,  but
     // if it is destroyed before an asynchronous result completes, the request
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc
index 795386a..a98331a 100644
--- a/net/dns/host_resolver_manager.cc
+++ b/net/dns/host_resolver_manager.cc
@@ -650,7 +650,7 @@
     LogFinishRequest(error);
 
     DCHECK(callback_);
-    std::move(callback_).Run(error);
+    std::move(callback_).Run(HostResolver::SquashErrorCode(error));
   }
 
   Job* job() const { return job_; }
@@ -2992,7 +2992,7 @@
                     effective_secure_dns_mode, base::TimeDelta());
     request->set_error_info(results.error(),
                             false /* is_secure_network_error */);
-    return results.error();
+    return HostResolver::SquashErrorCode(results.error());
   }
 
   CreateAndStartJob(effective_query_type, effective_host_resolver_flags,
diff --git a/net/features.gni b/net/features.gni
index f9ae69ae..33b03ba 100644
--- a/net/features.gni
+++ b/net/features.gni
@@ -38,7 +38,7 @@
 
   # Platforms where the cert verifier comparison trial is supported.
   # See https://crbug.com/649026.
-  trial_comparison_cert_verifier_supported = is_desktop_linux || is_mac
+  trial_comparison_cert_verifier_supported = is_mac
 
   # Platforms where both the builtin cert verifier and a platform verifier are
   # supported and may be switched between using the CertVerifierBuiltin feature
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 81a2ad8..e7b00991 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -2515,7 +2515,6 @@
     { "name": "doridian.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "drtroyhendrickson.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "edelsteincosmetic.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "edge-cloud.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "ellegaard.dk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "enigmail.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "enterdev.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -5680,7 +5679,6 @@
     { "name": "darkhole.cn", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "darkside.re", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "darksideof.it", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "darwinkel.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "davidandersson.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "davidreinhardt.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dc585.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -6359,7 +6357,6 @@
     { "name": "toucedo.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "toutart.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "townhousedevelopments.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "trendkraft.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "trik.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "trollscave.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "trustmeimfancy.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -9037,7 +9034,6 @@
     { "name": "indredouglas.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "industreiler.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "informatiebeveiliging.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "infotics.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "inkable.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "insightera.co.th", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "inspire-av.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -12245,7 +12241,6 @@
     { "name": "4th-ave-studio.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "4vf.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "540.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "54below.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "7thcircledesigns.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "88.to", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "8mpay.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -12380,7 +12375,6 @@
     { "name": "bizzartech.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blakerandall.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blankersfamily.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "blayne.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blendr.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blenheimchalcot.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blissplan.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -12474,7 +12468,6 @@
     { "name": "cheapticket.in", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "chelseafs.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "chennien.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "chicisimo.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "choiralberta.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "chourishi-shigoto.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "chrismcclendon.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -13614,7 +13607,6 @@
     { "name": "thelanscape.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thenanfang.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thenexwork.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "thenib.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thepiratebay.tech", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thermity.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "theseosystem.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -17074,7 +17066,6 @@
     { "name": "belge.rs", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "beauty24.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "belanglos.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "blayneallan.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "alexismeza.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "alexismeza.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "biointelligence-explosion.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -19299,7 +19290,6 @@
     { "name": "atlantis-kh.noip.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "babyboom.pl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "alloinformatique.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "aubg.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "beanworks.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "bearden.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "autoverzekeringafsluiten.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -20602,7 +20592,6 @@
     { "name": "neave.tv", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "monpermismoto.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "navitime.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "myweb360.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nalepky-na-zed.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mytripcar.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nagios.by", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -24658,7 +24647,6 @@
     { "name": "milkingit.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "min-sky.no", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "minakov.pro", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "minantavla.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "minaprine.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "minecraft-forum.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "minecraft-server.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -25041,7 +25029,6 @@
     { "name": "platschi.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "play.cash", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "playdreamcraft.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "playform.cloud", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "playmfe.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "playpirates.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "playsnake.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -25085,7 +25072,6 @@
     { "name": "post-darwinian.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "post-darwinism.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "postal3.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "postback.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "postcardpayment.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "postdarwinian.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "postdarwinism.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -28606,7 +28592,6 @@
     { "name": "rootscope.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rosehosting.reviews", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rootedlifemontessori.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "rnb-storenbau.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rorymcdaniel.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rootcommand.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "reclusiam.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -30037,7 +30022,6 @@
     { "name": "customfitmarketing.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "elsword.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "edisonchee.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "eboek.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "electr0sheep.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "empese.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dznn.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -36131,7 +36115,6 @@
     { "name": "pedrosaurus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pelican.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pensanisso.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "pension-veldzigt.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "perfectionunite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "perfectoparty.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "perfectsnap.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -38828,7 +38811,6 @@
     { "name": "electricalconejovalley.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eleicoes2018.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elektronickakancelar.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "eleonorengland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elviraszabo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elwix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elysiria.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -39460,7 +39442,6 @@
     { "name": "onspring.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "opalesurfcasting.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "openclima.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "opentuition.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "operationforever.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oppag.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "optm.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -39938,7 +39919,6 @@
     { "name": "wezl.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "whistler-transfers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "whitehousedrugpolicy.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "whoasome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "whocybered.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "willowtree.school", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wisak.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -40802,7 +40782,6 @@
     { "name": "timonengelke.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tindallriley.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "titandirect.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tkeycoin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tndentalwellness.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "toerclub-ing-arnhem.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tokka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -45228,7 +45207,6 @@
     { "name": "bahnhelden.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bamahammer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bandar303.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "barnel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "barpodsosnami.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "basementfinishingohio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "batch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -47415,7 +47393,6 @@
     { "name": "stokvistrading.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "storytell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "studentpop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "studio-webdigi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "studioscherp.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "subculture.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sucretown.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -49213,7 +49190,6 @@
     { "name": "mat.tt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "matrimoni.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mayaimplant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "mbda.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mccoolesredlioninn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mcnoobs.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "meddatix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -51241,7 +51217,6 @@
     { "name": "bemindly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ben-jarvis.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "benedikt-tuchen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "bestdating.today", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bestschools.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "biancolievito.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bjrn.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -51320,7 +51295,6 @@
     { "name": "due-diligence-security.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "duerlund-falkenberg.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "durbanlocksmiths.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "dw-loewe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "e-borneoshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "easyqr.codes", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ecomycie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -52191,7 +52165,6 @@
     { "name": "wezartt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wpccu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wxzm.sx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xerkus.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xhily.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xmlogin288.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ybt520.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -53068,7 +53041,6 @@
     { "name": "tokintu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tone.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "toomy.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "top5hosting.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "topkek.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "toppointrea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tosamja.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -54091,7 +54063,6 @@
     { "name": "worcade.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "workeria-personal.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "woti.dedyn.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "wp-webagentur.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "writer24.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wunschzettel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wuwuwu.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -54886,7 +54857,6 @@
     { "name": "nenkin-kikin.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "neurostimtms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nicesleepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "nicolasfriedli.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nipit.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "njujb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nsofficeinteriors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -56818,7 +56788,6 @@
     { "name": "huangjia79.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "huangjia99.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hypeitems.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "hyr.mn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "i2gether.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ibiu.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ibutikk.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -57163,7 +57132,6 @@
     { "name": "nototema.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nova-it.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "novacal.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "novelrealm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nureg.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nureg.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nureg.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -63278,7 +63246,6 @@
     { "name": "nichi.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nietmvwoensel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nippangift.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "nipplefucking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "noclegiwchecinach.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "norml.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "notariusz-bialystok.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -63369,7 +63336,6 @@
     { "name": "tor.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tranquillapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "trindonball.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "trk1234.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "truckers-auction.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tsriggingequipment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "turnout.rocks", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -63404,7 +63370,6 @@
     { "name": "zylai.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zzpwoerden.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00334.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "025ks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "060258.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "0x80.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "101010.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -63626,7 +63591,6 @@
     { "name": "olmcjc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "olschurch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "onestasolar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "output.clothing", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oxyx.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ozalp.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ozarktrailcooler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -64763,7 +64727,6 @@
     { "name": "bytepark.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "byteterrace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "c0o.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "cabuna.hr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cakeoffencesact.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "calendriergratuit.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "callerstrom.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -64917,7 +64880,6 @@
     { "name": "elettrodomestici.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elgrecohotel.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elitsa.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ell888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "emigratieplanner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "enderle.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "energy-healings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -67838,7 +67800,6 @@
     { "name": "boccabell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bochantinobgyn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bookwave.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "bou.ke", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "brianwalther.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "brizawen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "brooklynentdoc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -69890,7 +69851,6 @@
     { "name": "3333k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "36594.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "518k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "66619991.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "666k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "668k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "668k8.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70548,7 +70508,6 @@
     { "name": "javaweb.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jellysquid.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jenniferlucia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "jordanhamilton.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "julia-thonig.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jupuglia.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kaffeeringe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70684,7 +70643,6 @@
     { "name": "thenewclassics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thooka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tomthorogood.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tomthorogood.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "toparkinfo.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tourdatenarchiv.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "unclebens-specials.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -71108,7 +71066,6 @@
     { "name": "yapeal.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ystream.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yuzzamatuzz.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "zeckenhilfe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "0-24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "0-24.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "067310.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -71626,7 +71583,6 @@
     { "name": "your28days.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yumiandryan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yunhu365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "yuzulia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zalaxx.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zerocash.msk.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "022kb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -72897,7 +72853,6 @@
     { "name": "27878yy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "27878zz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "284365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "2evip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2kvn.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2lovebirdsblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "30n13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73125,11 +73080,9 @@
     { "name": "498663.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "4best.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "4dillusion.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "4evip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "4tgw34.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "500wordessay.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "5017503.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "5055990.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "51365a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "51365aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "51365b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73297,7 +73250,6 @@
     { "name": "66664048.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "666777bet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "666888bet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "6669255.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "666999bet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "666b58.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "6671365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73315,38 +73267,24 @@
     { "name": "678365cc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "678678365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "67894048.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "6863070.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "70365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "70n13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "71365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "733575.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "73365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "74365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "755243.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "755a.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "76365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "769k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "77774048.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "7788bet.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "77b58.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "78365aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "78365app.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "78365b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "78365bb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "78365c.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "78365cc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "78365dd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "78365ee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "7888813.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "7888815.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "7888821.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "78904048.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "80365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "80651a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "80n13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "811121.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "812221.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "81365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "8278aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "8278bet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "8278eee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73369,21 +73307,6 @@
     { "name": "866349.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "866374.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "866394.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "87365365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365app.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365bb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365c.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365cc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365dd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365ee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365ii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365jj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365ll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365mm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "878365nn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "88740n.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "888789j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "88884048.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73411,8 +73334,6 @@
     { "name": "97738.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "97739.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "988316.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "9988551.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "9988959.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "99994048.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "999b58.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "99n13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -74252,9 +74173,7 @@
     { "name": "h51365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "h6852.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "h6853.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "h6895.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "h6913.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "h9386.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "habernet.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hackthat.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hair-guide.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -74359,14 +74278,6 @@
     { "name": "j30365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "j32661.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "j32662.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32663.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32664.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32665.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32771.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32772.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32773.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32774.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j32775.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "j5563.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "j5573.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "j8846.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -74411,7 +74322,6 @@
     { "name": "just-heberg.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "just-keep-swimming.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "justknigi.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "k1958.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "k30365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kaatsen.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kabachok.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -74910,7 +74820,6 @@
     { "name": "putana.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "putanypitera.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "q30365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "q88588.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "qdrat.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "qq6396.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "qqq6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -75389,38 +75298,21 @@
     { "name": "v1.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v10006.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v10008.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v1951.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v3025.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v30365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v33v33.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v44v44.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v5075.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v55510.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v55520.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v55530.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v55v55.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v6021.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v6170.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v6350.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v637.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v6506.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v66618.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v66619.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v66629.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v66635.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v66638.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v6752.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v6791.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v700a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v700b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v88299.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v88559.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v88656.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v88799.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v9820.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v9821.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v9823.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "v9831.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vacati0n.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "valencianisme.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "valeravi.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -75459,7 +75351,6 @@
     { "name": "vmf365.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vneftekamske.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vns5656.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "vnsr112233.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "voetbalclubinfo.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "volosnet.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vovkamagazine.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -76054,7 +75945,6 @@
     { "name": "digitai.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "directorydashboard.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "directorydisc.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "discovermuscatine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dizayner.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dlyatepla.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "doc-baza.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77240,11 +77130,9 @@
     { "name": "w1717w.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "w6603.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "w6612.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "w66hao.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "w6863.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "w7355.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "w8093.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "w8605.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wa3368.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "waplumber.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wapspaces.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -78472,7 +78360,6 @@
     { "name": "zhihe.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zormeloandassociates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zs6688.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "zuenkov.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zz017.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zz993.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "0d222.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -79242,7 +79129,6 @@
     { "name": "zmiguel.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "znidar.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zollernalbtour.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "zupzup.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zz606.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bitbucket.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00rfb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -79367,7 +79253,6 @@
     { "name": "forexarby.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fortdodgeradio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "franklinmagic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "freefinancialhelp.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "freshbooks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "furgetmeknot.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "futuristacademy.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -79969,7 +79854,6 @@
     { "name": "9118inc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aanwp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "abraxasteam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "academie-musique-nice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "acmi.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "acneintelligence.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "acunetix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80009,7 +79893,6 @@
     { "name": "bring-heaven.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "brojagraphics.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bumble.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "cabinet-life.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "campo-salado.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "carbonvision.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "caycehouse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80047,7 +79930,6 @@
     { "name": "digitalcronies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "digitiqo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dobryautoskup.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "docteurcardin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "domainname.forsale", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "domyiadaptacje.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "doradocomputer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80057,12 +79939,10 @@
     { "name": "eaglemoe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "easypets.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ecotechnologyti.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "electrichome.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elprint.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "emeraldislerealty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "employer411.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eqiware.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "escandille.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eurotop.net.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "evolvingsouls.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "examopedia.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80070,14 +79950,12 @@
     { "name": "eyemedica.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "febeditora.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "feilestrokestown.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "fiduciaire-azur.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fieldexpert.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "firtreetechnology.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "formi9.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fourmies.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "francepandi.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "freedomhkg.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "freegovernmentcellphoneguide.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "frosoku.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "funfun.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gemeentestein.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80090,15 +79968,12 @@
     { "name": "gridtennis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "h-server.myfirewall.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "heightselectrical.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "histoiresdecontenu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "home-sud-renovation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "honeymaze.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ictindia.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "incomeproshoutr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "irequi.re", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "itsallaboutplumbing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "itschromeos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "iycharter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jakse.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jan-gerd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "japonyol.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80123,28 +79998,21 @@
     { "name": "ks597.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ks89.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kstr.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "la-bolle.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "labastidedesaromes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lacochinacounselor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lacocina.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "laimut.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "landsbankinn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lederkleren.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lelac-capfrance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "leoservicosetc.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "leruevintage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "letsbrand.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lettings101.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "libertyachts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lightography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lindajahn.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "loader.us.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lookingstores.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lorenzocampagna.myqnapcloud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lou-castelet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ltcwaterwijk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lueurexterne-audiovisuel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lueurexterne.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "macaos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "madeinolive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "magniflood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80180,7 +80048,6 @@
     { "name": "nvoip.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "omangrid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "onceuponabow.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "only-fragrances.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oortcast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oralb.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "orgoniteindonesia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80188,14 +80055,12 @@
     { "name": "paesi.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "page-rank1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "paknetworking.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "parfumerie-de-grasse.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "parkeerbordenhuren.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "paroisses-theix-surzur.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pcdbank.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pfonks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "piektraining.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pitoufi.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "plage-les-pirates.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "planisys.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "playlisten.radio.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "prankstercompany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80234,7 +80099,6 @@
     { "name": "simmtronic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sinakuhestani.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "siulam-wingchun.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "skooks.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "skyblockrebellion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "slalix.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "smaltimento-rifiuti.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80266,15 +80130,12 @@
     { "name": "ucc.edu.gh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "unblocked.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "unitedfitness.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "univet-veterinaire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "univetnature.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "upliving.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "urb-budex.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vangore.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ventadecolchones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "veryswing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "voix-bien-etre.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "votre-avenir.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vrikshamindia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vsactivity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vsportage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81017,7 +80878,6 @@
     { "name": "lunis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "m36594.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "m4all.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "m51365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "madisoncountyhelps.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mariage-protestant.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "martinboerhof.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81114,7 +80974,6 @@
     { "name": "rogersnowing.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "rory.best", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "roulettecarnival.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "rthsoftware.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "rtwcourse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ruri.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ryanhowell.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -82608,7 +82467,6 @@
     { "name": "whiteeagleca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wibness.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wikileaks.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "williamvds.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "winckelmann2020.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "woodwo.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wossl.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -82687,7 +82545,6 @@
     { "name": "6666365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "7777365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "77zxdy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "7878365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "8225.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "8888365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "889vip5.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83672,7 +83529,6 @@
     { "name": "lc90000.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9108.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9256.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lc973.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9862.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9899.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9900.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -84085,7 +83941,6 @@
     { "name": "friedberg2020.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "frozensector.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ftgeufyihreufheriofeuozirgrgd.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "furryrex.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fuseyahoken.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "g-lab.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gasinstallationsjohannesburg.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -84669,7 +84524,6 @@
     { "name": "iotekha.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "iqsecurity.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "istormsolutions.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "itbloginfo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "itdata.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ithedgehog.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ithink.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -85049,7 +84903,6 @@
     { "name": "xn--uisz44m.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xn--ukasik-2db.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xn--wby9t.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xotv.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xpods.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yavorivanov.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yeptechnology.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -87407,7 +87260,6 @@
     { "name": "1234365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "1voz.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2dua.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "36536555.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "3798.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "3798.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "3aexpert.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -87893,7 +87745,6 @@
     { "name": "rouair.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "rswebsols.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "rt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "rthe.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "s81365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "s82365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sait.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -88021,7 +87872,6 @@
     { "name": "xn--80abwhtbgbedcy6h.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "y81365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "y82365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "yangshangzhen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yify.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ytsdownload.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yumepolo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -88996,7 +88846,6 @@
     { "name": "dleet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dmitriid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dns-check.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "dnstats.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dogma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dogurai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dolciariasimonini.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -89867,9 +89716,6 @@
     { "name": "alteralife.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "am156.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "am8.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "am85168.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "am8811.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "amm6e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "amorgosrentandgo.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ankitha.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arbavere.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -90204,6 +90050,514 @@
     { "name": "zaprefy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zhainanyouhuo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zolotoy-standart.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "01.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "038899.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "0verl0rd.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1248.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1eanda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2fr3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2travel8.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651201.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651202.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651203.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651204.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651205.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365123456.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3653650000.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3653651111.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3653653333.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3653654444.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3655053.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "51cls.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "616578.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "616728.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "616758.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "616798.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "666648.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6upagent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "76678.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "878989.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "96678.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a1demolitionhauling.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a66.la", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6619.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6621.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6623.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6627.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6631.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6651.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6652.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6657.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6659.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6671.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6672.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6673.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6675.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6682.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6683.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6687.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6691.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6692.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a6695.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aardvarksoep.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abbtw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abstimmen.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acpica.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adagia.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "addictedtolength.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agagent.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agahi90.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agds.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agonworks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "algustionesa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aliancapelobrasil.rio.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alimentsduquebecaumenu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alternatyv.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "angiewickes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antoniotirado.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "appmobi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "armensc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arminsure.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "avgindiantech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "avhwelding.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b538.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5901.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5902.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5903.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5904.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5905.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5906.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5907.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5908.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b5910.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b6530.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b6531.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ballenatales.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "barkstop.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "basedos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bayer.earth", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bel-snegirek.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "benedictoaguilar.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bergenson.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "birsinghdhami.com.np", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bitclusive.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bitcorner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluenailsstudio.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bodagratis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bodasgratis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bodin.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bolivar80.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brianwylie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bridgeforcefinancial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brownchair.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bullseyemetrics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bushfirerecovery.gov.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caai.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cabooneconstruction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canperclinicaveterinaria.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canvas-gift.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caudohay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chus-plongee.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cimtools.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "circus-maximus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cloudindex.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coinespe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "colabug.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "comprachida.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "connorcordell.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "controlewiki.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coochiehacks.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cryptofox.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "curvemedia.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyrano-books.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daibetter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "danwise.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "datadraugen.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "datumplus.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "davidelstob.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dfagent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dfc52.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diamondyacca.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diesicheremail.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "digipolis.gent", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dogsdailylife.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dominionedge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "douzer.earth", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dreamingwolf.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drtis.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drvaidyas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dsaengineering.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "edailystar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "edumaster.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ellhofen-peccioli.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elradix.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "empoweraces.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "enity.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "farizhan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fatiguesyndrome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fauwater.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "favedog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feelnet.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fidz.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "funkfamily.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fusionetics.plus", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gda.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "germistonrubbleremovals.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "getcalc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "getwhelp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globaltiendat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glosiko.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glosiko.com.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glosiko.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glosiko.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goldenyacca.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gomu.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goodcreds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goplango.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gossiplolly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "groundengenharia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gtupgrade.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "halloweenmusic.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hallspumpandwellservice.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hearkener.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "herbsupplements.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "herlynlingerie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hierer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "honeycomb.com.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "howonce.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "howonce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "howonce.com.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "howonce.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "howonce.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "howtorunfasterandlonger.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "humitat-stop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "huntyourshitaround.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "i36588.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "i7.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ilab.health", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iletisimmakinesi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "illuminatisocietyworldwide.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "image.hosting", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impactparcels.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impactparcels.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ineffect.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "innovationacademy.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ironycats.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "italianisiert.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itidying.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "j8hs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jessicaevrard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jimsefton.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jobastudio.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joyousisle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jrjuristen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jrstehlik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jrstehlik.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justacoupleofclarkes.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justninja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kadenba.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kakuch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kashrutbaking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kingnascholing.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitchenpad.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitchenpad.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitchenpad.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitchenpad.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitchenpad.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitchenpad.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitchenpadtimer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kotmale.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kubeico.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laissezparler.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laqueuedevache.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leonvermunt.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lesalpinistes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lianglongcredit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lilith-magic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "litecache.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "logibow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lucade.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lumoria.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "luxury-inside.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maisapanama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maisie.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "malcolmellis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manasakcijas.lv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mandalevydesigns.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marliesfens.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "martemeo-wetterau.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mate.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mathsai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matthijsvos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matthijsvos.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maxi-corp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mayblossom.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mdhosting.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meherbaba.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "membershipnetworksite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "memoriadeunaciudadzccm2019.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "midrandrubbleremovals.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "milesdewitt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mintplayer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mojekonsultacje.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "monsterx.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moviro.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mrjones.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mycompanysite.host", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nanxin.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nayefalebrahim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ncrypt.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neroshana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newmanwebsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newsvoice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nicolascornet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "niekbrekelmans.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nixnet.services", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nkio.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "noosxe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "normansolutions.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutritionalsupplement.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "obliviate.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "officevibe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onlinecasinolisboa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "opendoorcounselingpa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "opnaarsalto.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "opticasocialvision.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ortopedio.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "osto.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pabloalbertoazar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pagespeedtweaks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "palmbeachcuisine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "palmbeachwebsitehosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pano-guru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "panthenolplus.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "panthenolplus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paparazzie.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parallaxsite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "passmefaster.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pavelfucik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pavelfucik.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pavelfucik.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pebmarketing.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pentestit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "permaculture.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petherwick.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petherwick.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petherwicks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petitu.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "phongthuyhoangmanh.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pier1url.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pk8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pk9.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "planettimer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "plantsupplement.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "play-the-furyu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "playit.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pm.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "practicalbytes.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "praguemakeover.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "profootballnetwork.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "promods.download", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "promods.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proxmox-airsonic.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pyhello.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qdstationary.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qdstationery.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qliving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quiq-url.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quiq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "radarequation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rany.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rany.int.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redwater.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "remont-warszawa.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "repceszentgyorgy.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "resveratrolsupplement.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ripuree.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "riverviewurologic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rkbegraafplaats.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "royal71.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "royal72.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "royal929.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rpattisonroofing.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rubidi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rubidium.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salariominimo.com.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sardinianvillas.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sardinianvillas.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saxis.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scarabcoder.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schiau.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schoolofequineshiatsu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "servermacher.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shfzzz.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shiroanime.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skalis-portage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skwlkrs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slothless.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smarthealthinnovationlab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sonicseo.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sonomacountywriterscamp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soolid.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soulshinecreators.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "startnowmakingmoneyonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stefanviehbacher.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stehlik.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "studiodpe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "study-support-beans.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suburbansites.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunrichtec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "syncevolution.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sysgap-gsci.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tannerdewitt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tea-empire.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tech-mfoda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teletxt.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teq-automotive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tervemaja.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tewkesburyyoga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texteditor.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thechallenge.fit", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thecreativeedgeinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thinkbot.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "time100.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tinyurl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tirupatinightwear.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tjian.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tocasoft.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tomvst.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tonymaster21.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tout-a-fait.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tredevlet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "turismonochile.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "twentyfournow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uniekglas.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vaccineskill.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vault.investments", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velocityfiber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "villagemagazines.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "virostack.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vlqnc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vnetboard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "voedselbankmoerwijk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vontainment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vvtv.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warmsquirrel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warupu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "web-wakakusa.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webaccio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webclymber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webcreatortool.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webinfotech.com.np", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "willtc.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "willtc.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wiruji.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woningverfspuiten.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woodbornekitchens.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woodbornekitchens.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woodcat.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wwweb.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5901.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5902.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5903.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5904.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5905.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5906.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5907.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5908.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59088.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x5910.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59288.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59388.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59488.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59588.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59688.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59788.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x59988.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x7713.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x7719.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x7782.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x7785.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x7795.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77dd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77hh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77jj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77kk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77mm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77nn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77pp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77qq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77tt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77ww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98f.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98g.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98h.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98i.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98l.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98m.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98n.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98o.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98p.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98r.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98w.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98y.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x98z.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x993.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xamax.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xemcloud.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xiaoneijun.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xiaoneimao.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--lti-3qa.lv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj000444.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj000555.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj000666.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj678678.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj909.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj909.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj909.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj909.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj909.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj919.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj919.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpj919.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjbeting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjcs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjcu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjdi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjei.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjfan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjmd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjtop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjwa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjwb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjwc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpjwd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "y365188.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yellsy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourbusinesscommunity.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourdomain.host", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourpalmbeachcountyrealtor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yule.hk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "z.tl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "z4-forum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeihsel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeparadox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zerox-security.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zfxhzc.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zhenn.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zilv.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zkwolf.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohra.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zondervanacademic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zuzannastrycharska.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc
index 7f404ad..9cda941 100644
--- a/net/server/http_server_unittest.cc
+++ b/net/server/http_server_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
@@ -219,9 +220,11 @@
       return;
 
     base::RunLoop run_loop;
-    run_loop_quit_func_ = run_loop.QuitClosure();
+    base::AutoReset<base::RepeatingClosure> run_loop_quit_func(
+        &run_loop_quit_func_, run_loop.QuitClosure());
     run_loop.Run();
-    run_loop_quit_func_.Reset();
+
+    ASSERT_EQ(requests_.size(), count);
   }
 
   void RunUntilConnectionIdClosed(int connection_id) {
@@ -233,9 +236,13 @@
     }
 
     base::RunLoop run_loop;
-    run_loop_quit_func_ = run_loop.QuitClosure();
+    base::AutoReset<base::RepeatingClosure> run_loop_quit_func(
+        &run_loop_quit_func_, run_loop.QuitClosure());
     run_loop.Run();
-    run_loop_quit_func_.Reset();
+
+    iter = connection_map_.find(connection_id);
+    ASSERT_TRUE(iter != connection_map_.end());
+    ASSERT_FALSE(iter->second);
   }
 
   HttpServerRequestInfo GetRequest(size_t request_index) {
diff --git a/net/url_request/http_with_dns_over_https_unittest.cc b/net/url_request/http_with_dns_over_https_unittest.cc
index 12fe95c0..d4f1d9e 100644
--- a/net/url_request/http_with_dns_over_https_unittest.cc
+++ b/net/url_request/http_with_dns_over_https_unittest.cc
@@ -313,7 +313,7 @@
   EXPECT_EQ(test_https_requests_served_, 0u);
 
   EXPECT_TRUE(d.response_completed());
-  EXPECT_EQ(d.request_status(), net::ERR_DNS_MALFORMED_RESPONSE);
+  EXPECT_EQ(d.request_status(), net::ERR_NAME_NOT_RESOLVED);
 
   const auto& resolve_error_info = req->response_info().resolve_error_info;
   EXPECT_TRUE(resolve_error_info.is_secure_network_error);
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index 9c3c5396..cdc89cc 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -1009,6 +1009,10 @@
 
   viewport_info.zoom = zoom_;
   viewport_info.scale = device_scale_;
+  viewport_info.total_scrollable_size = {GetTotalScrollableWidth(),
+                                         GetTotalScrollableHeight()};
+  viewport_info.current_scroll_position = {GetHorizontalScrollPosition(),
+                                           GetVerticalScrollPosition()};
 
   engine_->GetSelection(&viewport_info.selection_start_page_index,
                         &viewport_info.selection_start_char_index,
@@ -1291,6 +1295,25 @@
       ceil(document_size_.height() * zoom_ * device_scale_));
 }
 
+int OutOfProcessInstance::GetTotalScrollableWidth() const {
+  return std::max(GetDocumentPixelWidth() - plugin_size_.width(), 0);
+}
+
+int OutOfProcessInstance::GetTotalScrollableHeight() const {
+  return std::max(static_cast<int>(GetDocumentPixelHeight() +
+                                   GetToolbarHeightInScreenCoords() -
+                                   plugin_size_.height()),
+                  0);
+}
+
+int OutOfProcessInstance::GetHorizontalScrollPosition() const {
+  return static_cast<int>(scroll_offset_.x() * device_scale_);
+}
+
+int OutOfProcessInstance::GetVerticalScrollPosition() const {
+  return static_cast<int>(scroll_offset_.y() * device_scale_);
+}
+
 void OutOfProcessInstance::FillRect(const pp::Rect& rect, uint32_t color) {
   DCHECK(!image_data_.is_null() || rect.IsEmpty());
   uint32_t* buffer_start = static_cast<uint32_t*>(image_data_.data());
@@ -1982,7 +2005,7 @@
   pp::PDF::SetPluginCanSave(this, ShouldSaveEdits());
 }
 
-float OutOfProcessInstance::GetToolbarHeightInScreenCoords() {
+float OutOfProcessInstance::GetToolbarHeightInScreenCoords() const {
   return top_toolbar_height_in_viewport_coords_ * device_scale_;
 }
 
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h
index de8ab5fc..4ed34bd8 100644
--- a/pdf/out_of_process_instance.h
+++ b/pdf/out_of_process_instance.h
@@ -149,7 +149,7 @@
   void IsSelectingChanged(bool is_selecting) override;
   void SelectionChanged(const pp::Rect& left, const pp::Rect& right) override;
   void IsEditModeChanged(bool is_edit_mode) override;
-  float GetToolbarHeightInScreenCoords() override;
+  float GetToolbarHeightInScreenCoords() const override;
 
   // PreviewModeClient::Client implementation.
   void PreviewDocumentLoadComplete() override;
@@ -179,6 +179,14 @@
   int GetDocumentPixelWidth() const;
   int GetDocumentPixelHeight() const;
 
+  // Computes total scrollable Width and Height of the document.
+  int GetTotalScrollableWidth() const;
+  int GetTotalScrollableHeight() const;
+
+  // Computes current horizontal and scroll position of the document.
+  int GetHorizontalScrollPosition() const;
+  int GetVerticalScrollPosition() const;
+
   // Draws a rectangle with the specified dimensions and color in our buffer.
   void FillRect(const pp::Rect& rect, uint32_t color);
 
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index 48b22de..566f40b 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -281,7 +281,7 @@
 
     // Gets the height of the top toolbar in screen coordinates. This is
     // independent of whether it is hidden or not at the moment.
-    virtual float GetToolbarHeightInScreenCoords() = 0;
+    virtual float GetToolbarHeightInScreenCoords() const = 0;
   };
 
   struct AccessibilityLinkInfo {
diff --git a/pdf/preview_mode_client.cc b/pdf/preview_mode_client.cc
index 141b9eb..ee73d2cd 100644
--- a/pdf/preview_mode_client.cc
+++ b/pdf/preview_mode_client.cc
@@ -150,7 +150,7 @@
   return false;
 }
 
-float PreviewModeClient::GetToolbarHeightInScreenCoords() {
+float PreviewModeClient::GetToolbarHeightInScreenCoords() const {
   return 0.0f;
 }
 
diff --git a/pdf/preview_mode_client.h b/pdf/preview_mode_client.h
index e7b2e28..3df2019 100644
--- a/pdf/preview_mode_client.h
+++ b/pdf/preview_mode_client.h
@@ -67,7 +67,7 @@
   void DocumentHasUnsupportedFeature(const std::string& feature) override;
   void FormTextFieldFocusChange(bool in_focus) override;
   bool IsPrintPreview() override;
-  float GetToolbarHeightInScreenCoords() override;
+  float GetToolbarHeightInScreenCoords() const override;
   uint32_t GetBackgroundColor() override;
 
  private:
diff --git a/pdf/test/test_client.cc b/pdf/test/test_client.cc
index 7fab6611..4b979d56 100644
--- a/pdf/test/test_client.cc
+++ b/pdf/test/test_client.cc
@@ -56,7 +56,7 @@
   return 0;
 }
 
-float TestClient::GetToolbarHeightInScreenCoords() {
+float TestClient::GetToolbarHeightInScreenCoords() const {
   return 0;
 }
 
diff --git a/pdf/test/test_client.h b/pdf/test/test_client.h
index 4eaf930..0abea0b 100644
--- a/pdf/test/test_client.h
+++ b/pdf/test/test_client.h
@@ -37,7 +37,7 @@
   pp::Instance* GetPluginInstance() override;
   bool IsPrintPreview() override;
   uint32_t GetBackgroundColor() override;
-  float GetToolbarHeightInScreenCoords() override;
+  float GetToolbarHeightInScreenCoords() const override;
 
  private:
   // Not owned. Expected to dangle briefly, as the engine usually is destroyed
diff --git a/ppapi/c/private/ppb_pdf.h b/ppapi/c/private/ppb_pdf.h
index cfa0ef1..c209670 100644
--- a/ppapi/c/private/ppb_pdf.h
+++ b/ppapi/c/private/ppb_pdf.h
@@ -36,6 +36,10 @@
 struct PP_PrivateAccessibilityViewportInfo {
   double zoom;
   double scale;
+  // |total_scrollable_size| and |current_scroll_position| are relative
+  // to plugin embed and in screen coordinates.
+  struct PP_Size total_scrollable_size;
+  struct PP_Point current_scroll_position;
   struct PP_Point scroll;
   struct PP_Point offset;
   uint32_t selection_start_page_index;
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 88911ac..a80fd2d 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -268,6 +268,8 @@
 IPC_STRUCT_TRAITS_BEGIN(PP_PrivateAccessibilityViewportInfo)
   IPC_STRUCT_TRAITS_MEMBER(zoom)
   IPC_STRUCT_TRAITS_MEMBER(scale)
+  IPC_STRUCT_TRAITS_MEMBER(total_scrollable_size)
+  IPC_STRUCT_TRAITS_MEMBER(current_scroll_position)
   IPC_STRUCT_TRAITS_MEMBER(scroll)
   IPC_STRUCT_TRAITS_MEMBER(offset)
   IPC_STRUCT_TRAITS_MEMBER(selection_start_page_index)
diff --git a/remoting/resources/remoting_strings_ar.xtb b/remoting/resources/remoting_strings_ar.xtb
index 32e055b..874a6045 100644
--- a/remoting/resources/remoting_strings_ar.xtb
+++ b/remoting/resources/remoting_strings_ar.xtb
@@ -188,7 +188,7 @@
 <translation id="5327248766486351172">الاسم</translation>
 <translation id="533625276787323658">لا يوجد أي جهاز كمبيوتر للاتصال به</translation>
 <translation id="5363265567587775042">اطلب من المستخدم الذي ترغب في الدخول إلى جهاز الكمبيوتر التابع له أن ينقر على "<ph name="SHARE" />" وأن يمنحك رمز الدخول.</translation>
-<translation id="5379087427956679853">‏يسمح لك سطح المكتب البعيد من Chrome بمشاركة جهاز الكمبيوتر التابع لك بشكل آمن عبر الويب. ويجب أن يشغّل كلا المستخدمَين تطبيق سطح المكتب البعيد من Chrome، والذي يمكن العثور عليه على <ph name="URL" />.</translation>
+<translation id="5379087427956679853">‏يسمح لك سطح المكتب البعيد من Chrome بمشاركة جهاز الكمبيوتر التابع لك بشكل آمن على الويب. ويجب أن يشغّل كلا المستخدمَين تطبيق سطح المكتب البعيد من Chrome، والذي يمكن العثور عليه على <ph name="URL" />.</translation>
 <translation id="5397086374758643919">‏أداة إزالة مضيف سطح المكتب البعيد من Chrome</translation>
 <translation id="5419185025274123272">تعذر إعادة ضبط التطبيق. لا يزال بإمكانك إرسال تقرير للإبلاغ عن خلل.</translation>
 <translation id="5419418238395129586">آخر اتصال بالإنترنت: <ph name="DATE" /></translation>
@@ -208,7 +208,7 @@
 <translation id="5841343754884244200">خيارات العرض</translation>
 <translation id="5843054235973879827">ما سبب تمتع هذه العملية بالأمان؟</translation>
 <translation id="5859141382851488196">نافذة جديدة…</translation>
-<translation id="6011539954251327702">‏يسمح لك تطبيق التوافق مع نظام التشغيل Chrome بمشاركة جهاز الكمبيوتر التابع لك بشكل آمن عبر الويب. ويجب أن يشغّل كلا المستخدمَين تطبيق التوافق مع نظام التشغيل Chrome، والذي يمكن العثور عليه على <ph name="URL" />.</translation>
+<translation id="6011539954251327702">‏يسمح لك تطبيق التوافق مع نظام التشغيل Chrome بمشاركة جهاز الكمبيوتر التابع لك بشكل آمن على الويب. ويجب أن يشغّل كلا المستخدمَين تطبيق التوافق مع نظام التشغيل Chrome، والذي يمكن العثور عليه على <ph name="URL" />.</translation>
 <translation id="6033507038939587647">خيارات لوحة المفاتيح</translation>
 <translation id="6040143037577758943">إغلاق</translation>
 <translation id="6062854958530969723">فشلت تهيئة المضيف.</translation>
diff --git a/remoting/resources/remoting_strings_it.xtb b/remoting/resources/remoting_strings_it.xtb
index d85c240..294650d 100644
--- a/remoting/resources/remoting_strings_it.xtb
+++ b/remoting/resources/remoting_strings_it.xtb
@@ -106,7 +106,7 @@
 <translation id="3581045510967524389">Impossibile collegarsi alla rete. Controlla che il dispositivo sia online.</translation>
 <translation id="3596628256176442606">Questo servizio consente connessioni in entrata da client Chromoting.</translation>
 <translation id="3606997049964069799">Non hai eseguito l'accesso a Chromium. Accedi e riprova.</translation>
-<translation id="3649256019230929621">Riduci la finestra</translation>
+<translation id="3649256019230929621">Riduce la finestra</translation>
 <translation id="369442766917958684">Offline.</translation>
 <translation id="3695446226812920698">Scopri come</translation>
 <translation id="3718805989288361841">Si è verificato un errore con le impostazioni delle norme per Chrome Remote Desktop. Contatta l'amministratore di sistema per ricevere assistenza.</translation>
diff --git a/remoting/resources/remoting_strings_sv.xtb b/remoting/resources/remoting_strings_sv.xtb
index 1a4ab1b..c7da790 100644
--- a/remoting/resources/remoting_strings_sv.xtb
+++ b/remoting/resources/remoting_strings_sv.xtb
@@ -83,7 +83,7 @@
 <translation id="2926340305933667314">Det gick inte att inaktivera fjärråtkomst till den här datorn. Försök igen senare.</translation>
 <translation id="2930135165929238380">Vissa obligatoriska komponenter saknas. Öppna chrome://plugins och kontrollera att Native Client har aktiverats.</translation>
 <translation id="2939145106548231838">Autentisera till värd</translation>
-<translation id="3020807351229499221">Det gick inte att uppdatera PIN-koden. Försök igen senare.</translation>
+<translation id="3020807351229499221">Det gick inte att uppdatera pinkoden. Försök igen senare.</translation>
 <translation id="3025388528294795783">Hjälp oss att lösa problemet och berätta vad som har gått fel.</translation>
 <translation id="3027681561976217984">Tryckläge</translation>
 <translation id="3106379468611574572">Fjärrdatorn svarar inte på anslutningsbegäran. Kontrollera att den är ansluten till Internet och försök igen.</translation>
@@ -98,7 +98,7 @@
 <translation id="332624996707057614">Ändra datorns namn</translation>
 <translation id="3339299787263251426">Säker åtkomst till datorn via internet</translation>
 <translation id="3360306038446926262">Fönster</translation>
-<translation id="3362124771485993931">Ange PIN-koden igen</translation>
+<translation id="3362124771485993931">Ange pinkoden igen</translation>
 <translation id="337167041784729019">Visa statistik</translation>
 <translation id="3385242214819933234">Ogiltig ägare till värden.</translation>
 <translation id="3403830762023901068">Enligt policyinställningarna får du inte dela den här datorn som en Chromoting-värd. Kontakta systemadministratören om du behöver hjälp.</translation>
@@ -128,7 +128,7 @@
 <translation id="4126409073460786861">När konfigureringen är klar uppdaterar du den här sidan. Sedan kan du ansluta till datorn genom att välja enheten och ange pinkoden</translation>
 <translation id="4145029455188493639">Inloggad som <ph name="EMAIL_ADDRESS" />.</translation>
 <translation id="4155497795971509630">Vissa obligatoriska komponenter saknas. Kontrollera att du har installerat den senaste versionen av programvaran och försök igen.</translation>
-<translation id="4156740505453712750">Om du vill skydda åtkomsten till den här datorn väljer du en PIN-kod som består av <ph name="BOLD_START" />minst sex siffror<ph name="BOLD_END" />. PIN-koden krävs när du ansluter från en annan plats.</translation>
+<translation id="4156740505453712750">Om du vill skydda åtkomsten till den här datorn väljer du en pinkod som består av <ph name="BOLD_START" />minst sex siffror<ph name="BOLD_END" />. Pinkoden krävs när du ansluter från en annan plats.</translation>
 <translation id="4169432154993690151">Ge Chrome Remote Desktop åtkomst till kameran om du vill välja profilbild</translation>
 <translation id="4176825807642096119">Åtkomstkod</translation>
 <translation id="4207623512727273241">Kör installationsprogrammet innan du fortsätter.</translation>
@@ -163,7 +163,7 @@
 <translation id="4795786176190567663">Du har inte behörighet att utföra den åtgärden.</translation>
 <translation id="4798680868612952294">Musalternativ</translation>
 <translation id="4804818685124855865">Koppla från</translation>
-<translation id="4808503597364150972">Ange din PIN-kod för <ph name="HOSTNAME" />.</translation>
+<translation id="4808503597364150972">Ange din pinkod för <ph name="HOSTNAME" />.</translation>
 <translation id="4812684235631257312">Värd</translation>
 <translation id="4867841927763172006">Skicka PrtScn</translation>
 <translation id="4913529628896049296">väntar på anslutning ...</translation>
@@ -176,14 +176,14 @@
 <translation id="5070121137485264635">Fjärrvärden kräver att du autentiserar via en tredje parts webbplats. Om du vill fortsätta måste du ge Chrome Remote Desktop ytterligare behörigheter att komma åt den här adressen:</translation>
 <translation id="507204348399810022">Är du säker på att du vill inaktivera fjärranslutningar till <ph name="HOSTNAME" />?</translation>
 <translation id="5081343395220691640">Det gick inte att kommunicera med servern: <ph name="ERROR" /></translation>
-<translation id="5156271271724754543">Ange samma PIN-kod i båda rutorna.</translation>
+<translation id="5156271271724754543">Ange samma pinkod i båda rutorna.</translation>
 <translation id="5170982930780719864">Ogiltigt värd-id.</translation>
 <translation id="518094545883702183">Den här informationen används bara för att diagnostisera det som felrapporten gäller. Bara den som arbetar med ärendet kan se den och den sparas i högst 30 dagar.</translation>
 <translation id="5204575267916639804">Vanliga frågor</translation>
 <translation id="5222676887888702881">Logga ut</translation>
 <translation id="5234764350956374838">Ta bort permanent</translation>
 <translation id="5254120496627797685">Om du lämnar sidan avslutas sessionen i Chrome Remote Desktop.</translation>
-<translation id="5308380583665731573">Ansluta</translation>
+<translation id="5308380583665731573">Anslut</translation>
 <translation id="5327248766486351172">Namn</translation>
 <translation id="533625276787323658">Det finns inget att ansluta till</translation>
 <translation id="5363265567587775042">Be användaren vars dator du vill använda att klicka på <ph name="SHARE" /> och ge dig åtkomstkoden.</translation>
@@ -194,7 +194,7 @@
 <translation id="544077782045763683">Värdenheten har stängts av.</translation>
 <translation id="5510035215749041527">Koppla från nu</translation>
 <translation id="5593560073513909978">Tjänsten är inte tillgänglig för närvarande. Försök igen senare.</translation>
-<translation id="5601503069213153581">PIN-kod</translation>
+<translation id="5601503069213153581">Pinkod</translation>
 <translation id="5619148062500147964">Till den här datorn</translation>
 <translation id="5625493749705183369">Få åtkomst till andra datorer eller ge andra åtkomst till din dator över internet på ett säkert sätt.</translation>
 <translation id="5702987232842159181">Ansluten:</translation>
@@ -219,7 +219,7 @@
 <translation id="6178645564515549384">Lokal meddelandevärd för fjärrhjälp</translation>
 <translation id="618120821413932081">Uppdaterar fjärrskrivbordets upplösning så att det passar fönstret</translation>
 <translation id="6193698048504518729">Anslut till <ph name="HOSTNAME" /></translation>
-<translation id="6198252989419008588">Byt PIN</translation>
+<translation id="6198252989419008588">Byt pinkod</translation>
 <translation id="6204583485351780592"><ph name="HOSTNAME" /> (inaktuellt)</translation>
 <translation id="6221358653751391898">Du är inte inloggad i Chrome. Logga in och försök igen.</translation>
 <translation id="6223301979382383752">Öppna inställningarna för skärminspelning</translation>
@@ -235,7 +235,7 @@
 
 Om <ph name="SERVICE_SCRIPT_NAME" /> redan har markerats avmarkerar du rutan och markerar den på nytt.</translation>
 <translation id="6441316101718669559">Integrering med skrivbordet stöds inte på den här plattformen. Du kan använda appen ändå, men användarupplevelsen försämras.</translation>
-<translation id="652218476070540101">PIN-koden för den här datorn uppdateras …</translation>
+<translation id="652218476070540101">Pinkoden för den här datorn uppdateras …</translation>
 <translation id="6527303717912515753">Dela</translation>
 <translation id="6541219117979389420">Programloggar kan innehålla privata uppgifter, som din identitet (e-postadress) och namn på och egenskaper hos filer och mappar på Google Drive.</translation>
 <translation id="6542902059648396432">Rapportera ett problem …</translation>
@@ -244,7 +244,7 @@
 <translation id="6583902294974160967">Support</translation>
 <translation id="6612717000975622067">Skicka Ctrl-Alt-Del</translation>
 <translation id="6654753848497929428">Dela</translation>
-<translation id="6668065415969892472">PIN-koden har uppdaterats.</translation>
+<translation id="6668065415969892472">Pinkoden har uppdaterats.</translation>
 <translation id="6681800064886881394">Upphovsrätt 2013 Google Inc. Med ensamrätt.</translation>
 <translation id="6705482892455291412">När den andra parten har angett koden blir du ombedd att godkänna anslutningen och börja delningssessionen.</translation>
 <translation id="6746493157771801606">Rensa historik</translation>
@@ -268,7 +268,7 @@
 <translation id="7116737094673640201">Välkommen till Chrome Remote Desktop</translation>
 <translation id="7144878232160441200">Försök igen</translation>
 <translation id="7149517134817561223">Program som används för att skicka kommandon till värddatorn för Chrome Remote Desktop.</translation>
-<translation id="7215059001581613786">Ange en PIN-kod som består av minst sex siffror.</translation>
+<translation id="7215059001581613786">Ange en pinkod som består av minst sex siffror.</translation>
 <translation id="7312846573060934304">Värden är offline.</translation>
 <translation id="7319983568955948908">Sluta dela</translation>
 <translation id="7401733114166276557">Chrome Remote Desktop</translation>
diff --git a/sandbox/win/src/sandbox_nt_util.cc b/sandbox/win/src/sandbox_nt_util.cc
index 2dc59c9f..d7f6f032 100644
--- a/sandbox/win/src/sandbox_nt_util.cc
+++ b/sandbox/win/src/sandbox_nt_util.cc
@@ -9,6 +9,7 @@
 
 #include <string>
 
+#include "base/compiler_specific.h"
 #include "base/win/pe_image.h"
 #include "sandbox/win/src/sandbox_factory.h"
 #include "sandbox/win/src/target_services.h"
@@ -58,18 +59,8 @@
   const char* top_address = base + kMaxSize;
 
   while (base < top_address) {
-    // Initialize all fields to avoid memset with init_stack_vars = true.
-    // "= {}" or  -ftrivial-auto-var-init=pattern may insert memset or memcpy
-    // here. However if memset was used here even "init_stack_vars = false
-    // is_debug = true" on x86_64 crashes in GPU process.
-    MEMORY_BASIC_INFORMATION mem_info;
-    mem_info.BaseAddress = nullptr;
-    mem_info.AllocationBase = nullptr;
-    mem_info.AllocationProtect = 0;
-    mem_info.RegionSize = 0;
-    mem_info.State = 0;
-    mem_info.Protect = 0;
-    mem_info.Type = 0;
+    // Avoid memset inserted by -ftrivial-auto-var-init=pattern.
+    STACK_UNINITIALIZED MEMORY_BASIC_INFORMATION mem_info;
     NTSTATUS status =
         g_nt.QueryVirtualMemory(NtCurrentProcess, base, MemoryBasicInformation,
                                 &mem_info, sizeof(mem_info), nullptr);
diff --git a/services/content/service.cc b/services/content/service.cc
index 0e63868..5e295321 100644
--- a/services/content/service.cc
+++ b/services/content/service.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "mojo/public/cpp/bindings/binding.h"
 #include "services/content/navigable_contents_factory_impl.h"
 #include "services/content/navigable_contents_impl.h"
 #include "services/content/public/mojom/navigable_contents_factory.mojom.h"
diff --git a/services/device/generic_sensor/platform_sensor_fusion_unittest.cc b/services/device/generic_sensor/platform_sensor_fusion_unittest.cc
index b3bd493..de9dfbb 100644
--- a/services/device/generic_sensor/platform_sensor_fusion_unittest.cc
+++ b/services/device/generic_sensor/platform_sensor_fusion_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/test/task_environment.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h"
 #include "services/device/generic_sensor/fake_platform_sensor_and_provider.h"
 #include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
diff --git a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
index 36748199..f411c1b4 100644
--- a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
+++ b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
@@ -612,8 +612,7 @@
                     continue;
                 }
             }
-            if (!options.mediaType.isEmpty()
-                    && !options.mediaType.equals(message.data[i].mediaType)) {
+            if (options.mediaType != null && !options.mediaType.equals(message.data[i].mediaType)) {
                 continue;
             }
 
diff --git a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
index eb48e4e..661c3d5 100644
--- a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
+++ b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
@@ -1234,7 +1234,6 @@
 
     private NdefScanOptions createNdefScanOptions() {
         NdefScanOptions options = new NdefScanOptions();
-        options.mediaType = "";
         return options;
     }
 
diff --git a/services/device/public/mojom/nfc.mojom b/services/device/public/mojom/nfc.mojom
index 0fd7d21..251b020 100644
--- a/services/device/public/mojom/nfc.mojom
+++ b/services/device/public/mojom/nfc.mojom
@@ -106,11 +106,13 @@
   // string means must match on empty.
   string? id;
 
-  // Defines record type filtering constraint.
+  // Defines record type filtering constraint. Null means don't filter, empty
+  // string means must match on empty.
   string? record_type;
 
-  // Defines media type filtering constraint. Empty string means don't filter.
-  string media_type;
+  // Defines media type filtering constraint. Null means don't filter, empty
+  // string means must match on empty.
+  string? media_type;
 };
 
 interface NFC {
diff --git a/services/network/network_change_manager_unittest.cc b/services/network/network_change_manager_unittest.cc
index 45dc5aa2..249c0d9 100644
--- a/services/network/network_change_manager_unittest.cc
+++ b/services/network/network_change_manager_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/network_change_notifier.h"
 #include "services/network/public/mojom/network_change_manager.mojom.h"
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index e275ed3..c18c3d9f 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -1162,7 +1162,8 @@
     const net::NetworkIsolationKey& key,
     mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
         pending_handshake_client) {
-  // TODO(yhirano): Implement this and have a security review on the impl too.
+  quic_transports_.insert(std::make_unique<QuicTransport>(
+      url, origin, key, this, std::move(pending_handshake_client)));
 }
 
 void NetworkContext::CreateNetLogExporter(
@@ -1615,6 +1616,13 @@
   return &http_auth_merged_preferences_;
 }
 
+size_t NetworkContext::NumOpenQuicTransports() const {
+  return std::count_if(quic_transports_.begin(), quic_transports_.end(),
+                       [](const std::unique_ptr<QuicTransport>& transport) {
+                         return !transport->torn_down();
+                       });
+}
+
 void NetworkContext::OnHttpAuthDynamicParamsChanged(
     const mojom::HttpAuthDynamicParams*
         http_auth_dynamic_network_service_params) {
diff --git a/services/network/network_context.h b/services/network/network_context.h
index 27824853..1e2f6641 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -467,7 +467,7 @@
 
   const net::HttpAuthPreferences* GetHttpAuthPreferences() const;
 
-  size_t num_open_quic_transports() const { return quic_transports_.size(); }
+  size_t NumOpenQuicTransports() const;
 
  private:
   URLRequestContextOwner MakeURLRequestContext(
diff --git a/services/network/public/cpp/cors/cors.cc b/services/network/public/cpp/cors/cors.cc
index 28a76e6..5473216c 100644
--- a/services/network/public/cpp/cors/cors.cc
+++ b/services/network/public/cpp/cors/cors.cc
@@ -274,10 +274,9 @@
   // request doesn't have one, CORS should not work.
   DCHECK(request_initiator);
 
-  // TODO(crbug.com/870173): Remove following scheme check once the network
-  // service is fully enabled.
-  if (request_url.SchemeIs(url::kDataScheme))
-    return false;
+  // |request_url| should not contain the url::kDataScheme here, but have a
+  // DCHECK for a while, just in case.
+  DCHECK(!request_url.SchemeIs(url::kDataScheme));
 
   if (request_initiator->IsSameOriginWith(url::Origin::Create(request_url)))
     return false;
diff --git a/services/network/public/cpp/cors/cors.h b/services/network/public/cpp/cors/cors.h
index c76913b..231421f 100644
--- a/services/network/public/cpp/cors/cors.h
+++ b/services/network/public/cpp/cors/cors.h
@@ -60,8 +60,9 @@
     const url::Origin& origin);
 
 // Returns true if |request_mode| is not kNavigate nor kNoCors, and the
-// origin of |request_url| is not a data URL, and |request_initiator| is not
-// same as the origin of |request_url|,
+// |request_initiator| is not same as the origin of |request_url|. The
+// |request_url| is expected to have a http or https scheme as they are only
+// schemes that the spec officially supports.
 COMPONENT_EXPORT(NETWORK_CPP)
 bool ShouldCheckCors(const GURL& request_url,
                      const base::Optional<url::Origin>& request_initiator,
diff --git a/services/network/public/cpp/server/http_server_unittest.cc b/services/network/public/cpp/server/http_server_unittest.cc
index ba00cb7b..6ccde8fa 100644
--- a/services/network/public/cpp/server/http_server_unittest.cc
+++ b/services/network/public/cpp/server/http_server_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/run_loop.h"
@@ -228,9 +229,11 @@
       return;
 
     base::RunLoop run_loop;
-    run_loop_quit_func_ = run_loop.QuitClosure();
+    base::AutoReset<base::RepeatingClosure> run_loop_quit_func(
+        &run_loop_quit_func_, run_loop.QuitClosure());
     run_loop.Run();
-    run_loop_quit_func_.Reset();
+
+    ASSERT_EQ(requests_.size(), count);
   }
 
   void RunUntilConnectionIdClosed(int connection_id) {
@@ -242,9 +245,13 @@
     }
 
     base::RunLoop run_loop;
-    run_loop_quit_func_ = run_loop.QuitClosure();
+    base::AutoReset<base::RepeatingClosure> run_loop_quit_func(
+        &run_loop_quit_func_, run_loop.QuitClosure());
     run_loop.Run();
-    run_loop_quit_func_.Reset();
+
+    iter = connection_map_.find(connection_id);
+    ASSERT_TRUE(iter != connection_map_.end());
+    ASSERT_FALSE(iter->second);
   }
 
   HttpServerRequestInfo GetRequest(size_t request_index) {
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index 369e6ad..e6f1c1c 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -1120,7 +1120,9 @@
         pending_remote<AuthenticationHandler>? auth_handler,
         pending_remote<TrustedHeaderClient>? header_client);
 
-  // Creates a QuicTransport connection to |url|.
+  // Creates a QuicTransport connection to |url|. |origin| is used for the
+  // client indication - see
+  // https://tools.ietf.org/html/draft-vvv-webtransport-quic-01#section-3.2 .
   //
   // It is recommended to detect mojo connection errors on |handshake_client|.
   CreateQuicTransport(
diff --git a/services/network/quic_transport.cc b/services/network/quic_transport.cc
index afb7fa8..80607f49 100644
--- a/services/network/quic_transport.cc
+++ b/services/network/quic_transport.cc
@@ -4,6 +4,8 @@
 
 #include "services/network/quic_transport.h"
 
+#include "base/bind.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "net/base/io_buffer.h"
 #include "net/quic/platform/impl/quic_mem_slice_impl.h"
 #include "net/third_party/quiche/src/quic/core/quic_session.h"
@@ -40,6 +42,8 @@
 
 void QuicTransport::SendDatagram(base::span<const uint8_t> data,
                                  base::OnceCallback<void(bool)> callback) {
+  DCHECK(!torn_down_);
+
   auto buffer = base::MakeRefCounted<net::IOBuffer>(data.size());
   memcpy(buffer->data(), data.data(), data.size());
   quic::QuicMemSlice slice(
@@ -50,6 +54,10 @@
 }
 
 void QuicTransport::OnConnected() {
+  if (torn_down_) {
+    return;
+  }
+
   DCHECK(handshake_client_);
 
   handshake_client_->OnConnectionEstablished(
@@ -62,32 +70,52 @@
 }
 
 void QuicTransport::OnConnectionFailed() {
+  if (torn_down_) {
+    return;
+  }
+
   DCHECK(handshake_client_);
 
   handshake_client_->OnHandshakeFailed();
 
-  Dispose();
-  // |this| is deleted.
+  TearDown();
 }
 
 void QuicTransport::OnClosed() {
+  if (torn_down_) {
+    return;
+  }
+
   DCHECK(!handshake_client_);
 
-  Dispose();
-  // |this| is deleted.
+  TearDown();
 }
 
 void QuicTransport::OnError() {
+  if (torn_down_) {
+    return;
+  }
+
   DCHECK(!handshake_client_);
 
-  Dispose();
-  // |this| is deleted.
+  TearDown();
 }
 
 void QuicTransport::OnIncomingBidirectionalStreamAvailable() {}
 
 void QuicTransport::OnIncomingUnidirectionalStreamAvailable() {}
 
+void QuicTransport::TearDown() {
+  torn_down_ = true;
+  receiver_.reset();
+  handshake_client_.reset();
+  client_.reset();
+
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&QuicTransport::Dispose, weak_factory_.GetWeakPtr()));
+}
+
 void QuicTransport::Dispose() {
   context_->Remove(this);
   // |this| is deleted.
diff --git a/services/network/quic_transport.h b/services/network/quic_transport.h
index ed42325..36a45dd2 100644
--- a/services/network/quic_transport.h
+++ b/services/network/quic_transport.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/quic/quic_transport_client.h"
@@ -53,15 +54,23 @@
   void OnIncomingBidirectionalStreamAvailable() override;
   void OnIncomingUnidirectionalStreamAvailable() override;
 
-  void Dispose();
+  bool torn_down() const { return torn_down_; }
 
  private:
+  void TearDown();
+  void Dispose();
+
   const std::unique_ptr<net::QuicTransportClient> transport_;
   NetworkContext* const context_;  // outlives |this|.
 
   mojo::Receiver<mojom::QuicTransport> receiver_;
   mojo::Remote<mojom::QuicTransportHandshakeClient> handshake_client_;
   mojo::Remote<mojom::QuicTransportClient> client_;
+
+  bool torn_down_ = false;
+
+  // This must be the last member.
+  base::WeakPtrFactory<QuicTransport> weak_factory_{this};
 };
 
 }  // namespace network
diff --git a/services/network/quic_transport_unittest.cc b/services/network/quic_transport_unittest.cc
index 2f30f8df..26e1d0fc 100644
--- a/services/network/quic_transport_unittest.cc
+++ b/services/network/quic_transport_unittest.cc
@@ -109,22 +109,22 @@
   }
   ~QuicTransportTest() override = default;
 
-  std::unique_ptr<QuicTransport> CreateQuicTransport(
+  void CreateQuicTransport(
       const GURL& url,
       const url::Origin& origin,
       const net::NetworkIsolationKey& key,
       mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
           handshake_client) {
-    return std::make_unique<QuicTransport>(url, origin, key, &network_context_,
-                                           std::move(handshake_client));
+    network_context_.CreateQuicTransport(url, origin, key,
+                                         std::move(handshake_client));
   }
-  std::unique_ptr<QuicTransport> CreateQuicTransport(
+  void CreateQuicTransport(
       const GURL& url,
       const url::Origin& origin,
       mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
           handshake_client) {
-    return CreateQuicTransport(url, origin, net::NetworkIsolationKey(),
-                               std::move(handshake_client));
+    CreateQuicTransport(url, origin, net::NetworkIsolationKey(),
+                        std::move(handshake_client));
   }
 
   GURL GetURL(base::StringPiece suffix) {
@@ -156,14 +156,15 @@
       handshake_client.InitWithNewPipeAndPassReceiver(),
       run_loop_for_handshake.QuitClosure());
 
-  auto transport = CreateQuicTransport(GetURL("/discard"), origin(),
-                                       std::move(handshake_client));
+  CreateQuicTransport(GetURL("/discard"), origin(),
+                      std::move(handshake_client));
 
   run_loop_for_handshake.Run();
 
   EXPECT_TRUE(test_handshake_client.has_seen_connection_establishment());
   EXPECT_FALSE(test_handshake_client.has_seen_handshake_failure());
   EXPECT_FALSE(test_handshake_client.has_seen_mojo_connection_error());
+  EXPECT_EQ(1u, network_context().NumOpenQuicTransports());
 }
 
 TEST_F(QuicTransportTest, ConnectWithError) {
@@ -174,9 +175,9 @@
       run_loop_for_handshake.QuitClosure());
 
   // This should fail due to the wrong origin
-  auto transport = CreateQuicTransport(
-      GetURL("/discard"), url::Origin::Create(GURL("https://evil.com")),
-      std::move(handshake_client));
+  CreateQuicTransport(GetURL("/discard"),
+                      url::Origin::Create(GURL("https://evil.com")),
+                      std::move(handshake_client));
 
   run_loop_for_handshake.Run();
 
@@ -193,9 +194,9 @@
       handshake_client.InitWithNewPipeAndPassReceiver(),
       run_loop_for_handshake.QuitClosure());
 
-  auto transport = CreateQuicTransport(
-      GetURL("/discard"), url::Origin::Create(GURL("https://example.org/")),
-      std::move(handshake_client));
+  CreateQuicTransport(GetURL("/discard"),
+                      url::Origin::Create(GURL("https://example.org/")),
+                      std::move(handshake_client));
 
   run_loop_for_handshake.Run();
 
@@ -220,9 +221,9 @@
       handshake_client.InitWithNewPipeAndPassReceiver(),
       run_loop_for_handshake.QuitClosure());
 
-  auto transport = CreateQuicTransport(
-      GetURL("/discard"), url::Origin::Create(GURL("https://example.org/")),
-      std::move(handshake_client));
+  CreateQuicTransport(GetURL("/discard"),
+                      url::Origin::Create(GURL("https://example.org/")),
+                      std::move(handshake_client));
 
   run_loop_for_handshake.Run();
 
diff --git a/services/network/test/test_network_service_client.h b/services/network/test/test_network_service_client.h
index aa7cb2c..8845eca6 100644
--- a/services/network/test/test_network_service_client.h
+++ b/services/network/test/test_network_service_client.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "build/build_config.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "net/cookies/canonical_cookie.h"
diff --git a/services/network/tls_socket_factory.cc b/services/network/tls_socket_factory.cc
index a5b51ff..7f7dd14f 100644
--- a/services/network/tls_socket_factory.cc
+++ b/services/network/tls_socket_factory.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/optional.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/net_errors.h"
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 98f7fd4..5424e5c 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -1008,8 +1008,10 @@
           network::features::kOutOfBlinkFrameAncestors)) {
     // Parse the Content-Security-Policy headers.
     ContentSecurityPolicy policy;
-    if (policy.Parse(url_request_->url(), *url_request_->response_headers()))
+    if (url_request_->response_headers() &&
+        policy.Parse(url_request_->url(), *url_request_->response_headers())) {
       response_->content_security_policy = policy.TakeContentSecurityPolicy();
+    }
   }
 
   if (base::FeatureList::IsEnabled(features::kCrossOriginIsolation)) {
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
index 1f55838..09395e2ef 100644
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/time/time.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "build/build_config.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/services/service_manager/sandbox/sandbox_type.h b/services/service_manager/sandbox/sandbox_type.h
index 41a104a9..40dacf66 100644
--- a/services/service_manager/sandbox/sandbox_type.h
+++ b/services/service_manager/sandbox/sandbox_type.h
@@ -38,8 +38,7 @@
   // Renderer or worker process. Most common case.
   kRenderer,
 
-  // Utility process is as restrictive as the worker process except full
-  // access is allowed to one configurable directory.
+  // Utility processes. Used by most isolated services.
   kUtility,
 
   // GPU process.
diff --git a/services/service_manager/tests/service_manager/service_manager_unittest.cc b/services/service_manager/tests/service_manager/service_manager_unittest.cc
index 7149fe83..0e7ef3b 100644
--- a/services/service_manager/tests/service_manager/service_manager_unittest.cc
+++ b/services/service_manager/tests/service_manager/service_manager_unittest.cc
@@ -23,6 +23,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/token.h"
 #include "build/build_config.h"
+#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/services/tracing/perfetto/consumer_host.h b/services/tracing/perfetto/consumer_host.h
index 25f9f3b..b8bc8e12 100644
--- a/services/tracing/perfetto/consumer_host.h
+++ b/services/tracing/perfetto/consumer_host.h
@@ -17,7 +17,6 @@
 #include "base/sequence_checker.h"
 #include "base/threading/sequence_bound.h"
 #include "base/timer/timer.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/tracing/public/mojom/perfetto_service.mojom.h"
 #include "third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h"
diff --git a/services/tracing/perfetto/perfetto_integration_unittest.cc b/services/tracing/perfetto/perfetto_integration_unittest.cc
index b7e5035f..eb2775c 100644
--- a/services/tracing/perfetto/perfetto_integration_unittest.cc
+++ b/services/tracing/perfetto/perfetto_integration_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "services/tracing/perfetto/perfetto_service.h"
 #include "services/tracing/perfetto/producer_host.h"
 #include "services/tracing/perfetto/test_utils.h"
diff --git a/services/tracing/public/cpp/traced_process_impl.h b/services/tracing/public/cpp/traced_process_impl.h
index 026db3c..14c3f450 100644
--- a/services/tracing/public/cpp/traced_process_impl.h
+++ b/services/tracing/public/cpp/traced_process_impl.h
@@ -11,7 +11,6 @@
 #include "base/component_export.h"
 #include "base/no_destructor.h"
 #include "base/sequence_checker.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/tracing/public/mojom/traced_process.mojom.h"
 
diff --git a/services/video_capture/video_source_impl.h b/services/video_capture/video_source_impl.h
index 7a8379be..6d2e33b7 100644
--- a/services/video_capture/video_source_impl.h
+++ b/services/video_capture/video_source_impl.h
@@ -9,7 +9,6 @@
 
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 00cf5e4..0f55ba4 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1791,6 +1791,44 @@
     "isolated_scripts": [
       {
         "args": [
+          "--gtest-benchmark-name",
+          "dawn_perf_tests"
+        ],
+        "isolate_name": "dawn_perf_tests",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "dawn_perf_tests",
+        "override_compile_targets": [
+          "dawn_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "1002:6821-4.0.20-3.2.8",
+              "os": "Mac-10.13.3",
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_APPLE SSD SM0512G"
+            }
+          ],
+          "expiration": 7200,
+          "hard_timeout": 19800,
+          "ignore_task_failure": false,
+          "io_timeout": 19800,
+          "shards": 1
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
           "-v",
           "--browser=release",
           "--upload-results",
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py
index 410defc..7a7d266a 100755
--- a/testing/buildbot/generate_buildbot_json.py
+++ b/testing/buildbot/generate_buildbot_json.py
@@ -1299,44 +1299,99 @@
               filename, node_dumped,
               node.lineno, typ, type(node)))
 
-  def ensure_ast_dict_keys_sorted(self, node, filename, verbose):
-    is_valid = True
+  def check_ast_list_formatted(self, keys, filename, verbose,
+                               check_sorting=False):
+    """Checks if a list of ast keys are correctly formatted.
 
+    Currently only checks to ensure they're correctly sorted, and that there
+    are no duplicates.
+
+    Args:
+      keys: An python list of AST nodes.
+
+            It's a list of AST nodes instead of a list of strings because
+            when verbose is set, it tries to print out context of where the
+            diffs are in the file.
+      filename: The name of the file this node is from.
+      verbose: If set, print out diff information about how the keys are
+               incorrectly formatted.
+      check_sorting: If true, checks if the list is sorted.
+    Returns:
+      If the keys are correctly formatted.
+    """
+    if not keys:
+      return True
+
+    assert isinstance(keys[0], ast.Str)
+
+    keys_strs = [k.s for k in keys]
+    # Keys to diff against. Used below.
+    keys_to_diff_against = None
+    # If the list is properly formatted.
+    list_formatted = True
+
+    # Duplicates are always bad.
+    if len(set(keys_strs)) != len(keys_strs):
+      list_formatted = False
+      keys_to_diff_against = list(collections.OrderedDict.fromkeys(keys_strs))
+
+    if check_sorting and sorted(keys_strs) != keys_strs:
+      list_formatted = False
+    if list_formatted:
+      return True
+
+    if verbose:
+      line_num = keys[0].lineno
+      keys = [k.s for k in keys]
+      if check_sorting:
+        # If we have duplicates, sorting this will take care of it anyways.
+        keys_to_diff_against = sorted(set(keys))
+      # else, keys_to_diff_against is set above already
+
+      self.print_line('=' * 80)
+      self.print_line('(First line of keys is %s)' % line_num)
+      for line in difflib.context_diff(
+          keys, keys_to_diff_against,
+          fromfile='current (%r)' % filename, tofile='sorted', lineterm=''):
+        self.print_line(line)
+      self.print_line('=' * 80)
+
+    return False
+
+  def check_ast_dict_formatted(self, node, filename, verbose,
+                               check_sorting=True):
+    """Checks if an ast dictionary's keys are correctly formatted.
+
+    Just a simple wrapper around check_ast_list_formatted.
+    Args:
+      node: An AST node. Assumed to be a dictionary.
+      filename: The name of the file this node is from.
+      verbose: If set, print out diff information about how the keys are
+               incorrectly formatted.
+      check_sorting: If true, checks if the list is sorted.
+    Returns:
+      If the dictionary is correctly formatted.
+    """
     keys = []
     # The keys of this dict are ordered as ordered in the file; normal python
     # dictionary keys are given an arbitrary order, but since we parsed the
     # file itself, the order as given in the file is preserved.
     for key in node.keys:
       self.type_assert(key, ast.Str, filename, verbose)
-      keys.append(key.s)
+      keys.append(key)
 
-    keys_sorted = sorted(keys)
-    if keys_sorted != keys:
-      is_valid = False
-      if verbose:
-        for line in difflib.unified_diff(
-            keys,
-            keys_sorted, fromfile='current (%r)' % filename, tofile='sorted'):
-          self.print_line(line)
-
-    if len(set(keys)) != len(keys):
-      for i in range(len(keys_sorted)-1):
-        if keys_sorted[i] == keys_sorted[i+1]:
-          self.print_line('Key %s is duplicated' % keys_sorted[i])
-          is_valid = False
-    return is_valid
+    return self.check_ast_list_formatted(
+        keys, filename, verbose, check_sorting=check_sorting)
 
   def check_input_files_sorting(self, verbose=False):
     # TODO(https://crbug.com/886993): Add the ability for this script to
     # actually format the files, rather than just complain if they're
     # incorrectly formatted.
     bad_files = set()
+    def parse_file(filename):
+      """Parses and validates a .pyl file.
 
-    for filename in (
-        'mixins.pyl',
-        'test_suites.pyl',
-        'test_suite_exceptions.pyl',
-    ):
+      Returns an AST node representing the value in the pyl file."""
       parsed = ast.parse(self.read_file(self.pyl_file_path(filename)))
 
       # Must be a module.
@@ -1350,10 +1405,47 @@
       expr = module[0]
       self.type_assert(expr, ast.Expr, filename, verbose)
 
+      return expr.value
+
+    # Handle this separately
+    filename = 'waterfalls.pyl'
+    value = parse_file(filename)
+    # Value should be a list.
+    self.type_assert(value, ast.List, filename, verbose)
+
+    keys = []
+    for val in value.elts:
+      self.type_assert(val, ast.Dict, filename, verbose)
+      waterfall_name = None
+      for key, val in zip(val.keys, val.values):
+        self.type_assert(key, ast.Str, filename, verbose)
+        if key.s == 'machines':
+          if not self.check_ast_dict_formatted(val, filename, verbose):
+            bad_files.add(filename)
+
+        if key.s == "name":
+          self.type_assert(val, ast.Str, filename, verbose)
+          waterfall_name = val
+      assert waterfall_name
+      keys.append(waterfall_name)
+
+    if not self.check_ast_list_formatted(
+        keys, filename, verbose, check_sorting=True):
+      bad_files.add(filename)
+
+    for filename in (
+        'mixins.pyl',
+        'test_suites.pyl',
+        'test_suite_exceptions.pyl',
+    ):
+      value = parse_file(filename)
       # Value should be a dictionary.
-      value = expr.value
       self.type_assert(value, ast.Dict, filename, verbose)
 
+      if not self.check_ast_dict_formatted(
+          value, filename, verbose):
+        bad_files.add(filename)
+
       if filename == 'test_suites.pyl':
         expected_keys = ['basic_suites',
                          'compound_suites',
@@ -1366,62 +1458,41 @@
         # Only two keys should mean only 1 or 2 values
         assert len(suite_dicts) <= 3
         for suite_group in suite_dicts:
-          if not self.ensure_ast_dict_keys_sorted(
+          if not self.check_ast_dict_formatted(
               suite_group, filename, verbose):
             bad_files.add(filename)
 
-      else:
-        if not self.ensure_ast_dict_keys_sorted(
-            value, filename, verbose):
-          bad_files.add(filename)
+        for key, suite in zip(value.keys, value.values):
+          # The compound suites are checked in
+          # 'check_composition_type_test_suites()'
+          if key.s == 'basic_suites':
+            for group in suite.values:
+              if not self.check_ast_dict_formatted(
+                  group, filename, verbose, check_sorting=False):
+                bad_files.add(filename)
+            break
 
-    # waterfalls.pyl is slightly different, just do it manually here
-    filename = 'waterfalls.pyl'
-    parsed = ast.parse(self.read_file(self.pyl_file_path(filename)))
-
-    # Must be a module.
-    self.type_assert(parsed, ast.Module, filename, verbose)
-    module = parsed.body
-
-    # Only one expression in the module.
-    self.type_assert(module, list, filename, verbose)
-    if len(module) != 1: # pragma: no cover
-      raise BBGenErr('Invalid .pyl file %s' % filename)
-    expr = module[0]
-    self.type_assert(expr, ast.Expr, filename, verbose)
-
-    # Value should be a list.
-    value = expr.value
-    self.type_assert(value, ast.List, filename, verbose)
-
-    keys = []
-    for val in value.elts:
-      self.type_assert(val, ast.Dict, filename, verbose)
-      waterfall_name = None
-      for key, val in zip(val.keys, val.values):
-        self.type_assert(key, ast.Str, filename, verbose)
-        if key.s == 'machines':
-          if not self.ensure_ast_dict_keys_sorted(val, filename, verbose):
-            bad_files.add(filename)
-
-        if key.s == "name":
-          self.type_assert(val, ast.Str, filename, verbose)
-          waterfall_name = val.s
-      assert waterfall_name
-      keys.append(waterfall_name)
-
-    if sorted(keys) != keys:
-      bad_files.add(filename)
-      if verbose: # pragma: no cover
-        for line in difflib.unified_diff(
-            keys,
-            sorted(keys), fromfile='current', tofile='sorted'):
-          self.print_line(line)
+      elif filename == 'test_suite_exceptions.pyl':
+        # Check the values for each test.
+        for test in value.values:
+          for kind, node in zip(test.keys, test.values):
+            if isinstance(node, ast.Dict):
+              if not self.check_ast_dict_formatted(
+                  node, filename, verbose, check_sorting=False):
+                bad_files.add(filename)
+            elif kind.s == 'remove_from':
+              # Don't care about sorting; these are usually grouped, since the
+              # same bug can affect multiple builders. Do want to make sure
+              # there aren't duplicates.
+              if not self.check_ast_list_formatted(node.elts, filename, verbose,
+                                               check_sorting=False):
+                bad_files.add(filename)
 
     if bad_files:
       raise BBGenErr(
           'The following files have invalid keys: %s\n. They are either '
-          'unsorted, or have duplicates.' % ', '.join(bad_files))
+          'unsorted, or have duplicates. Re-run this with --verbose to see '
+          'more details.' % ', '.join(bad_files))
 
   def check_output_file_consistency(self, verbose=False):
     self.load_configuration_files()
diff --git a/testing/buildbot/generate_buildbot_json_unittest.py b/testing/buildbot/generate_buildbot_json_unittest.py
index cda3f158..ba5ec5b 100755
--- a/testing/buildbot/generate_buildbot_json_unittest.py
+++ b/testing/buildbot/generate_buildbot_json_unittest.py
@@ -573,6 +573,17 @@
 }
 """
 
+FOO_TEST_SUITE_NOT_SORTED = """\
+{
+  'basic_suites': {
+    'foo_tests': {
+      'foo_test': {},
+      'a_test': {},
+    },
+  },
+}
+"""
+
 FOO_TEST_SUITE_WITH_ARGS = """\
 {
   'basic_suites': {
@@ -913,6 +924,37 @@
 }
 """
 
+EXCEPTIONS_PER_TEST_UNSORTED = """\
+{
+  'suite_d': {
+    'modifications': {
+      'Other Tester': {
+        'foo': 'baz',
+      },
+      'Fake Tester': {
+        'foo': 'baz',
+      },
+    },
+  },
+}
+"""
+
+EXCEPTIONS_DUPS_REMOVE_FROM = """\
+{
+  'suite_d': {
+    'remove_from': [
+      'Fake Tester',
+      'Fake Tester',
+    ],
+    'modifications': {
+      'Fake Tester': {
+        'foo': 'baz',
+      },
+    },
+  },
+}
+"""
+
 FOO_TEST_MODIFICATIONS = """\
 {
   'foo_test': {
@@ -2454,9 +2496,9 @@
       fbb.check_input_file_consistency(verbose=True)
     joined_lines = '\n'.join(fbb.printed_lines)
     self.assertRegexpMatches(
-      joined_lines, '.*\+chromium\..*test.*')
+      joined_lines, '.*\+ chromium\..*test.*')
     self.assertRegexpMatches(
-      joined_lines, '.*\-chromium\..*test.*')
+      joined_lines, '.*\- chromium\..*test.*')
     fbb.printed_lines = []
     self.assertFalse(fbb.printed_lines)
 
@@ -2486,14 +2528,65 @@
     fbb = FakeBBGen(TEST_SUITE_SORTING_WATERFALL,
                     TEST_SUITE_SORTED,
                     LUCI_MILO_CFG,
+                    exceptions=EXCEPTIONS_DUPS_REMOVE_FROM)
+    with self.assertRaises(generate_buildbot_json.BBGenErr):
+      fbb.check_input_file_consistency(verbose=True)
+    joined_lines = ' '.join(fbb.printed_lines)
+    self.assertRegexpMatches(
+        joined_lines, '.*\- Fake Tester.*')
+    fbb.printed_lines = []
+    self.assertFalse(fbb.printed_lines)
+
+  def test_test_suite_exceptions_no_dups_remove_from(self):
+    fbb = FakeBBGen(TEST_SUITE_SORTING_WATERFALL,
+                    TEST_SUITE_SORTED,
+                    LUCI_MILO_CFG,
+                    exceptions=EXCEPTIONS_SORTED)
+    fbb.check_input_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+    fbb = FakeBBGen(TEST_SUITE_SORTING_WATERFALL,
+                    TEST_SUITE_SORTED,
+                    LUCI_MILO_CFG,
+                    exceptions=EXCEPTIONS_PER_TEST_UNSORTED)
+    real_dict_format = fbb.check_ast_dict_formatted
+    def fake_dict_format(*args, **kwargs):
+      kwargs['check_sorting'] = True
+      return real_dict_format(*args, **kwargs)
+
+    # Mock this out for now. A future CL will enable sorting by default. Still
+    # want to test the codepath, even if it's not used it production yet.
+    fbb.check_ast_dict_formatted = fake_dict_format
+
+    with self.assertRaises(generate_buildbot_json.BBGenErr):
+      fbb.check_input_file_consistency(verbose=True)
+    joined_lines = ' '.join(fbb.printed_lines)
+    self.assertRegexpMatches(
+        joined_lines, '.*\+ Fake Tester.*')
+    self.assertRegexpMatches(
+        joined_lines, '.*\- Fake Tester.*')
+    fbb.printed_lines = []
+    self.assertFalse(fbb.printed_lines)
+
+  def test_test_suite_exceptions_per_test_must_be_sorted(self):
+    fbb = FakeBBGen(TEST_SUITE_SORTING_WATERFALL,
+                    TEST_SUITE_SORTED,
+                    LUCI_MILO_CFG,
+                    exceptions=EXCEPTIONS_SORTED)
+    fbb.check_input_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+    fbb = FakeBBGen(TEST_SUITE_SORTING_WATERFALL,
+                    TEST_SUITE_SORTED,
+                    LUCI_MILO_CFG,
                     exceptions=EXCEPTIONS_UNSORTED)
     with self.assertRaises(generate_buildbot_json.BBGenErr):
       fbb.check_input_file_consistency(verbose=True)
     joined_lines = ' '.join(fbb.printed_lines)
     self.assertRegexpMatches(
-        joined_lines, '.*\+suite_.*')
+        joined_lines, '.*\+ suite_.*')
     self.assertRegexpMatches(
-        joined_lines, '.*\-suite_.*')
+        joined_lines, '.*\- suite_.*')
     fbb.printed_lines = []
     self.assertFalse(fbb.printed_lines)
 
@@ -2516,9 +2609,9 @@
         fbb.check_input_file_consistency(verbose=True)
       joined_lines = ' '.join(fbb.printed_lines)
       self.assertRegexpMatches(
-          joined_lines, '.*\+suite_.*')
+          joined_lines, '.*\+ suite_.*')
       self.assertRegexpMatches(
-          joined_lines, '.*\-suite_.*')
+          joined_lines, '.*\- suite_.*')
       fbb.printed_lines = []
       self.assertFalse(fbb.printed_lines)
 
@@ -3031,11 +3124,11 @@
                     mixins=SWARMING_MIXINS_UNSORTED)
     with self.assertRaises(generate_buildbot_json.BBGenErr):
       fbb.check_input_file_consistency(verbose=True)
-    joined_lines = ' '.join(fbb.printed_lines)
+    joined_lines = '\n'.join(fbb.printed_lines)
     self.assertRegexpMatches(
-        joined_lines, '.*\+._mixin.*')
+        joined_lines, '.*\+ ._mixin.*')
     self.assertRegexpMatches(
-        joined_lines, '.*\-._mixin.*')
+        joined_lines, '.*\- ._mixin.*')
     fbb.printed_lines = []
     self.assertFalse(fbb.printed_lines)
 
@@ -3153,9 +3246,32 @@
         generate_buildbot_json.BBGenErr,
         'The following files have invalid keys: mixins.pyl'):
       fbb.check_input_file_consistency(verbose=True)
-    joined_lines = ' '.join(fbb.printed_lines)
+    joined_lines = '\n'.join(fbb.printed_lines)
     self.assertRegexpMatches(
-        joined_lines, 'Key .* is duplicated')
+        joined_lines, '.*\- builder_mixin')
+    fbb.printed_lines = []
+    self.assertFalse(fbb.printed_lines)
+
+  def test_no_duplicate_keys_basic_test_suite(self):
+    fbb = FakeBBGen(FOO_GTESTS_WATERFALL,
+                    FOO_TEST_SUITE_NOT_SORTED,
+                    LUCI_MILO_CFG)
+    real_dict_format = fbb.check_ast_dict_formatted
+    def fake_dict_format(*args, **kwargs):
+      kwargs['check_sorting'] = True
+      return real_dict_format(*args, **kwargs)
+
+    # Mock this out for now. A future CL will enable sorting by default. Still
+    # want to test the codepath, even if it's not used it production yet.
+    fbb.check_ast_dict_formatted = fake_dict_format
+
+    with self.assertRaisesRegexp(
+        generate_buildbot_json.BBGenErr,
+        'The following files have invalid keys: test_suites.pyl'):
+      fbb.check_input_file_consistency(verbose=True)
+    joined_lines = '\n'.join(fbb.printed_lines)
+    self.assertRegexpMatches(joined_lines, '.*\- a_test')
+    self.assertRegexpMatches(joined_lines, '.*\+ a_test')
     fbb.printed_lines = []
     self.assertFalse(fbb.printed_lines)
 
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 222db2c7..16f8dbe 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -715,22 +715,6 @@
         },
         'use_xvfb': False,
       },
-      'Linux ASan LSan Tests (1)': {
-        'args': [
-          '--use-gpu-in-tests',
-          '--no-xvfb',
-        ],
-        'swarming': {
-          'dimension_sets': [
-            {
-              'gpu': '10de:1cb3',
-              'os': 'Ubuntu',
-              'pool': 'chromium.tests.gpu',
-            },
-          ],
-        },
-        'use_xvfb': False,
-      },
       'Linux CFI': {
         'args': [
           '--use-gpu-in-tests',
@@ -1133,7 +1117,6 @@
       'Mac10.13 Tests',
       'Mac10.13 Tests (dbg)',
       'Mac ASan 64 Tests (1)',
-      'Mac ASan 64 Tests (1)',
       'ToTMacASan',
     ],
     'modifications': {
@@ -1165,7 +1148,6 @@
       'Mac10.13 Tests',
       'Mac10.13 Tests (dbg)',
       'Mac ASan 64 Tests (1)',
-      'Mac ASan 64 Tests (1)',
       'ToTMacASan',
     ],
   },
@@ -1186,7 +1168,6 @@
       'Mac10.13 Tests',
       'Mac10.13 Tests (dbg)',
       'Mac ASan 64 Tests (1)',
-      'Mac ASan 64 Tests (1)',
       'ToTMacASan',
     ],
   },
@@ -1206,7 +1187,6 @@
       'Mac10.13 Tests',
       'Mac10.13 Tests (dbg)',
       'Mac ASan 64 Tests (1)',
-      'Mac ASan 64 Tests (1)',
       'ToTMacASan',
     ],
   },
@@ -1232,7 +1212,6 @@
       'Mac10.13 Tests',
       'Mac10.13 Tests (dbg)',
       'Mac ASan 64 Tests (1)',
-      'Mac ASan 64 Tests (1)',
       'ToTMacASan',
     ],
     'modifications': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index f45fd91e..3347ded4 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3276,12 +3276,6 @@
                  '--test-launcher-timeout=120000'],
         'test': 'content_browsertests',
       },
-      'content_browsertests_stress': {
-        'args': ['--gtest_filter=WebRtc*MANUAL*:-UsingRealWebcam*',
-                 '--run-manual', '--ui-test-action-max-timeout=110000',
-                 '--test-launcher-timeout=120000'],
-        'test': 'content_browsertests',
-      },
       'browser_tests_functional': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/webrtc_functional.browser_tests.filter',
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json
index 5b166cdf..45380e6 100644
--- a/testing/buildbot/trybot_analyze_config.json
+++ b/testing/buildbot/trybot_analyze_config.json
@@ -23,7 +23,6 @@
       "infra/scripts/.*",
       "DEPS",
       "testing/buildbot/.*json",
-      "testing/buildbot/.*pyl",
       "testing/merge_scripts/.*",
       "testing/scripts/.*",
       "testing/test_env.py",
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py
index 4184ab8..7990b39 100755
--- a/testing/scripts/run_performance_tests.py
+++ b/testing/scripts/run_performance_tests.py
@@ -107,6 +107,7 @@
   'validating_command_buffer_perftests',
   'views_perftests',
   'viz_perftests',
+  'wayland_client_perftests',
   'xr.vr.common_perftests',
 ]
 
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 01fc27b..3465473b 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1535,7 +1535,6 @@
     "CertDualVerificationTrial": [
         {
             "platforms": [
-                "linux",
                 "mac"
             ],
             "experiments": [
@@ -1548,21 +1547,6 @@
             ]
         }
     ],
-    "CertVerifierBuiltin": [
-        {
-            "platforms": [
-                "linux"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_V2",
-                    "enable_features": [
-                        "CertVerifierBuiltin"
-                    ]
-                }
-            ]
-        }
-    ],
     "ChromeCleanupDistribution": [
         {
             "platforms": [
@@ -3650,24 +3634,6 @@
             ]
         }
     ],
-    "MixedContentShieldRemoval": [
-        {
-            "platforms": [
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "MixedContentSiteSetting"
-                    ]
-                }
-            ]
-        }
-    ],
     "MyChromeEverywhere": [
         {
             "platforms": [
@@ -5033,7 +4999,8 @@
                     "params": {
                         "http_rtt_multiplier_for_proactive_throttling_2G": "1.0",
                         "http_rtt_multiplier_for_proactive_throttling_3G": "1.0",
-                        "http_rtt_multiplier_for_proactive_throttling_Slow-2G": "1.0"
+                        "http_rtt_multiplier_for_proactive_throttling_Slow-2G": "1.0",
+                        "queued_requests_dispatch_periodicity_ms": "5"
                     },
                     "enable_features": [
                         "ProactivelyThrottleLowPriorityRequests"
diff --git a/third_party/android_sdk/README.chromium b/third_party/android_sdk/README.chromium
index cdc373b..f49e174 100644
--- a/third_party/android_sdk/README.chromium
+++ b/third_party/android_sdk/README.chromium
@@ -2,6 +2,7 @@
 URL: http://developer.android.com/sdk/index.html
 Version: 29
   Android SDK Build-tools 29.0.2
+  Android SDK Command-line Tools 1.0.0 rc1
   Android SDK Emulator 29.1.12
   Android SDK Platform-tools 29.0.5
   Android SDK Platform API 29
@@ -20,9 +21,7 @@
 Local Modifications:
 
 - public/
-  - Included the Android support library and required extras packages.
   - Added extras/chromium/.
-  - Added build-tools/25.0.2/lib/dx.jar for //third_party/byte_buddy
 - public/tools-lint/
   - Go to go/studio-master-grid
   - Find the first green build under sdk_tools_linux
@@ -39,10 +38,11 @@
 Update Instructions:
 
 * public/tools/bin/sdkmanager --list  # Look for "Installed packages:"
+* For cmdline-tools run: sdkmanager --channel=3 'cmdline-tools;latest'
 * Prepare the CIPD yaml files for packages that need update and add them
   to android-sdk-packager buildbucket configuation file.
   Submit the changes into gerrit (See crrev.com/c/1803895 as a reference)
-* Wait till the builder android-sdk-packager create new CIPD packages
+* Wait until the builder android-sdk-packager creates new CIPD packages
 * Update //DEPS with InstanceIds from the CIPD
 * Update versions in this README.chromium.
-  * The overall Version field should corresponde to the Platform API version.
+  * The overall Version field should correspond to the Platform API version.
diff --git a/third_party/android_sdk/cipd/cmdline-tools.yaml b/third_party/android_sdk/cipd/cmdline-tools.yaml
new file mode 100644
index 0000000..aba91f4
--- /dev/null
+++ b/third_party/android_sdk/cipd/cmdline-tools.yaml
@@ -0,0 +1,13 @@
+# 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.
+
+package: chromium/third_party/android_sdk/public/cmdline-tools
+description: Android SDK "cmdline-tools" package
+root: ../public/
+data:
+  - dir: cmdline-tools
+# Some tools inspect their argv0 and don't handle CIPD's symlink structure
+# correctly. Install in copy mode so that they can find the other directories
+# relative to themselves.
+install_mode: copy
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 24610008..b003d6e 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -48,6 +48,7 @@
     "indexeddb/indexeddb_key_range.cc",
     "indexeddb/indexeddb_metadata.cc",
     "input/web_gesture_event.cc",
+    "input/web_keyboard_event.cc",
     "input/web_mouse_event.cc",
     "input/web_mouse_wheel_event.cc",
     "input/web_pointer_event.cc",
diff --git a/third_party/blink/common/input/web_gesture_event.cc b/third_party/blink/common/input/web_gesture_event.cc
index 512cd96..85a0dc6 100644
--- a/third_party/blink/common/input/web_gesture_event.cc
+++ b/third_party/blink/common/input/web_gesture_event.cc
@@ -6,6 +6,10 @@
 
 namespace blink {
 
+std::unique_ptr<WebInputEvent> WebGestureEvent::Clone() const {
+  return std::make_unique<WebGestureEvent>(*this);
+}
+
 float WebGestureEvent::DeltaXInRootFrame() const {
   if (type_ == WebInputEvent::kGestureScrollBegin)
     return data.scroll_begin.delta_x_hint / frame_scale_;
diff --git a/third_party/blink/common/input/web_keyboard_event.cc b/third_party/blink/common/input/web_keyboard_event.cc
new file mode 100644
index 0000000..a75be6d
--- /dev/null
+++ b/third_party/blink/common/input/web_keyboard_event.cc
@@ -0,0 +1,13 @@
+// Copyright 2019 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 "third_party/blink/public/common/input/web_keyboard_event.h"
+
+namespace blink {
+
+std::unique_ptr<WebInputEvent> WebKeyboardEvent::Clone() const {
+  return std::make_unique<WebKeyboardEvent>(*this);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/common/input/web_mouse_event.cc b/third_party/blink/common/input/web_mouse_event.cc
index 1942ad5..5057d07b 100644
--- a/third_party/blink/common/input/web_mouse_event.cc
+++ b/third_party/blink/common/input/web_mouse_event.cc
@@ -15,7 +15,7 @@
                              int modifiers,
                              base::TimeTicks time_stamp,
                              PointerId id_param)
-    : WebInputEvent(sizeof(WebMouseEvent), type, modifiers, time_stamp),
+    : WebInputEvent(type, modifiers, time_stamp),
       WebPointerProperties(id_param,
                            WebPointerProperties::PointerType::kMouse,
                            button_param),
@@ -34,6 +34,10 @@
          frame_translate_;
 }
 
+std::unique_ptr<WebInputEvent> WebMouseEvent::Clone() const {
+  return std::make_unique<WebMouseEvent>(*this);
+}
+
 WebMouseEvent WebMouseEvent::FlattenTransform() const {
   WebMouseEvent result = *this;
   result.FlattenTransformSelf();
diff --git a/third_party/blink/common/input/web_mouse_wheel_event.cc b/third_party/blink/common/input/web_mouse_wheel_event.cc
index 7de30cb..eea98f9a 100644
--- a/third_party/blink/common/input/web_mouse_wheel_event.cc
+++ b/third_party/blink/common/input/web_mouse_wheel_event.cc
@@ -6,6 +6,10 @@
 
 namespace blink {
 
+std::unique_ptr<WebInputEvent> WebMouseWheelEvent::Clone() const {
+  return std::make_unique<WebMouseWheelEvent>(*this);
+}
+
 float WebMouseWheelEvent::DeltaXInRootFrame() const {
   return delta_x / frame_scale_;
 }
diff --git a/third_party/blink/common/input/web_pointer_event.cc b/third_party/blink/common/input/web_pointer_event.cc
index 3cc2213..aa09d60 100644
--- a/third_party/blink/common/input/web_pointer_event.cc
+++ b/third_party/blink/common/input/web_pointer_event.cc
@@ -30,8 +30,7 @@
 
 WebPointerEvent::WebPointerEvent(const WebTouchEvent& touch_event,
                                  const WebTouchPoint& touch_point)
-    : WebInputEvent(sizeof(WebPointerEvent),
-                    PointerEventTypeForTouchPointState(touch_point.state),
+    : WebInputEvent(PointerEventTypeForTouchPointState(touch_point.state),
                     touch_event.GetModifiers(),
                     touch_event.TimeStamp()),
 
@@ -58,10 +57,7 @@
 
 WebPointerEvent::WebPointerEvent(WebInputEvent::Type type,
                                  const WebMouseEvent& mouse_event)
-    : WebInputEvent(sizeof(WebPointerEvent),
-                    type,
-                    mouse_event.GetModifiers(),
-                    mouse_event.TimeStamp()),
+    : WebInputEvent(type, mouse_event.GetModifiers(), mouse_event.TimeStamp()),
       WebPointerProperties(mouse_event),
       hovering(true),
       width(std::numeric_limits<float>::quiet_NaN()),
@@ -72,6 +68,10 @@
   SetFrameTranslate(mouse_event.FrameTranslate());
 }
 
+std::unique_ptr<WebInputEvent> WebPointerEvent::Clone() const {
+  return std::make_unique<WebPointerEvent>(*this);
+}
+
 WebPointerEvent WebPointerEvent::CreatePointerCausesUaActionEvent(
     WebPointerProperties::PointerType type,
     base::TimeTicks time_stamp) {
diff --git a/third_party/blink/common/input/web_touch_event.cc b/third_party/blink/common/input/web_touch_event.cc
index ed49046..20a55c2 100644
--- a/third_party/blink/common/input/web_touch_event.cc
+++ b/third_party/blink/common/input/web_touch_event.cc
@@ -6,6 +6,10 @@
 
 namespace blink {
 
+std::unique_ptr<WebInputEvent> WebTouchEvent::Clone() const {
+  return std::make_unique<WebTouchEvent>(*this);
+}
+
 WebTouchEvent WebTouchEvent::FlattenTransform() const {
   WebTouchEvent transformed_event = *this;
   for (unsigned i = 0; i < touches_length; ++i) {
diff --git a/third_party/blink/public/common/input/web_gesture_event.h b/third_party/blink/public/common/input/web_gesture_event.h
index 58195555..947c1b6 100644
--- a/third_party/blink/public/common/input/web_gesture_event.h
+++ b/third_party/blink/public/common/input/web_gesture_event.h
@@ -26,7 +26,7 @@
     kMaxValue = kMomentum,
   };
 
-  bool is_source_touch_event_set_non_blocking;
+  bool is_source_touch_event_set_non_blocking = false;
 
   // The pointer type for the first touch point in the gesture.
   WebPointerProperties::PointerType primary_pointer_type =
@@ -38,7 +38,7 @@
   // not released through a touch event (e.g. timer-released gesture events or
   // gesture events with source_device != WebGestureDevice::kTouchscreen), the
   // field contains 0. See crbug.com/618738.
-  uint32_t unique_touch_event_id;
+  uint32_t unique_touch_event_id = 0;
 
   union {
     // Tap information must be set for GestureTap, GestureTapUnconfirmed,
@@ -180,23 +180,24 @@
   // Screen coordinate
   gfx::PointF position_in_screen_;
 
-  WebGestureDevice source_device_;
+  WebGestureDevice source_device_ = WebGestureDevice::kUninitialized;
 
  public:
   WebGestureEvent(Type type,
                   int modifiers,
                   base::TimeTicks time_stamp,
                   WebGestureDevice device = WebGestureDevice::kUninitialized)
-      : WebInputEvent(sizeof(WebGestureEvent), type, modifiers, time_stamp),
-        source_device_(device) {}
+      : WebInputEvent(type, modifiers, time_stamp), source_device_(device) {
+    memset(&data, 0, sizeof(data));
+  }
 
-  WebGestureEvent()
-      : WebInputEvent(sizeof(WebGestureEvent)),
-        source_device_(WebGestureDevice::kUninitialized) {}
+  WebGestureEvent() { memset(&data, 0, sizeof(data)); }
 
   const gfx::PointF& PositionInWidget() const { return position_in_widget_; }
   const gfx::PointF& PositionInScreen() const { return position_in_screen_; }
 
+  std::unique_ptr<WebInputEvent> Clone() const override;
+
   void SetPositionInWidget(const gfx::PointF& point) {
     position_in_widget_ = point;
   }
diff --git a/third_party/blink/public/common/input/web_input_event.h b/third_party/blink/public/common/input/web_input_event.h
index c137231..5d30b5ea 100644
--- a/third_party/blink/public/common/input/web_input_event.h
+++ b/third_party/blink/public/common/input/web_input_event.h
@@ -42,7 +42,7 @@
 
 // WebInputEvent --------------------------------------------------------------
 
-class WebInputEvent {
+class BLINK_COMMON_EXPORT WebInputEvent {
  public:
   // When we use an input method (or an input method editor), we receive
   // two events for a keypress. The former event is a keydown, which
@@ -426,61 +426,30 @@
   base::TimeTicks TimeStamp() const { return time_stamp_; }
   void SetTimeStamp(base::TimeTicks time_stamp) { time_stamp_ = time_stamp; }
 
-  unsigned size() const { return size_; }
-
   void SetTargetFrameMovedRecently() {
     modifiers_ |= kTargetFrameMovedRecently;
   }
 
+  virtual ~WebInputEvent() = default;
+
+  virtual std::unique_ptr<WebInputEvent> Clone() const = 0;
+
  protected:
   // The root frame scale.
-  float frame_scale_;
+  float frame_scale_ = 1;
 
   // The root frame translation (applied post scale).
   gfx::Vector2dF frame_translate_;
 
-  WebInputEvent(unsigned size,
-                Type type,
-                int modifiers,
-                base::TimeTicks time_stamp) {
-    // TODO(dtapuska): Remove this memset when we remove the chrome IPC of this
-    // struct.
-    memset(this, 0, size);
-    time_stamp_ = time_stamp;
-    size_ = size;
-    type_ = type;
-    modifiers_ = modifiers;
-#if DCHECK_IS_ON()
-    // If dcheck is on force failures if frame scale is not initialized
-    // correctly by causing DIV0.
-    frame_scale_ = 0;
-#else
-    frame_scale_ = 1;
-#endif
-  }
+  WebInputEvent(Type type, int modifiers, base::TimeTicks time_stamp)
+      : time_stamp_(time_stamp), type_(type), modifiers_(modifiers) {}
 
-  explicit WebInputEvent(unsigned size_param) {
-    // TODO(dtapuska): Remove this memset when we remove the chrome IPC of this
-    // struct.
-    memset(this, 0, size_param);
-    time_stamp_ = base::TimeTicks();
-    size_ = size_param;
-    type_ = kUndefined;
-#if DCHECK_IS_ON()
-    // If dcheck is on force failures if frame scale is not initialized
-    // correctly by causing DIV0.
-    frame_scale_ = 0;
-#else
-    frame_scale_ = 1;
-#endif
-  }
+  WebInputEvent() { time_stamp_ = base::TimeTicks(); }
 
   // Event time since platform start with microsecond resolution.
   base::TimeTicks time_stamp_;
-  // The size of this structure, for serialization.
-  unsigned size_;
-  Type type_;
-  int modifiers_;
+  Type type_ = kUndefined;
+  int modifiers_ = kNoModifiers;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/common/input/web_keyboard_event.h b/third_party/blink/public/common/input/web_keyboard_event.h
index 18cfb20d..5f38e9e 100644
--- a/third_party/blink/public/common/input/web_keyboard_event.h
+++ b/third_party/blink/public/common/input/web_keyboard_event.h
@@ -12,7 +12,7 @@
 
 // WebKeyboardEvent -----------------------------------------------------------
 
-class WebKeyboardEvent : public WebInputEvent {
+class BLINK_COMMON_EXPORT WebKeyboardEvent : public WebInputEvent {
  public:
   // Caps on string lengths so we can make them static arrays and keep
   // them PODs.
@@ -26,32 +26,32 @@
   // what is returned by the Windows API. For example, it should
   // store VK_SHIFT instead of VK_RSHIFT. The location information
   // should be stored in |modifiers|.
-  int windows_key_code;
+  int windows_key_code = 0;
 
   // The actual key code genenerated by the platform. The DOM spec runs
   // on Windows-equivalent codes (thus |windows_key_code| above) but it
   // doesn't hurt to have this one around.
-  int native_key_code;
+  int native_key_code = 0;
 
   // The DOM code enum of the key pressed as passed by the embedder. DOM code
   // enums are defined in ui/events/keycodes/dom/keycode_converter_data.inc.
-  int dom_code;
+  int dom_code = 0;
 
   // The DOM key enum of the key pressed as passed by the embedder. DOM
   // key enums are defined in ui/events/keycodes/dom/dom_key_data.inc.
-  int dom_key;
+  int dom_key = 0;
 
   // This identifies whether this event was tagged by the system as being a
   // "system key" event (see
   // https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-syskeydown for
   // details). Other platforms don't have this concept, but it's just
   // easier to leave it always false than ifdef.
-  bool is_system_key;
+  bool is_system_key = false;
 
   // Whether the event forms part of a browser-handled keyboard shortcut.
   // This can be used to conditionally suppress Char events after a
   // shortcut-triggering RawKeyDown goes unhandled.
-  bool is_browser_shortcut;
+  bool is_browser_shortcut = false;
 
   // |text| is the text generated by this keystroke.  |unmodified_text| is
   // |text|, but unmodified by an concurrently-held modifiers (except
@@ -59,13 +59,15 @@
   // Windows guarantee one character per event.  The Mac does not, but in
   // reality that's all it ever gives.  We're generous, and cap it a bit
   // longer.
-  base::char16 text[kTextLengthCap];
-  base::char16 unmodified_text[kTextLengthCap];
+  base::char16 text[kTextLengthCap] = {};
+  base::char16 unmodified_text[kTextLengthCap] = {};
 
   WebKeyboardEvent(Type type, int modifiers, base::TimeTicks time_stamp)
-      : WebInputEvent(sizeof(WebKeyboardEvent), type, modifiers, time_stamp) {}
+      : WebInputEvent(type, modifiers, time_stamp) {}
 
-  WebKeyboardEvent() : WebInputEvent(sizeof(WebKeyboardEvent)) {}
+  WebKeyboardEvent() = default;
+
+  std::unique_ptr<WebInputEvent> Clone() const override;
 
   // Please refer to bug http://b/issue?id=961192, which talks about Webkit
   // keyboard event handling changes. It also mentions the list of keys
diff --git a/third_party/blink/public/common/input/web_mouse_event.h b/third_party/blink/public/common/input/web_mouse_event.h
index 25da4f1..957e83c2 100644
--- a/third_party/blink/public/common/input/web_mouse_event.h
+++ b/third_party/blink/public/common/input/web_mouse_event.h
@@ -20,10 +20,10 @@
  public:
   static constexpr PointerId kMousePointerId = std::numeric_limits<int>::max();
 
-  int click_count;
+  int click_count = {};
 
   // Only used for contextmenu events.
-  WebMenuSourceType menu_source_type;
+  WebMenuSourceType menu_source_type = kMenuSourceNone;
 
   WebMouseEvent(Type type_param,
                 gfx::PointF position,
@@ -34,10 +34,7 @@
                 base::TimeTicks time_stamp_param,
                 WebMenuSourceType menu_source_type_param = kMenuSourceNone,
                 PointerId id_param = kMousePointerId)
-      : WebInputEvent(sizeof(WebMouseEvent),
-                      type_param,
-                      modifiers_param,
-                      time_stamp_param),
+      : WebInputEvent(type_param, modifiers_param, time_stamp_param),
         WebPointerProperties(id_param,
                              PointerType::kMouse,
                              button_param,
@@ -53,13 +50,10 @@
                 int modifiers_param,
                 base::TimeTicks time_stamp_param,
                 PointerId id_param = kMousePointerId)
-      : WebMouseEvent(sizeof(WebMouseEvent),
-                      type_param,
-                      modifiers_param,
-                      time_stamp_param,
-                      id_param) {}
+      : WebInputEvent(type_param, modifiers_param, time_stamp_param),
+        WebPointerProperties(id_param) {}
 
-  WebMouseEvent() : WebMouseEvent(sizeof(WebMouseEvent), kMousePointerId) {}
+  WebMouseEvent() : WebMouseEvent(kMousePointerId) {}
 
   bool FromTouch() const {
     return (GetModifiers() & kIsCompatibilityEventForTouch) != 0;
@@ -73,6 +67,8 @@
                 base::TimeTicks time_stamp_param,
                 PointerId id_param = kMousePointerId);
 
+  std::unique_ptr<WebInputEvent> Clone() const override;
+
   gfx::PointF PositionInRootFrame() const;
 
   // Sets any scaled values to be their computed values and sets |frame_scale_|
@@ -80,16 +76,7 @@
   WebMouseEvent FlattenTransform() const;
 
  protected:
-  WebMouseEvent(unsigned size_param, PointerId id_param)
-      : WebInputEvent(size_param), WebPointerProperties(id_param) {}
-
-  WebMouseEvent(unsigned size_param,
-                Type type,
-                int modifiers,
-                base::TimeTicks time_stamp,
-                PointerId id_param)
-      : WebInputEvent(size_param, type, modifiers, time_stamp),
-        WebPointerProperties(id_param) {}
+  WebMouseEvent(PointerId id_param) : WebPointerProperties(id_param) {}
 
   void FlattenTransformSelf();
 
diff --git a/third_party/blink/public/common/input/web_mouse_wheel_event.h b/third_party/blink/public/common/input/web_mouse_wheel_event.h
index 605740b8..79697fe 100644
--- a/third_party/blink/public/common/input/web_mouse_wheel_event.h
+++ b/third_party/blink/public/common/input/web_mouse_wheel_event.h
@@ -52,25 +52,25 @@
     kScrollVertical
   };
 
-  float delta_x;
-  float delta_y;
-  float wheel_ticks_x;
-  float wheel_ticks_y;
+  float delta_x = 0.0f;
+  float delta_y = 0.0f;
+  float wheel_ticks_x = 0.0f;
+  float wheel_ticks_y = 0.0f;
 
-  float acceleration_ratio_x;
-  float acceleration_ratio_y;
+  float acceleration_ratio_x = 1.0f;
+  float acceleration_ratio_y = 1.0f;
 
-  Phase phase;
-  Phase momentum_phase;
+  Phase phase = kPhaseNone;
+  Phase momentum_phase = kPhaseNone;
 
-  RailsMode rails_mode;
+  RailsMode rails_mode = kRailsModeFree;
 
   // Whether the event is blocking, non-blocking, all event
   // listeners were passive or was forced to be non-blocking.
-  DispatchType dispatch_type;
+  DispatchType dispatch_type = kBlocking;
 
   // The expected result of this wheel event (if not canceled).
-  EventAction event_action;
+  EventAction event_action = EventAction::kPageZoom;
 
   // True when phase information is added in mouse_wheel_phase_handler based
   // on its timer.
@@ -80,39 +80,13 @@
   // kScrollByPrecisePixel, kScrollByPixel, and kScrollByPage, as they are
   // the only values expected after converting an OS event to a
   // WebMouseWheelEvent.
-  ui::input_types::ScrollGranularity delta_units;
+  ui::input_types::ScrollGranularity delta_units =
+      ui::input_types::ScrollGranularity::kScrollByPixel;
 
   WebMouseWheelEvent(Type type, int modifiers, base::TimeTicks time_stamp)
-      : WebMouseEvent(sizeof(WebMouseWheelEvent),
-                      type,
-                      modifiers,
-                      time_stamp,
-                      kMousePointerId),
-        delta_x(0.0f),
-        delta_y(0.0f),
-        wheel_ticks_x(0.0f),
-        wheel_ticks_y(0.0f),
-        acceleration_ratio_x(1.0f),
-        acceleration_ratio_y(1.0f),
-        phase(kPhaseNone),
-        momentum_phase(kPhaseNone),
-        rails_mode(kRailsModeFree),
-        dispatch_type(kBlocking),
-        delta_units(ui::input_types::ScrollGranularity::kScrollByPixel) {}
+      : WebMouseEvent(type, modifiers, time_stamp, kMousePointerId) {}
 
-  WebMouseWheelEvent()
-      : WebMouseEvent(sizeof(WebMouseWheelEvent), kMousePointerId),
-        delta_x(0.0f),
-        delta_y(0.0f),
-        wheel_ticks_x(0.0f),
-        wheel_ticks_y(0.0f),
-        acceleration_ratio_x(1.0f),
-        acceleration_ratio_y(1.0f),
-        phase(kPhaseNone),
-        momentum_phase(kPhaseNone),
-        rails_mode(kRailsModeFree),
-        dispatch_type(kBlocking),
-        delta_units(ui::input_types::ScrollGranularity::kScrollByPixel) {}
+  WebMouseWheelEvent() : WebMouseEvent(kMousePointerId) {}
 
   float DeltaXInRootFrame() const;
   float DeltaYInRootFrame() const;
@@ -122,6 +96,8 @@
   WebMouseWheelEvent FlattenTransform() const;
 
   bool IsCancelable() const { return dispatch_type == kBlocking; }
+
+  std::unique_ptr<WebInputEvent> Clone() const override;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/common/input/web_pointer_event.h b/third_party/blink/public/common/input/web_pointer_event.h
index cdf6b99..efb5847e 100644
--- a/third_party/blink/public/common/input/web_pointer_event.h
+++ b/third_party/blink/public/common/input/web_pointer_event.h
@@ -21,14 +21,12 @@
 class BLINK_COMMON_EXPORT WebPointerEvent : public WebInputEvent,
                                             public WebPointerProperties {
  public:
-  WebPointerEvent()
-      : WebInputEvent(sizeof(WebPointerEvent)), WebPointerProperties(0) {}
+  WebPointerEvent() : WebPointerProperties(0) {}
   WebPointerEvent(WebInputEvent::Type type_param,
                   WebPointerProperties web_pointer_properties_param,
                   float width_param,
                   float height_param)
-      : WebInputEvent(sizeof(WebPointerEvent)),
-        WebPointerProperties(web_pointer_properties_param),
+      : WebPointerProperties(web_pointer_properties_param),
         width(width_param),
         height(height_param) {
     SetType(type_param);
@@ -36,44 +34,46 @@
   WebPointerEvent(const WebTouchEvent&, const WebTouchPoint&);
   WebPointerEvent(WebInputEvent::Type, const WebMouseEvent&);
 
+  std::unique_ptr<WebInputEvent> Clone() const override;
+
   static WebPointerEvent CreatePointerCausesUaActionEvent(
       WebPointerProperties::PointerType,
       base::TimeTicks time_stamp);
 
   // ------------ Touch Point Specific ------------
 
-  float rotation_angle;
+  float rotation_angle = 0.0f;
 
   // ------------ Touch Event Specific ------------
 
   // A unique identifier for the touch event. Valid ids start at one and
   // increase monotonically. Zero means an unknown id.
-  uint32_t unique_touch_event_id;
+  uint32_t unique_touch_event_id = 0;
 
   // Whether the event is blocking, non-blocking, all event
   // listeners were passive or was forced to be non-blocking.
-  DispatchType dispatch_type;
+  DispatchType dispatch_type = kBlocking;
 
   // For a single touch, this is true after the touch-point has moved beyond
   // the platform slop region. For a multitouch, this is true after any
   // touch-point has moved (by whatever amount).
-  bool moved_beyond_slop_region;
+  bool moved_beyond_slop_region = false;
 
   // Whether this touch event is a touchstart or a first touchmove event per
   // scroll.
-  bool touch_start_or_first_touch_move;
+  bool touch_start_or_first_touch_move = false;
 
   // ------------ Common fields across pointer types ------------
 
   // True if this pointer was hovering and false otherwise. False value entails
   // the event was processed as part of gesture detection and it may cause
   // scrolling.
-  bool hovering;
+  bool hovering = false;
 
   // TODO(crbug.com/736014): We need a clarified definition of the scale and
   // the coordinate space on these attributes.
-  float width;
-  float height;
+  float width = 0.0f;
+  float height = 0.0f;
 
   bool IsCancelable() const { return dispatch_type == kBlocking; }
   bool HasWidth() const { return !std::isnan(width); }
diff --git a/third_party/blink/public/common/input/web_pointer_properties.h b/third_party/blink/public/common/input/web_pointer_properties.h
index d122090f..c642fab 100644
--- a/third_party/blink/public/common/input/web_pointer_properties.h
+++ b/third_party/blink/public/common/input/web_pointer_properties.h
@@ -60,16 +60,10 @@
       int movement_x = 0,
       int movement_y = 0)
       : id(id_param),
-        force(std::numeric_limits<float>::quiet_NaN()),
-        tilt_x(0),
-        tilt_y(0),
-        tangential_pressure(0.0f),
-        twist(0),
         button(button_param),
         pointer_type(pointer_type_param),
         movement_x(movement_x),
         movement_y(movement_y),
-        is_raw_movement_event(false),
         position_in_widget_(position_in_widget),
         position_in_screen_(position_in_screen) {}
 
@@ -96,23 +90,23 @@
 
   // The valid range is [0,1], with NaN meaning pressure is not supported by
   // the input device.
-  float force;
+  float force = std::numeric_limits<float>::quiet_NaN();
 
   // Tilt of a pen stylus from surface normal as plane angles in degrees,
   // Values lie in [-90,90]. A positive tiltX is to the right and a positive
   // tiltY is towards the user.
-  int tilt_x;
-  int tilt_y;
+  int tilt_x = 0;
+  int tilt_y = 0;
 
   // The normalized tangential pressure (or barrel pressure), typically set by
   // an additional control of the stylus, which has a range of [-1,1], where 0
   // is the neutral position of the control. Always 0 if the device does not
   // support it.
-  float tangential_pressure;
+  float tangential_pressure = 0.0f;
 
   // The clockwise rotation of a pen stylus around its own major axis, in
   // degrees in the range [0,359]. Always 0 if the device does not support it.
-  int twist;
+  int twist = 0;
 
   // - For pointerup/down events, the button of pointing device that triggered
   // the event.
@@ -128,7 +122,7 @@
 
   // True if this event has raw movement value from OS.
   // TODO(crbug.com/982379): Figure out how to avoid using this boolean.
-  bool is_raw_movement_event;
+  bool is_raw_movement_event = false;
 
  protected:
   // Widget coordinate, which is relative to the bound of current RenderWidget
diff --git a/third_party/blink/public/common/input/web_touch_event.h b/third_party/blink/public/common/input/web_touch_event.h
index 795976c..9a59b3f 100644
--- a/third_party/blink/public/common/input/web_touch_event.h
+++ b/third_party/blink/public/common/input/web_touch_event.h
@@ -19,37 +19,37 @@
   // Ash/Aura.
   enum { kTouchesLengthCap = 16 };
 
-  unsigned touches_length;
+  unsigned touches_length = 0;
   // List of all touches, regardless of state.
-  WebTouchPoint touches[kTouchesLengthCap];
+  WebTouchPoint touches[kTouchesLengthCap] = {};
 
   // Whether the event is blocking, non-blocking, all event
   // listeners were passive or was forced to be non-blocking.
-  DispatchType dispatch_type;
+  DispatchType dispatch_type = kBlocking;
 
   // For a single touch, this is true after the touch-point has moved beyond
   // the platform slop region. For a multitouch, this is true after any
   // touch-point has moved (by whatever amount).
-  bool moved_beyond_slop_region;
+  bool moved_beyond_slop_region = false;
 
   // True for events from devices like some pens that support hovering
   // over digitizer and the events are sent while the device was hovering.
-  bool hovering;
+  bool hovering = false;
 
   // Whether this touch event is a touchstart or a first touchmove event per
   // scroll.
-  bool touch_start_or_first_touch_move;
+  bool touch_start_or_first_touch_move = false;
 
   // A unique identifier for the touch event. Valid ids start at one and
   // increase monotonically. Zero means an unknown id.
-  uint32_t unique_touch_event_id;
+  uint32_t unique_touch_event_id = 0;
 
-  WebTouchEvent()
-      : WebInputEvent(sizeof(WebTouchEvent)), dispatch_type(kBlocking) {}
+  WebTouchEvent() = default;
 
   WebTouchEvent(Type type, int modifiers, base::TimeTicks time_stamp)
-      : WebInputEvent(sizeof(WebTouchEvent), type, modifiers, time_stamp),
-        dispatch_type(kBlocking) {}
+      : WebInputEvent(type, modifiers, time_stamp) {}
+
+  std::unique_ptr<WebInputEvent> Clone() const override;
 
   // Sets any scaled values to be their computed values and sets |frame_scale_|
   // back to 1 and |frame_translate_| X and Y coordinates back to 0.
diff --git a/third_party/blink/public/common/input/web_touch_point.h b/third_party/blink/public/common/input/web_touch_point.h
index de8971f6..939142e 100644
--- a/third_party/blink/public/common/input/web_touch_point.h
+++ b/third_party/blink/public/common/input/web_touch_point.h
@@ -38,16 +38,12 @@
 
 // TODO(mustaq): Unify WebTouchPoint & WebMouseEvent into WebPointerEvent.
 // crbug.com/508283
-class WebTouchPoint : public WebPointerProperties {
+class BLINK_COMMON_EXPORT WebTouchPoint : public WebPointerProperties {
  public:
   WebTouchPoint() : WebTouchPoint(WebPointerProperties(0)) {}
 
   WebTouchPoint(WebPointerProperties web_pointer_properties)
-      : WebPointerProperties(web_pointer_properties),
-        state(kStateUndefined),
-        radius_x(0),
-        radius_y(0),
-        rotation_angle(0) {}
+      : WebPointerProperties(web_pointer_properties) {}
 
   enum State {
     kStateUndefined,
@@ -59,11 +55,11 @@
     kStateMax = kStateCancelled
   };
 
-  State state;
+  State state = kStateUndefined;
 
-  float radius_x;
-  float radius_y;
-  float rotation_angle;
+  float radius_x = 0.0f;
+  float radius_y = 0.0f;
+  float rotation_angle = 0.0f;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
index 95fdb07..382be0b 100644
--- a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
+++ b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
@@ -30,4 +30,8 @@
   // TODO(https://crbug.com/900700): Make this non-nullable when implementation
   // is complete (including support for navigation requests).
   pending_remote<blink.mojom.WorkerTimingContainer>? worker_timing_remote;
+
+  // Whether this is a "fake" fetch event used to detect the offline capability
+  // of the service worker. See more details at https://crbug.com/965802.
+  bool is_offline_capability_check = false;
 };
diff --git a/third_party/blink/public/platform/web_coalesced_input_event.h b/third_party/blink/public/platform/web_coalesced_input_event.h
index bcf03594..3095d0bb 100644
--- a/third_party/blink/public/platform/web_coalesced_input_event.h
+++ b/third_party/blink/public/platform/web_coalesced_input_event.h
@@ -42,12 +42,7 @@
   WebVector<const WebInputEvent*> GetPredictedEventsPointers() const;
 
  private:
-  struct BLINK_PLATFORM_EXPORT WebInputEventDeleter {
-    void operator()(blink::WebInputEvent*) const;
-  };
-
-  using WebScopedInputEvent =
-      std::unique_ptr<WebInputEvent, WebInputEventDeleter>;
+  using WebScopedInputEvent = std::unique_ptr<WebInputEvent>;
 
   WebScopedInputEvent MakeWebScopedInputEvent(const blink::WebInputEvent&);
 
diff --git a/third_party/blink/public/platform/web_worker_fetch_context.h b/third_party/blink/public/platform/web_worker_fetch_context.h
index d7a5085..defe3e49 100644
--- a/third_party/blink/public/platform/web_worker_fetch_context.h
+++ b/third_party/blink/public/platform/web_worker_fetch_context.h
@@ -150,6 +150,10 @@
   // request has not been intercepted by a service worker.
   virtual mojo::ScopedMessagePipeHandle TakePendingWorkerTimingReceiver(
       int request_id) = 0;
+
+  // This flag is set to disallow all network accesses in the context. Used for
+  // offline capability detection in service workers.
+  virtual void SetIsOfflineMode(bool is_offline_mode) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/BUILD.gn b/third_party/blink/renderer/bindings/BUILD.gn
index 48e2a46d..90910159 100644
--- a/third_party/blink/renderer/bindings/BUILD.gn
+++ b/third_party/blink/renderer/bindings/BUILD.gn
@@ -182,3 +182,29 @@
     ]
   }
 }
+
+action_with_pydeps("generate_high_entropy_list") {
+  script = "${bindings_scripts_dir}/generate_high_entropy_list.py"
+
+  web_idl_database_outputs = get_target_outputs(":web_idl_database")
+  web_idl_database = web_idl_database_outputs[0]
+
+  inputs = [
+    web_idl_database,
+  ]
+  output_data_file = "${bindings_output_dir}/high_entropy_list.txt"
+  outputs = [
+    output_data_file,
+  ]
+
+  args = [
+    "--web_idl_database",
+    rebase_path(web_idl_database, root_build_dir),
+    "--output",
+    rebase_path(output_data_file, root_build_dir),
+  ]
+
+  deps = [
+    ":web_idl_database",
+  ]
+}
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc b/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc
index 0efef7b37..cb2fe11 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc
@@ -13,6 +13,7 @@
 
 bool V8ObjectParser::ParseCSSPropertyList(
     v8::Local<v8::Context> context,
+    const ExecutionContext* execution_context,
     v8::Local<v8::Object> constructor,
     const AtomicString list_name,
     Vector<CSSPropertyID>* native_properties,
@@ -37,7 +38,7 @@
       return false;
 
     for (const auto& property : properties) {
-      CSSPropertyID property_id = cssPropertyID(property);
+      CSSPropertyID property_id = cssPropertyID(execution_context, property);
       if (property_id == CSSPropertyID::kVariable) {
         custom_properties->push_back(std::move(property));
       } else if (property_id != CSSPropertyID::kInvalid) {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h b/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h
index 5d35e474..66617f48 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h
+++ b/third_party/blink/renderer/bindings/core/v8/v8_object_parser.h
@@ -14,6 +14,7 @@
 namespace blink {
 
 class ExceptionState;
+class ExecutionContext;
 
 class CORE_EXPORT V8ObjectParser final {
   STATIC_ONLY(V8ObjectParser);
@@ -24,6 +25,7 @@
   // Vector<String> type. It does not fail if the list contains invalid CSS
   // properties, to ensure forward compatibility.
   static bool ParseCSSPropertyList(v8::Local<v8::Context>,
+                                   const ExecutionContext*,
                                    v8::Local<v8::Object> constructor,
                                    const AtomicString list_name,
                                    Vector<CSSPropertyID>* native_properties,
diff --git a/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py b/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py
new file mode 100644
index 0000000..24e06e0
--- /dev/null
+++ b/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py
@@ -0,0 +1,49 @@
+# 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.
+
+"""
+Given the Web IDL database as input, output a list of all high entropy entities.
+
+High entropy entities (methods, attributes, constants) are annotated with
+the [HighEntropy] extended attribute.
+"""
+
+import optparse
+
+from utilities import write_file
+import web_idl
+
+
+def parse_options():
+    parser = optparse.OptionParser(usage="%prog [options]")
+    parser.add_option("--web_idl_database", type="string",
+                      help="filepath of the input database")
+    parser.add_option("--output", type="string",
+                      help="filepath of output file")
+    options, args = parser.parse_args()
+
+    required_option_names = ("web_idl_database", "output")
+    for opt_name in required_option_names:
+        if getattr(options, opt_name) is None:
+            parser.error("--{} is a required option.".format(opt_name))
+
+    return options, args
+
+
+def main():
+    options, _ = parse_options()
+
+    web_idl_database = web_idl.Database.read_from_file(options.web_idl_database)
+    high_entropy_list = []
+    for interface in web_idl_database.interfaces:
+        for entity in (interface.attributes + interface.operations +
+                       interface.constants):
+            if "HighEntropy" in entity.extended_attributes:
+                high_entropy_list.append('%s.%s' % (interface.identifier,
+                                                    entity.identifier))
+    write_file('\n'.join(high_entropy_list) + '\n', options.output)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps b/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps
new file mode 100644
index 0000000..9e3e877
--- /dev/null
+++ b/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps
@@ -0,0 +1,47 @@
+# Generated by running:
+#   build/print_python_deps.py --root third_party/blink/renderer/bindings/scripts --output third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py
+../../../../pyjson5/src/json5/__init__.py
+../../../../pyjson5/src/json5/arg_parser.py
+../../../../pyjson5/src/json5/host.py
+../../../../pyjson5/src/json5/lib.py
+../../../../pyjson5/src/json5/parser.py
+../../../../pyjson5/src/json5/tool.py
+../../../../pyjson5/src/json5/version.py
+../../build/scripts/blinkbuild/__init__.py
+../../build/scripts/blinkbuild/name_style_converter.py
+generate_high_entropy_list.py
+utilities.py
+web_idl/__init__.py
+web_idl/argument.py
+web_idl/ast_group.py
+web_idl/attribute.py
+web_idl/callback_function.py
+web_idl/callback_interface.py
+web_idl/code_generator_info.py
+web_idl/composition_parts.py
+web_idl/constant.py
+web_idl/constructor.py
+web_idl/database.py
+web_idl/database_builder.py
+web_idl/dictionary.py
+web_idl/enumeration.py
+web_idl/exposure.py
+web_idl/extended_attribute.py
+web_idl/file_io.py
+web_idl/function_like.py
+web_idl/idl_compiler.py
+web_idl/idl_type.py
+web_idl/includes.py
+web_idl/interface.py
+web_idl/ir_builder.py
+web_idl/ir_map.py
+web_idl/literal_constant.py
+web_idl/make_copy.py
+web_idl/namespace.py
+web_idl/operation.py
+web_idl/reference.py
+web_idl/runtime_enabled_features.py
+web_idl/typedef.py
+web_idl/union.py
+web_idl/user_defined_type.py
+web_idl/validator.py
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py b/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
index 98a491d2..959908b 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
@@ -7,6 +7,7 @@
 _CODE_GENERATOR_INFO_ATTRIBUTES = (
     'defined_in_mixin',
     'defined_in_partial',
+    'blink_headers',
     'property_implemented_as',
     'receiver_implemented_as',
 )
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py b/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py
index dfb8de1..ce730a3 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py
@@ -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 posixpath
+
 from .code_generator_info import CodeGeneratorInfo
 from .code_generator_info import CodeGeneratorInfoMutable
 from .exposure import Exposure
@@ -138,10 +140,20 @@
 
 
 class Location(object):
+    _blink_path_prefix = posixpath.sep + posixpath.join(
+        'third_party', 'blink', 'renderer', '')
+
     def __init__(self, filepath=None, line_number=None, position=None):
         assert filepath is None or isinstance(filepath, str)
         assert line_number is None or isinstance(line_number, int)
         assert position is None or isinstance(position, int)
+
+        # idl_parser produces paths based on the working directory, which may
+        # not be the project root directory, e.g. "../../third_party/blink/...".
+        # Canonicalize the paths heuristically.
+        index = filepath.find(self._blink_path_prefix)
+        if index >= 0:
+            filepath = filepath[index + 1:]
         self._filepath = filepath
         self._line_number = line_number
         self._position = position  # Position number in a file
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
index c70bfec..38479b7 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
@@ -4,6 +4,7 @@
 
 import functools
 import itertools
+import posixpath
 
 from .callback_function import CallbackFunction
 from .callback_interface import CallbackInterface
@@ -80,6 +81,7 @@
         # Merge partial definitions.
         self._record_defined_in_partial_and_mixin()
         self._propagate_extattrs_per_idl_fragment()
+        self._determine_blink_headers()
         self._merge_partial_interface_likes()
         self._merge_partial_dictionaries()
         # Merge mixins.
@@ -211,6 +213,21 @@
 
         map(process_interface_like, old_irs)
 
+    def _determine_blink_headers(self):
+        irs = self._ir_map.irs_of_kinds(
+            IRMap.IR.Kind.INTERFACE, IRMap.IR.Kind.NAMESPACE,
+            IRMap.IR.Kind.PARTIAL_INTERFACE, IRMap.IR.Kind.PARTIAL_NAMESPACE)
+
+        self._ir_map.move_to_new_phase()
+
+        for old_ir in irs:
+            new_ir = make_copy(old_ir)
+            self._ir_map.add(new_ir)
+            basepath, _ = posixpath.splitext(
+                new_ir.debug_info.location.filepath)
+            header = posixpath.extsep.join([basepath, "h"])
+            new_ir.code_generator_info.set_blink_headers([header])
+
     def _merge_partial_interface_likes(self):
         irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
                                         IRMap.IR.Kind.INTERFACE_MIXIN,
@@ -286,6 +303,13 @@
                 new_ir.constants.extend(to_be_merged.constants)
                 new_ir.operations.extend(to_be_merged.operations)
 
+                new_ir_headers = new_ir.code_generator_info.blink_headers
+                to_be_merged_headers = (
+                    to_be_merged.code_generator_info.blink_headers)
+                if (new_ir_headers is not None
+                        and to_be_merged_headers is not None):
+                    new_ir_headers.extend(to_be_merged_headers)
+
     def _process_interface_inheritances(self):
         def is_own_member(member):
             return 'Unforgeable' in member.extended_attributes
diff --git a/third_party/blink/renderer/core/animation/animation_input_helpers.cc b/third_party/blink/renderer/core/animation/animation_input_helpers.cc
index 9981603..59d8f53 100644
--- a/third_party/blink/renderer/core/animation/animation_input_helpers.cc
+++ b/third_party/blink/renderer/core/animation/animation_input_helpers.cc
@@ -79,7 +79,7 @@
       builder.Append('-');
     builder.Append(property[i]);
   }
-  return cssPropertyID(builder.ToString());
+  return cssPropertyID(&document, builder.ToString());
 }
 
 CSSPropertyID AnimationInputHelpers::KeyframeAttributeToPresentationAttribute(
@@ -92,7 +92,7 @@
   String unprefixed_property = RemoveSVGPrefix(property);
   if (SVGElement::IsAnimatableCSSProperty(QualifiedName(
           g_null_atom, AtomicString(unprefixed_property), g_null_atom)))
-    return cssPropertyID(unprefixed_property);
+    return cssPropertyID(&element->GetDocument(), unprefixed_property);
 
   return CSSPropertyID::kInvalid;
 }
diff --git a/third_party/blink/renderer/core/animation/animation_test_helper.cc b/third_party/blink/renderer/core/animation/animation_test_helper.cc
index a7bf2c2..1539c7e 100644
--- a/third_party/blink/renderer/core/animation/animation_test_helper.cc
+++ b/third_party/blink/renderer/core/animation/animation_test_helper.cc
@@ -89,7 +89,8 @@
     auto type = cssvalue::CSSPendingInterpolationValue::Type::kCSSProperty;
     auto* pending = cssvalue::CSSPendingInterpolationValue::Create(type);
     auto origin = StyleCascade::Origin::kAuthor;
-    cascade.Add(*CSSPropertyName::From("--unused"), pending, origin);
+    cascade.Add(*CSSPropertyName::From(&state.GetDocument(), "--unused"),
+                pending, origin);
 
     TestAnimator animator(state, cascade, map, interpolations);
     cascade.Apply(animator);
diff --git a/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc b/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
index dbd9993..05df9469 100644
--- a/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
+++ b/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
@@ -70,7 +70,8 @@
 
 String AbstractPropertySetCSSStyleDeclaration::getPropertyValue(
     const String& property_name) {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id =
+      cssPropertyID(GetExecutionContext(), property_name);
   if (!isValidCSSPropertyID(property_id))
     return String();
   if (property_id == CSSPropertyID::kVariable)
@@ -80,7 +81,8 @@
 
 String AbstractPropertySetCSSStyleDeclaration::getPropertyPriority(
     const String& property_name) {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id =
+      cssPropertyID(GetExecutionContext(), property_name);
   if (!isValidCSSPropertyID(property_id))
     return String();
 
@@ -94,7 +96,8 @@
 
 String AbstractPropertySetCSSStyleDeclaration::GetPropertyShorthand(
     const String& property_name) {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id =
+      cssPropertyID(GetExecutionContext(), property_name);
 
   // Custom properties don't have shorthands, so we can ignore them here.
   if (!isValidCSSPropertyID(property_id) ||
@@ -108,7 +111,8 @@
 
 bool AbstractPropertySetCSSStyleDeclaration::IsPropertyImplicit(
     const String& property_name) {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id =
+      cssPropertyID(GetExecutionContext(), property_name);
 
   // Custom properties don't have shorthands, so we can ignore them here.
   if (property_id < firstCSSProperty)
@@ -139,7 +143,8 @@
 String AbstractPropertySetCSSStyleDeclaration::removeProperty(
     const String& property_name,
     ExceptionState& exception_state) {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id =
+      cssPropertyID(GetExecutionContext(), property_name);
   if (!isValidCSSPropertyID(property_id))
     return String();
 
@@ -171,7 +176,8 @@
 const CSSValue*
 AbstractPropertySetCSSStyleDeclaration::GetPropertyCSSValueInternal(
     AtomicString custom_property_name) {
-  DCHECK_EQ(CSSPropertyID::kVariable, cssPropertyID(custom_property_name));
+  DCHECK_EQ(CSSPropertyID::kVariable,
+            cssPropertyID(GetExecutionContext(), custom_property_name));
   return PropertySet().GetPropertyCSSValue(custom_property_name);
 }
 
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
index a41986a..326aa9f 100644
--- a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
+++ b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
@@ -504,7 +504,8 @@
 
 String CSSComputedStyleDeclaration::getPropertyValue(
     const String& property_name) {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id =
+      cssPropertyID(GetExecutionContext(), property_name);
   if (!isValidCSSPropertyID(property_id))
     return String();
   if (property_id == CSSPropertyID::kVariable) {
@@ -564,7 +565,8 @@
 
 const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValueInternal(
     AtomicString custom_property_name) {
-  DCHECK_EQ(CSSPropertyID::kVariable, cssPropertyID(custom_property_name));
+  DCHECK_EQ(CSSPropertyID::kVariable,
+            cssPropertyID(GetExecutionContext(), custom_property_name));
   return GetPropertyCSSValue(custom_property_name);
 }
 
diff --git a/third_party/blink/renderer/core/css/css_property_name.h b/third_party/blink/renderer/core/css/css_property_name.h
index 64d34c4..e8f7a46 100644
--- a/third_party/blink/renderer/core/css/css_property_name.h
+++ b/third_party/blink/renderer/core/css/css_property_name.h
@@ -12,6 +12,8 @@
 
 namespace blink {
 
+class ExecutionContext;
+
 // This class may be used to represent the name of any valid CSS property,
 // including custom properties.
 class CORE_EXPORT CSSPropertyName {
@@ -29,8 +31,10 @@
     DCHECK(!custom_property_name.IsNull());
   }
 
-  static base::Optional<CSSPropertyName> From(const String& value) {
-    const CSSPropertyID property_id = cssPropertyID(value);
+  static base::Optional<CSSPropertyName> From(
+      const ExecutionContext* execution_context,
+      const String& value) {
+    const CSSPropertyID property_id = cssPropertyID(execution_context, value);
     if (property_id == CSSPropertyID::kInvalid)
       return base::nullopt;
     if (property_id == CSSPropertyID::kVariable)
diff --git a/third_party/blink/renderer/core/css/css_property_name_test.cc b/third_party/blink/renderer/core/css/css_property_name_test.cc
index 7714843..102a359e 100644
--- a/third_party/blink/renderer/core/css/css_property_name_test.cc
+++ b/third_party/blink/renderer/core/css/css_property_name_test.cc
@@ -3,13 +3,13 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/core/css/css_property_name.h"
-#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/css/properties/css_property.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 
 namespace blink {
 
-class CSSPropertyNameTest : public testing::Test {
+class CSSPropertyNameTest : public PageTestBase {
  public:
   CSSPropertyName Empty() const {
     return CSSPropertyName(CSSPropertyName::kEmptyValue);
@@ -61,14 +61,15 @@
 }
 
 TEST_F(CSSPropertyNameTest, From) {
-  EXPECT_TRUE(CSSPropertyName::From("color"));
-  EXPECT_TRUE(CSSPropertyName::From("--x"));
-  EXPECT_FALSE(CSSPropertyName::From("notaproperty"));
-  EXPECT_FALSE(CSSPropertyName::From("-not-a-property"));
+  EXPECT_TRUE(CSSPropertyName::From(&GetDocument(), "color"));
+  EXPECT_TRUE(CSSPropertyName::From(&GetDocument(), "--x"));
+  EXPECT_FALSE(CSSPropertyName::From(&GetDocument(), "notaproperty"));
+  EXPECT_FALSE(CSSPropertyName::From(&GetDocument(), "-not-a-property"));
 
-  EXPECT_EQ(*CSSPropertyName::From("color"),
+  EXPECT_EQ(*CSSPropertyName::From(&GetDocument(), "color"),
             CSSPropertyName(CSSPropertyID::kColor));
-  EXPECT_EQ(*CSSPropertyName::From("--x"), CSSPropertyName("--x"));
+  EXPECT_EQ(*CSSPropertyName::From(&GetDocument(), "--x"),
+            CSSPropertyName("--x"));
 }
 
 TEST_F(CSSPropertyNameTest, FromNativeCSSProperty) {
diff --git a/third_party/blink/renderer/core/css/cssom/css_style_value.cc b/third_party/blink/renderer/core/css/cssom/css_style_value.cc
index 53dd6b1..5e26e4e5 100644
--- a/third_party/blink/renderer/core/css/cssom/css_style_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_style_value.cc
@@ -24,7 +24,8 @@
     const String& property_name,
     const String& value,
     ExceptionState& exception_state) {
-  const CSSPropertyID property_id = cssPropertyID(property_name);
+  const CSSPropertyID property_id =
+      cssPropertyID(execution_context, property_name);
 
   if (property_id == CSSPropertyID::kInvalid) {
     exception_state.ThrowTypeError("Invalid property name");
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
index c50b855c..a0524a7a 100644
--- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
+++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
@@ -172,7 +172,7 @@
     const ExecutionContext* execution_context,
     const String& property_name,
     ExceptionState& exception_state) const {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id = cssPropertyID(execution_context, property_name);
   if (property_id == CSSPropertyID::kInvalid) {
     exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
     return CSSStyleValueVector();
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map.cc b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
index 8c174ca..6f20d09 100644
--- a/third_party/blink/renderer/core/css/cssom/style_property_map.cc
+++ b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
@@ -254,7 +254,8 @@
                            const String& property_name,
                            const HeapVector<CSSStyleValueOrString>& values,
                            ExceptionState& exception_state) {
-  const CSSPropertyID property_id = cssPropertyID(property_name);
+  const CSSPropertyID property_id =
+      cssPropertyID(execution_context, property_name);
   if (property_id == CSSPropertyID::kInvalid) {
     exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
     return;
@@ -318,7 +319,8 @@
   if (values.IsEmpty())
     return;
 
-  const CSSPropertyID property_id = cssPropertyID(property_name);
+  const CSSPropertyID property_id =
+      cssPropertyID(execution_context, property_name);
 
   if (property_id == CSSPropertyID::kInvalid) {
     exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
@@ -360,9 +362,10 @@
   SetProperty(property_id, *current_value);
 }
 
-void StylePropertyMap::remove(const String& property_name,
+void StylePropertyMap::remove(const ExecutionContext* execution_context,
+                              const String& property_name,
                               ExceptionState& exception_state) {
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property_id = cssPropertyID(execution_context, property_name);
   if (property_id == CSSPropertyID::kInvalid) {
     exception_state.ThrowTypeError("Invalid property name: " + property_name);
     return;
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map.h b/third_party/blink/renderer/core/css/cssom/style_property_map.h
index 6bbc19b..6b9e16c 100644
--- a/third_party/blink/renderer/core/css/cssom/style_property_map.h
+++ b/third_party/blink/renderer/core/css/cssom/style_property_map.h
@@ -27,7 +27,9 @@
               const String& property_name,
               const HeapVector<CSSStyleValueOrString>& values,
               ExceptionState&);
-  void remove(const String& property_name, ExceptionState&);
+  void remove(const ExecutionContext*,
+              const String& property_name,
+              ExceptionState&);
   void clear();
 
  protected:
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map.idl b/third_party/blink/renderer/core/css/cssom/style_property_map.idl
index 775ab0b..f4d3584 100644
--- a/third_party/blink/renderer/core/css/cssom/style_property_map.idl
+++ b/third_party/blink/renderer/core/css/cssom/style_property_map.idl
@@ -10,6 +10,6 @@
     // TODO(https://crbug.com/838890): DOMString should be CSSOMString
     [RaisesException, CallWith=ExecutionContext] void set(CSSOMString property, (CSSStyleValue or DOMString)... values);
     [RaisesException, CallWith=ExecutionContext] void append(CSSOMString property, (CSSStyleValue or DOMString)... values);
-    [RaisesException, ImplementedAs=remove] void delete(CSSOMString property);
+    [RaisesException, CallWith=ExecutionContext, ImplementedAs=remove] void delete(CSSOMString property);
     void clear();
 };
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
index 97fc4a49..acff621c 100644
--- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
+++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
@@ -62,7 +62,8 @@
     const ExecutionContext* execution_context,
     const String& property_name,
     ExceptionState& exception_state) const {
-  base::Optional<CSSPropertyName> name = CSSPropertyName::From(property_name);
+  base::Optional<CSSPropertyName> name =
+      CSSPropertyName::From(execution_context, property_name);
 
   if (!name) {
     exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
@@ -94,7 +95,8 @@
     const ExecutionContext* execution_context,
     const String& property_name,
     ExceptionState& exception_state) const {
-  base::Optional<CSSPropertyName> name = CSSPropertyName::From(property_name);
+  base::Optional<CSSPropertyName> name =
+      CSSPropertyName::From(execution_context, property_name);
 
   if (!name) {
     exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
index db2c9d0..ce930ad 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -72,7 +72,7 @@
            String value,
            Priority priority = Origin::kAuthor,
            AnimationTainted animation_tainted = AnimationTainted::kNo) {
-    return Add(*CSSPropertyName::From(name), value, priority,
+    return Add(*CSSPropertyName::From(&GetDocument(), name), value, priority,
                animation_tainted);
   }
 
@@ -90,7 +90,7 @@
   void Add(String name,
            const CSSValue* value,
            Priority priority = Origin::kAuthor) {
-    Add(*CSSPropertyName::From(name), value, priority);
+    Add(*CSSPropertyName::From(&GetDocument(), name), value, priority);
   }
 
   void Add(const CSSPropertyName& name,
@@ -106,7 +106,9 @@
   }
 
   void Apply(const CSSPropertyName& name) { cascade_.Apply(name); }
-  void Apply(String name) { Apply(*CSSPropertyName::From(name)); }
+  void Apply(String name) {
+    Apply(*CSSPropertyName::From(&GetDocument(), name));
+  }
   void Apply() { cascade_.Apply(); }
   void Apply(StyleCascade::Animator& animator) { cascade_.Apply(animator); }
   void Exclude(CSSProperty::Flag flag, bool set) {
@@ -155,11 +157,12 @@
   }
 
   bool HasValue(String name, const CSSValue* value) {
-    return cascade_.HasValue(*CSSPropertyName::From(name), value);
+    return cascade_.HasValue(*CSSPropertyName::From(&GetDocument(), name),
+                             value);
   }
 
   const CSSValue* GetCSSValue(String name) {
-    return cascade_.GetValue(*CSSPropertyName::From(name));
+    return cascade_.GetValue(*CSSPropertyName::From(&GetDocument(), name));
   }
 
   const String GetValue(String name) {
@@ -1542,8 +1545,10 @@
 
   cascade.Apply(animator);
 
-  EXPECT_TRUE(animator.record.Contains(*CSSPropertyName::From("--x")));
-  EXPECT_TRUE(animator.record.Contains(*CSSPropertyName::From("--y")));
+  EXPECT_TRUE(
+      animator.record.Contains(*CSSPropertyName::From(&GetDocument(), "--x")));
+  EXPECT_TRUE(
+      animator.record.Contains(*CSSPropertyName::From(&GetDocument(), "--y")));
 }
 
 TEST_F(StyleCascadeTest, PendingKeyframeAnimation) {
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc
index 395de26..47ee407 100644
--- a/third_party/blink/renderer/core/dom/events/event.cc
+++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -103,6 +103,7 @@
       legacy_did_listeners_throw_flag_(false),
       fire_only_capture_listeners_at_target_(false),
       fire_only_non_capture_listeners_at_target_(false),
+      copy_event_path_from_underlying_event_(false),
       handling_passive_(PassiveMode::kNotPassiveDefault),
       event_phase_(0),
       current_target_(nullptr),
@@ -292,7 +293,9 @@
 }
 
 void Event::InitEventPath(Node& node) {
-  if (!event_path_) {
+  if (copy_event_path_from_underlying_event_) {
+    event_path_ = underlying_event_->GetEventPath();
+  } else if (!event_path_) {
     event_path_ = MakeGarbageCollected<EventPath>(node, this);
   } else {
     event_path_->InitializeWith(node, this);
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h
index 5e4bf51..650e935c 100644
--- a/third_party/blink/renderer/core/dom/events/event.h
+++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -292,6 +292,10 @@
     legacy_did_listeners_throw_flag_ = true;
   }
 
+  void SetCopyEventPathFromUnderlyingEvent() {
+    copy_event_path_from_underlying_event_ = true;
+  }
+
   // In general, event listeners do not run when related execution contexts are
   // paused.  However, when this function returns true, event listeners ignore
   // the pause and run.
@@ -343,6 +347,8 @@
   unsigned fire_only_capture_listeners_at_target_ : 1;
   unsigned fire_only_non_capture_listeners_at_target_ : 1;
 
+  unsigned copy_event_path_from_underlying_event_ : 1;
+
   PassiveMode handling_passive_;
   uint8_t event_phase_;
   probe::AsyncTaskId async_task_id_;
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index 18191cc..7f19424 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -51,6 +51,7 @@
 #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
 #include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
+#include "third_party/blink/renderer/core/dom/events/event_path.h"
 #include "third_party/blink/renderer/core/dom/flat_tree_node_data.h"
 #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
 #include "third_party/blink/renderer/core/dom/get_root_node_options.h"
@@ -2886,6 +2887,8 @@
                     GetDocument().domWindow(), detail);
   event.SetUnderlyingEvent(&underlying_event);
   event.SetComposed(underlying_event.composed());
+  if (!isConnected())
+    event.SetCopyEventPathFromUnderlyingEvent();
   DispatchScopedEvent(event);
 
   // TODO(dtapuska): Dispatching scoped events shouldn't check the return
diff --git a/third_party/blink/renderer/core/events/web_input_event_conversion.cc b/third_party/blink/renderer/core/events/web_input_event_conversion.cc
index 716617985..fcf3fc6b 100644
--- a/third_party/blink/renderer/core/events/web_input_event_conversion.cc
+++ b/third_party/blink/renderer/core/events/web_input_event_conversion.cc
@@ -120,8 +120,8 @@
 WebPointerEvent TransformWebPointerEvent(float frame_scale,
                                          gfx::Vector2dF frame_translate,
                                          const WebPointerEvent& event) {
-  // frameScale is default initialized in debug builds to be 0.
-  DCHECK_EQ(0, event.FrameScale());
+  // frameScale is default initialized to 1.
+  DCHECK_EQ(1, event.FrameScale());
   DCHECK_EQ(0, event.FrameTranslate().x());
   DCHECK_EQ(0, event.FrameTranslate().y());
   WebPointerEvent result = event;
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
index ffb66f0..482fb35a 100644
--- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -2202,15 +2202,15 @@
   if (element->GetPseudoId())
     return Response::Error("Elements is pseudo");
 
-  CSSPropertyID property = cssPropertyID(property_name);
-  if (!isValidCSSPropertyID(property))
-    return Response::Error("Invalid property name");
-
   Document* owner_document = element->ownerDocument();
   if (!owner_document->IsActive())
     return Response::Error("Can't edit a node from a non-active document");
 
-  CSSPropertyID property_id = cssPropertyID(property_name);
+  CSSPropertyID property = cssPropertyID(owner_document, property_name);
+  if (!isValidCSSPropertyID(property))
+    return Response::Error("Invalid property name");
+
+  CSSPropertyID property_id = cssPropertyID(owner_document, property_name);
   const CSSProperty& property_class = CSSProperty::Get(property_id);
   CSSStyleDeclaration* style =
       FindEffectiveDeclaration(property_class, MatchingStyles(element));
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
index 4e2b9fc..b70ddca 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
@@ -241,7 +241,7 @@
   css_property_filter_ = std::make_unique<CSSPropertyFilter>();
   // Look up the CSSPropertyIDs for each entry in |computed_styles|.
   for (String& entry : *computed_styles) {
-    CSSPropertyID property_id = cssPropertyID(entry);
+    CSSPropertyID property_id = cssPropertyID(main_document, entry);
     if (property_id == CSSPropertyID::kInvalid)
       continue;
     css_property_filter_->emplace_back(std::move(entry),
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
index 47c3d807..bed31f3 100644
--- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -488,7 +488,8 @@
       MakeGarbageCollected<CSSComputedStyleDeclaration>(node, true);
   for (size_t i = 0; i < style->length(); ++i) {
     AtomicString name(style->item(i));
-    const CSSValue* value = style->GetPropertyCSSValue(cssPropertyID(name));
+    const CSSValue* value =
+        style->GetPropertyCSSValue(cssPropertyID(&node->GetDocument(), name));
     if (!value)
       continue;
     if (value->IsColorValue()) {
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
index 43e65da..c91869d4 100644
--- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -1731,6 +1731,11 @@
   return page_style_sheet_->Contents()->SourceMapURL();
 }
 
+const Document* InspectorStyleSheet::GetDocument() {
+  return CSSStyleSheet::SingleOwnerDocument(
+      InspectorStyleSheet::PageStyleSheet());
+}
+
 CSSRuleSourceData* InspectorStyleSheet::FindRuleByHeaderRange(
     const SourceRange& source_range) {
   if (!source_data_)
@@ -1986,4 +1991,8 @@
   InspectorStyleSheetBase::Trace(visitor);
 }
 
+const Document* InspectorStyleSheetForInlineStyle::GetDocument() {
+  return &InspectorStyleSheetForInlineStyle::element_->GetDocument();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.h b/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
index f6fa38f7..7e8911a0 100644
--- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
+++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
@@ -43,6 +43,7 @@
 class CSSStyleDeclaration;
 class CSSStyleRule;
 class CSSStyleSheet;
+class Document;
 class Element;
 class ExceptionState;
 class InspectorNetworkAgent;
@@ -59,6 +60,9 @@
                  InspectorStyleSheetBase* parent_style_sheet);
 
   CSSStyleDeclaration* CssStyle() { return style_.Get(); }
+  InspectorStyleSheetBase* InspectorStyleSheet() {
+    return parent_style_sheet_.Get();
+  }
   std::unique_ptr<protocol::CSS::CSSStyle> BuildObjectForStyle();
   bool StyleText(String* result);
   bool TextForRange(const SourceRange&, String* result);
@@ -92,6 +96,7 @@
   virtual bool SetText(const String&, ExceptionState&) = 0;
   virtual bool GetText(String* result) = 0;
   virtual String SourceMapURL() { return String(); }
+  virtual const Document* GetDocument() = 0;
 
   std::unique_ptr<protocol::CSS::CSSStyle> BuildObjectForStyle(
       CSSStyleDeclaration*);
@@ -181,6 +186,7 @@
   const CSSRuleVector& FlatRules();
   CSSRuleSourceData* SourceDataForRule(CSSRule*);
   String SourceMapURL() override;
+  const Document* GetDocument() override;
 
  protected:
   InspectorStyle* GetInspectorStyle(CSSStyleDeclaration*) override;
@@ -250,6 +256,8 @@
 
   void Trace(blink::Visitor*) override;
 
+  const Document* GetDocument() override;
+
  protected:
   InspectorStyle* GetInspectorStyle(CSSStyleDeclaration*) override;
 
diff --git a/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc b/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
index e2f99df..be9928b7 100644
--- a/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
+++ b/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
@@ -124,7 +124,7 @@
 
   // Look up the CSSPropertyIDs for each entry in |style_filter|.
   for (const String& entry : *style_filter) {
-    CSSPropertyID property_id = cssPropertyID(entry);
+    CSSPropertyID property_id = cssPropertyID(document, entry);
     if (property_id == CSSPropertyID::kInvalid)
       continue;
     css_property_filter_->emplace_back(entry, property_id);
diff --git a/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc b/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc
index fc3cb6b4c..3aac3eaa 100644
--- a/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc
+++ b/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc
@@ -104,7 +104,8 @@
   Vector<AtomicString> custom_invalidation_properties;
 
   if (!V8ObjectParser::ParseCSSPropertyList(
-          current_context, layout_ctor->CallbackObject(), "inputProperties",
+          current_context, GetFrame()->GetDocument(),
+          layout_ctor->CallbackObject(), "inputProperties",
           &native_invalidation_properties, &custom_invalidation_properties,
           &exception_state))
     return;
@@ -113,8 +114,9 @@
   Vector<AtomicString> child_custom_invalidation_properties;
 
   if (!V8ObjectParser::ParseCSSPropertyList(
-          current_context, layout_ctor->CallbackObject(),
-          "childInputProperties", &child_native_invalidation_properties,
+          current_context, GetFrame()->GetDocument(),
+          layout_ctor->CallbackObject(), "childInputProperties",
+          &child_native_invalidation_properties,
           &child_custom_invalidation_properties, &exception_state))
     return;
 
diff --git a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
index 605807e..cc6640d 100644
--- a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
+++ b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
@@ -24,7 +24,10 @@
     : frame_or_imported_document_(frame_or_imported_document),
       fetch_client_settings_object_(
           MakeGarbageCollected<FetchClientSettingsObjectImpl>(
-              frame_or_imported_document.GetDocument())) {}
+              frame_or_imported_document.GetDocument())),
+      web_bundle_physical_url_(
+          frame_or_imported_document_->GetMasterDocumentLoader()
+              .WebBundlePhysicalUrl()) {}
 
 void FrameResourceFetcherProperties::Trace(Visitor* visitor) {
   visitor->Trace(frame_or_imported_document_);
@@ -107,8 +110,7 @@
 }
 
 const KURL& FrameResourceFetcherProperties::WebBundlePhysicalUrl() const {
-  return frame_or_imported_document_->GetMasterDocumentLoader()
-      .WebBundlePhysicalUrl();
+  return web_bundle_physical_url_;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
index 85ec89e..e07906c5 100644
--- a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
+++ b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
 namespace blink {
 
@@ -46,6 +47,7 @@
  private:
   const Member<FrameOrImportedDocument> frame_or_imported_document_;
   Member<const FetchClientSettingsObject> fetch_client_settings_object_;
+  const KURL web_bundle_physical_url_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/resource/font_resource.cc b/third_party/blink/renderer/core/loader/resource/font_resource.cc
index d64d4bb..0ae350d2 100644
--- a/third_party/blink/renderer/core/loader/resource/font_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/font_resource.cc
@@ -49,35 +49,6 @@
 constexpr base::TimeDelta kFontLoadWaitLong =
     base::TimeDelta::FromMilliseconds(3000);
 
-enum FontPackageFormat {
-  kPackageFormatUnknown,
-  kPackageFormatSFNT,
-  kPackageFormatWOFF,
-  kPackageFormatWOFF2,
-  kPackageFormatSVG,
-  kPackageFormatEnumMax
-};
-
-static FontPackageFormat PackageFormatOf(SharedBuffer* buffer) {
-  static constexpr size_t kMaxHeaderSize = 4;
-  char data[kMaxHeaderSize];
-  if (!buffer->GetBytes(data, kMaxHeaderSize))
-    return kPackageFormatUnknown;
-
-  if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F')
-    return kPackageFormatWOFF;
-  if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == '2')
-    return kPackageFormatWOFF2;
-  return kPackageFormatSFNT;
-}
-
-static void RecordPackageFormatHistogram(FontPackageFormat format) {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      EnumerationHistogram, package_format_histogram,
-      ("WebFont.PackageFormat", kPackageFormatEnumMax));
-  package_format_histogram.Count(format);
-}
-
 FontResource* FontResource::Fetch(FetchParameters& params,
                                   ResourceFetcher* fetcher,
                                   FontResourceClient* client) {
@@ -146,12 +117,8 @@
     if (Data())
       font_data_ = FontCustomPlatformData::Create(Data(), ots_parsing_message_);
 
-    if (font_data_) {
-      RecordPackageFormatHistogram(PackageFormatOf(Data()));
-    } else {
+    if (!font_data_)
       SetStatus(ResourceStatus::kDecodeError);
-      RecordPackageFormatHistogram(kPackageFormatUnknown);
-    }
   }
   return font_data_;
 }
diff --git a/third_party/blink/renderer/core/script/import_map.cc b/third_party/blink/renderer/core/script/import_map.cc
index 0aed827a..7368ed0 100644
--- a/third_party/blink/renderer/core/script/import_map.cc
+++ b/third_party/blink/renderer/core/script/import_map.cc
@@ -439,10 +439,6 @@
 base::Optional<ImportMap::MatchResult> ImportMap::MatchPrefix(
     const ParsedSpecifier& parsed_specifier,
     const SpecifierMap& specifier_map) const {
-  // Do not perform prefix match for non-bare specifiers.
-  if (parsed_specifier.GetType() != ParsedSpecifier::Type::kBare)
-    return base::nullopt;
-
   const String key = parsed_specifier.GetImportMapKeyString();
 
   // Prefix match, i.e. "Packages" via trailing slashes.
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc
index fc5ade5..55c95aa0 100644
--- a/third_party/blink/renderer/core/style/computed_style_test.cc
+++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -594,15 +594,19 @@
     ScopedCSSCascadeForTest scoped_cascade_enabled(true);
 
     StyleCascade cascade1(state);
-    cascade1.Add(*CSSPropertyName::From("color"), internal_light_dark, origin);
-    cascade1.Add(*CSSPropertyName::From("color-scheme"), dark_value, origin);
+    cascade1.Add(*CSSPropertyName::From(&state.GetDocument(), "color"),
+                 internal_light_dark, origin);
+    cascade1.Add(*CSSPropertyName::From(&state.GetDocument(), "color-scheme"),
+                 dark_value, origin);
     cascade1.Apply();
     EXPECT_EQ(Color::kWhite,
               style->VisitedDependentColor(GetCSSPropertyColor()));
 
     StyleCascade cascade2(state);
-    cascade2.Add(*CSSPropertyName::From("color"), internal_light_dark, origin);
-    cascade2.Add(*CSSPropertyName::From("color-scheme"), light_value, origin);
+    cascade2.Add(*CSSPropertyName::From(&state.GetDocument(), "color"),
+                 internal_light_dark, origin);
+    cascade2.Add(*CSSPropertyName::From(&state.GetDocument(), "color-scheme"),
+                 light_value, origin);
     cascade2.Apply();
     EXPECT_EQ(Color::kBlack,
               style->VisitedDependentColor(GetCSSPropertyColor()));
diff --git a/third_party/blink/renderer/core/svg/svg_animate_element.cc b/third_party/blink/renderer/core/svg/svg_animate_element.cc
index 326e8c2..5da81f1 100644
--- a/third_party/blink/renderer/core/svg/svg_animate_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_animate_element.cc
@@ -181,7 +181,8 @@
   } else {
     type_ = SVGElement::AnimatedPropertyTypeForCSSAttribute(AttributeName());
     css_property_id_ = type_ != kAnimatedUnknown
-                           ? cssPropertyID(AttributeName().LocalName())
+                           ? cssPropertyID(&targetElement()->GetDocument(),
+                                           AttributeName().LocalName())
                            : CSSPropertyID::kInvalid;
   }
   // Blacklist <script> targets here for now to prevent unpleasantries. This
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc
index 8e8a080..42342fd 100644
--- a/third_party/blink/renderer/core/svg/svg_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -354,6 +354,7 @@
 }
 
 CSSPropertyID SVGElement::CssPropertyIdForSVGAttributeName(
+    const ExecutionContext* execution_context,
     const QualifiedName& attr_name) {
   if (!attr_name.NamespaceURI().IsNull())
     return CSSPropertyID::kInvalid;
@@ -424,7 +425,8 @@
         &svg_names::kWritingModeAttr,
     };
     for (size_t i = 0; i < base::size(attr_names); i++) {
-      CSSPropertyID property_id = cssPropertyID(attr_names[i]->LocalName());
+      CSSPropertyID property_id =
+          cssPropertyID(execution_context, attr_names[i]->LocalName());
       DCHECK_GT(property_id, CSSPropertyID::kInvalid);
       property_name_to_id_map->Set(attr_names[i]->LocalName().Impl(),
                                    property_id);
@@ -735,14 +737,16 @@
 bool SVGElement::IsPresentationAttribute(const QualifiedName& name) const {
   if (const SVGAnimatedPropertyBase* property = PropertyFromAttribute(name))
     return property->HasPresentationAttributeMapping();
-  return CssPropertyIdForSVGAttributeName(name) > CSSPropertyID::kInvalid;
+  return CssPropertyIdForSVGAttributeName(&GetDocument(), name) >
+         CSSPropertyID::kInvalid;
 }
 
 void SVGElement::CollectStyleForPresentationAttribute(
     const QualifiedName& name,
     const AtomicString& value,
     MutableCSSPropertyValueSet* style) {
-  CSSPropertyID property_id = CssPropertyIdForSVGAttributeName(name);
+  CSSPropertyID property_id =
+      CssPropertyIdForSVGAttributeName(&GetDocument(), name);
   if (property_id > CSSPropertyID::kInvalid)
     AddPropertyToPresentationAttributeStyle(style, property_id, value);
 }
@@ -876,7 +880,7 @@
 
 void SVGElement::SvgAttributeChanged(const QualifiedName& attr_name) {
   CSSPropertyID prop_id =
-      SVGElement::CssPropertyIdForSVGAttributeName(attr_name);
+      SVGElement::CssPropertyIdForSVGAttributeName(&GetDocument(), attr_name);
   if (prop_id > CSSPropertyID::kInvalid) {
     InvalidateInstances();
     return;
diff --git a/third_party/blink/renderer/core/svg/svg_element.h b/third_party/blink/renderer/core/svg/svg_element.h
index 7ba76683..fb005d70 100644
--- a/third_party/blink/renderer/core/svg/svg_element.h
+++ b/third_party/blink/renderer/core/svg/svg_element.h
@@ -38,6 +38,7 @@
 class AffineTransform;
 class Document;
 class ElementSMILAnimations;
+class ExecutionContext;
 class SVGAnimatedPropertyBase;
 class SubtreeLayoutScope;
 class SVGAnimatedString;
@@ -237,7 +238,8 @@
 
   void DetachLayoutTree(bool performing_reattach) override;
 
-  static CSSPropertyID CssPropertyIdForSVGAttributeName(const QualifiedName&);
+  static CSSPropertyID CssPropertyIdForSVGAttributeName(const ExecutionContext*,
+                                                        const QualifiedName&);
   void UpdateRelativeLengthsInformation() {
     UpdateRelativeLengthsInformation(SelfHasRelativeLengths(), this);
   }
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
index 091cad2..8ab810c 100644
--- a/third_party/blink/renderer/core/timing/performance_resource_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -388,11 +388,19 @@
   builder.AddNumber("encodedBodySize", encodedBodySize());
   builder.AddNumber("decodedBodySize", decodedBodySize());
 
-  ScriptState* script_state = builder.GetScriptState();
-  builder.Add("serverTiming", FreezeV8Object(ToV8(serverTiming(), script_state),
-                                             script_state->GetIsolate()));
-  builder.Add("workerTiming", FreezeV8Object(ToV8(workerTiming(), script_state),
-                                             script_state->GetIsolate()));
+  HeapVector<ScriptValue> server_timing;
+  server_timing.ReserveCapacity(server_timing_.size());
+  for (const auto& timing : server_timing_) {
+    server_timing.push_back(timing->toJSONForBinding(builder.GetScriptState()));
+  }
+  builder.Add("serverTiming", server_timing);
+
+  HeapVector<ScriptValue> worker_timing;
+  worker_timing.ReserveCapacity(worker_timing_.size());
+  for (const auto& timing : worker_timing_) {
+    worker_timing.push_back(timing->toJSONForBinding(builder.GetScriptState()));
+  }
+  builder.Add("workerTiming", worker_timing);
 }
 
 void PerformanceResourceTiming::AddPerformanceEntry(
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc
index 1924298e..4419e27 100644
--- a/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -220,8 +220,9 @@
 
 void WindowPerformance::BuildJSONValue(V8ObjectBuilder& builder) const {
   Performance::BuildJSONValue(builder);
-  builder.Add("timing", timing());
-  builder.Add("navigation", navigation());
+  builder.Add("timing", timing()->toJSONForBinding(builder.GetScriptState()));
+  builder.Add("navigation",
+              navigation()->toJSONForBinding(builder.GetScriptState()));
 }
 
 void WindowPerformance::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
index 45b0c5c..51a6b20 100644
--- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
+++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
@@ -170,6 +170,11 @@
     return outside_content_security_policy_headers_;
   }
 
+  void SetIsOfflineMode(bool is_offline_mode) {
+    DCHECK(web_worker_fetch_context_);
+    web_worker_fetch_context_->SetIsOfflineMode(is_offline_mode);
+  }
+
  private:
   void InitializeWebFetchContextIfNeeded();
   ResourceFetcher* CreateFetcherInternal(const FetchClientSettingsObject&,
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
index e579547d..e00f788 100644
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -127,7 +127,7 @@
 // A class that is passed into V8 Interrupt and via a PostTask. Once both have
 // run this object will be destroyed in
 // PauseOrFreezeWithInterruptDataOnWorkerThread. The V8 API only takes a raw ptr
-// otherwise this could have been done with base::Bind and ref counted objects.
+// otherwise this could have been done with WTF::Bind and ref counted objects.
 class WorkerThread::InterruptData {
  public:
   InterruptData(WorkerThread* worker_thread, mojom::FrameLifecycleState state)
diff --git a/third_party/blink/renderer/modules/content_index/content_index.cc b/third_party/blink/renderer/modules/content_index/content_index.cc
index 929c596..c0ac35d 100644
--- a/third_party/blink/renderer/modules/content_index/content_index.cc
+++ b/third_party/blink/renderer/modules/content_index/content_index.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/modules/content_index/content_icon_definition.h"
 #include "third_party/blink/renderer/modules/content_index/content_index_icon_loader.h"
 #include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -73,21 +74,19 @@
 ContentIndex::~ContentIndex() = default;
 
 ScriptPromise ContentIndex::add(ScriptState* script_state,
-                                const ContentDescription* description) {
+                                const ContentDescription* description,
+                                ExceptionState& exception_state) {
   if (!registration_->active()) {
-    return ScriptPromise::Reject(
-        script_state,
-        V8ThrowException::CreateTypeError(script_state->GetIsolate(),
-                                          "No active registration available on "
-                                          "the ServiceWorkerRegistration."));
+    exception_state.ThrowTypeError(
+        "No active registration available on the ServiceWorkerRegistration.");
+    return ScriptPromise();
   }
 
   WTF::String description_error =
       ValidateDescription(*description, registration_.Get());
   if (!description_error.IsNull()) {
-    return ScriptPromise::Reject(
-        script_state, V8ThrowException::CreateTypeError(
-                          script_state->GetIsolate(), description_error));
+    exception_state.ThrowTypeError(description_error);
+    return ScriptPromise();
   }
 
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -176,13 +175,12 @@
 }
 
 ScriptPromise ContentIndex::deleteDescription(ScriptState* script_state,
-                                              const String& id) {
+                                              const String& id,
+                                              ExceptionState& exception_state) {
   if (!registration_->active()) {
-    return ScriptPromise::Reject(
-        script_state,
-        V8ThrowException::CreateTypeError(script_state->GetIsolate(),
-                                          "No active registration available on "
-                                          "the ServiceWorkerRegistration."));
+    exception_state.ThrowTypeError(
+        "No active registration available on the ServiceWorkerRegistration.");
+    return ScriptPromise();
   }
 
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -221,13 +219,12 @@
   }
 }
 
-ScriptPromise ContentIndex::getDescriptions(ScriptState* script_state) {
+ScriptPromise ContentIndex::getDescriptions(ScriptState* script_state,
+                                            ExceptionState& exception_state) {
   if (!registration_->active()) {
-    return ScriptPromise::Reject(
-        script_state,
-        V8ThrowException::CreateTypeError(script_state->GetIsolate(),
-                                          "No active registration available on "
-                                          "the ServiceWorkerRegistration."));
+    exception_state.ThrowTypeError(
+        "No active registration available on the ServiceWorkerRegistration.");
+    return ScriptPromise();
   }
 
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
diff --git a/third_party/blink/renderer/modules/content_index/content_index.h b/third_party/blink/renderer/modules/content_index/content_index.h
index 49e2ff85..ab73fce6 100644
--- a/third_party/blink/renderer/modules/content_index/content_index.h
+++ b/third_party/blink/renderer/modules/content_index/content_index.h
@@ -16,6 +16,7 @@
 namespace blink {
 
 class ContentDescription;
+class ExceptionState;
 class ScriptPromiseResolver;
 class ScriptState;
 class ServiceWorkerRegistration;
@@ -30,9 +31,13 @@
 
   // Web-exposed function defined in the IDL file.
   ScriptPromise add(ScriptState* script_state,
-                    const ContentDescription* description);
-  ScriptPromise deleteDescription(ScriptState* script_state, const String& id);
-  ScriptPromise getDescriptions(ScriptState* script_state);
+                    const ContentDescription* description,
+                    ExceptionState& exception_state);
+  ScriptPromise deleteDescription(ScriptState* script_state,
+                                  const String& id,
+                                  ExceptionState& exception_state);
+  ScriptPromise getDescriptions(ScriptState* script_state,
+                                ExceptionState& exception_state);
 
   void Trace(blink::Visitor* visitor) override;
 
diff --git a/third_party/blink/renderer/modules/content_index/content_index.idl b/third_party/blink/renderer/modules/content_index/content_index.idl
index 8a116d0..fa954d1 100644
--- a/third_party/blink/renderer/modules/content_index/content_index.idl
+++ b/third_party/blink/renderer/modules/content_index/content_index.idl
@@ -8,7 +8,7 @@
     Exposed=(Window,Worker),
     RuntimeEnabled=ContentIndex
 ] interface ContentIndex {
-    [CallWith=ScriptState, MeasureAs=ContentIndexAdd] Promise<void> add(ContentDescription description);
-    [CallWith=ScriptState, MeasureAs=ContentIndexDelete, ImplementedAs=deleteDescription] Promise<void> delete(DOMString id);
-    [CallWith=ScriptState, MeasureAs=ContentIndexGet, ImplementedAs=getDescriptions] Promise<sequence<ContentDescription>> getAll();
-};
\ No newline at end of file
+    [CallWith=ScriptState, RaisesException, MeasureAs=ContentIndexAdd] Promise<void> add(ContentDescription description);
+    [CallWith=ScriptState, RaisesException, MeasureAs=ContentIndexDelete, ImplementedAs=deleteDescription] Promise<void> delete(DOMString id);
+    [CallWith=ScriptState, RaisesException, MeasureAs=ContentIndexGet, ImplementedAs=getDescriptions] Promise<sequence<ContentDescription>> getAll();
+};
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
index 128562b..8b30f7d 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
@@ -146,7 +146,8 @@
   WorkletGlobalScope::Dispose();
 }
 
-void PaintWorkletGlobalScope::registerPaint(const String& name,
+void PaintWorkletGlobalScope::registerPaint(const ScriptState* script_state,
+                                            const String& name,
                                             V8NoArgumentConstructor* paint_ctor,
                                             ExceptionState& exception_state) {
   // https://drafts.css-houdini.org/css-paint-api/#dom-paintworkletglobalscope-registerpaint
@@ -178,8 +179,11 @@
   Vector<CSSPropertyID> native_invalidation_properties;
   Vector<AtomicString> custom_invalidation_properties;
 
+  const ExecutionContext* execution_context =
+      ExecutionContext::From(script_state);
+
   if (!V8ObjectParser::ParseCSSPropertyList(
-          context, v8_paint_ctor, "inputProperties",
+          context, execution_context, v8_paint_ctor, "inputProperties",
           &native_invalidation_properties, &custom_invalidation_properties,
           &exception_state))
     return;
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
index 0c1e72c..f3d52a8 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
@@ -16,6 +16,7 @@
 
 class CSSPaintDefinition;
 class ExceptionState;
+class ScriptState;
 class V8NoArgumentConstructor;
 class WorkerReportingProxy;
 
@@ -44,7 +45,8 @@
   void Dispose() final;
 
   bool IsPaintWorkletGlobalScope() const final { return true; }
-  void registerPaint(const String& name,
+  void registerPaint(const ScriptState* script_state,
+                     const String& name,
                      V8NoArgumentConstructor* paint_ctor,
                      ExceptionState&);
 
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl
index bc86a89..21bfbf3 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl
@@ -9,7 +9,7 @@
     Global=(Worklet,PaintWorklet)
 ] interface PaintWorkletGlobalScope : WorkletGlobalScope {
     [Measure] readonly attribute unrestricted double devicePixelRatio;
-    [Measure, RaisesException] void registerPaint(DOMString name, NoArgumentConstructor paintCtor);
+    [Measure, RaisesException, CallWith=ScriptState] void registerPaint(DOMString name, NoArgumentConstructor paintCtor);
 };
 
 // Blink-specific type for paint function
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc
index fe48c57e..48735ac 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -23,6 +23,7 @@
 #include "third_party/blink/renderer/modules/mediastream/media_track_supported_constraints.h"
 #include "third_party/blink/renderer/modules/mediastream/navigator_media_stream.h"
 #include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h"
@@ -63,15 +64,15 @@
 
 MediaDevices::~MediaDevices() = default;
 
-ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state) {
+ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state,
+                                             ExceptionState& exception_state) {
   UpdateWebRTCMethodCount(RTCAPIName::kEnumerateDevices);
   LocalFrame* frame =
       To<Document>(ExecutionContext::From(script_state))->GetFrame();
   if (!frame) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state,
-        MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
-                                           "Current frame is detached."));
+    exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+                                      "Current frame is detached.");
+    return ScriptPromise();
   }
 
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -111,11 +112,10 @@
   UserMediaController* user_media =
       UserMediaController::From(document->GetFrame());
   if (!user_media) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state, MakeGarbageCollected<DOMException>(
-                          DOMExceptionCode::kNotSupportedError,
-                          "No media device controller available; is this a "
-                          "detached window?"));
+    exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+                                      "No media device controller available; "
+                                      "is this a detached window?");
+    return ScriptPromise();
   }
 
   MediaErrorState error_state;
@@ -134,9 +134,9 @@
 
   String error_message;
   if (!request->IsSecureContextUse(error_message)) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state, MakeGarbageCollected<DOMException>(
-                          DOMExceptionCode::kNotSupportedError, error_message));
+    exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+                                      error_message);
+    return ScriptPromise();
   }
   auto promise = resolver->Promise();
   request->Start();
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.h b/third_party/blink/renderer/modules/mediastream/media_devices.h
index 63ccf33d..b1f10b6 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices.h
+++ b/third_party/blink/renderer/modules/mediastream/media_devices.h
@@ -21,6 +21,7 @@
 
 namespace blink {
 
+class ExceptionState;
 class LocalFrame;
 class MediaStreamConstraints;
 class MediaTrackSupportedConstraints;
@@ -41,7 +42,7 @@
   explicit MediaDevices(ExecutionContext*);
   ~MediaDevices() override;
 
-  ScriptPromise enumerateDevices(ScriptState*);
+  ScriptPromise enumerateDevices(ScriptState*, ExceptionState&);
   MediaTrackSupportedConstraints* getSupportedConstraints() const;
   ScriptPromise getUserMedia(ScriptState*,
                              const MediaStreamConstraints*,
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.idl b/third_party/blink/renderer/modules/mediastream/media_devices.idl
index 51d7f54..16d463d 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices.idl
+++ b/third_party/blink/renderer/modules/mediastream/media_devices.idl
@@ -13,7 +13,7 @@
 ] interface MediaDevices : EventTarget {
     [RuntimeEnabled=OnDeviceChange] attribute EventHandler ondevicechange;
     [
-      CallWith = ScriptState, HighEntropy, MeasureAs = MediaDevicesEnumerateDevices
+      CallWith = ScriptState, RaisesException, HighEntropy, MeasureAs = MediaDevicesEnumerateDevices
     ] Promise<sequence<MediaDeviceInfo>>
     enumerateDevices();
     MediaTrackSupportedConstraints getSupportedConstraints();
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
index 28727631..5ef57be 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
@@ -163,57 +163,6 @@
   mojo::Receiver<mojom::blink::MediaDevicesDispatcherHost> receiver_{this};
 };
 
-class PromiseObserver {
- public:
-  PromiseObserver(ScriptState* script_state, ScriptPromise promise)
-      : is_rejected_(false), is_fulfilled_(false) {
-    v8::Local<v8::Function> on_fulfilled = MyScriptFunction::CreateFunction(
-        script_state, &is_fulfilled_, &saved_arg_);
-    v8::Local<v8::Function> on_rejected = MyScriptFunction::CreateFunction(
-        script_state, &is_rejected_, &saved_arg_);
-    promise.Then(on_fulfilled, on_rejected);
-  }
-
-  bool isDecided() { return is_rejected_ || is_fulfilled_; }
-
-  bool isFulfilled() { return is_fulfilled_; }
-  bool isRejected() { return is_rejected_; }
-  ScriptValue argument() { return saved_arg_; }
-  void Trace(blink::Visitor* visitor) { visitor->Trace(saved_arg_); }
-
- private:
-  class MyScriptFunction : public ScriptFunction {
-   public:
-    static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
-                                                  bool* flag_to_set,
-                                                  ScriptValue* arg_to_set) {
-      MyScriptFunction* self = MakeGarbageCollected<MyScriptFunction>(
-          script_state, flag_to_set, arg_to_set);
-      return self->BindToV8Function();
-    }
-
-    MyScriptFunction(ScriptState* script_state,
-                     bool* flag_to_set,
-                     ScriptValue* arg_to_set)
-        : ScriptFunction(script_state),
-          flag_to_set_(flag_to_set),
-          arg_to_set_(arg_to_set) {}
-    ScriptValue Call(ScriptValue arg) override {
-      *flag_to_set_ = true;
-      *arg_to_set_ = arg;
-      return arg;
-    }
-
-   private:
-    bool* flag_to_set_;
-    ScriptValue* arg_to_set_;
-  };
-
-  bool is_rejected_;
-  bool is_fulfilled_;
-  ScriptValue saved_arg_;
-};
-
 class MediaDevicesTest : public testing::Test {
  public:
   using MediaDeviceInfos = HeapVector<Member<MediaDeviceInfo>>;
@@ -298,24 +247,13 @@
       GetMediaDevices(scope.GetExecutionContext())
           ->getUserMedia(scope.GetScriptState(), constraints,
                          scope.GetExceptionState());
-  ASSERT_FALSE(promise.IsEmpty());
-  PromiseObserver promise_observer(scope.GetScriptState(), promise);
-  EXPECT_FALSE(promise_observer.isDecided());
-  v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
-  EXPECT_TRUE(promise_observer.isDecided());
+  ASSERT_TRUE(promise.IsEmpty());
   // In the default test environment, we expect a DOM rejection because
   // the script state's execution context's document's frame doesn't
   // have an UserMediaController.
-  EXPECT_TRUE(promise_observer.isRejected());
-  // TODO(hta): Check that the correct error ("not supported") is returned.
-  EXPECT_FALSE(promise_observer.argument().IsNull());
-  // This log statement is included as a demonstration of how to get the string
-  // value of the argument.
-  VLOG(1) << "Argument is"
-          << ToCoreString(promise_observer.argument()
-                              .V8Value()
-                              ->ToString(scope.GetContext())
-                              .ToLocalChecked());
+  DCHECK_EQ(scope.GetExceptionState().Code(),
+            ToExceptionCode(DOMExceptionCode::kNotSupportedError));
+  VLOG(1) << "Exception message is" << scope.GetExceptionState().Message();
 }
 
 TEST_F(MediaDevicesTest, EnumerateDevices) {
@@ -323,8 +261,8 @@
   auto* media_devices = GetMediaDevices(scope.GetExecutionContext());
   media_devices->SetEnumerateDevicesCallbackForTesting(
       WTF::Bind(&MediaDevicesTest::DevicesEnumerated, WTF::Unretained(this)));
-  ScriptPromise promise =
-      media_devices->enumerateDevices(scope.GetScriptState());
+  ScriptPromise promise = media_devices->enumerateDevices(
+      scope.GetScriptState(), scope.GetExceptionState());
   platform()->RunUntilIdle();
   ASSERT_FALSE(promise.IsEmpty());
 
@@ -385,8 +323,8 @@
   CloseBinding();
   platform()->RunUntilIdle();
 
-  ScriptPromise promise =
-      media_devices->enumerateDevices(scope.GetScriptState());
+  ScriptPromise promise = media_devices->enumerateDevices(
+      scope.GetScriptState(), scope.GetExceptionState());
   platform()->RunUntilIdle();
   ASSERT_FALSE(promise.IsEmpty());
   EXPECT_TRUE(dispatcher_host_connection_error());
@@ -403,8 +341,8 @@
                 WTF::Unretained(this)));
   EXPECT_FALSE(dispatcher_host_connection_error());
 
-  ScriptPromise promise =
-      media_devices->enumerateDevices(scope.GetScriptState());
+  ScriptPromise promise = media_devices->enumerateDevices(
+      scope.GetScriptState(), scope.GetExceptionState());
   platform()->RunUntilIdle();
   ASSERT_FALSE(promise.IsEmpty());
 
diff --git a/third_party/blink/renderer/modules/nfc/ndef_message.cc b/third_party/blink/renderer/modules/nfc/ndef_message.cc
index 5f6413e..a288bb26 100644
--- a/third_party/blink/renderer/modules/nfc/ndef_message.cc
+++ b/third_party/blink/renderer/modules/nfc/ndef_message.cc
@@ -64,7 +64,8 @@
         static_cast<wtf_size_t>(byte_length));
     NDEFMessage* message = MakeGarbageCollected<NDEFMessage>();
     message->records_.push_back(MakeGarbageCollected<NDEFRecord>(
-        std::move(payload_data), "application/octet-stream"));
+        String() /* id */, "application/octet-stream",
+        std::move(payload_data)));
     return message;
   }
 
@@ -83,7 +84,8 @@
         static_cast<wtf_size_t>(byte_length));
     NDEFMessage* message = MakeGarbageCollected<NDEFMessage>();
     message->records_.push_back(MakeGarbageCollected<NDEFRecord>(
-        std::move(payload_data), "application/octet-stream"));
+        String() /* id */, "application/octet-stream",
+        std::move(payload_data)));
     return message;
   }
 
diff --git a/third_party/blink/renderer/modules/nfc/ndef_record.cc b/third_party/blink/renderer/modules/nfc/ndef_record.cc
index f8e145e7..ff77b9aa 100644
--- a/third_party/blink/renderer/modules/nfc/ndef_record.cc
+++ b/third_party/blink/renderer/modules/nfc/ndef_record.cc
@@ -118,7 +118,8 @@
   return document_language;
 }
 
-static NDEFRecord* CreateTextRecord(const ExecutionContext* execution_context,
+static NDEFRecord* CreateTextRecord(const String& id,
+                                    const ExecutionContext* execution_context,
                                     const String& encoding,
                                     const String& lang,
                                     const NDEFRecordDataSource& data,
@@ -165,12 +166,13 @@
     }
   }
 
-  return MakeGarbageCollected<NDEFRecord>("text", encoding_label, language,
+  return MakeGarbageCollected<NDEFRecord>(id, encoding_label, language,
                                           std::move(bytes));
 }
 
 // Create a 'url' record or an 'absolute-url' record.
 static NDEFRecord* CreateUrlRecord(const String& record_type,
+                                   const String& id,
                                    const NDEFRecordDataSource& data,
                                    ExceptionState& exception_state) {
   // https://w3c.github.io/web-nfc/#mapping-url-to-ndef
@@ -187,11 +189,13 @@
                                       "Cannot parse data for url record.");
     return nullptr;
   }
-  return MakeGarbageCollected<NDEFRecord>(record_type,
-                                          GetUTF8DataFromString(url));
+  return MakeGarbageCollected<NDEFRecord>(
+      device::mojom::NDEFRecordTypeCategory::kStandardized, record_type, id,
+      GetUTF8DataFromString(url));
 }
 
-static NDEFRecord* CreateMimeRecord(const NDEFRecordDataSource& data,
+static NDEFRecord* CreateMimeRecord(const String& id,
+                                    const NDEFRecordDataSource& data,
                                     const String& media_type,
                                     ExceptionState& exception_state) {
   // https://w3c.github.io/web-nfc/#mapping-binary-data-to-ndef
@@ -205,10 +209,18 @@
   if (!GetBytesOfBufferSource(data, &bytes, exception_state)) {
     return nullptr;
   }
-  return MakeGarbageCollected<NDEFRecord>(bytes, media_type);
+
+  // ExtractMIMETypeFromMediaType() ignores parameters of the MIME type.
+  String mime_type = ExtractMIMETypeFromMediaType(AtomicString(media_type));
+  if (mime_type.IsEmpty()) {
+    mime_type = "application/octet-stream";
+  }
+
+  return MakeGarbageCollected<NDEFRecord>(id, mime_type, bytes);
 }
 
-static NDEFRecord* CreateUnknownRecord(const NDEFRecordDataSource& data,
+static NDEFRecord* CreateUnknownRecord(const String& id,
+                                       const NDEFRecordDataSource& data,
                                        ExceptionState& exception_state) {
   if (!IsBufferSource(data)) {
     exception_state.ThrowTypeError(
@@ -220,10 +232,13 @@
   if (!GetBytesOfBufferSource(data, &bytes, exception_state)) {
     return nullptr;
   }
-  return MakeGarbageCollected<NDEFRecord>("unknown", bytes);
+  return MakeGarbageCollected<NDEFRecord>(
+      device::mojom::NDEFRecordTypeCategory::kStandardized, "unknown", id,
+      bytes);
 }
 
-static NDEFRecord* CreateExternalRecord(const String& custom_type,
+static NDEFRecord* CreateExternalRecord(const String& record_type,
+                                        const String& id,
                                         const NDEFRecordDataSource& data,
                                         ExceptionState& exception_state) {
   // TODO(https://crbug.com/520391): Add support in case of |data| being an
@@ -241,7 +256,7 @@
     return nullptr;
   }
   NDEFRecord* record = MakeGarbageCollected<NDEFRecord>(
-      device::mojom::NDEFRecordTypeCategory::kExternal, custom_type, bytes);
+      device::mojom::NDEFRecordTypeCategory::kExternal, record_type, id, bytes);
   return record;
 }
 
@@ -271,64 +286,60 @@
     return nullptr;
   }
 
-  NDEFRecord* instance = nullptr;
   if (record_type == "empty") {
     // https://w3c.github.io/web-nfc/#mapping-empty-record-to-ndef
-    instance =
-        MakeGarbageCollected<NDEFRecord>(record_type, WTF::Vector<uint8_t>());
+    return MakeGarbageCollected<NDEFRecord>(
+        device::mojom::NDEFRecordTypeCategory::kStandardized, record_type,
+        init->id(), WTF::Vector<uint8_t>());
   } else if (record_type == "text") {
-    instance = CreateTextRecord(execution_context, init->encoding(),
-                                init->lang(), init->data(), exception_state);
+    return CreateTextRecord(init->id(), execution_context, init->encoding(),
+                            init->lang(), init->data(), exception_state);
   } else if (record_type == "url" || record_type == "absolute-url") {
-    instance = CreateUrlRecord(record_type, init->data(), exception_state);
+    return CreateUrlRecord(record_type, init->id(), init->data(),
+                           exception_state);
   } else if (record_type == "mime") {
-    instance =
-        CreateMimeRecord(init->data(), init->mediaType(), exception_state);
+    return CreateMimeRecord(init->id(), init->data(), init->mediaType(),
+                            exception_state);
   } else if (record_type == "unknown") {
-    instance = CreateUnknownRecord(init->data(), exception_state);
+    return CreateUnknownRecord(init->id(), init->data(), exception_state);
   } else if (record_type == "smart-poster") {
     // TODO(https://crbug.com/520391): Support creating smart-poster records.
     exception_state.ThrowTypeError("smart-poster type is not supported yet");
     return nullptr;
   } else if (IsValidExternalType(record_type)) {
-    instance = CreateExternalRecord(record_type, init->data(), exception_state);
+    return CreateExternalRecord(record_type, init->id(), init->data(),
+                                exception_state);
   } else {
     // TODO(https://crbug.com/520391): Support local type records.
-    exception_state.ThrowTypeError("Invalid NDEFRecord type.");
-    return nullptr;
   }
 
-  if (instance && init->hasId()) {
-    instance->id_ = init->id();
-  }
-  return instance;
+  exception_state.ThrowTypeError("Invalid NDEFRecord type.");
+  return nullptr;
 }
 
-NDEFRecord::NDEFRecord(const String& record_type, WTF::Vector<uint8_t> data)
-    : category_(device::mojom::NDEFRecordTypeCategory::kStandardized),
-      record_type_(record_type),
-      payload_data_(std::move(data)) {}
-
-NDEFRecord::NDEFRecord(const String& record_type,
-                       const String& encoding,
-                       const String& lang,
-                       WTF::Vector<uint8_t> data)
-    : category_(device::mojom::NDEFRecordTypeCategory::kStandardized),
-      record_type_(record_type),
-      encoding_(encoding),
-      lang_(lang),
-      payload_data_(std::move(data)) {}
-
 NDEFRecord::NDEFRecord(device::mojom::NDEFRecordTypeCategory category,
                        const String& record_type,
+                       const String& id,
                        WTF::Vector<uint8_t> data)
     : category_(category),
       record_type_(record_type),
+      id_(id),
       payload_data_(std::move(data)) {
   DCHECK_EQ(category_ == device::mojom::NDEFRecordTypeCategory::kExternal,
             IsValidExternalType(record_type_));
 }
 
+NDEFRecord::NDEFRecord(const String& id,
+                       const String& encoding,
+                       const String& lang,
+                       WTF::Vector<uint8_t> data)
+    : category_(device::mojom::NDEFRecordTypeCategory::kStandardized),
+      record_type_("text"),
+      id_(id),
+      encoding_(encoding),
+      lang_(lang),
+      payload_data_(std::move(data)) {}
+
 NDEFRecord::NDEFRecord(const ExecutionContext* execution_context,
                        const String& text)
     : category_(device::mojom::NDEFRecordTypeCategory::kStandardized),
@@ -337,33 +348,30 @@
       lang_(getDocumentLanguage(execution_context)),
       payload_data_(GetUTF8DataFromString(text)) {}
 
-NDEFRecord::NDEFRecord(WTF::Vector<uint8_t> payload_data,
-                       const String& media_type)
+NDEFRecord::NDEFRecord(const String& id,
+                       const String& media_type,
+                       WTF::Vector<uint8_t> data)
     : category_(device::mojom::NDEFRecordTypeCategory::kStandardized),
       record_type_("mime"),
-      payload_data_(std::move(payload_data)) {
-  // ExtractMIMETypeFromMediaType() ignores parameters of the MIME type.
-  media_type_ = ExtractMIMETypeFromMediaType(AtomicString(media_type));
-  if (media_type_.IsEmpty()) {
-    media_type_ = "application/octet-stream";
-  }
-}
+      id_(id),
+      media_type_(media_type),
+      payload_data_(std::move(data)) {}
 
 NDEFRecord::NDEFRecord(const device::mojom::blink::NDEFRecord& record)
     : category_(record.category),
       record_type_(record.record_type),
-      media_type_(record.media_type),
       id_(record.id),
+      media_type_(record.media_type),
       encoding_(record.encoding),
       lang_(record.lang),
-      payload_data_(record.data) {
+      payload_data_(record.data),
+      payload_message_(
+          record.payload_message
+              ? MakeGarbageCollected<NDEFMessage>(*record.payload_message)
+              : nullptr) {
   DCHECK_NE(record_type_ == "mime", media_type_.IsNull());
   DCHECK_EQ(category_ == device::mojom::NDEFRecordTypeCategory::kExternal,
             IsValidExternalType(record_type_));
-  if (record.payload_message) {
-    payload_message_ =
-        MakeGarbageCollected<NDEFMessage>(*record.payload_message);
-  }
 }
 
 const String& NDEFRecord::mediaType() const {
diff --git a/third_party/blink/renderer/modules/nfc/ndef_record.h b/third_party/blink/renderer/modules/nfc/ndef_record.h
index 1c4701fa..4065ddd 100644
--- a/third_party/blink/renderer/modules/nfc/ndef_record.h
+++ b/third_party/blink/renderer/modules/nfc/ndef_record.h
@@ -28,26 +28,29 @@
                             const NDEFRecordInit*,
                             ExceptionState&);
 
-  // Construct a "text" record from a string.
-  explicit NDEFRecord(const ExecutionContext*, const String&);
+  explicit NDEFRecord(device::mojom::NDEFRecordTypeCategory,
+                      const String& /* record_type */,
+                      const String& /* id */,
+                      WTF::Vector<uint8_t>);
 
-  // Construct a "mime" record from the raw payload bytes.
-  explicit NDEFRecord(WTF::Vector<uint8_t> /* payload_data */,
-                      const String& /* media_type */);
-
-  explicit NDEFRecord(const String& /* record_type */,
-                      WTF::Vector<uint8_t> /* data */);
-  explicit NDEFRecord(const String& /* record_type */,
+  // Only for constructing "text" type record. The type category will be
+  // device::mojom::NDEFRecordTypeCategory::kStandardized.
+  explicit NDEFRecord(const String& /* id */,
                       const String& /* encoding */,
                       const String& /* lang */,
-                      WTF::Vector<uint8_t> /* data */);
+                      WTF::Vector<uint8_t>);
 
-  // All above Ctors by default set the type category to
+  // Only for constructing "text" type record from just a text. The type
+  // category will be device::mojom::NDEFRecordTypeCategory::kStandardized.
+  // Called by NDEFMessage.
+  explicit NDEFRecord(const ExecutionContext*, const String&);
+
+  // Only for constructing "mime" type record. The type category will be
   // device::mojom::NDEFRecordTypeCategory::kStandardized.
+  explicit NDEFRecord(const String& /* id */,
+                      const String& /* media_type */,
+                      WTF::Vector<uint8_t>);
 
-  explicit NDEFRecord(device::mojom::NDEFRecordTypeCategory /* category */,
-                      const String& /* record_type */,
-                      WTF::Vector<uint8_t> /* data */);
   explicit NDEFRecord(const device::mojom::blink::NDEFRecord&);
 
   const String& recordType() const { return record_type_; }
@@ -68,16 +71,16 @@
  private:
   const device::mojom::NDEFRecordTypeCategory category_;
   const String record_type_;
-  String media_type_;
-  String id_;
-  String encoding_;
-  String lang_;
+  const String id_;
+  const String media_type_;
+  const String encoding_;
+  const String lang_;
   // Holds the NDEFRecord.[[PayloadData]] bytes defined at
   // https://w3c.github.io/web-nfc/#the-ndefrecord-interface.
-  WTF::Vector<uint8_t> payload_data_;
+  const WTF::Vector<uint8_t> payload_data_;
   // |payload_data_| parsed as an NDEFMessage. This field will be set for some
   // "smart-poster" and external type records.
-  Member<NDEFMessage> payload_message_;
+  const Member<NDEFMessage> payload_message_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/nfc/ndef_scan_options.idl b/third_party/blink/renderer/modules/nfc/ndef_scan_options.idl
index 26d129f..cf20cf59 100644
--- a/third_party/blink/renderer/modules/nfc/ndef_scan_options.idl
+++ b/third_party/blink/renderer/modules/nfc/ndef_scan_options.idl
@@ -6,6 +6,6 @@
 dictionary NDEFScanOptions {
     USVString id;
     USVString recordType;
-    USVString mediaType = "";
+    USVString mediaType;
     AbortSignal? signal;
 };
diff --git a/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc b/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
index 94e5dcb7..5b38736f 100644
--- a/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
+++ b/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
@@ -70,9 +70,8 @@
     const blink::NDEFScanOptions* scanOptions) {
   // https://w3c.github.io/web-nfc/#dom-ndefscanoptions
   // Default values for NDEFScanOptions dictionary are:
-  // id = undefined, recordType = undefined, mediaType = ""
+  // id = undefined, recordType = undefined, mediaType = undefined
   NDEFScanOptionsPtr scanOptionsPtr = NDEFScanOptions::New();
-  scanOptionsPtr->media_type = scanOptions->mediaType();
 
   if (scanOptions->hasId()) {
     scanOptionsPtr->id = scanOptions->id();
@@ -82,6 +81,10 @@
     scanOptionsPtr->record_type = scanOptions->recordType();
   }
 
+  if (scanOptions->hasMediaType()) {
+    scanOptionsPtr->media_type = scanOptions->mediaType();
+  }
+
   return scanOptionsPtr;
 }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
index 21adc2f8..e0db936 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
+++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
@@ -403,7 +403,7 @@
 }
 
 void MockRTCPeerConnectionHandlerPlatform::
-    RunSynchronousOnceClosureOnSignalingThread(base::OnceClosure closure,
+    RunSynchronousOnceClosureOnSignalingThread(CrossThreadOnceClosure closure,
                                                const char* trace_event_name) {}
 
 void MockRTCPeerConnectionHandlerPlatform::
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
index 6bf3e08..2db98e0 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
+++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
@@ -76,7 +76,7 @@
   void Stop() override;
   webrtc::PeerConnectionInterface* NativePeerConnection() override;
   void RunSynchronousOnceClosureOnSignalingThread(
-      base::OnceClosure closure,
+      CrossThreadOnceClosure closure,
       const char* trace_event_name) override;
   void RunSynchronousRepeatingClosureOnSignalingThread(
       const base::RepeatingClosure& closure,
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
index 2239a3f..2f5018d8 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -234,7 +234,7 @@
   // thread. Done in a single synchronous call to the signaling thread to ensure
   // channel state consistency.
   peer_connection_handler->RunSynchronousOnceClosureOnSignalingThread(
-      ConvertToBaseOnceCallback(CrossThreadBindOnce(
+      CrossThreadBindOnce(
           [](scoped_refptr<RTCDataChannel::Observer> observer,
              webrtc::DataChannelInterface::DataState current_state) {
             scoped_refptr<webrtc::DataChannelInterface> channel =
@@ -244,7 +244,7 @@
               observer->OnStateChange();
             }
           },
-          observer_, state_)),
+          observer_, state_),
       "RegisterObserverAndGetStateUpdate");
 
   IncrementCounters(*channel.get());
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
index e916d0b..9f831ddc 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
@@ -52,7 +52,7 @@
       : signaling_thread_(signaling_thread) {}
 
   void RunSynchronousOnceClosureOnSignalingThread(
-      base::OnceClosure closure,
+      CrossThreadOnceClosure closure,
       const char* trace_event_name) override {
     closure_ = std::move(closure);
     RunSynchronous(
@@ -68,7 +68,7 @@
   }
 
   scoped_refptr<base::TestSimpleTaskRunner> signaling_thread_;
-  base::OnceClosure closure_;
+  CrossThreadOnceClosure closure_;
 
   DISALLOW_COPY_AND_ASSIGN(MockPeerConnectionHandler);
 };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index 0578d21d..057f7cef 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -50,7 +50,6 @@
 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_void_request.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
 #include "third_party/webrtc/api/data_channel_interface.h"
@@ -66,6 +65,30 @@
 using webrtc::StatsReport;
 using webrtc::StatsReports;
 
+namespace WTF {
+
+template <>
+struct CrossThreadCopier<scoped_refptr<DataChannelInterface>>
+    : public CrossThreadCopierPassThrough<scoped_refptr<DataChannelInterface>> {
+  STATIC_ONLY(CrossThreadCopier);
+};
+
+template <>
+struct CrossThreadCopier<scoped_refptr<PeerConnectionInterface>>
+    : public CrossThreadCopierPassThrough<
+          scoped_refptr<PeerConnectionInterface>> {
+  STATIC_ONLY(CrossThreadCopier);
+};
+
+template <typename T>
+struct CrossThreadCopier<rtc::scoped_refptr<T>> {
+  STATIC_ONLY(CrossThreadCopier);
+  using Type = rtc::scoped_refptr<T>;
+  static Type Copy(Type pointer) { return pointer; }
+};
+
+}  // namespace WTF
+
 namespace blink {
 namespace {
 
@@ -107,7 +130,7 @@
   std::move(closure).Run();
 }
 
-void RunSynchronousOnceClosure(base::OnceClosure closure,
+void RunSynchronousOnceClosure(CrossThreadOnceClosure closure,
                                const char* trace_event_name,
                                base::WaitableEvent* event) {
   {
@@ -130,7 +153,7 @@
 // Initializes |description| if |description_callback| returns non-null,
 // otherwise does nothing.
 void GetRTCSessionDescriptionPlatformFromSessionDescriptionCallback(
-    base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+    CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
         description_callback,
     std::string* out_type,
     std::string* out_sdp,
@@ -240,11 +263,12 @@
 
   void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
     if (!main_thread_->BelongsToCurrentThread()) {
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(
               &CreateSessionDescriptionRequest::OnSuccess,
-              rtc::scoped_refptr<CreateSessionDescriptionRequest>(this), desc));
+              rtc::scoped_refptr<CreateSessionDescriptionRequest>(this),
+              CrossThreadUnretained(desc)));
       return;
     }
 
@@ -265,9 +289,9 @@
   }
   void OnFailure(webrtc::RTCError error) override {
     if (!main_thread_->BelongsToCurrentThread()) {
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(
               &CreateSessionDescriptionRequest::OnFailure,
               rtc::scoped_refptr<CreateSessionDescriptionRequest>(this),
               std::move(error)));
@@ -732,11 +756,12 @@
       // Instead, do it all synchronously. This must happen as the last step
       // before returning so that all effects of SRD have occurred when the
       // event executes. https://crbug.com/788558
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(&RTCPeerConnectionHandler::
-                             WebRtcSetDescriptionObserverImpl::ResolvePromise,
-                         this));
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(
+              &RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl::
+                  ResolvePromise,
+              WrapRefCounted(this)));
     } else {
       // Resolve promise immediately if we can. https://crbug.com/788558 still
       // needs to be addressed for "setLocalDescription(answer)" rejecting a
@@ -847,6 +872,8 @@
   // When an RTC event log is sent back from PeerConnection, it arrives here.
   void OnWebRtcEventLogWrite(const std::string& output) override {
     if (!main_thread_->BelongsToCurrentThread()) {
+      // TODO(crbug.com/787254): Convert this call to PostCrossThreadTask,
+      // after crrev.com/c/1976250 lands.
       main_thread_->PostTask(
           FROM_HERE,
           base::BindOnce(
@@ -867,9 +894,9 @@
 
   void OnDataChannel(
       rtc::scoped_refptr<DataChannelInterface> data_channel) override {
-    main_thread_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
+    PostCrossThreadTask(
+        *main_thread_.get(), FROM_HERE,
+        CrossThreadBindOnce(
             &RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
             WrapCrossThreadPersistent(this),
             base::WrapRefCounted<DataChannelInterface>(data_channel.get())));
@@ -877,9 +904,9 @@
 
   void OnRenegotiationNeeded() override {
     if (!main_thread_->BelongsToCurrentThread()) {
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(
               &RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded,
               WrapCrossThreadPersistent(this)));
     } else if (handler_) {
@@ -892,11 +919,11 @@
   void OnStandardizedIceConnectionChange(
       PeerConnectionInterface::IceConnectionState new_state) override {
     if (!main_thread_->BelongsToCurrentThread()) {
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(&RTCPeerConnectionHandler::Observer::
-                             OnStandardizedIceConnectionChange,
-                         WrapCrossThreadPersistent(this), new_state));
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(&RTCPeerConnectionHandler::Observer::
+                                  OnStandardizedIceConnectionChange,
+                              WrapCrossThreadPersistent(this), new_state));
     } else if (handler_) {
       handler_->OnIceConnectionChange(new_state);
     }
@@ -905,9 +932,9 @@
   void OnConnectionChange(
       PeerConnectionInterface::PeerConnectionState new_state) override {
     if (!main_thread_->BelongsToCurrentThread()) {
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(
               &RTCPeerConnectionHandler::Observer::OnConnectionChange,
               WrapCrossThreadPersistent(this), new_state));
     } else if (handler_) {
@@ -918,9 +945,9 @@
   void OnIceGatheringChange(
       PeerConnectionInterface::IceGatheringState new_state) override {
     if (!main_thread_->BelongsToCurrentThread()) {
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(
               &RTCPeerConnectionHandler::Observer::OnIceGatheringChange,
               WrapCrossThreadPersistent(this), new_state));
     } else if (handler_) {
@@ -935,23 +962,23 @@
       return;
     }
 
-    main_thread_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
-                       WrapCrossThreadPersistent(this), String::FromUTF8(sdp),
-                       String::FromUTF8(candidate->sdp_mid()),
-                       candidate->sdp_mline_index(),
-                       candidate->candidate().component(),
-                       candidate->candidate().address().family()));
+    PostCrossThreadTask(
+        *main_thread_.get(), FROM_HERE,
+        CrossThreadBindOnce(
+            &RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
+            WrapCrossThreadPersistent(this), String::FromUTF8(sdp),
+            String::FromUTF8(candidate->sdp_mid()),
+            candidate->sdp_mline_index(), candidate->candidate().component(),
+            candidate->candidate().address().family()));
   }
 
   void OnIceCandidateError(const std::string& host_candidate,
                            const std::string& url,
                            int error_code,
                            const std::string& error_text) override {
-    main_thread_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
+    PostCrossThreadTask(
+        *main_thread_.get(), FROM_HERE,
+        CrossThreadBindOnce(
             &RTCPeerConnectionHandler::Observer::OnIceCandidateErrorImpl,
             WrapCrossThreadPersistent(this), String::FromUTF8(host_candidate),
             String::FromUTF8(url), error_code, String::FromUTF8(error_text)));
@@ -987,9 +1014,9 @@
   }
 
   void OnInterestingUsage(int usage_pattern) override {
-    main_thread_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
+    PostCrossThreadTask(
+        *main_thread_.get(), FROM_HERE,
+        CrossThreadBindOnce(
             &RTCPeerConnectionHandler::Observer::OnInterestingUsageImpl,
             WrapCrossThreadPersistent(this), usage_pattern));
   }
@@ -1443,10 +1470,10 @@
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
 
-  base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
-      description_cb =
-          base::BindOnce(&webrtc::PeerConnectionInterface::local_description,
-                         native_peer_connection_);
+  CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
+      description_cb = CrossThreadBindOnce(
+          &webrtc::PeerConnectionInterface::local_description,
+          native_peer_connection_);
   return GetRTCSessionDescriptionPlatformOnSignalingThread(
       std::move(description_cb), "localDescription");
 }
@@ -1454,10 +1481,11 @@
 RTCSessionDescriptionPlatform* RTCPeerConnectionHandler::RemoteDescription() {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
-  base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
-      description_cb =
-          base::BindOnce(&webrtc::PeerConnectionInterface::remote_description,
-                         native_peer_connection_);
+
+  CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
+      description_cb = CrossThreadBindOnce(
+          &webrtc::PeerConnectionInterface::remote_description,
+          native_peer_connection_);
   return GetRTCSessionDescriptionPlatformOnSignalingThread(
       std::move(description_cb), "remoteDescription");
 }
@@ -1467,8 +1495,8 @@
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::currentLocalDescription");
 
-  base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
-      description_cb = base::BindOnce(
+  CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
+      description_cb = CrossThreadBindOnce(
           &webrtc::PeerConnectionInterface::current_local_description,
           native_peer_connection_);
   return GetRTCSessionDescriptionPlatformOnSignalingThread(
@@ -1479,8 +1507,9 @@
 RTCPeerConnectionHandler::CurrentRemoteDescription() {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::currentRemoteDescription");
-  base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
-      description_cb = base::BindOnce(
+
+  CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
+      description_cb = CrossThreadBindOnce(
           &webrtc::PeerConnectionInterface::current_remote_description,
           native_peer_connection_);
   return GetRTCSessionDescriptionPlatformOnSignalingThread(
@@ -1491,8 +1520,9 @@
 RTCPeerConnectionHandler::PendingLocalDescription() {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::pendingLocalDescription");
-  base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
-      description_cb = base::BindOnce(
+
+  CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
+      description_cb = CrossThreadBindOnce(
           &webrtc::PeerConnectionInterface::pending_local_description,
           native_peer_connection_);
   return GetRTCSessionDescriptionPlatformOnSignalingThread(
@@ -1503,8 +1533,8 @@
 RTCPeerConnectionHandler::PendingRemoteDescription() {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::pendingRemoteDescription");
-  base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
-      description_cb = base::BindOnce(
+  CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
+      description_cb = CrossThreadBindOnce(
           &webrtc::PeerConnectionInterface::pending_remote_description,
           native_peer_connection_);
   return GetRTCSessionDescriptionPlatformOnSignalingThread(
@@ -2081,7 +2111,7 @@
 }
 
 void RTCPeerConnectionHandler::RunSynchronousOnceClosureOnSignalingThread(
-    base::OnceClosure closure,
+    CrossThreadOnceClosure closure,
     const char* trace_event_name) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
@@ -2091,11 +2121,11 @@
   } else {
     base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                               base::WaitableEvent::InitialState::NOT_SIGNALED);
-    thread->PostTask(
-        FROM_HERE,
-        base::BindOnce(&RunSynchronousOnceClosure, std::move(closure),
-                       base::Unretained(trace_event_name),
-                       base::Unretained(&event)));
+    PostCrossThreadTask(
+        *thread.get(), FROM_HERE,
+        CrossThreadBindOnce(&RunSynchronousOnceClosure, std::move(closure),
+                            CrossThreadUnretained(trace_event_name),
+                            CrossThreadUnretained(&event)));
     event.Wait();
   }
 }
@@ -2590,7 +2620,7 @@
 
 RTCSessionDescriptionPlatform*
 RTCPeerConnectionHandler::GetRTCSessionDescriptionPlatformOnSignalingThread(
-    base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+    CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
         description_cb,
     const char* log_text) {
   // Since the webrtc::PeerConnectionInterface::*_description() functions
@@ -2604,10 +2634,10 @@
   std::string type, sdp;
   bool success = false;
   RunSynchronousOnceClosureOnSignalingThread(
-      base::BindOnce(
+      CrossThreadBindOnce(
           &GetRTCSessionDescriptionPlatformFromSessionDescriptionCallback,
-          std::move(description_cb), base::Unretained(&type),
-          base::Unretained(&sdp), base::Unretained(&success)),
+          std::move(description_cb), CrossThreadUnretained(&type),
+          CrossThreadUnretained(&sdp), CrossThreadUnretained(&success)),
       log_text);
 
   if (!success)
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
index 8d6776e..89be851e 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
@@ -164,7 +164,7 @@
   void Stop() override;
   webrtc::PeerConnectionInterface* NativePeerConnection() override;
   void RunSynchronousOnceClosureOnSignalingThread(
-      base::OnceClosure closure,
+      CrossThreadOnceClosure closure,
       const char* trace_event_name) override;
   void RunSynchronousRepeatingClosureOnSignalingThread(
       const base::RepeatingClosure& closure,
@@ -265,7 +265,7 @@
 
   RTCSessionDescriptionPlatform*
   GetRTCSessionDescriptionPlatformOnSignalingThread(
-      base::OnceCallback<const webrtc::SessionDescriptionInterface*()>
+      CrossThreadOnceFunction<const webrtc::SessionDescriptionInterface*()>
           description_cb,
       const char* log_text);
 
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
index c8327ba..9d21f454 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
+++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
@@ -18,11 +18,12 @@
 
 namespace {
 
-static ScriptPromise RejectPromiseImmediately(ScriptState* script_state) {
-  return ScriptPromise::RejectWithDOMException(
-      script_state,
-      MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
-                                         "Current document is detached"));
+static ScriptPromise RejectPromiseImmediately(ExceptionState& exception_state) {
+  // The bindings layer implicitly converts thrown exceptions in
+  // promise-returning functions to promise rejections.
+  exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+                                    "Current document is detached");
+  return ScriptPromise();
 }
 
 }  // namespace
@@ -65,9 +66,10 @@
 ScriptPromise DOMScheduler::postTask(ScriptState* script_state,
                                      V8Function* callback_function,
                                      SchedulerPostTaskOptions* options,
-                                     const HeapVector<ScriptValue>& args) {
+                                     const HeapVector<ScriptValue>& args,
+                                     ExceptionState& exception_state) {
   if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
-    return RejectPromiseImmediately(script_state);
+    return RejectPromiseImmediately(exception_state);
 
   // Always honor the priority and the task signal if given. Therefore:
   // * If both priority and signal are set, use the signal but choose the
@@ -89,7 +91,7 @@
   } else if (auto* task_signal = DynamicTo<DOMTaskSignal>(options->signal())) {
     task_runner = task_signal->GetTaskRunner();
     if (!task_runner)
-      return RejectPromiseImmediately(script_state);
+      return RejectPromiseImmediately(exception_state);
   } else {
     task_runner = GetTaskRunnerFor(WebSchedulingPriority::kDefaultPriority);
   }
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.h b/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
index f83cd93..276c223 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
+++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
@@ -18,6 +18,7 @@
 namespace blink {
 
 class DOMTask;
+class ExceptionState;
 class ExecutionContext;
 class SchedulerPostTaskOptions;
 class ScriptValue;
@@ -46,7 +47,8 @@
   ScriptPromise postTask(ScriptState*,
                          V8Function*,
                          SchedulerPostTaskOptions*,
-                         const HeapVector<ScriptValue>& args);
+                         const HeapVector<ScriptValue>& args,
+                         ExceptionState&);
 
   // Callbacks invoked by DOMTasks when they run.
   void OnTaskStarted(DOMTask*);
diff --git a/third_party/blink/renderer/modules/scheduler/scheduler.idl b/third_party/blink/renderer/modules/scheduler/scheduler.idl
index 5c2f4b7a0..7268c07 100644
--- a/third_party/blink/renderer/modules/scheduler/scheduler.idl
+++ b/third_party/blink/renderer/modules/scheduler/scheduler.idl
@@ -8,5 +8,5 @@
     ImplementedAs=DOMScheduler,
     RuntimeEnabled=WebScheduler
 ] interface Scheduler {
-    [CallWith=ScriptState] Promise<any> postTask(Function callback, optional SchedulerPostTaskOptions options, any... arguments);
+    [CallWith=ScriptState, RaisesException] Promise<any> postTask(Function callback, optional SchedulerPostTaskOptions options, any... arguments);
 };
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc
index 7c52d2b..4a8f399 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc
@@ -52,14 +52,19 @@
 }
 
 ServiceWorkerEventQueue::ServiceWorkerEventQueue(
+    BeforeStartEventCallback before_start_event_callback,
     base::RepeatingClosure idle_callback)
-    : ServiceWorkerEventQueue(std::move(idle_callback),
+    : ServiceWorkerEventQueue(std::move(before_start_event_callback),
+                              std::move(idle_callback),
                               base::DefaultTickClock::GetInstance()) {}
 
 ServiceWorkerEventQueue::ServiceWorkerEventQueue(
+    BeforeStartEventCallback before_start_event_callback,
     base::RepeatingClosure idle_callback,
     const base::TickClock* tick_clock)
-    : idle_callback_(std::move(idle_callback)), tick_clock_(tick_clock) {}
+    : before_start_event_callback_(std::move(before_start_event_callback)),
+      idle_callback_(std::move(idle_callback)),
+      tick_clock_(tick_clock) {}
 
 ServiceWorkerEventQueue::~ServiceWorkerEventQueue() {
   in_dtor_ = true;
@@ -156,6 +161,8 @@
                     tick_clock_->NowTicks() +
                         event->custom_timeout.value_or(kEventTimeout),
                     WTF::Bind(std::move(event->abort_callback), event_id)));
+  if (before_start_event_callback_)
+    before_start_event_callback_.Run(event->type == Event::Type::Offline);
   std::move(event->start_callback).Run(event_id);
 }
 
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h
index 37a556d..8fd7047 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h
@@ -60,9 +60,14 @@
       base::OnceCallback<void(int /* event_id */,
                               mojom::blink::ServiceWorkerEventStatus)>;
 
-  explicit ServiceWorkerEventQueue(base::RepeatingClosure idle_callback);
+  using BeforeStartEventCallback =
+      base::RepeatingCallback<void(/*is_offline_event=*/bool)>;
+
+  ServiceWorkerEventQueue(BeforeStartEventCallback before_start_event_callback,
+                          base::RepeatingClosure idle_callback);
   // For testing.
-  ServiceWorkerEventQueue(base::RepeatingClosure idle_callback,
+  ServiceWorkerEventQueue(BeforeStartEventCallback before_start_event_callback,
+                          base::RepeatingClosure idle_callback,
                           const base::TickClock* tick_clock);
   ~ServiceWorkerEventQueue();
 
@@ -210,6 +215,9 @@
   // inflight events finish.
   bool zero_idle_timer_delay_ = false;
 
+  // Callback which is run just before starting an event.
+  BeforeStartEventCallback before_start_event_callback_;
+
   // For idle timeouts. Invoked when UpdateStatus() is called after
   // |idle_time_|.
   base::RepeatingClosure idle_callback_;
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue_test.cc b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue_test.cc
index a32e588..7e6209b 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue_test.cc
@@ -134,7 +134,8 @@
       base::TimeDelta::FromSeconds(1);
 
   bool is_idle = false;
-  ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+  ServiceWorkerEventQueue event_queue(base::NullCallback(),
+                                      CreateReceiverWithCalledFlag(&is_idle),
                                       task_runner()->GetMockTickClock());
   task_runner()->FastForwardBy(kIdleInterval);
   // Nothing should happen since the event queue has not started yet.
@@ -196,7 +197,8 @@
       base::TimeDelta::FromSeconds(1);
 
   bool is_idle = false;
-  ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                      CreateReceiverWithCalledFlag(&is_idle),
                                       task_runner()->GetMockTickClock());
   MockEvent event;
   event.EnqueueTo(&event_queue);
@@ -218,7 +220,8 @@
 // In the first UpdateStatus() the idle callback should be triggered.
 TEST_F(ServiceWorkerEventQueueTest, EventFinishedBeforeStart) {
   bool is_idle = false;
-  ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                      CreateReceiverWithCalledFlag(&is_idle),
                                       task_runner()->GetMockTickClock());
   // Start and finish an event before starting the timer.
   MockEvent event;
@@ -242,7 +245,7 @@
 }
 
 TEST_F(ServiceWorkerEventQueueTest, EventTimer) {
-  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(), base::DoNothing(),
                                       task_runner()->GetMockTickClock());
   event_queue.Start();
 
@@ -265,7 +268,7 @@
 }
 
 TEST_F(ServiceWorkerEventQueueTest, CustomTimeouts) {
-  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(), base::DoNothing(),
                                       task_runner()->GetMockTickClock());
   event_queue.Start();
   MockEvent event1, event2;
@@ -293,7 +296,8 @@
 
 TEST_F(ServiceWorkerEventQueueTest, BecomeIdleAfterAbort) {
   bool is_idle = false;
-  ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                      CreateReceiverWithCalledFlag(&is_idle),
                                       task_runner()->GetMockTickClock());
   event_queue.Start();
 
@@ -312,7 +316,7 @@
 TEST_F(ServiceWorkerEventQueueTest, AbortAllOnDestruction) {
   MockEvent event1, event2;
   {
-    ServiceWorkerEventQueue event_queue(base::DoNothing(),
+    ServiceWorkerEventQueue event_queue(base::DoNothing(), base::DoNothing(),
                                         task_runner()->GetMockTickClock());
     event_queue.Start();
 
@@ -335,7 +339,7 @@
 }
 
 TEST_F(ServiceWorkerEventQueueTest, PushPendingTask) {
-  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(), base::DoNothing(),
                                       task_runner()->GetMockTickClock());
   event_queue.Start();
   task_runner()->FastForwardBy(ServiceWorkerEventQueue::kIdleDelay +
@@ -357,7 +361,7 @@
 // Test that pending tasks are run when StartEvent() is called while there the
 // idle event_queue.delay is zero. Regression test for https://crbug.com/878608.
 TEST_F(ServiceWorkerEventQueueTest, RunPendingTasksWithZeroIdleTimerDelay) {
-  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(), base::DoNothing(),
                                       task_runner()->GetMockTickClock());
   event_queue.Start();
   event_queue.SetIdleTimerDelayToZero();
@@ -384,7 +388,8 @@
 TEST_F(ServiceWorkerEventQueueTest, SetIdleTimerDelayToZero) {
   {
     bool is_idle = false;
-    ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+    ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                        CreateReceiverWithCalledFlag(&is_idle),
                                         task_runner()->GetMockTickClock());
     event_queue.Start();
     EXPECT_FALSE(is_idle);
@@ -396,7 +401,8 @@
 
   {
     bool is_idle = false;
-    ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+    ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                        CreateReceiverWithCalledFlag(&is_idle),
                                         task_runner()->GetMockTickClock());
     event_queue.Start();
     MockEvent event;
@@ -412,7 +418,8 @@
 
   {
     bool is_idle = false;
-    ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+    ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                        CreateReceiverWithCalledFlag(&is_idle),
                                         task_runner()->GetMockTickClock());
     event_queue.Start();
     MockEvent event1, event2;
@@ -434,7 +441,8 @@
 
   {
     bool is_idle = false;
-    ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+    ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                        CreateReceiverWithCalledFlag(&is_idle),
                                         task_runner()->GetMockTickClock());
     event_queue.Start();
     std::unique_ptr<StayAwakeToken> token_1 =
@@ -456,7 +464,7 @@
 }
 
 TEST_F(ServiceWorkerEventQueueTest, EnqueuOffline) {
-  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(), base::DoNothing(),
                                       task_runner()->GetMockTickClock());
   event_queue.Start();
 
@@ -550,7 +558,8 @@
       base::TimeDelta::FromSeconds(1);
 
   bool is_idle = false;
-  ServiceWorkerEventQueue event_queue(CreateReceiverWithCalledFlag(&is_idle),
+  ServiceWorkerEventQueue event_queue(base::DoNothing(),
+                                      CreateReceiverWithCalledFlag(&is_idle),
                                       task_runner()->GetMockTickClock());
   event_queue.Start();
 
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
index 6a593439..aa72458 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -218,10 +218,13 @@
     : WorkerGlobalScope(std::move(creation_params), thread, time_origin),
       installed_scripts_manager_(std::move(installed_scripts_manager)),
       cache_storage_remote_(std::move(cache_storage_remote)) {
-  // Create the event queue. At this point the timer is not started. It will be
+  // Create the event queue. At this point its timer is not started. It will be
   // started by DidEvaluateScript().
-  event_queue_ = std::make_unique<ServiceWorkerEventQueue>(WTF::BindRepeating(
-      &ServiceWorkerGlobalScope::OnIdleTimeout, WrapWeakPersistent(this)));
+  event_queue_ = std::make_unique<ServiceWorkerEventQueue>(
+      WTF::BindRepeating(&ServiceWorkerGlobalScope::OnBeforeStartEvent,
+                         WrapWeakPersistent(this)),
+      WTF::BindRepeating(&ServiceWorkerGlobalScope::OnIdleTimeout,
+                         WrapWeakPersistent(this)));
 }
 
 ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope() = default;
@@ -1288,6 +1291,11 @@
   return service_worker_host_.get();
 }
 
+void ServiceWorkerGlobalScope::OnBeforeStartEvent(bool is_offline_event) {
+  DCHECK(IsContextThread());
+  SetIsOfflineMode(is_offline_event);
+}
+
 void ServiceWorkerGlobalScope::OnIdleTimeout() {
   DCHECK(IsContextThread());
   // RequestedTermination() returns true if ServiceWorkerEventQueue agrees
@@ -1833,12 +1841,21 @@
 
   // We can use kNone as a |requestor_coep| for the main resource because it
   // must be the same origin.
-  event_queue_->EnqueueNormal(
-      WTF::Bind(&ServiceWorkerGlobalScope::StartFetchEvent,
-                WrapWeakPersistent(this), std::move(params),
-                network::mojom::blink::CrossOriginEmbedderPolicy::kNone,
-                std::move(response_callback), std::move(callback)),
-      CreateAbortCallback(&fetch_event_callbacks_), base::nullopt);
+  if (params->is_offline_capability_check) {
+    event_queue_->EnqueueOffline(
+        WTF::Bind(&ServiceWorkerGlobalScope::StartFetchEvent,
+                  WrapWeakPersistent(this), std::move(params),
+                  network::mojom::blink::CrossOriginEmbedderPolicy::kNone,
+                  std::move(response_callback), std::move(callback)),
+        CreateAbortCallback(&fetch_event_callbacks_), base::nullopt);
+  } else {
+    event_queue_->EnqueueNormal(
+        WTF::Bind(&ServiceWorkerGlobalScope::StartFetchEvent,
+                  WrapWeakPersistent(this), std::move(params),
+                  network::mojom::blink::CrossOriginEmbedderPolicy::kNone,
+                  std::move(response_callback), std::move(callback)),
+        CreateAbortCallback(&fetch_event_callbacks_), base::nullopt);
+  }
 }
 
 void ServiceWorkerGlobalScope::DispatchNotificationClickEvent(
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
index 4236b3d..78495a61 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -339,6 +339,9 @@
   // number of scripts and the total bytes of scripts.
   void CountScriptInternal(size_t script_size, size_t cached_metadata_size);
 
+  // Called by ServiceWorkerEventQueue just before they start an event.
+  void OnBeforeStartEvent(bool is_offline_event);
+
   // Called by ServiceWorkerEventQueue when a certain time has passed since
   // the last task finished.
   void OnIdleTimeout();
diff --git a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
index 1cc5397f..8d8b36f 100644
--- a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
@@ -115,6 +115,7 @@
       int request_id) override {
     return {};
   }
+  void SetIsOfflineMode(bool is_offline_mode) override {}
 
  private:
   FakeWebURLLoaderFactory fake_web_url_loader_factory_;
diff --git a/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc b/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
index ac42cd7..21edc5f 100644
--- a/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
+++ b/third_party/blink/renderer/platform/exported/web_coalesced_input_event.cc
@@ -12,46 +12,6 @@
 
 namespace blink {
 
-namespace {
-
-struct WebInputEventDelete {
-  template <class EventType>
-  bool Execute(WebInputEvent* event) const {
-    if (!event)
-      return false;
-    DCHECK_EQ(sizeof(EventType), event->size());
-    delete static_cast<EventType*>(event);
-    return true;
-  }
-};
-
-template <typename Operator, typename ArgIn>
-bool Apply(Operator op, WebInputEvent::Type type, const ArgIn& arg_in) {
-  if (WebInputEvent::IsMouseEventType(type))
-    return op.template Execute<WebMouseEvent>(arg_in);
-  if (type == WebInputEvent::kMouseWheel)
-    return op.template Execute<WebMouseWheelEvent>(arg_in);
-  if (WebInputEvent::IsKeyboardEventType(type))
-    return op.template Execute<WebKeyboardEvent>(arg_in);
-  if (WebInputEvent::IsTouchEventType(type))
-    return op.template Execute<WebTouchEvent>(arg_in);
-  if (WebInputEvent::IsGestureEventType(type))
-    return op.template Execute<WebGestureEvent>(arg_in);
-  if (WebInputEvent::IsPointerEventType(type))
-    return op.template Execute<WebPointerEvent>(arg_in);
-
-  NOTREACHED() << "Unknown webkit event type " << type;
-  return false;
-}
-}
-
-void WebCoalescedInputEvent::WebInputEventDeleter::operator()(
-    WebInputEvent* event) const {
-  if (!event)
-    return;
-  Apply(WebInputEventDelete(), event->GetType(), event);
-}
-
 WebInputEvent* WebCoalescedInputEvent::EventPointer() {
   return event_.get();
 }
diff --git a/third_party/blink/renderer/platform/fonts/web_font_decoder.cc b/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
index 9b5a8ed..e72f801 100644
--- a/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
+++ b/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
@@ -30,15 +30,12 @@
 
 #include "third_party/blink/renderer/platform/fonts/web_font_decoder.h"
 
-#include "base/timer/elapsed_timer.h"
 #include "build/build_config.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
 #include "third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 #include "third_party/ots/include/ots-memory-stream.h"
 #include "third_party/skia/include/core/SkStream.h"
@@ -145,38 +142,6 @@
   }
 }
 
-void RecordDecodeSpeedHistogram(const char* data,
-                                size_t length,
-                                double decode_time,
-                                size_t decoded_size) {
-  if (decode_time <= 0)
-    return;
-
-  double kb_per_second = decoded_size / (1000 * decode_time);
-  if (length >= 4) {
-    if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, woff_histogram,
-          ("WebFont.DecodeSpeed.WOFF", 1000, 300000, 50));
-      woff_histogram.Count(kb_per_second);
-      return;
-    }
-
-    if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == '2') {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, woff2_histogram,
-          ("WebFont.DecodeSpeed.WOFF2", 1000, 300000, 50));
-      woff2_histogram.Count(kb_per_second);
-      return;
-    }
-  }
-
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      CustomCountHistogram, sfnt_histogram,
-      ("WebFont.DecodeSpeed.SFNT", 1000, 300000, 50));
-  sfnt_histogram.Count(kb_per_second);
-}
-
 }  // namespace
 
 sk_sp<SkTypeface> WebFontDecoder::Decode(SharedBuffer* buffer) {
@@ -196,14 +161,13 @@
   // Most web fonts are compressed, so the result can be much larger than
   // the original.
   ots::ExpandingMemoryStream output(buffer->size(), kMaxWebFontSize);
-  base::ElapsedTimer timer;
   BlinkOTSContext ots_context;
   SharedBuffer::DeprecatedFlatData flattened_buffer(buffer);
-  const char* data = flattened_buffer.Data();
 
   TRACE_EVENT_BEGIN0("blink", "DecodeFont");
-  bool ok = ots_context.Process(&output, reinterpret_cast<const uint8_t*>(data),
-                                buffer->size());
+  bool ok = ots_context.Process(
+      &output, reinterpret_cast<const uint8_t*>(flattened_buffer.Data()),
+      buffer->size());
   TRACE_EVENT_END0("blink", "DecodeFont");
 
   if (!ok) {
@@ -212,9 +176,6 @@
   }
 
   const size_t decoded_length = SafeCast<size_t>(output.Tell());
-  RecordDecodeSpeedHistogram(data, buffer->size(), timer.Elapsed().InSecondsF(),
-                             decoded_length);
-
   sk_sp<SkData> sk_data = SkData::MakeWithCopy(output.get(), decoded_length);
 
   sk_sp<SkTypeface> new_typeface;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
index 6144589..1159bfb 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
@@ -61,7 +61,7 @@
     return webgl_preferences_;
   }
   viz::GLHelper* GetGLHelper() override { return nullptr; }
-  void SetLostContextCallback(base::Closure) override {}
+  void SetLostContextCallback(base::RepeatingClosure) override {}
   void SetErrorMessageCallback(
       base::RepeatingCallback<void(const char*, int32_t id)>) override {}
   cc::ImageDecodeCache* ImageDecodeCache(SkColorType color_type) override {
diff --git a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
index 48748d58..8d0dd35 100644
--- a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
+++ b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
@@ -75,7 +75,7 @@
   gpu::webgpu::WebGPUInterface* WebGPUInterface() override { return nullptr; }
 
   bool BindToCurrentThread() override { return false; }
-  void SetLostContextCallback(base::Closure) override {}
+  void SetLostContextCallback(base::RepeatingClosure) override {}
   void SetErrorMessageCallback(
       base::RepeatingCallback<void(const char*, int32_t id)>) override {}
   cc::ImageDecodeCache* ImageDecodeCache(SkColorType color_type) override {
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h b/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h
index 62e94ee..6b8da26c 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_platform.h
@@ -36,6 +36,7 @@
 
 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
@@ -150,7 +151,7 @@
   virtual webrtc::PeerConnectionInterface* NativePeerConnection() = 0;
 
   virtual void RunSynchronousOnceClosureOnSignalingThread(
-      base::OnceClosure closure,
+      CrossThreadOnceClosure closure,
       const char* trace_event_name) = 0;
   virtual void RunSynchronousRepeatingClosureOnSignalingThread(
       const base::RepeatingClosure& closure,
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index 63d7ca8f..c44eecf 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -58,10 +58,13 @@
  public:
   explicit FakeInputEvent(blink::WebInputEvent::Type event_type,
                           int modifiers = WebInputEvent::kNoModifiers)
-      : WebInputEvent(sizeof(FakeInputEvent),
-                      event_type,
+      : WebInputEvent(event_type,
                       modifiers,
                       WebInputEvent::GetStaticTimeStampForTests()) {}
+
+  std::unique_ptr<WebInputEvent> Clone() const override {
+    return std::make_unique<FakeInputEvent>(*this);
+  }
 };
 
 class FakeTouchEvent : public blink::WebTouchEvent {
diff --git a/third_party/blink/renderer/platform/wtf/cross_thread_functional.h b/third_party/blink/renderer/platform/wtf/cross_thread_functional.h
index 86f5856..973b8138 100644
--- a/third_party/blink/renderer/platform/wtf/cross_thread_functional.h
+++ b/third_party/blink/renderer/platform/wtf/cross_thread_functional.h
@@ -75,10 +75,10 @@
                                           std::decay_t<Ps>...>::ok,
       "A bound argument uses a bad pattern.");
   return internal::MakeCrossThreadFunction(
-      base::Bind(internal::CoerceFunctorForCrossThreadBind(
-                     std::forward<FunctionType>(function)),
-                 CrossThreadCopier<std::decay_t<Ps>>::Copy(
-                     std::forward<Ps>(parameters))...));
+      base::BindRepeating(internal::CoerceFunctorForCrossThreadBind(
+                              std::forward<FunctionType>(function)),
+                          CrossThreadCopier<std::decay_t<Ps>>::Copy(
+                              std::forward<Ps>(parameters))...));
 }
 
 template <typename FunctionType, typename... Ps>
diff --git a/third_party/blink/renderer/platform/wtf/shared_buffer.cc b/third_party/blink/renderer/platform/wtf/shared_buffer.cc
index 9d3eb78..cb8c3f8 100644
--- a/third_party/blink/renderer/platform/wtf/shared_buffer.cc
+++ b/third_party/blink/renderer/platform/wtf/shared_buffer.cc
@@ -28,6 +28,7 @@
 
 #include <memory>
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/text/unicode.h"
 #include "third_party/blink/renderer/platform/wtf/text/utf8.h"
@@ -171,7 +172,8 @@
 }
 
 void SharedBuffer::MergeSegmentsIntoBuffer() {
-  wtf_size_t bytes_left = size_ - buffer_.size();
+  wtf_size_t bytes_left =
+      base::checked_cast<wtf_size_t>(size_ - buffer_.size());
   for (const auto& segment : segments_) {
     wtf_size_t bytes_to_copy = std::min<wtf_size_t>(bytes_left, kSegmentSize);
     buffer_.Append(segment.get(), bytes_to_copy);
diff --git a/third_party/blink/web_tests/FlagExpectations/use-vulkan=native b/third_party/blink/web_tests/FlagExpectations/use-vulkan=native
index d430c27..0507c61 100644
--- a/third_party/blink/web_tests/FlagExpectations/use-vulkan=native
+++ b/third_party/blink/web_tests/FlagExpectations/use-vulkan=native
@@ -20,24 +20,6 @@
 crbug.com/993384 transforms/transformed-document-element.html [ Skip ]
 crbug.com/993384 transforms/3d/point-mapping/3d-point-mapping-deep.html [ Skip ]
 
-# OffscreenCanvas not rendering.
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-drawImage-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-drawImage.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-gradients-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-imageSmoothing-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-imageSmoothing.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-pattern-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-pattern.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-Bitmaprenderer-TransferToImageBitmapResetsToBlack.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-clearRect-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-fillRect-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-filter-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-paths-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-strokeRect-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-text-FontFace-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-text-rendering-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-transform-shadow-in-worker.html [ Skip ]
-
 # Expected Image Region Rendering Nothing.
 crbug.com/1002547 fast/canvas/imagebitmap/transferFromImageBitmap-alpha.html [ Skip ]
 crbug.com/1002547 fast/canvas/imagebitmap/transferFromImageBitmap-no-alpha.html [ Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader b/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader
index ad4e1e5..21af7956 100644
--- a/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader
+++ b/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader
@@ -3,24 +3,6 @@
 # tags: [ Release Debug ]
 # results: [ Timeout Crash Pass Failure Slow Skip ]
 
-# OffscreenCanvas not rendering.
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-drawImage-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-drawImage.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-gradients-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-imageSmoothing-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-imageSmoothing.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-pattern-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-2d-pattern.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-Bitmaprenderer-TransferToImageBitmapResetsToBlack.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-clearRect-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-fillRect-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-filter-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-paths-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-strokeRect-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-text-FontFace-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-text-rendering-in-worker.html [ Skip ]
-crbug.com/1002538 fast/canvas/OffscreenCanvas-transform-shadow-in-worker.html [ Skip ]
-
 # Expected Image Region Rendering Nothing.
 crbug.com/1002547 fast/canvas/imagebitmap/transferFromImageBitmap-alpha.html [ Skip ]
 crbug.com/1002547 fast/canvas/imagebitmap/transferFromImageBitmap-no-alpha.html [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 5fff69c..18a0cc2 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -7155,3 +7155,24 @@
 # Sheriff 2020-01-02
 crbug.com/1038656 [ Mac ] http/tests/devtools/coverage/coverage-view-unused.js [ Pass Failure ]
 crbug.com/1038656 [ Win ] http/tests/devtools/coverage/coverage-view-unused.js [ Pass Failure ]
+
+# Temporarily disabled to land breakpoints changes in devtools
+crbug.com/963183 http/tests/devtools/persistence/persistence-move-breakpoints.js [ Pass Failure ]
+crbug.com/963183 [ Mac ] http/tests/devtools/persistence/persistence-move-breakpoints-on-reload.js [ Pass Failure ]
+crbug.com/963183 [ Win ] http/tests/devtools/persistence/persistence-move-breakpoints-on-reload.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-breakpoints/breakpoints-sidebar-pane.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-breakpoints/debugger-reload-breakpoints-with-source-maps.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-breakpoints/set-breakpoint.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-breakpoints/set-conditional-breakpoint.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-breakpoints/set-logpoint.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-ui/click-gutter-breakpoint.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-2.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-3.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/sources/debugger/js-with-inline-stylesheets.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-1.js [ Pass Failure ]
+crbug.com/963183 http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-inline-with-sourceURL.js [ Pass Failure ]
+
+# Sheriff 2020-01-06
+crbug.com/1039578 external/wpt/webdriver/tests/take_screenshot/iframe.py>>test_frame_content [ Pass Failure ]
+crbug.com/1039578 external/wpt/webdriver/tests/take_element_screenshot/iframe.py>>test_frame_element [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index afb24b2..916b485 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -89495,6 +89495,18 @@
      {}
     ]
    ],
+   "css/css-ui/resize-change-margin.html": [
+    [
+     "css/css-ui/resize-change-margin.html",
+     [
+      [
+       "/css/css-ui/resize-change-margin-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-ui/text-overflow-001.html": [
     [
      "css/css-ui/text-overflow-001.html",
@@ -149949,6 +149961,9 @@
    "css/css-ui/reference/text-overflow-ellipsis-indent-001-ref.html": [
     []
    ],
+   "css/css-ui/resize-change-margin-ref.html": [
+    []
+   ],
    "css/css-ui/support/1x1-red.png": [
     []
    ],
@@ -152931,6 +152946,9 @@
    "css/cssom/CSSKeyframesRule-expected.txt": [
     []
    ],
+   "css/cssom/CSSStyleSheet-constructable-expected.txt": [
+    []
+   ],
    "css/cssom/HTMLLinkElement-disabled-001.tentative-expected.txt": [
     []
    ],
@@ -169698,6 +169716,9 @@
    "mst-content-hint/META.yml": [
     []
    ],
+   "mst-content-hint/idlharness.window-expected.txt": [
+    []
+   ],
    "native-file-system/README.md": [
     []
    ],
@@ -256896,6 +256917,18 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-button-element/button-submit-remove-children-jssubmit.html": [
+    [
+     "html/semantics/forms/the-button-element/button-submit-remove-children-jssubmit.html",
+     {}
+    ]
+   ],
+   "html/semantics/forms/the-button-element/button-submit-remove-children.html": [
+    [
+     "html/semantics/forms/the-button-element/button-submit-remove-children.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-button-element/button-type.html": [
     [
      "html/semantics/forms/the-button-element/button-type.html",
@@ -423403,6 +423436,14 @@
    "709551f15903ac671ba78284885c56c277984d7b",
    "manual"
   ],
+  "css/css-ui/resize-change-margin-ref.html": [
+   "b326c5f8d2c52f08bc2a09e651ae87f6c005979d",
+   "support"
+  ],
+  "css/css-ui/resize-change-margin.html": [
+   "a957ac931e8647958baf0d1891d3e69dd4435c0d",
+   "reftest"
+  ],
   "css/css-ui/select-cursor-001-manual.html": [
    "30aa9b20f8d23c6f0985db4b09b921c850973d0b",
    "manual"
@@ -433219,8 +433260,12 @@
    "3acdfb12852356ac28e91af25c82052d45864b0e",
    "testharness"
   ],
+  "css/cssom/CSSStyleSheet-constructable-expected.txt": [
+   "c88a70ef92c4e4a34ea3cd6f22c039166b8c4df9",
+   "support"
+  ],
   "css/cssom/CSSStyleSheet-constructable.html": [
-   "c30e764152deddcfcb3311636aa8cadcb5295dee",
+   "d7be1677f8c3afffbb7fcea3536969fd083d0fe9",
    "testharness"
   ],
   "css/cssom/CSSStyleSheet.html": [
@@ -443804,7 +443849,7 @@
    "testharness"
   ],
   "dom/idlharness.window_exclude=Node-expected.txt": [
-   "ae194bdc7c2351171740a736db1c425291a99492",
+   "0dcf7948b20e0d6d6905016af892d26de6503d25",
    "support"
   ],
   "dom/interface-objects.html": [
@@ -444260,11 +444305,11 @@
    "support"
   ],
   "dom/nodes/Document-createEvent.https-expected.txt": [
-   "154cf010abb5f60464e54db6b98535a89c36208d",
+   "34759173797cbd50c3959a9d878033381049c755",
    "support"
   ],
   "dom/nodes/Document-createEvent.https.html": [
-   "8108f20f6593e721e132ca16bbe509fd1e06dfd2",
+   "bdc1895879bfa613e72229b44d535f76f785c5a2",
    "testharness"
   ],
   "dom/nodes/Document-createEvent.js": [
@@ -468199,6 +468244,14 @@
    "06218f4fc9e99efe2d87a9eb85582d3dc84434a1",
    "testharness"
   ],
+  "html/semantics/forms/the-button-element/button-submit-remove-children-jssubmit.html": [
+   "26ce16dd2d0df51b4dad3e41e8b22b9ffa05ca48",
+   "testharness"
+  ],
+  "html/semantics/forms/the-button-element/button-submit-remove-children.html": [
+   "1dc259564cadadb99105a329b62dc12eea6bd878",
+   "testharness"
+  ],
   "html/semantics/forms/the-button-element/button-type.html": [
    "6cfd6687c707479600534de03156afa698daa314",
    "testharness"
@@ -476196,7 +476249,7 @@
    "support"
   ],
   "interfaces/dom.idl": [
-   "d1557a676ef0f7c458c8654c59ec713a42833d0a",
+   "f7a10d890ab892e990bf9a81b87884e54089dcaa",
    "support"
   ],
   "interfaces/element-timing.idl": [
@@ -476340,7 +476393,7 @@
    "support"
   ],
   "interfaces/mst-content-hint.idl": [
-   "15e17cf5364c83fc70bf373cd7f500c13b153b5f",
+   "f7d3f20e72364a1bf7df019e3115c34c10d811ba",
    "support"
   ],
   "interfaces/navigation-timing.idl": [
@@ -476428,7 +476481,7 @@
    "support"
   ],
   "interfaces/requestidlecallback.idl": [
-   "b485dc07805fe864cf79abd1ec11a7e3ffb68d41",
+   "c763b50bde782bb484564b49e25068fff88f782b",
    "support"
   ],
   "interfaces/resize-observer.idl": [
@@ -476528,7 +476581,7 @@
    "support"
   ],
   "interfaces/web-nfc.idl": [
-   "de23fac0c118c2a773a5e9627c6b1af99c861838",
+   "12ea9d58bc055ee57efb65ae1495ebf4301427a5",
    "support"
   ],
   "interfaces/web-share.idl": [
@@ -482855,6 +482908,10 @@
    "98c88e66ea1ec137cdcf794c63a14d9af4b964b1",
    "testharness"
   ],
+  "mst-content-hint/idlharness.window-expected.txt": [
+   "6f8ebbac7e4ff849dc49a7b5b8c24ccc6f4dfb3c",
+   "support"
+  ],
   "mst-content-hint/idlharness.window.js": [
    "0d9137dc6fb91b1499d922e01d6ad96049f5757b",
    "testharness"
@@ -505904,27 +505961,27 @@
    "support"
   ],
   "remote-playback/cancel-watch-availability.html": [
-   "e4b633066a4c0a257adc30996c8424a37b6a1b20",
+   "d83c8cecb006d738be1280f44d7d8d302f85003f",
    "testharness"
   ],
   "remote-playback/disable-remote-playback-cancel-watch-availability-throws.html": [
-   "fdcc734346ed5825f572536877175f2c6dbddda5",
+   "bdd35d8101bdf0e4ae96e63de9f51b1ba6a7b5d4",
    "testharness"
   ],
   "remote-playback/disable-remote-playback-prompt-throws.html": [
-   "7ddc2ad13f3691e1b40a89bf0494b06c6da8cb5d",
+   "076b1630606f658be2ee574fba2fb15d9f6741c0",
    "testharness"
   ],
   "remote-playback/disable-remote-playback-watch-availability-throws.html": [
-   "3c21f017b48293f778eca1061a7215187fda9eac",
+   "1cec5278d522afd986a772eb3fffe11650b6b97d",
    "testharness"
   ],
   "remote-playback/idlharness.window.js": [
-   "73bc998f7433be4ea77fc18a62c7445d9688d907",
+   "ba40f199633165111ab2bfd37624eb94871052d6",
    "testharness"
   ],
   "remote-playback/watch-availability-initial-callback.html": [
-   "851558b06f211ac2cda5d38b1d447a2e0475586d",
+   "352321b06ae66c5a3e31c1d3d7cf40a5e3b4c460",
    "testharness"
   ],
   "reporting/META.yml": [
@@ -520424,7 +520481,7 @@
    "support"
   ],
   "tools/webdriver/webdriver/client.py": [
-   "0c5bbff5629868fdc48a1a41cf882fabe5617c1b",
+   "cf4c5fd35fd98bb54ba248d1c1c31590310727ed",
    "support"
   ],
   "tools/webdriver/webdriver/error.py": [
@@ -528944,15 +529001,15 @@
    "wdspec"
   ],
   "webdriver/tests/take_element_screenshot/__init__.py": [
-   "9de8792460797f4a31ee50d112c7132a2c2714ad",
+   "9a82cc48eab7993dcd6588d89b5aae9ed4ebfc82",
    "support"
   ],
   "webdriver/tests/take_element_screenshot/iframe.py": [
-   "242122f0b5e7359c364a8aa1da345fc3da15acf1",
+   "83f55deff753a4525839d3c0675acfb459f64395",
    "wdspec"
   ],
   "webdriver/tests/take_element_screenshot/screenshot.py": [
-   "fd460b656ae307a289174f9180ecc9ed23f0da07",
+   "50d33a266db75f0fc918ac5fa6d1edc6e548385f",
    "wdspec"
   ],
   "webdriver/tests/take_element_screenshot/user_prompts.py": [
@@ -528960,11 +529017,11 @@
    "wdspec"
   ],
   "webdriver/tests/take_screenshot/__init__.py": [
-   "c07f8d167030d03abbb263ef08d8846bb7a71eba",
+   "f3001d946df56e58c4e3fa1319db12bf29f3e341",
    "support"
   ],
   "webdriver/tests/take_screenshot/iframe.py": [
-   "4cf8ad06b56d8f44af06550af4c4a1b7715b908b",
+   "6186cf3c4be9b220db59c78a3f94ddccc31659bd",
    "wdspec"
   ],
   "webdriver/tests/take_screenshot/screenshot.py": [
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable-expected.txt
new file mode 100644
index 0000000..c88a70e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable-expected.txt
@@ -0,0 +1,27 @@
+This is a testharness.js-based test.
+PASS document.adoptedStyleSheets should initially have length 0.
+FAIL new CSSStyleSheet produces empty CSSStyleSheet assert_equals: expected (object) null but got (string) ""
+PASS CSSStyleSheet.replace produces Promise<CSSStyleSheet>
+PASS Constructed style sheets can be applied on document
+PASS Constructed style sheets can be applied on shadow root
+PASS Re-attaching shadow host with adopted stylesheets work
+PASS Attaching a shadow root that already has adopted stylesheets work
+PASS Re-attaching shadow host and updating attributes work
+PASS Changes to constructed stylesheets through CSSOM is reflected
+PASS Constructed stylesheet can be used and modified in multiple TreeScopes
+PASS Stylesheets constructed on the main Document cannot be used in iframes
+PASS Stylesheet constructed on iframe cannot be used in the main Document
+PASS Adding non-constructed stylesheet to AdoptedStyleSheets is not allowed when the owner document of the stylesheet is in the same document tree as the AdoptedStyleSheets
+PASS Adding non-constructed stylesheet to AdoptedStyleSheets is not allowed when the owner document of the stylesheet and the AdoptedStyleSheets are in different document trees
+PASS CSSStyleSheet.replaceSync replaces stylesheet text synchronously
+PASS CSSStyleSheet.replaceSync throws exception when there is import rule inside
+PASS Inserting an @import rule through insertRule on a constructed stylesheet throws an exception
+PASS CSSStyleSheet.replace allows import rule inside
+PASS CSSStyleSheet.replace returns rejected promise on failed imports
+PASS Cloning a shadow host will not clone shadow root, and also adoptedStyleSheets
+PASS Importing a shadow host will not copy shadow root, and also adoptedStyleSheets
+PASS Adopting a shadow host will empty adoptedStyleSheets if adopting to a different document
+PASS Forcing a style update after adding an adopted stylesheet on a disconnected shadow root should not crash.
+PASS Modifying an adopted stylesheet on a disconnected shadow root should not crash.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
index c30e7641..d7be167 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
@@ -66,7 +66,7 @@
   assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]);
 
   const sheet2 = new CSSStyleSheet({});
-  assert_equals(sheet2.title, "")
+  assert_equals(sheet2.title, null);
   assert_equals(sheet2.ownerNode, null);
   assert_equals(sheet2.ownerRule, null);
   assert_equals(sheet2.media.length, 0);
@@ -80,8 +80,8 @@
   sheet2.deleteRule(0);
   assert_equals(sheet2.cssRules.length, 0);
 
-const sheet3 = new CSSStyleSheet();
-  assert_equals(sheet3.title, "")
+  const sheet3 = new CSSStyleSheet();
+  assert_equals(sheet3.title, null);
   assert_equals(sheet3.ownerNode, null);
   assert_equals(sheet3.ownerRule, null);
   assert_equals(sheet3.media.length, 0);
diff --git a/third_party/blink/web_tests/external/wpt/dom/idlharness.window_exclude=Node-expected.txt b/third_party/blink/web_tests/external/wpt/dom/idlharness.window_exclude=Node-expected.txt
index ae194bd..0dcf794 100644
--- a/third_party/blink/web_tests/external/wpt/dom/idlharness.window_exclude=Node-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/dom/idlharness.window_exclude=Node-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1241 tests; 1215 PASS, 26 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1238 tests; 1215 PASS, 23 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS Partial interface Window: original interface defined
@@ -265,7 +265,6 @@
 PASS Document interface: attribute implementation
 PASS Document interface: attribute URL
 PASS Document interface: attribute documentURI
-FAIL Document interface: attribute origin assert_true: The prototype object must have a property "origin" expected true got false
 PASS Document interface: attribute compatMode
 PASS Document interface: attribute characterSet
 PASS Document interface: attribute charset
@@ -308,7 +307,6 @@
 PASS Document interface: new Document() must inherit property "implementation" with the proper type
 PASS Document interface: new Document() must inherit property "URL" with the proper type
 PASS Document interface: new Document() must inherit property "documentURI" with the proper type
-FAIL Document interface: new Document() must inherit property "origin" with the proper type assert_inherits: property "origin" not found in prototype chain
 PASS Document interface: new Document() must inherit property "compatMode" with the proper type
 PASS Document interface: new Document() must inherit property "characterSet" with the proper type
 PASS Document interface: new Document() must inherit property "charset" with the proper type
@@ -387,7 +385,6 @@
 PASS Document interface: xmlDoc must inherit property "implementation" with the proper type
 PASS Document interface: xmlDoc must inherit property "URL" with the proper type
 PASS Document interface: xmlDoc must inherit property "documentURI" with the proper type
-FAIL Document interface: xmlDoc must inherit property "origin" with the proper type assert_inherits: property "origin" not found in prototype chain
 PASS Document interface: xmlDoc must inherit property "compatMode" with the proper type
 PASS Document interface: xmlDoc must inherit property "characterSet" with the proper type
 PASS Document interface: xmlDoc must inherit property "charset" with the proper type
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https-expected.txt b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https-expected.txt
index 154cf010..3475917 100644
--- a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https-expected.txt
@@ -143,8 +143,8 @@
 PASS createEvent('UIEVENTS') should be initialized correctly.
 PASS Should throw NOT_SUPPORTED_ERR for unrecognized arguments
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AnimationEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AnimationPlaybackEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationPlaybackEvents"
@@ -163,16 +163,16 @@
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ClipboardEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ClipboardEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "CloseEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CloseEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "CommandEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CommandEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "DataContainerEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DataContainerEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ErrorEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ErrorEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ExtendableEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ExtendableEvents"
@@ -187,8 +187,8 @@
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "GeofencingEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "GeofencingEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "IDBVersionChangeEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "IDBVersionChangeEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "InstallEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "InstallEvents"
@@ -213,8 +213,8 @@
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MouseScrollEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MouseScrollEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MutationEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 FAIL Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MutationEvents" assert_throws: function "function () {
         var evt = document.createEvent(eventInterface + "s");
       }" did not throw
@@ -229,14 +229,14 @@
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PageTransition"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PageTransitions"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PageTransitionEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PageTransitionEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PointerEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PointerEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PopStateEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PopStateEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PopUpEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PopUpEvents"
@@ -284,24 +284,24 @@
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TimeEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TimeEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TrackEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TrackEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TransitionEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TransitionEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebGLContextEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebGLContextEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitAnimationEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitAnimationEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitTransitionEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitTransitionEvents"
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WheelEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+      var evt = document.createEvent(eventInterface);
+    }" did not throw
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WheelEvents"
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "XULCommandEvent"
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "XULCommandEvents"
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https.html b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https.html
index 8108f20..bdc1895 100644
--- a/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https.html
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Document-createEvent.https.html
@@ -143,17 +143,14 @@
   "XULCommandEvent",
 ];
 someNonCreateableEvents.forEach(function (eventInterface) {
-  // SVGEvents is allowed, but not SVGEvent.  Make sure we only test if it's
-  // not whitelisted.
-  if (!(eventInterface in aliases)) {
-    test(function () {
-      assert_throws("NOT_SUPPORTED_ERR", function () {
-        var evt = document.createEvent(eventInterface);
-      });
-    }, 'Should throw NOT_SUPPORTED_ERR for non-legacy event interface "' + eventInterface + '"');
-  }
+  test(function () {
+    assert_throws("NOT_SUPPORTED_ERR", function () {
+      var evt = document.createEvent(eventInterface);
+    });
+  }, 'Should throw NOT_SUPPORTED_ERR for non-legacy event interface "' + eventInterface + '"');
 
-  if (!(eventInterface + "s" in aliases)) {
+  // SVGEvents is allowed, other plurals are not
+  if (eventInterface !== "SVGEvent") {
     test(function () {
       assert_throws("NOT_SUPPORTED_ERR", function () {
         var evt = document.createEvent(eventInterface + "s");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-submit-remove-children-jssubmit.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-submit-remove-children-jssubmit.html
new file mode 100644
index 0000000..26ce16d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-submit-remove-children-jssubmit.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-2">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<iframe name=frame1 id=frame1></iframe>
+<form id=form1 target=frame1 action="does_not_exist.html">
+  <button id=submitbutton type=submit>
+    <span id=outerchild>
+      <span id=innerchild>submit</span>
+    </span>
+  </button>
+</form>
+
+<script>
+async_test(t => {
+  window.addEventListener('load', () => {
+    const frame1 = document.getElementById('frame1');
+    frame1.addEventListener('load', t.step_func_done(() => {}));
+
+    const submitButton = document.getElementById('submitbutton');
+    submitButton.addEventListener('click', event => {
+      document.getElementById('outerchild').remove();
+      document.getElementById('form1').submit();
+    });
+
+    document.getElementById('innerchild').click();
+  });
+}, 'This test will pass if a form navigation successfully occurs when clicking a child element of a <button type=submit> element with a onclick event handler which removes the button\'s child and then calls form.submit().');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-submit-remove-children.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-submit-remove-children.html
new file mode 100644
index 0000000..1dc2595
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-submit-remove-children.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-2">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<iframe name=frame1 id=frame1></iframe>
+<form id=form1 target=frame1 action="does_not_exist.html">
+  <button id=submitbutton type=submit>
+    <span id=outerchild>
+      <span id=innerchild>submit</span>
+    </span>
+  </button>
+</form>
+
+<script>
+async_test(t => {
+  window.addEventListener('load', () => {
+    const frame1 = document.getElementById('frame1');
+    frame1.addEventListener('load', t.step_func_done(() => {}));
+
+    const submitButton = document.getElementById('submitbutton');
+    submitButton.addEventListener('click', event => {
+      document.getElementById('outerchild').remove();
+    });
+
+    document.getElementById('innerchild').click();
+  });
+}, 'This test will pass if a form navigation successfully occurs when clicking a child element of a <button type=submit> element with a onclick event handler which removes the button\'s child.');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt
index a92b060..cd370fa 100644
--- a/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt
@@ -2,12 +2,12 @@
 PASS Unmapped built-in module specifiers / should resolve "std:blank" to "std:blank"
 FAIL Unmapped built-in module specifiers / should error resolving "std:none" assert_throws: function "() => resolveUnderTest(NONE)" did not throw
 PASS Remapping built-in module specifiers / should remap built-in modules
-FAIL Remapping built-in module specifiers / should remap built-in modules with slashes assert_equals: expected "https://example.com/app/blank-slash/bar" but got "std:blank/bar"
+PASS Remapping built-in module specifiers / should remap built-in modules with slashes
 FAIL Remapping built-in module specifiers / should remap built-in modules with fallbacks Failed to resolve module specifier std:blank: Import Map: "std:blank" matches with "std:blank" but fails to be mapped (no viable URLs)
 FAIL Remapping built-in module specifiers / should remap built-in modules with slashes and fallbacks Failed to resolve module specifier std:blank/: Import Map: "std:blank/" matches with "std:blank/" but fails to be mapped (no viable URLs)
 PASS Remapping to built-in modules / should remap to "std:blank"
 PASS Remapping to built-in modules / should fail when remapping to "std:blank/"
-FAIL Remapping to built-in modules / should remap to "std:blank/for-testing" assert_equals: expected "std:blank/for-testing" but got "https://example.com/blank/for-testing"
+FAIL Remapping to built-in modules / should remap to "std:blank/for-testing" Failed to resolve module specifier /blank/for-testing: Import Map: "https://example.com/blank/for-testing" matches with "https://example.com/blank/" but fails to be mapped (no viable URLs)
 PASS Remapping to built-in modules / should remap to "std:blank" for URL-like specifiers
 PASS Remapping to built-in modules / should fail when remapping to "std:none"
 FAIL Fallbacks with built-in module addresses / should resolve to "std:blank" Failed to resolve module specifier blank: Import Map: "blank" matches with "blank" but fails to be mapped (no viable URLs)
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt
index 39ebb09..ec4b7209 100644
--- a/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt
@@ -17,7 +17,7 @@
 PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap to other URLs
 PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should fail for URLs that remap to empty arrays
 PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap URLs that are just composed from / and .
-FAIL Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap URLs that are prefix-matched by keys with trailing slashes assert_equals: expected "https://example.com/lib/url-trailing-slash/foo.mjs" but got "https://example.com/test/foo.mjs"
+PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap URLs that are prefix-matched by keys with trailing slashes
 PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should use the last entry's address when URL-like specifiers parse to the same absolute URL
 PASS Mapped using the "imports" key only (no scopes) / Overlapping entries with trailing slashes / should favor the most-specific key (no empty arrays)
 PASS Mapped using the "imports" key only (no scopes) / Overlapping entries with trailing slashes / should favor the most-specific key when empty arrays are involved for less-specific keys
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/common/resolving.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/import-maps/common/resolving.tentative-expected.txt
deleted file mode 100644
index cf7a3a1..0000000
--- a/third_party/blink/web_tests/external/wpt/import-maps/common/resolving.tentative-expected.txt
+++ /dev/null
@@ -1,141 +0,0 @@
-This is a testharness.js-based test.
-Found 137 tests; 135 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS Test helper: fetching and sanity checking test JSON: resources/scopes.json
-PASS Test helper: fetching and sanity checking test JSON: resources/empty-import-map.json
-PASS Test helper: fetching and sanity checking test JSON: resources/packages-via-trailing-slashes.json
-PASS Test helper: fetching and sanity checking test JSON: resources/tricky-specifiers.json
-PASS Test helper: fetching and sanity checking test JSON: resources/url-specifiers.json
-PASS Test helper: fetching and sanity checking test JSON: resources/data-base-url.json
-PASS Test helper: fetching and sanity checking test JSON: resources/scopes-exact-vs-prefix.json
-PASS Test helper: fetching and sanity checking test JSON: resources/overlapping-entries.json
-PASS Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: a
-PASS Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: b
-PASS Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: c
-PASS Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: d
-PASS Fallback to toplevel and between scopes: should use a direct scope override: a
-PASS Fallback to toplevel and between scopes: should use a direct scope override: b
-PASS Fallback to toplevel and between scopes: should use a direct scope override: c
-PASS Fallback to toplevel and between scopes: should use a direct scope override: d
-PASS Fallback to toplevel and between scopes: should use an indirect scope override: a
-PASS Fallback to toplevel and between scopes: should use an indirect scope override: b
-PASS Fallback to toplevel and between scopes: should use an indirect scope override: c
-PASS Fallback to toplevel and between scopes: should use an indirect scope override: d
-PASS Relative URL scope keys: An empty string scope is a scope with import map base URL: a
-PASS Relative URL scope keys: An empty string scope is a scope with import map base URL: b
-PASS Relative URL scope keys: An empty string scope is a scope with import map base URL: c
-PASS Relative URL scope keys: './' scope is a scope with import map base URL's directory: a
-PASS Relative URL scope keys: './' scope is a scope with import map base URL's directory: b
-PASS Relative URL scope keys: './' scope is a scope with import map base URL's directory: c
-PASS Relative URL scope keys: '../' scope is a scope with import map base URL's parent directory: a
-PASS Relative URL scope keys: '../' scope is a scope with import map base URL's parent directory: b
-PASS Relative URL scope keys: '../' scope is a scope with import map base URL's parent directory: c
-PASS Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dot
-PASS Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dot/foo
-PASS Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dotdot
-PASS Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dotdot/foo
-PASS Package-like scenarios: Base URLs inside the scope fallback to less specific scope: moment
-PASS Package-like scenarios: Base URLs inside the scope fallback to less specific scope: vue
-PASS Package-like scenarios: Base URLs inside the scope fallback to toplevel: moment/foo
-PASS Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dot
-PASS Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dotdot
-PASS Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dot/foo
-PASS Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dotdot/foo
-PASS Package-like scenarios: Fallback to toplevel or not, depending on trailing slash match: moment
-PASS Package-like scenarios: Fallback to toplevel or not, depending on trailing slash match: moment/foo
-PASS Package-like scenarios: should still fail for package-like specifiers that are not declared: underscore/
-PASS Package-like scenarios: should still fail for package-like specifiers that are not declared: underscore/foo
-PASS valid relative specifiers: ./foo
-PASS valid relative specifiers: ./foo/bar
-PASS valid relative specifiers: ./foo/../bar
-PASS valid relative specifiers: ./foo/../../bar
-PASS valid relative specifiers: ../foo
-PASS valid relative specifiers: ../foo/bar
-PASS valid relative specifiers: ../../../foo/bar
-PASS valid relative specifiers: /foo
-PASS valid relative specifiers: /foo/bar
-PASS valid relative specifiers: /../../foo/bar
-PASS valid relative specifiers: /../foo/../bar
-PASS fetch scheme absolute URLs: about:fetch-scheme
-PASS fetch scheme absolute URLs: https://fetch-scheme.net
-PASS fetch scheme absolute URLs: https:fetch-scheme.org
-PASS fetch scheme absolute URLs: https://fetch%2Dscheme.com/
-PASS fetch scheme absolute URLs: https://///fetch-scheme.com///
-PASS non-fetch scheme absolute URLs: mailto:non-fetch-scheme
-PASS non-fetch scheme absolute URLs: import:non-fetch-scheme
-PASS non-fetch scheme absolute URLs: javascript:non-fetch-scheme
-PASS non-fetch scheme absolute URLs: wss:non-fetch-scheme
-PASS valid relative URLs that are invalid as specifiers should fail: invalid-specifier
-PASS valid relative URLs that are invalid as specifiers should fail: \invalid-specifier
-PASS valid relative URLs that are invalid as specifiers should fail: :invalid-specifier
-PASS valid relative URLs that are invalid as specifiers should fail: @invalid-specifier
-PASS valid relative URLs that are invalid as specifiers should fail: %2E/invalid-specifier
-PASS valid relative URLs that are invalid as specifiers should fail: %2E%2E/invalid-specifier
-PASS valid relative URLs that are invalid as specifiers should fail: .%2Finvalid-specifier
-PASS invalid absolute URLs should fail: https://invalid-url.com:demo
-PASS invalid absolute URLs should fail: http://[invalid-url.com]/
-PASS Package-like scenarios: package main modules: moment
-PASS Package-like scenarios: package main modules: lodash-dot
-PASS Package-like scenarios: package main modules: lodash-dotdot
-PASS Package-like scenarios: package submodules: moment/foo
-PASS Package-like scenarios: package submodules: lodash-dot/foo
-PASS Package-like scenarios: package submodules: lodash-dotdot/foo
-PASS Package-like scenarios: package names that end in a slash should just pass through: moment/
-PASS Package-like scenarios: package modules that are not declared should fail: underscore/
-PASS Package-like scenarios: package modules that are not declared should fail: underscore/foo
-PASS Tricky specifiers: explicitly-mapped specifiers that happen to have a slash: package/withslash
-PASS Tricky specifiers: specifier with punctuation: .
-PASS Tricky specifiers: specifier with punctuation: ..
-PASS Tricky specifiers: specifier with punctuation: ..\
-PASS Tricky specifiers: specifier with punctuation: %2E
-PASS Tricky specifiers: specifier with punctuation: %2F
-PASS Tricky specifiers: submodule of something not declared with a trailing slash should fail: not-a-package/foo
-PASS Tricky specifiers: module for which only a trailing-slash version is present should fail: only-slash
-PASS URL-like specifiers: Ordinal URL-like specifiers: https://example.com/lib/foo.mjs
-PASS URL-like specifiers: Ordinal URL-like specifiers: https://///example.com/lib/foo.mjs
-PASS URL-like specifiers: Ordinal URL-like specifiers: /lib/foo.mjs
-PASS URL-like specifiers: Ordinal URL-like specifiers: https://example.com/app/dotrelative/foo.mjs
-PASS URL-like specifiers: Ordinal URL-like specifiers: ../app/dotrelative/foo.mjs
-PASS URL-like specifiers: Ordinal URL-like specifiers: https://example.com/dotdotrelative/foo.mjs
-PASS URL-like specifiers: Ordinal URL-like specifiers: ../dotdotrelative/foo.mjs
-PASS URL-like specifiers: Import map entries just composed from / and .: https://example.com/
-PASS URL-like specifiers: Import map entries just composed from / and .: /
-PASS URL-like specifiers: Import map entries just composed from / and .: ../
-PASS URL-like specifiers: Import map entries just composed from / and .: https://example.com/app/
-PASS URL-like specifiers: Import map entries just composed from / and .: /app/
-PASS URL-like specifiers: Import map entries just composed from / and .: ../app/
-FAIL URL-like specifiers: prefix-matched by keys with trailing slashes: /test/foo.mjs assert_equals: expected "https://example.com/lib/url-trailing-slash/foo.mjs" but got "https://example.com/test/foo.mjs"
-FAIL URL-like specifiers: prefix-matched by keys with trailing slashes: https://example.com/app/test/foo.mjs assert_equals: expected "https://example.com/lib/url-trailing-slash-dot/foo.mjs" but got "https://example.com/app/test/foo.mjs"
-PASS URL-like specifiers: should use the last entry's address when URL-like specifiers parse to the same absolute URL: /test
-PASS data: base URL (?): should favor the most-specific key: foo/bar
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Non-trailing-slash base URL (exact match): moment
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Non-trailing-slash base URL (exact match): moment/foo
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Trailing-slash base URL (fail): moment
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Trailing-slash base URL (fail): moment/foo
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Subpath base URL (fail): moment
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Subpath base URL (fail): moment/foo
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Non-subpath base URL (fail): moment
-PASS Exact vs. prefix based matching: Scope without trailing slash only: Non-subpath base URL (fail): moment/foo
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Non-trailing-slash base URL (fail): moment
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Non-trailing-slash base URL (fail): moment/foo
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Trailing-slash base URL (exact match): moment
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Trailing-slash base URL (exact match): moment/foo
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Subpath base URL (prefix match): moment
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Subpath base URL (prefix match): moment/foo
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Non-subpath base URL (fail): moment
-PASS Exact vs. prefix based matching: Scope with trailing slash only: Non-subpath base URL (fail): moment/foo
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Non-trailing-slash base URL (exact match): moment
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Non-trailing-slash base URL (exact match): moment/foo
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Trailing-slash base URL (exact match): moment
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Trailing-slash base URL (exact match): moment/foo
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Subpath base URL (prefix match): moment
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Subpath base URL (prefix match): moment/foo
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Non-subpath base URL (fail): moment
-PASS Exact vs. prefix based matching: Scopes with and without trailing slash: Non-subpath base URL (fail): moment/foo
-PASS should favor the most-specific key: Overlapping entries with trailing slashes: a
-PASS should favor the most-specific key: Overlapping entries with trailing slashes: a/
-PASS should favor the most-specific key: Overlapping entries with trailing slashes: a/x
-PASS should favor the most-specific key: Overlapping entries with trailing slashes: a/b
-PASS should favor the most-specific key: Overlapping entries with trailing slashes: a/b/
-PASS should favor the most-specific key: Overlapping entries with trailing slashes: a/b/c
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/dom.idl b/third_party/blink/web_tests/external/wpt/interfaces/dom.idl
index d1557a6..f7a10d8 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/dom.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/dom.idl
@@ -263,7 +263,6 @@
   [SameObject] readonly attribute DOMImplementation implementation;
   readonly attribute USVString URL;
   readonly attribute USVString documentURI;
-  readonly attribute USVString origin;
   readonly attribute DOMString compatMode;
   readonly attribute DOMString characterSet;
   readonly attribute DOMString charset; // historical alias of .characterSet
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/mst-content-hint.idl b/third_party/blink/web_tests/external/wpt/interfaces/mst-content-hint.idl
index 15e17cf..f7d3f20 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/mst-content-hint.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/mst-content-hint.idl
@@ -6,3 +6,13 @@
 partial interface MediaStreamTrack {
   attribute DOMString contentHint;
 };
+
+enum RTCDegradationPreference {
+  "maintain-framerate",
+  "maintain-resolution",
+  "balanced"
+};
+
+partial dictionary RTCRtpSendParameters {
+ RTCDegradationPreference degradationPreference;
+};
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/requestidlecallback.idl b/third_party/blink/web_tests/external/wpt/interfaces/requestidlecallback.idl
index b485dc0..c763b50b 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/requestidlecallback.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/requestidlecallback.idl
@@ -11,8 +11,10 @@
 dictionary IdleRequestOptions {
   unsigned long timeout;
 };
+
 [Exposed=Window] interface IdleDeadline {
   DOMHighResTimeStamp timeRemaining();
   readonly attribute boolean didTimeout;
 };
+
 callback IdleRequestCallback = void (IdleDeadline deadline);
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl b/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl
index de23fac..12ea9d5 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl
@@ -3,7 +3,7 @@
 // (https://github.com/tidoust/reffy-reports)
 // Source: Web NFC (https://w3c.github.io/web-nfc/)
 
-[Exposed=Window]
+[SecureContext, Exposed=Window]
 interface NDEFMessage {
   constructor(NDEFMessageInit messageInit);
   readonly attribute FrozenArray<NDEFRecord> records;
@@ -15,7 +15,7 @@
 
 typedef (DOMString or BufferSource or NDEFMessageInit) NDEFRecordDataSource;
 
-[Exposed=Window]
+[SecureContext, Exposed=Window]
 interface NDEFRecord {
   constructor(NDEFRecordInit recordInit);
 
@@ -27,7 +27,7 @@
   readonly attribute USVString? encoding;
   readonly attribute USVString? lang;
 
-  sequence<NDEFRecord> toRecords();
+  sequence<NDEFRecord>? toRecords();
 };
 
 dictionary NDEFRecordInit {
@@ -89,6 +89,6 @@
 dictionary NDEFScanOptions {
   USVString id;
   USVString recordType;
-  USVString mediaType = "";
+  USVString mediaType;
   AbortSignal? signal;
 };
diff --git a/third_party/blink/web_tests/external/wpt/mst-content-hint/idlharness.window-expected.txt b/third_party/blink/web_tests/external/wpt/mst-content-hint/idlharness.window-expected.txt
new file mode 100644
index 0000000..6f8ebba
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mst-content-hint/idlharness.window-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+PASS idl_test setup
+PASS idl_test validation
+PASS Partial interface MediaStreamTrack: original interface defined
+PASS Partial interface MediaStreamTrack: member names are unique
+FAIL Partial dictionary RTCRtpSendParameters: original dictionary defined assert_true: Original dictionary should be defined expected true got false
+PASS MediaStreamTrack interface: attribute contentHint
+PASS MediaStreamTrack interface: audioTrack must inherit property "contentHint" with the proper type
+PASS MediaStreamTrack interface: videoTrack must inherit property "contentHint" with the proper type
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js b/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js
index 2ec9c75..8cc3546b 100644
--- a/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js
+++ b/third_party/blink/web_tests/external/wpt/navigation-timing/idlharness.window.js
@@ -6,8 +6,8 @@
 // http://www.w3.org/TR/navigation-timing/
 
 idl_test(
-  ['hr-time', 'navigation-timing'],
-  ['resource-timing', 'performance-timeline', 'html', 'dom'],
+  ['navigation-timing'],
+  ['resource-timing', 'performance-timeline', 'hr-time', 'dom'],
   idl_array => {
     idl_array.add_objects({
       Performance: ['performance'],
diff --git a/third_party/blink/web_tests/external/wpt/remote-playback/cancel-watch-availability.html b/third_party/blink/web_tests/external/wpt/remote-playback/cancel-watch-availability.html
index e4b6330..d83c8cec 100644
--- a/third_party/blink/web_tests/external/wpt/remote-playback/cancel-watch-availability.html
+++ b/third_party/blink/web_tests/external/wpt/remote-playback/cancel-watch-availability.html
@@ -7,7 +7,7 @@
 <script>
 async_test(t => {
   var v = document.createElement('video');
-  v.src = getVideoURI('movie_5');
+  v.src = getVideoURI('/media/movie_5');
 
   v.remote.watchAvailability(function() {})
     .then(t.step_func(id => {
@@ -23,7 +23,7 @@
 
 async_test(t => {
   var v = document.createElement('video');
-  v.src = getVideoURI('movie_5');
+  v.src = getVideoURI('/media/movie_5');
 
   Promise.all([
       v.remote.watchAvailability(function() {}),
diff --git a/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-cancel-watch-availability-throws.html b/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-cancel-watch-availability-throws.html
index fdcc734..bdd35d8 100644
--- a/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-cancel-watch-availability-throws.html
+++ b/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-cancel-watch-availability-throws.html
@@ -7,7 +7,7 @@
 <script>
 async_test(t => {
   var v = document.createElement('video');
-  v.src = getVideoURI('movie_5');
+  v.src = getVideoURI('/media/movie_5');
 
   v.remote.watchAvailability(function() {})
     .then(id => {
diff --git a/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-prompt-throws.html b/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-prompt-throws.html
index 7ddc2ad1..076b163 100644
--- a/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-prompt-throws.html
+++ b/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-prompt-throws.html
@@ -7,7 +7,7 @@
 <script>
 promise_test(t => {
   var v = document.createElement('video');
-  v.src = getVideoURI('movie_5');
+  v.src = getVideoURI('/media/movie_5');
   v.disableRemotePlayback = true;
 
   return promise_rejects(t, 'InvalidStateError', v.remote.prompt());
diff --git a/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-watch-availability-throws.html b/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-watch-availability-throws.html
index 3c21f01..1cec5278 100644
--- a/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-watch-availability-throws.html
+++ b/third_party/blink/web_tests/external/wpt/remote-playback/disable-remote-playback-watch-availability-throws.html
@@ -7,7 +7,7 @@
 <script>
 promise_test(t => {
   var v = document.createElement('video');
-  v.src = getVideoURI('movie_5');
+  v.src = getVideoURI('/media/movie_5');
   v.disableRemotePlayback = true;
 
   return promise_rejects(t, 'InvalidStateError',
diff --git a/third_party/blink/web_tests/external/wpt/remote-playback/idlharness.window.js b/third_party/blink/web_tests/external/wpt/remote-playback/idlharness.window.js
index 73bc998f..ba40f19 100644
--- a/third_party/blink/web_tests/external/wpt/remote-playback/idlharness.window.js
+++ b/third_party/blink/web_tests/external/wpt/remote-playback/idlharness.window.js
@@ -12,7 +12,7 @@
   idl_array => {
     try {
       const media = document.createElement('video');
-      media.src = getVideoURI('movie_5');
+      media.src = getVideoURI('/media/movie_5');
       media.width = media.height = 10;
       document.body.appendChild(media);
       self.media = media;
diff --git a/third_party/blink/web_tests/external/wpt/remote-playback/watch-availability-initial-callback.html b/third_party/blink/web_tests/external/wpt/remote-playback/watch-availability-initial-callback.html
index 851558b..352321b 100644
--- a/third_party/blink/web_tests/external/wpt/remote-playback/watch-availability-initial-callback.html
+++ b/third_party/blink/web_tests/external/wpt/remote-playback/watch-availability-initial-callback.html
@@ -7,7 +7,7 @@
 <script>
 async_test(t => {
   var v = document.createElement('video');
-  v.src = getVideoURI('movie_5');
+  v.src = getVideoURI('/media/movie_5');
 
   var promiseResolved = false;
 
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js b/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js
index 2c1724b..5cac21b 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js
@@ -133,7 +133,7 @@
         options.recordType !== record.recordType) {
       continue;
     }
-    if (options.mediaType !== '' && options.mediaType !== record.mediaType) {
+    if (options.mediaType != null && options.mediaType !== record.mediaType) {
       continue;
     }
 
diff --git a/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js b/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js
index b55c741..ded320f0 100644
--- a/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/server-timing/idlharness.https.any.js
@@ -6,23 +6,11 @@
 // https://w3c.github.io/server-timing/
 
 idl_test(
-  ['resource-timing', 'server-timing'],
-  ['performance-timeline', 'hr-time', 'dom'],
-  idl_array => new Promise((resolve, reject) => {
-    new PerformanceObserver(entries => {
-      entries.getEntries().forEach(e => {
-        if (!e.name.endsWith('blue.png'))
-          return;
-
-        self.resource = e;
-        self.server = e.serverTiming[0];
-        idl_array.add_objects({
-          PerformanceResourceTiming: ['resource'],
-          PerformanceServerTiming: ['server']
-        });
-        resolve();
-      })
-    }).observe({entryTypes: ['resource']});
-    fetch('resources/blue.png');
-  })
+  ['server-timing'],
+  ['resource-timing', 'performance-timeline'],
+  idl_array => {
+    idl_array.add_objects({
+      Performance: ['performance'],
+    });
+  }
 );
diff --git a/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py b/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py
index 0c5bbff5..cf4c5fd 100644
--- a/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py
+++ b/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py
@@ -738,6 +738,10 @@
         return self.send_element_command("GET", "selected")
 
     @command
+    def screenshot(self):
+        return self.send_element_command("GET", "screenshot")
+
+    @command
     def attribute(self, name):
         return self.send_element_command("GET", "attribute/%s" % name)
 
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/__init__.py
index 9de87924..9a82cc4 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/__init__.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/__init__.py
@@ -1,12 +1,10 @@
-def element_rect(session, element):
-    return session.execute_script("""
-        let {devicePixelRatio} = window;
-        let {left, top, width, height} = arguments[0].getBoundingClientRect();
+def element_dimensions(session, element):
+    return tuple(session.execute_script("""
+        const {devicePixelRatio} = window;
+        let {width, height} = arguments[0].getBoundingClientRect();
 
-        return {
-            x: Math.floor((left + window.pageXOffset) * devicePixelRatio),
-            y: Math.floor((top + window.pageYOffset) * devicePixelRatio),
-            width: Math.floor(width * devicePixelRatio),
-            height: Math.floor(height * devicePixelRatio),
-        };
-        """, args=(element,))
+        return [
+          Math.floor(width * devicePixelRatio),
+          Math.floor(height * devicePixelRatio),
+        ];
+        """, args=(element,)))
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/iframe.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/iframe.py
index 242122f0..83f55def 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/iframe.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/iframe.py
@@ -4,21 +4,58 @@
 from tests.support.image import png_dimensions
 from tests.support.inline import iframe, inline
 
-from . import element_rect
+from . import element_dimensions
 
+DEFAULT_CONTENT = "<div id='content'>Lorem ipsum dolor sit amet.</div>"
 
-DEFAULT_CSS_STYLE = """
+REFERENCE_CONTENT = "<div id='outer'>{}</div>".format(DEFAULT_CONTENT)
+REFERENCE_STYLE = """
     <style>
-      div, iframe {
+      #outer {
         display: block;
-        border: 1px solid blue;
-        width: 10em;
-        height: 10em;
+        margin: 0;
+        border: 0;
+        width: 200px;
+        height: 200px;
+      }
+      #content {
+        display: block;
+        margin: 0;
+        border: 0;
+        width: 100px;
+        height: 100px;
+        background: green;
       }
     </style>
 """
 
-DEFAULT_CONTENT = "<div>Lorem ipsum dolor sit amet.</div>"
+OUTER_IFRAME_STYLE = """
+    <style>
+      iframe {
+        display: block;
+        margin: 0;
+        border: 0;
+        width: 200px;
+        height: 200px;
+      }
+    </style>
+"""
+
+INNER_IFRAME_STYLE = """
+    <style>
+      body {
+        margin: 0;
+      }
+      div {
+        display: block;
+        margin: 0;
+        border: 0;
+        width: 100px;
+        height: 100px;
+        background: green;
+      }
+    </style>
+"""
 
 
 def take_element_screenshot(session, element_id):
@@ -31,24 +68,55 @@
     )
 
 
+def test_frame_element(session):
+    # Create a reference element which looks exactly like the frame's content
+    session.url = inline("{0}{1}".format(REFERENCE_STYLE, REFERENCE_CONTENT))
+
+    # Capture the inner content as reference image
+    ref_el = session.find.css("#content", all=False)
+    ref_screenshot = ref_el.screenshot()
+    ref_dimensions = element_dimensions(session, ref_el)
+
+    assert png_dimensions(ref_screenshot) == ref_dimensions
+
+    # Capture the frame's element
+    iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
+    session.url = inline("""{0}{1}""".format(OUTER_IFRAME_STYLE, iframe(iframe_content)))
+
+    frame = session.find.css("iframe", all=False)
+    session.switch_frame(frame)
+    div = session.find.css("div", all=False)
+    div_dimensions = element_dimensions(session, div)
+    assert div_dimensions == ref_dimensions
+
+    response = take_element_screenshot(session, div.id)
+    div_screenshot = assert_success(response)
+
+    assert png_dimensions(div_screenshot) == ref_dimensions
+    assert div_screenshot == ref_screenshot
+
+
 @pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
 def test_source_origin(session, url, domain):
-    session.url = inline("""{0}{1}""".format(DEFAULT_CSS_STYLE, DEFAULT_CONTENT))
-    element = session.find.css("div", all=False)
-    rect = element_rect(session, element)
+    # Create a reference element which looks exactly like the iframe
+    session.url = inline("{0}{1}".format(REFERENCE_STYLE, REFERENCE_CONTENT))
 
-    response = take_element_screenshot(session, element.id)
+    div = session.find.css("div", all=False)
+    div_dimensions = element_dimensions(session, div)
+
+    response = take_element_screenshot(session, div.id)
     reference_screenshot = assert_success(response)
-    assert png_dimensions(reference_screenshot) == (rect["width"], rect["height"])
+    assert png_dimensions(reference_screenshot) == div_dimensions
 
-    iframe_content = "<style>body {{ margin: 0; }}</style>{}".format(DEFAULT_CONTENT)
+    iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
     session.url = inline("""{0}{1}""".format(
-        DEFAULT_CSS_STYLE, iframe(iframe_content, domain=domain)))
+        OUTER_IFRAME_STYLE, iframe(iframe_content, domain=domain)))
+
     frame_element = session.find.css("iframe", all=False)
-    frame_rect = element_rect(session, frame_element)
+    frame_dimensions = element_dimensions(session, frame_element)
 
     response = take_element_screenshot(session, frame_element.id)
     screenshot = assert_success(response)
-    assert png_dimensions(screenshot) == (frame_rect["width"], frame_rect["height"])
+    assert png_dimensions(screenshot) == frame_dimensions
 
     assert screenshot == reference_screenshot
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/screenshot.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/screenshot.py
index fd460b65..50d33a2 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/screenshot.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_element_screenshot/screenshot.py
@@ -2,7 +2,7 @@
 from tests.support.image import png_dimensions
 from tests.support.inline import inline
 
-from . import element_rect
+from . import element_dimensions
 
 
 def take_element_screenshot(session, element_id):
@@ -32,9 +32,8 @@
 def test_format_and_dimensions(session):
     session.url = inline("<input>")
     element = session.find.css("input", all=False)
-    rect = element_rect(session, element)
 
     response = take_element_screenshot(session, element.id)
     screenshot = assert_success(response)
 
-    assert png_dimensions(screenshot) == (rect["width"], rect["height"])
+    assert png_dimensions(screenshot) == element_dimensions(session, element)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/__init__.py
index c07f8d1..f3001d9 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/__init__.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/__init__.py
@@ -1,6 +1,18 @@
+def element_dimensions(session, element):
+    return tuple(session.execute_script("""
+        const {devicePixelRatio} = window;
+        let {width, height} = arguments[0].getBoundingClientRect();
+
+        return [
+          Math.floor(width * devicePixelRatio),
+          Math.floor(height * devicePixelRatio),
+        ];
+        """, args=(element,)))
+
+
 def viewport_dimensions(session):
     return tuple(session.execute_script("""
-        let {devicePixelRatio, innerHeight, innerWidth} = window;
+        const {devicePixelRatio, innerHeight, innerWidth} = window;
 
         return [
           Math.floor(innerWidth * devicePixelRatio),
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/iframe.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/iframe.py
index 4cf8ad0..6186cf3 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/iframe.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/take_screenshot/iframe.py
@@ -4,21 +4,58 @@
 from tests.support.image import png_dimensions
 from tests.support.inline import iframe, inline
 
-from . import viewport_dimensions
+from . import element_dimensions, viewport_dimensions
 
+DEFAULT_CONTENT = "<div id='content'>Lorem ipsum dolor sit amet.</div>"
 
-DEFAULT_CSS_STYLE = """
+REFERENCE_CONTENT = "<div id='outer'>{}</div>".format(DEFAULT_CONTENT)
+REFERENCE_STYLE = """
     <style>
-      div, iframe {
+      #outer {
         display: block;
-        border: 1px solid blue;
-        width: 10em;
-        height: 10em;
+        margin: 0;
+        border: 0;
+        width: 200px;
+        height: 200px;
+      }
+      #content {
+        display: block;
+        margin: 0;
+        border: 0;
+        width: 100px;
+        height: 100px;
+        background: green;
       }
     </style>
 """
 
-DEFAULT_CONTENT = "<div>Lorem ipsum dolor sit amet.</div>"
+OUTER_IFRAME_STYLE = """
+    <style>
+      iframe {
+        display: block;
+        margin: 0;
+        border: 0;
+        width: 200px;
+        height: 200px;
+      }
+    </style>
+"""
+
+INNER_IFRAME_STYLE = """
+    <style>
+      body {
+        margin: 0;
+      }
+      div {
+        display: block;
+        margin: 0;
+        border: 0;
+        width: 100px;
+        height: 100px;
+        background: green;
+      }
+    </style>
+"""
 
 
 def take_screenshot(session):
@@ -26,17 +63,45 @@
         "GET", "session/{session_id}/screenshot".format(**vars(session)))
 
 
+def test_frame_content(session):
+    # Create a reference element which looks exactly like the frame's content
+    session.url = inline("{0}{1}".format(REFERENCE_STYLE, REFERENCE_CONTENT))
+
+    # Capture the inner content as reference image
+    ref_el = session.find.css("div", all=False)
+    ref_screenshot = ref_el.screenshot()
+    ref_dimensions = element_dimensions(session, ref_el)
+
+    assert ref_dimensions != viewport_dimensions
+    assert png_dimensions(ref_screenshot) == ref_dimensions
+
+    # Capture the frame's content
+    iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
+    session.url = inline("""{0}{1}""".format(OUTER_IFRAME_STYLE, iframe(iframe_content)))
+
+    frame = session.find.css("iframe", all=False)
+    session.switch_frame(frame)
+    frame_dimensions = viewport_dimensions(session)
+    assert frame_dimensions == ref_dimensions
+
+    response = take_screenshot(session)
+    frame_screenshot = assert_success(response)
+
+    assert png_dimensions(frame_screenshot) == ref_dimensions
+    assert frame_screenshot == ref_screenshot
+
+
 @pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
-def test_source_origin(session, url, domain):
-    session.url = inline("""{0}{1}""".format(DEFAULT_CSS_STYLE, DEFAULT_CONTENT))
+def test_source_origin(session, domain):
+    session.url = inline("{0}{1}".format(REFERENCE_STYLE, REFERENCE_CONTENT))
 
     response = take_screenshot(session)
     reference_screenshot = assert_success(response)
     assert png_dimensions(reference_screenshot) == viewport_dimensions(session)
 
-    iframe_content = "<style>body {{ margin: 0; }}</style>{}".format(DEFAULT_CONTENT)
+    iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
     session.url = inline("""{0}{1}""".format(
-        DEFAULT_CSS_STYLE, iframe(iframe_content, domain=domain)))
+        OUTER_IFRAME_STYLE, iframe(iframe_content, domain=domain)))
 
     response = take_screenshot(session)
     screenshot = assert_success(response)
diff --git a/third_party/blink/web_tests/http/tests/content_index/content-index.html b/third_party/blink/web_tests/http/tests/content_index/content-index.html
index 37eb1ec..53b928be 100644
--- a/third_party/blink/web_tests/http/tests/content_index/content-index.html
+++ b/third_party/blink/web_tests/http/tests/content_index/content-index.html
@@ -22,19 +22,19 @@
 contentIndexTest(async (t, index) => {
   await expectTypeErrorWithMessage(
       index.add(createDescription({id: ''})),
-      'ID cannot be empty');
+      `Failed to execute 'add' on 'ContentIndex': ID cannot be empty`);
   await expectTypeErrorWithMessage(
       index.add(createDescription({title: ''})),
-      'Title cannot be empty');
+      `Failed to execute 'add' on 'ContentIndex': Title cannot be empty`);
   await expectTypeErrorWithMessage(
       index.add(createDescription({description:''})),
-      'Description cannot be empty');
+      `Failed to execute 'add' on 'ContentIndex': Description cannot be empty`);
   await expectTypeErrorWithMessage(
       index.add(createDescription({category: 'fake-category'})));
 
   await expectTypeErrorWithMessage(
       index.add(createDescription({iconUrl: 'file://some-local-file.png'})),
-      'Invalid icon URL protocol');
+      `Failed to execute 'add' on 'ContentIndex': Invalid icon URL protocol`);
   await expectTypeErrorWithMessage(
       index.add(createDescription({includeIcons: false})),
       'icons must be provided');
@@ -47,10 +47,10 @@
 
   await expectTypeErrorWithMessage(
       index.add(createDescription({launchUrl: 'https://other-domain.com/'})),
-      'Service Worker cannot request provided launch URL');
+      `Failed to execute 'add' on 'ContentIndex': Service Worker cannot request provided launch URL`);
   await expectTypeErrorWithMessage(
       index.add(createDescription({launchUrl: '/different-scope'})),
-      `Launch URL must belong to the Service Worker's scope`);
+      `Failed to execute 'add' on 'ContentIndex': Launch URL must belong to the Service Worker's scope`);
 
   await index.add(createDescription({}));
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test-expected.txt b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test-expected.txt
new file mode 100644
index 0000000..a289ea3
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test-expected.txt
@@ -0,0 +1,14 @@
+Testing accessibility in the scope pane.
+
+Script execution paused.
+Scope pane content: Localthis: WindowClosure (makeClosure)WindowGlobal
+Running the axe-core linter on the scope pane.
+aXe violations: []
+
+Expanding the makeClosure closure.
+Scope pane content: Localthis: WindowClosure (makeClosure)x: 5WindowGlobal
+Running the axe-core linter on the scope pane.
+aXe violations: []
+
+Script execution resumed.
+
diff --git a/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test.js b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test.js
new file mode 100644
index 0000000..24fb59c44
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test.js
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(async function() {
+  await TestRunner.loadModule('axe_core_test_runner');
+  await TestRunner.loadModule('sources_test_runner');
+  await TestRunner.showPanel('sources');
+  await UI.viewManager.showView('sources.scopeChain');
+
+  TestRunner.addResult('Testing accessibility in the scope pane.\n');
+  await SourcesTestRunner.startDebuggerTestPromise();
+  TestRunner.evaluateInPagePromise(`
+  function makeClosure() {
+    let x = 5;
+    function logX() {
+      console.log(x);
+      debugger;
+    }
+    return logX;
+  }
+  makeClosure()();
+  `);
+  await SourcesTestRunner.waitUntilPausedPromise();
+
+  await TestRunner.addSnifferPromise(Sources.ScopeChainSidebarPane.prototype, '_sidebarPaneUpdatedForTest');
+  const scopePane = self.runtime.sharedInstance(Sources.ScopeChainSidebarPane);
+  await TestRunner.addSnifferPromise(ObjectUI.ObjectPropertyTreeElement, 'populateWithProperties');
+  TestRunner.addResult(`Scope pane content: ${scopePane.contentElement.deepTextContent()}`);
+  TestRunner.addResult(`Running the axe-core linter on the scope pane.`);
+  await AxeCoreTestRunner.runValidation(scopePane.contentElement);
+
+  TestRunner.addResult('Expanding the makeClosure closure.');
+  scopePane._treeOutline._rootElement.childAt(1).expand();
+  await TestRunner.addSnifferPromise(ObjectUI.ObjectPropertyTreeElement, 'populateWithProperties');
+  TestRunner.addResult(`Scope pane content: ${scopePane.contentElement.deepTextContent()}`);
+  TestRunner.addResult(`Running the axe-core linter on the scope pane.`);
+  await AxeCoreTestRunner.runValidation(scopePane.contentElement);
+
+  SourcesTestRunner.completeDebuggerTest();
+})();
diff --git a/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt b/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt
index cfea38c..d0359d6 100644
--- a/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt
+++ b/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving-builtins.tentative-expected.txt
@@ -2,12 +2,12 @@
 PASS Unmapped built-in module specifiers / should resolve "std:blank" to "std:blank"
 FAIL Unmapped built-in module specifiers / should error resolving "std:none" assert_throws: function "() => resolveUnderTest(NONE)" did not throw
 PASS Remapping built-in module specifiers / should remap built-in modules
-FAIL Remapping built-in module specifiers / should remap built-in modules with slashes assert_equals: expected "https://example.com/app/blank-slash/bar" but got "std:blank/bar"
+PASS Remapping built-in module specifiers / should remap built-in modules with slashes
 FAIL Remapping built-in module specifiers / should remap built-in modules with fallbacks assert_equals: expected "https://example.com/app/none.mjs" but got "std:none"
 FAIL Remapping built-in module specifiers / should remap built-in modules with slashes and fallbacks assert_equals: expected "https://example.com/app/blank/" but got "std:blank/"
 PASS Remapping to built-in modules / should remap to "std:blank"
 FAIL Remapping to built-in modules / should fail when remapping to "std:blank/" assert_throws: function "() => resolveUnderTest('/blank/')" did not throw
-FAIL Remapping to built-in modules / should remap to "std:blank/for-testing" assert_equals: expected "std:blank/for-testing" but got "https://example.com/blank/for-testing"
+FAIL Remapping to built-in modules / should remap to "std:blank/for-testing" Failed to resolve module specifier /blank/for-testing: Import Map: "https://example.com/blank/for-testing" matches with "https://example.com/blank/" and is mapped to
 PASS Remapping to built-in modules / should remap to "std:blank" for URL-like specifiers
 FAIL Remapping to built-in modules / should fail when remapping to "std:none" assert_throws: function "() => resolveUnderTest('none')" did not throw
 FAIL Fallbacks with built-in module addresses / should resolve to "std:blank" Failed to resolve module specifier blank: Relative references must start with either "/", "./", or "../".
diff --git a/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt b/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt
index 3532634..f28a00f 100644
--- a/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt
+++ b/third_party/blink/web_tests/virtual/import-maps-without-builtin-modules/external/wpt/import-maps/builtin-support.tentative/imported/resolving.tentative-expected.txt
@@ -17,7 +17,7 @@
 PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap to other URLs
 FAIL Mapped using the "imports" key only (no scopes) / URL-like specifiers / should fail for URLs that remap to empty arrays assert_throws: function "() => resolveUnderTest('https://example.com/lib/no.mjs')" did not throw
 PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap URLs that are just composed from / and .
-FAIL Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap URLs that are prefix-matched by keys with trailing slashes assert_equals: expected "https://example.com/lib/url-trailing-slash/foo.mjs" but got "https://example.com/test/foo.mjs"
+PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should remap URLs that are prefix-matched by keys with trailing slashes
 PASS Mapped using the "imports" key only (no scopes) / URL-like specifiers / should use the last entry's address when URL-like specifiers parse to the same absolute URL
 PASS Mapped using the "imports" key only (no scopes) / Overlapping entries with trailing slashes / should favor the most-specific key (no empty arrays)
 PASS Mapped using the "imports" key only (no scopes) / Overlapping entries with trailing slashes / should favor the most-specific key when empty arrays are involved for less-specific keys
diff --git a/tools/binary_size/libsupersize/apkanalyzer.py b/tools/binary_size/libsupersize/apkanalyzer.py
index 259e95a..93ded40a 100644
--- a/tools/binary_size/libsupersize/apkanalyzer.py
+++ b/tools/binary_size/libsupersize/apkanalyzer.py
@@ -29,20 +29,25 @@
   return source_map
 
 
-def _RunApkAnalyzer(apk_path, mapping_path, output_directory):
-  args = [path_util.GetApkAnalyzerPath(output_directory), 'dex', 'packages',
-          apk_path]
+def _RunApkAnalyzer(apk_path, mapping_path):
+  args = [path_util.GetApkAnalyzerPath(), 'dex', 'packages', apk_path]
   if mapping_path and os.path.exists(mapping_path):
     args.extend(['--proguard-mappings', mapping_path])
-  output = subprocess.check_output(args)
+  env = os.environ.copy()
+  env['JAVA_HOME'] = path_util.GetJavaHome()
+  output = subprocess.check_output(args, env=env)
   data = []
   for line in output.splitlines():
-    vals = line.split()
-    # We want to name these columns so we know exactly which is which.
-    # pylint: disable=unused-variable
-    node_type, state, defined_methods, referenced_methods, size, name = (
-        vals[0], vals[1], vals[2], vals[3], vals[4], vals[5:])
-    data.append((node_type, ' '.join(name), int(size)))
+    try:
+      vals = line.split()
+      # We want to name these columns so we know exactly which is which.
+      # pylint: disable=unused-variable
+      node_type, state, defined_methods, referenced_methods, size, name = (
+          vals[0], vals[1], vals[2], vals[3], vals[4], vals[5:])
+      data.append((node_type, ' '.join(name), int(size)))
+    except Exception:
+      logging.error('Problem line was: %s', line)
+      raise
   return data
 
 
@@ -130,11 +135,10 @@
   return nodes
 
 
-def CreateDexSymbols(apk_path, mapping_path, size_info_prefix,
-                     output_directory):
+def CreateDexSymbols(apk_path, mapping_path, size_info_prefix):
   source_map = _ParseJarInfoFile(size_info_prefix + '.jar.info')
 
-  nodes = _RunApkAnalyzer(apk_path, mapping_path, output_directory)
+  nodes = _RunApkAnalyzer(apk_path, mapping_path)
   nodes = UndoHierarchicalSizing(nodes)
 
   dex_expected_size = _ExpectedDexTotalSize(apk_path)
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index c0cf3943..a315124 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -1469,8 +1469,8 @@
         size_info_prefix, knobs)
 
     if knobs.analyze_java:
-      dex_symbols = apkanalyzer.CreateDexSymbols(
-          apk_path, mapping_path, size_info_prefix, output_directory)
+      dex_symbols = apkanalyzer.CreateDexSymbols(apk_path, mapping_path,
+                                                 size_info_prefix)
       raw_symbols.extend(dex_symbols)
 
       # We can't meaningfully track section size of dex methods vs other, so
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py
index 20ae77a..78930c7 100755
--- a/tools/binary_size/libsupersize/integration_test.py
+++ b/tools/binary_size/libsupersize/integration_test.py
@@ -27,6 +27,7 @@
 
 _SCRIPT_DIR = os.path.dirname(__file__)
 _TEST_DATA_DIR = os.path.join(_SCRIPT_DIR, 'testdata')
+_TEST_SDK_DIR = os.path.join(_TEST_DATA_DIR, 'mock_sdk')
 _TEST_SOURCE_DIR = os.path.join(_TEST_DATA_DIR, 'mock_source_directory')
 _TEST_OUTPUT_DIR = os.path.join(_TEST_SOURCE_DIR, 'out', 'Release')
 _TEST_TOOL_PREFIX = os.path.join(
@@ -75,8 +76,13 @@
 def _AddMocksToPath():
   prev_path = os.environ['PATH']
   os.environ['PATH'] = _TEST_TOOL_PREFIX[:-1] + os.path.pathsep + prev_path
-  yield
-  os.environ['PATH'] = prev_path
+  os.environ['APK_ANALYZER'] = os.path.join(_TEST_SDK_DIR, 'tools', 'bin',
+                                            'apkanalyzer')
+  try:
+    yield
+  finally:
+    os.environ['PATH'] = prev_path
+    del os.environ['APK_ANALYZER']
 
 
 def _RunApp(name, args, debug_measures=False):
@@ -191,20 +197,26 @@
         pak_info_file = _TEST_PAK_INFO_PATH
       metadata = None
       linker_name = 'gold'
-      if use_elf:
-        with _AddMocksToPath():
+      with _AddMocksToPath():
+        if use_elf:
           metadata = archive.CreateMetadata(
               _TEST_MAP_PATH, elf_path, apk_path, minimal_apks_path,
               _TEST_TOOL_PREFIX, output_directory, linker_name)
-      section_sizes, raw_symbols = archive.CreateSectionSizesAndSymbols(
-          map_path=_TEST_MAP_PATH, tool_prefix=_TEST_TOOL_PREFIX,
-          elf_path=elf_path, output_directory=output_directory,
-          apk_path=apk_path or extracted_minimal_apk_path,
-          apk_so_path=apk_so_path, metadata=metadata, pak_files=pak_files,
-          pak_info_file=pak_info_file, linker_name=linker_name,
-          size_info_prefix=size_info_prefix, knobs=knobs)
-      IntegrationTest.cached_size_info[cache_key] = archive.CreateSizeInfo(
-          section_sizes, raw_symbols, metadata=metadata)
+        section_sizes, raw_symbols = archive.CreateSectionSizesAndSymbols(
+            map_path=_TEST_MAP_PATH,
+            tool_prefix=_TEST_TOOL_PREFIX,
+            elf_path=elf_path,
+            output_directory=output_directory,
+            apk_path=apk_path or extracted_minimal_apk_path,
+            apk_so_path=apk_so_path,
+            metadata=metadata,
+            pak_files=pak_files,
+            pak_info_file=pak_info_file,
+            linker_name=linker_name,
+            size_info_prefix=size_info_prefix,
+            knobs=knobs)
+        IntegrationTest.cached_size_info[cache_key] = archive.CreateSizeInfo(
+            section_sizes, raw_symbols, metadata=metadata)
     return copy.deepcopy(IntegrationTest.cached_size_info[cache_key])
 
   def _DoArchive(self,
diff --git a/tools/binary_size/libsupersize/path_util.py b/tools/binary_size/libsupersize/path_util.py
index 356d0ff..c6d5ac0 100644
--- a/tools/binary_size/libsupersize/path_util.py
+++ b/tools/binary_size/libsupersize/path_util.py
@@ -163,16 +163,15 @@
   return tool_prefix + 'nm'
 
 
-def GetApkAnalyzerPath(output_directory):
-  build_vars = _LoadBuildVars(output_directory)
-  sdk_analyzer = os.path.normpath(os.path.join(
-      output_directory, build_vars['android_sdk_root'], 'tools', 'bin',
-      'apkanalyzer'))
-  if os.path.exists(sdk_analyzer):
-    return sdk_analyzer
-  # Older SDKs do not contain the tool, so fall back to the one we know exists.
-  return os.path.join(SRC_ROOT, 'third_party', 'android_sdk', 'public',
-                      'tools', 'bin', 'apkanalyzer')
+def GetApkAnalyzerPath():
+  default_path = FromSrcRootRelative(
+      os.path.join('third_party', 'android_sdk', 'public', 'cmdline-tools',
+                   'latest', 'bin', 'apkanalyzer'))
+  return os.environ.get('APK_ANALYZER', default_path)
+
+
+def GetJavaHome():
+  return FromSrcRootRelative(os.path.join('third_party', 'jdk', 'current'))
 
 
 def GetObjDumpPath(tool_prefix):
diff --git a/tools/chrome_proxy/webdriver/https_previews.py b/tools/chrome_proxy/webdriver/https_previews.py
index 3c7edbe7..1426ad4 100644
--- a/tools/chrome_proxy/webdriver/https_previews.py
+++ b/tools/chrome_proxy/webdriver/https_previews.py
@@ -24,7 +24,6 @@
   def EnableLitePageServerPreviewsAndInit(self, t):
     t.EnableChromeFeature('Previews')
     t.EnableChromeFeature('LitePageServerPreviews')
-    t.EnableChromeFeature('HTTPSServerPreviewsUsingURLLoader')
 
     # RLH and NoScript may disable use of LitePageRedirect Previews.
     t.DisableChromeFeature('ResourceLoadingHints')
diff --git a/tools/gdb/gdbinit b/tools/gdb/gdbinit
index c6a531b4..10479fc 100644
--- a/tools/gdb/gdbinit
+++ b/tools/gdb/gdbinit
@@ -99,7 +99,7 @@
 # use try..except to avoid displaying errors in earlier GDB versions.
 try:
   # unlimited means "number of cores"
-  gdb.execute("maint set worket-threads unlimited")
+  gdb.execute("maint set worker-threads unlimited")
 except:
   pass
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 871c75fe..32a3c237 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -12477,6 +12477,8 @@
   <int value="22" label="Insufficient Disk Space"/>
   <int value="23" label="Error Configuring Container"/>
   <int value="24" label="User Cancelled While Configuring Container"/>
+  <int value="25" label="Error Creating Container"/>
+  <int value="26" label="Bug - Failed without capturing error code"/>
 </enum>
 
 <enum name="CrostiniUISurface">
@@ -66044,6 +66046,9 @@
 </enum>
 
 <enum name="WebFontPackageFormat">
+  <obsolete>
+    Removed Jan 2020.
+  </obsolete>
   <int value="0" label="Unknown / Decode error"/>
   <int value="1" label="SFNT"/>
   <int value="2" label="WOFF"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index d30b8a3..e0de2010 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -3357,7 +3357,8 @@
 </histogram>
 
 <histogram name="Android.Omnibox.InvalidMatch" enum="MatchResult"
-    expires_after="M81">
+    expires_after="2020-07-01">
+  <owner>ender@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
@@ -4657,8 +4658,9 @@
 </histogram>
 
 <histogram name="AppBanners.BeforeInstallEvent"
-    enum="AppBannersBeforeInstallEvent" expires_after="2020-05-03">
+    enum="AppBannersBeforeInstallEvent" expires_after="2021-01-01">
   <owner>dominickn@chromium.org</owner>
+  <owner>pjmclachlan@google.com</owner>
   <summary>
     App banners promote an application related to the current website, and are
     requested specifically through the current page's HTML. This stat tracks
@@ -4670,7 +4672,7 @@
 </histogram>
 
 <histogram name="AppBanners.DismissEvent" enum="AppBannersDismissEvent"
-    expires_after="2020-05-03">
+    expires_after="2021-01-01">
   <owner>pjmclachlan@google.com</owner>
   <owner>pcovell@google.com</owner>
   <summary>
@@ -4682,7 +4684,7 @@
 </histogram>
 
 <histogram name="AppBanners.DisplayEvent" enum="AppBannersDisplayEvent"
-    expires_after="2020-04-26">
+    expires_after="2021-01-01">
   <owner>pjmclachlan@google.com</owner>
   <owner>pcovell@google.com</owner>
   <summary>
@@ -4694,8 +4696,9 @@
 </histogram>
 
 <histogram name="AppBanners.InstallableStatusCode"
-    enum="AppBannersInstallableStatusCode" expires_after="M81">
+    enum="AppBannersInstallableStatusCode" expires_after="2021-01-01">
   <owner>dominickn@chromium.org</owner>
+  <owner>pjmclachlan@google.com</owner>
   <summary>
     App banners promote an application related to the current website, and are
     requested specifically through the current page's HTML. This stat tracks the
@@ -4706,7 +4709,7 @@
 </histogram>
 
 <histogram name="AppBanners.InstallEvent" enum="AppBannersInstallEvent"
-    expires_after="2020-06-21">
+    expires_after="2021-01-01">
   <owner>pjmclachlan@google.com</owner>
   <owner>pcovell@google.com</owner>
   <summary>
@@ -4718,8 +4721,9 @@
 </histogram>
 
 <histogram name="AppBanners.MinutesFromFirstVisitToBannerShown" units="minutes"
-    expires_after="M81">
+    expires_after="2021-01-01">
   <owner>dominickn@chromium.org</owner>
+  <owner>pjmclachlan@google.com</owner>
   <summary>
     App banners promote an application related to the current website, and are
     requested specifically through the current page's HTML. This stat tracks the
@@ -4729,8 +4733,9 @@
 </histogram>
 
 <histogram name="AppBanners.UserResponse" enum="AppBannersUserResponse"
-    expires_after="2020-06-28">
+    expires_after="2021-01-01">
   <owner>dominickn@chromium.org</owner>
+  <owner>pjmclachlan@google.com</owner>
   <summary>
     This stat tracks the user reponse when the add-to-homescreen dialog is shown
     either: (A) Via the website's JavaScript (B) Via the user tapping the app
@@ -22312,6 +22317,10 @@
 
 <histogram name="ChromeOS.CWP.CollectHeap"
     enum="ChromeOSProfileCollectionStatus" expires_after="2020-02-01">
+  <obsolete>
+    Removed 01/2020 in Issue 1036859 with the removal of the heap collection
+    code.
+  </obsolete>
   <owner>aalexand@google.com</owner>
   <owner>gmx@chromium.org</owner>
   <summary>
@@ -22364,6 +22373,10 @@
 
 <histogram name="ChromeOS.CWP.UploadHeap" units="reports"
     expires_after="2020-02-01">
+  <obsolete>
+    Removed 01/2020 in Issue 1036859 with the removal of the heap collection
+    code.
+  </obsolete>
   <owner>aalexand@google.com</owner>
   <owner>gmx@chromium.org</owner>
   <summary>
@@ -47661,6 +47674,18 @@
 </histogram>
 
 <histogram
+    name="Extensions.DeclarativeNetRequest.EvaluateBeforeRequestTime.SingleExtension"
+    units="ms" expires_after="2020-12-30">
+  <owner>karandeepb@chromium.org</owner>
+  <owner>extensions-core@chromium.org</owner>
+  <summary>
+    Time taken to evaluate the before-request action for a network request for a
+    single extension ruleset. Emitted for each network request that is visible
+    to the extension.
+  </summary>
+</histogram>
+
+<histogram
     name="Extensions.DeclarativeNetRequest.EvaluateRequestTime.AllExtensions"
     units="ms" expires_after="M80">
   <obsolete>
@@ -47793,6 +47818,10 @@
 <histogram
     name="Extensions.DeclarativeNetRequest.ShouldBlockRequestTime.SingleExtension"
     units="ms" expires_after="2020-12-30">
+  <obsolete>
+    Deprecated December 2019. Replaced with
+    Extensions.DeclarativeNetRequest.EvaluateBeforeRequestTime.SingleExtension
+  </obsolete>
   <owner>karandeepb@chromium.org</owner>
   <summary>
     Time taken to evaluate whether a network request should be blocked for a
@@ -47804,6 +47833,10 @@
 <histogram
     name="Extensions.DeclarativeNetRequest.ShouldRedirecRequestTime.SingleExtension"
     units="ms" expires_after="2020-12-30">
+  <obsolete>
+    Deprecated December 2019. Replaced with
+    Extensions.DeclarativeNetRequest.EvaluateBeforeRequestTime.SingleExtension
+  </obsolete>
   <owner>karandeepb@chromium.org</owner>
   <summary>
     Time taken to evaluate whether a network request should be redirected for a
@@ -57100,8 +57133,9 @@
 </histogram>
 
 <histogram name="Graphics.PresentationTimestamp.InvalidBeforeSwap" units="ms"
-    expires_after="2019-03-31">
+    expires_after="2021-03-01">
   <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
   <summary>
     Presentation timestamp comes from the driver when showing a display frame on
     screen. These timestamps could be invalid, and be earlier than the swap
@@ -57112,8 +57146,9 @@
 </histogram>
 
 <histogram name="Graphics.PresentationTimestamp.InvalidFromFuture" units="ms"
-    expires_after="2019-03-31">
+    expires_after="2021-03-01">
   <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
   <summary>
     Presentation timestamp comes from the driver when showing a display frame on
     screen. These timestamps can sometimes be in the future. This metric records
@@ -57123,8 +57158,9 @@
 </histogram>
 
 <histogram name="Graphics.PresentationTimestamp.LargePresentationDelta"
-    units="ms" expires_after="2020-03-01">
+    units="ms" expires_after="2021-03-01">
   <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
   <summary>
     Measures very large (more than 3 minutes) delay in presenting display
     frames. Presentation timestamp comes from the driver when showing a display
@@ -62716,8 +62752,10 @@
 </histogram>
 
 <histogram base="true" name="JSDialogs.OriginRelationship"
-    enum="DialogOriginRelationship" expires_after="M81">
+    enum="DialogOriginRelationship" expires_after="2020-07-01">
   <owner>avi@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
+  <owner>meacer@chromium.org</owner>
   <summary>
     For dialogs, the relationship of the origins of the main frame vs the
     alerting frame.
@@ -62725,8 +62763,10 @@
 </histogram>
 
 <histogram base="true" name="JSDialogs.Scheme" enum="NavigationScheme"
-    expires_after="M81">
+    expires_after="2020-07-01">
   <owner>avi@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
+  <owner>meacer@chromium.org</owner>
   <summary>The scheme of the URL showing a JavaScript dialog.</summary>
 </histogram>
 
@@ -120581,8 +120621,9 @@
 </histogram>
 
 <histogram name="Process.Sandbox.Launch.Warning" enum="WinGetLastError"
-    expires_after="M81">
+    expires_after="2021-01-02">
   <owner>forshaw@chromium.org</owner>
+  <owner>wfh@chromium.org</owner>
   <summary>
     Warnings returned while launching sandboxed process on Windows. For decoding
     error code please refer to http://goo.gl/fJJiAv. This will only be logged
@@ -120592,8 +120633,9 @@
 </histogram>
 
 <histogram name="Process.Sandbox.Launch.WarningResultCode"
-    units="LaunchErrorCodes" expires_after="M81">
+    units="LaunchErrorCodes" expires_after="2021-01-02">
   <owner>forshaw@chromium.org</owner>
+  <owner>wfh@chromium.org</owner>
   <summary>
     The warning launch error returned while launching sandboxed process on
     Windows. This will only be logged when SpawnTarget succeeds with SBOX_ALL_OK
@@ -136197,7 +136239,7 @@
 </histogram>
 
 <histogram base="true" name="Security.PageEndReason" enum="PageEndReason"
-    expires_after="M81">
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the reason the page visit ended (e.g., reload, tab closed, new
@@ -136282,7 +136324,7 @@
   </summary>
 </histogram>
 
-<histogram name="Security.PageInfo.TimeOpen" units="units">
+<histogram name="Security.PageInfo.TimeOpen" units="units" expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the amount of time the Page Info bubble is open before the user
@@ -136291,7 +136333,7 @@
 </histogram>
 
 <histogram name="Security.PageInfo.TimeOpen.Action" units="units"
-    expires_after="M81">
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the amount of time the Page Info bubble is open before the user
@@ -136299,7 +136341,8 @@
   </summary>
 </histogram>
 
-<histogram name="Security.PageInfo.TimeOpen.NoAction" units="units">
+<histogram name="Security.PageInfo.TimeOpen.NoAction" units="units"
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the amount of time the Page Info bubble is open before the user
@@ -136459,7 +136502,7 @@
 </histogram>
 
 <histogram name="Security.SecurityLevel.DownloadStarted" enum="SecurityLevel"
-    expires_after="M81">
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the security level of the page that initiated a download (rather
@@ -136471,7 +136514,8 @@
   </summary>
 </histogram>
 
-<histogram name="Security.SecurityLevel.FormSubmission" enum="SecurityLevel">
+<histogram name="Security.SecurityLevel.FormSubmission" enum="SecurityLevel"
+    expires_after="M86">
   <owner>carlosil@chromium.org</owner>
   <owner>cthomp@chromium.org</owner>
   <summary>
@@ -136502,7 +136546,7 @@
 </histogram>
 
 <histogram name="Security.SecurityLevel.OnCommit" enum="SecurityLevel"
-    expires_after="M81">
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the security level of a page at the time the navigation commits.
@@ -136513,7 +136557,7 @@
 </histogram>
 
 <histogram name="Security.SecurityLevel.OnComplete" enum="SecurityLevel"
-    expires_after="M81">
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the security level of a page at the end of the page visit (i.e.,
@@ -136525,7 +136569,7 @@
 </histogram>
 
 <histogram base="true" name="Security.SiteEngagement" units="units"
-    expires_after="M81">
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     The final Site Engagement score (0 to 100) of a URL during a visit to a
@@ -136534,7 +136578,7 @@
 </histogram>
 
 <histogram base="true" name="Security.SiteEngagementDelta" units="units"
-    expires_after="M81">
+    expires_after="M86">
   <owner>cthomp@chromium.org</owner>
   <summary>
     The change in Site Engagement score for a site between the page navigation
@@ -136564,7 +136608,7 @@
 </histogram>
 
 <histogram base="true" name="Security.TimeOnPage2" units="units"
-    expires_after="2020-02-16">
+    expires_after="2020-08-16">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the time spent on the page (the time that the page was in the
@@ -141063,7 +141107,7 @@
 </histogram>
 
 <histogram name="Sharing.ClickToCallContextMenuPhoneNumberParsingDelay"
-    units="microseconds" expires_after="M81">
+    units="microseconds" expires_after="M84">
 <!-- Name completed by histogram_suffixes name="PhoneNumberRegexVariant" -->
 
   <owner>himanshujaju@chromium.org</owner>
@@ -141072,6 +141116,10 @@
   <summary>
     Time taken to find a phone number in highlighted text for context menu.
     Desktop only.
+
+    Note: This metric drops reports on clients with low-resolution clocks, which
+    means these reports will be biased against a portion of the population on
+    Windows. See Windows.HasHighResolutionTimeTicks for the affected sample.
   </summary>
 </histogram>
 
@@ -141088,7 +141136,7 @@
 </histogram>
 
 <histogram name="Sharing.ClickToCallDialerPresent" enum="BooleanPresent"
-    expires_after="2020-02-02">
+    expires_after="M84">
   <owner>mvanouwerkerk@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <summary>
@@ -141099,7 +141147,10 @@
 </histogram>
 
 <histogram name="Sharing.ClickToCallDialIntent" enum="BooleanEmpty"
-    expires_after="2020-02-02">
+    expires_after="M81">
+  <obsolete>
+    Deprecated in M81 in favor of Sharing.ClickToCallDialerPresent
+  </obsolete>
   <owner>mvanouwerkerk@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <summary>
@@ -141120,7 +141171,10 @@
 </histogram>
 
 <histogram name="Sharing.ClickToCallHelpTextClicked" enum="SharingDialogType"
-    expires_after="2020-02-02">
+    expires_after="M81">
+  <obsolete>
+    Deprecated in M81 as there was not a lot of usage of the help link.
+  </obsolete>
   <owner>mvanouwerkerk@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <summary>
@@ -143953,7 +144007,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.DaysSinceLastShortcutLaunch"
-    units="days" expires_after="2020-06-01">
+    units="days" expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -143980,7 +144034,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.EngagementScore" units="units"
-    expires_after="2020-04-19">
+    expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144024,6 +144078,9 @@
 
 <histogram name="SiteEngagementService.EngagementScore.IsZero" enum="Boolean"
     expires_after="M81">
+  <obsolete>
+    Removed in M81.
+  </obsolete>
   <owner>charleszhao@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <owner>kcarattini@chromium.org</owner>
@@ -144035,8 +144092,9 @@
 </histogram>
 
 <histogram name="SiteEngagementService.EngagementScoreBucket" units="%"
-    expires_after="2020-04-19">
+    expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
+  <owner>dominickn@chromium.org</owner>
   <summary>
     The percentage of sites on a user's profile that have engagement scores that
     fall in these buckets, recorded at startup per non-incognito profile, and
@@ -144045,7 +144103,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.EngagementType"
-    enum="SiteEngagementServiceEngagementType" expires_after="2020-04-19">
+    enum="SiteEngagementServiceEngagementType" expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144055,7 +144113,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.MeanEngagement" units="units"
-    expires_after="M81">
+    expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144066,7 +144124,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.MedianEngagement" units="units"
-    expires_after="2020-04-19">
+    expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144077,7 +144135,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.OriginsEngaged" units="units"
-    expires_after="2020-04-19">
+    expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144088,7 +144146,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.OriginsWithMaxDailyEngagement"
-    units="units" expires_after="2020-06-01">
+    units="units" expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144101,7 +144159,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.OriginsWithMaxEngagement" units="units"
-    expires_after="2020-06-01">
+    expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144115,6 +144173,9 @@
 
 <histogram name="SiteEngagementService.PercentOriginsWithMaxEngagement"
     units="units" expires_after="2020-06-01">
+  <obsolete>
+    Removed in M81.
+  </obsolete>
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144127,6 +144188,9 @@
 
 <histogram name="SiteEngagementService.ScoreDecayedFrom"
     units="engagement score" expires_after="2020-06-01">
+  <obsolete>
+    Removed in M81.
+  </obsolete>
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144137,6 +144201,9 @@
 
 <histogram name="SiteEngagementService.ScoreDecayedTo" units="engagement score"
     expires_after="M81">
+  <obsolete>
+    Removed in M81.
+  </obsolete>
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -144146,7 +144213,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.TotalEngagement" units="units"
-    expires_after="2020-04-19">
+    expires_after="2021-01-01">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -157302,7 +157369,7 @@
   </summary>
 </histogram>
 
-<histogram name="Thumbnails.CopyFromSurfaceTime" units="ms" expires_after="M81">
+<histogram name="Thumbnails.CopyFromSurfaceTime" units="ms" expires_after="M84">
   <owner>dfried@chromium.org</owner>
   <owner>pbos@chromium.org</owner>
   <summary>
@@ -157333,7 +157400,7 @@
   </summary>
 </histogram>
 
-<histogram name="Thumbnails.ProcessBitmapTime" units="ms" expires_after="M81">
+<histogram name="Thumbnails.ProcessBitmapTime" units="ms" expires_after="M84">
   <owner>dfried@chromium.org</owner>
   <owner>pbos@chromium.org</owner>
   <summary>
@@ -165173,8 +165240,9 @@
 </histogram>
 
 <histogram name="Webapp.AddToHomescreenDialog.Timeout" units="ms"
-    expires_after="M81">
+    expires_after="2021-01-01">
   <owner>dominickn@chromium.org</owner>
+  <owner>peconn@chromium.org</owner>
   <summary>
     Records the number of milliseconds that the add to homescreen dialog
     required to check installability eligibility.
@@ -167610,6 +167678,9 @@
 </histogram>
 
 <histogram name="WebFont.DecodeSpeed" units="KB/s" expires_after="M81">
+  <obsolete>
+    Removed Jan 2020.
+  </obsolete>
   <owner>kenjibaheux@chromium.org</owner>
   <owner>ksakamoto@chromium.org</owner>
   <summary>
@@ -167917,6 +167988,9 @@
 
 <histogram name="WebFont.PackageFormat" enum="WebFontPackageFormat"
     expires_after="M81">
+  <obsolete>
+    Removed Jan 2020.
+  </obsolete>
   <owner>kenjibaheux@chromium.org</owner>
   <owner>ksakamoto@chromium.org</owner>
   <summary>
@@ -189713,6 +189787,9 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="WebFontFormat" separator=".">
+  <obsolete>
+    Removed Jan 2020.
+  </obsolete>
   <suffix name="SFNT" label="TrueType or OpenType fonts"/>
   <suffix name="WOFF" label="WOFF 1.0 fonts"/>
   <suffix name="WOFF2" label="WOFF 2.0 fonts"/>
diff --git a/tools/metrics/histograms/pretty_print.py b/tools/metrics/histograms/pretty_print.py
index 90194ab..0795961 100755
--- a/tools/metrics/histograms/pretty_print.py
+++ b/tools/metrics/histograms/pretty_print.py
@@ -101,7 +101,7 @@
       tree: The node of the xml tree.
       histograms: A list of histogram nodes inside histogram_suffixes_list
           node. This is a return element.
-      histogram_suffixes: A list of histogram_suffixes nodes inside hisotgrams
+      histogram_suffixes: A list of histogram_suffixes nodes inside histograms
           node. This is a return element.
     """
     for child in tree:
@@ -114,17 +114,17 @@
 
   ExtractMisplacedHistograms(tree)
 
-  def AddBackMisplacedHisotgrams(tree):
-    """Adds back those misplaced histogram and hsitogram_suffixes nodes."""
+  def AddBackMisplacedHistograms(tree):
+    """Adds back those misplaced histogram and histogram_suffixes nodes."""
     for child in tree:
       if child.tag == 'histograms':
         child.extend(histograms)
       elif child.tag == 'histogram_suffixes_list':
         child.extend(histogram_suffixes)
       else:
-        FixMisplacedHisotgrams(child)
+        AddBackMisplacedHistograms(child)
 
-  AddBackMisplacedHisotgrams(tree)
+  AddBackMisplacedHistograms(tree)
 
 def PrettyPrintHistograms(raw_xml):
   """Pretty-print the given histograms XML.
diff --git a/tools/metrics/histograms/pretty_print_test.py b/tools/metrics/histograms/pretty_print_test.py
index 7936363..3ec98db9 100755
--- a/tools/metrics/histograms/pretty_print_test.py
+++ b/tools/metrics/histograms/pretty_print_test.py
@@ -12,6 +12,7 @@
 <!-- Top level Comment 1 -->
 <!-- Top level Comment 2 -->
 <histogram-configuration>
+<!-- Second level Comment 1 -->
 <histograms>
  <histogram name="Test.Histogram" units="us">
    <owner>person@chromium.org</owner>
@@ -63,6 +64,8 @@
 
 <histogram-configuration>
 
+<!-- Second level Comment 1 -->
+
 <histograms>
 
 <histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz">
diff --git a/tools/perf/benchmark_schedules.csv b/tools/perf/benchmark_schedules.csv
index 99af6d52..0f01c09 100644
--- a/tools/perf/benchmark_schedules.csv
+++ b/tools/perf/benchmark_schedules.csv
@@ -29,7 +29,6 @@
 speedometer2-future,0.66,12,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.dom,0.64,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 dromaeo,0.57,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
-angle_perftests,0.55,1,0,android-pixel2-perf,
 blink_perf.svg,0.54,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 blink_perf.events,0.53,13,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, Win 7 Perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
 speedometer2,0.48,14,0,"Android Nexus5 Perf, Android Nexus5X WebView Perf, Android Nexus6 WebView Perf, Win 7 Nvidia GPU Perf, android-go-perf, android-go_webview-perf, android-nexus5x-perf, android-pixel2-perf, android-pixel2_webview-perf, linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index 62d2f7a..390d027 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -304,7 +304,8 @@
 _ANDROID_NEXUS_6_WEBVIEW_BENCHMARK_CONFIGS = (
     _OFFICIAL_EXCEPT_DISPLAY_LOCKING_JETSTREAM2)
 _ANDROID_PIXEL2_BENCHMARK_CONFIGS = _OFFICIAL_EXCEPT_DISPLAY_LOCKING
-_ANDROID_PIXEL2_EXECUTABLE_CONFIGS = frozenset([_ANGLE_PERFTESTS])
+_ANDROID_PIXEL2_EXECUTABLE_CONFIGS = frozenset([
+    _COMPONENTS_PERFTESTS, _MEDIA_PERFTESTS])
 _ANDROID_PIXEL2_WEBVIEW_BENCHMARK_CONFIGS = (
     _OFFICIAL_EXCEPT_DISPLAY_LOCKING_JETSTREAM2)
 _ANDROID_PIXEL2_WEBLAYER_BENCHMARK_CONFIGS = PerfSuite([
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 0ba9c5f..311b417 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -759,6 +759,11 @@
           '--assert-gpu-compositing',
         ],
       },
+      {
+        'isolate': 'dawn_perf_tests',
+        'num_shards': 1,
+        'type': TEST_TYPES.GTEST,
+      },
     ],
     'platform': 'mac',
     'dimension': {
diff --git a/tools/perf/core/shard_maps/android-pixel2-perf_map.json b/tools/perf/core/shard_maps/android-pixel2-perf_map.json
index e3221edb..f082ace 100644
--- a/tools/perf/core/shard_maps/android-pixel2-perf_map.json
+++ b/tools/perf/core/shard_maps/android-pixel2-perf_map.json
@@ -1,12 +1,11 @@
 {
     "0": {
         "executables": {
-            "angle_perftests": {
-                "path": "angle_perftests",
-                "arguments": [
-                    "--test-launcher-retry-limit=0",
-                    "--test-launcher-jobs=1"
-                ]
+            "media_perftests": {
+                "path": "media_perftests"
+            },
+            "components_perftests": {
+                "path": "components_perftests"
             }
         }
     },
diff --git a/tools/perf/core/shard_maps/timing_data/android-pixel2-perf_timing.json b/tools/perf/core/shard_maps/timing_data/android-pixel2-perf_timing.json
index d91106e..66e3374 100644
--- a/tools/perf/core/shard_maps/timing_data/android-pixel2-perf_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/android-pixel2-perf_timing.json
@@ -4914,9 +4914,5 @@
     {
         "duration": "39.0",
         "name": "webrtc/pause_play_peerconnections"
-    },
-    {
-        "duration": "1988.0",
-        "name": "angle_perftests/_gtest_"
     }
 ]
\ No newline at end of file
diff --git a/tools/perf/cycletime_contributions.csv b/tools/perf/cycletime_contributions.csv
index ae2f94f..9a5038b6 100644
--- a/tools/perf/cycletime_contributions.csv
+++ b/tools/perf/cycletime_contributions.csv
@@ -2,8 +2,7 @@
 View a prettier version of this at,https://docs.google.com/spreadsheets/d/15pJY4cxtM2NVNFKQDgDnoT5PLo0Nm5Td-Ov-5PZefAw
 platform,Android Nexus5 Perf,Android Nexus5X WebView Perf,Android Nexus6 WebView Perf,Win 7 Nvidia GPU Perf,Win 7 Perf,android-go-perf,android-go_webview-perf,android-nexus5x-perf,android-pixel2-perf,android-pixel2_weblayer-perf,android-pixel2_webview-perf,linux-perf,mac-10_12_laptop_low_end-perf,mac-10_13_laptop_high_end-perf,win-10-perf,win-10_laptop_low_end-perf
 shards,16,16,12,4,4,19,13,10,35,4,21,26,26,26,26,26
-idealized cycle time (hours),2.24,0.56,0.76,3.17,2.43,0.70,0.26,1.37,0.60,0.15,0.34,0.39,0.43,0.33,0.50,0.70
-angle_perftests,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.032,0.000,0.000,0.000,0.000,0.000,0.000,0.000
+idealized cycle time (hours),2.24,0.56,0.76,3.17,2.43,0.70,0.26,1.37,0.56,0.15,0.34,0.39,0.43,0.33,0.50,0.70
 blink_perf.accessibility,0.003,0.001,0.001,0.005,0.006,0.000,0.000,0.003,0.001,0.000,0.001,0.001,0.001,0.001,0.001,0.001
 blink_perf.bindings,0.052,0.014,0.029,0.052,0.061,0.000,0.000,0.050,0.013,0.000,0.009,0.006,0.009,0.007,0.008,0.011
 blink_perf.canvas,0.036,0.000,0.012,0.067,0.020,0.000,0.000,0.000,0.010,0.000,0.005,0.006,0.010,0.008,0.008,0.010
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index ac363f5..2857a2b 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -11,11 +11,7 @@
 # results: [ Skip ]
 # conflicts_allowed: True
 
-# Benchmark: blink_perf.accessibility
-crbug.com/1036846 [ highsierra ] blink_perf.accessibility/* [ Skip ]
-
 # Benchmark: blink_perf.bindings
-crbug.com/1036846 [ highsierra ] blink_perf.bindings/* [ Skip ]
 crbug.com/882881 [ android-nexus-5 ] blink_perf.bindings/structured-clone-json-deserialize.html [ Skip ]
 crbug.com/910207 [ android-nexus-5x ] blink_perf.bindings/structured-clone-json-deserialize.html [ Skip ]
 crbug.com/882881 [ android-nexus-5 ] blink_perf.bindings/structured-clone-json-serialize.html [ Skip ]
diff --git a/tools/perf/process_perf_results.py b/tools/perf/process_perf_results.py
index be058aa8..bdd026b 100755
--- a/tools/perf/process_perf_results.py
+++ b/tools/perf/process_perf_results.py
@@ -17,6 +17,11 @@
 import time
 import uuid
 
+logging.basicConfig(
+    level=logging.INFO,
+    format='(%(levelname)s) %(asctime)s pid=%(process)d'
+           '  %(module)s.%(funcName)s:%(lineno)d  %(message)s')
+
 from core import path_util
 from core import upload_results_to_perf_dashboard
 from core import results_merger
@@ -172,7 +177,8 @@
             # Output is null meaning the test didn't produce any results.
             # Want to output an error and continue loading the rest of the
             # test results.
-            print('No results produced for %s, skipping upload' % directory)
+            logging.warning(
+                'No results produced for %s, skipping upload' % directory)
             continue
           if json_results.get('version') == 3:
             # Non-telemetry tests don't have written json results but
@@ -193,7 +199,7 @@
       if not enabled:
         # We don't upload disabled benchmarks or tests that are run
         # as a smoke test
-        print(
+        logging.info(
             'Benchmark %s ran no tests on at least one shard' % benchmark_name)
         continue
       benchmark_enabled_map[benchmark_name] = True
@@ -410,7 +416,7 @@
       results_filename = os.path.join(directories[0], 'perf_results.json')
 
     results_size_in_mib = os.path.getsize(results_filename) / (2 ** 20)
-    print('Uploading perf results from %s benchmark (size %s Mib)' %
+    logging.info('Uploading perf results from %s benchmark (size %s Mib)' %
           (benchmark_name, results_size_in_mib))
     with open(output_json_file, 'w') as oj:
       upload_return_code = _upload_perf_results(
@@ -487,13 +493,15 @@
   # the problem is fixed on the dashboard side.
   # pool = multiprocessing.Pool(_GetCpuCount())
   pool = multiprocessing.Pool(2)
+  upload_result_timeout = False
   try:
     async_result = pool.map_async(
         _upload_individual_benchmark, invocations)
     # TODO(crbug.com/947035): What timeout is reasonable?
     results = async_result.get(timeout=4000)
   except multiprocessing.TimeoutError:
-    logging.error('Failed uploading benchmarks to perf dashboard in parallel')
+    upload_result_timeout = True
+    logging.error('Timeout uploading benchmarks to perf dashboard in parallel')
     results = []
     for benchmark_name in benchmark_directory_map:
       results.append((benchmark_name, False))
@@ -530,7 +538,7 @@
   extra_links[logdog_label] = logdog_stream
   end_time = time.time()
   print_duration('Uploading results to perf dashboard', begin_time, end_time)
-  if upload_failures_counter > 0:
+  if upload_result_timeout or upload_failures_counter > 0:
     return 1, benchmark_upload_result_map
   return 0, benchmark_upload_result_map
 
@@ -546,7 +554,7 @@
       try:
         results = json.load(f)
       except ValueError:
-        print('Error parsing perf results JSON for benchmark  %s' %
+        logging.error('Error parsing perf results JSON for benchmark  %s' %
               benchmark_name)
     if results:
       try:
@@ -554,12 +562,12 @@
         json.dump(results, output_json_file,
                   indent=4, separators=(',', ': '))
       except ValueError as e:
-        print('ValueError: "%s" while dumping output to logdog' % e)
+        logging.error('ValueError: "%s" while dumping output to logdog' % e)
       finally:
         output_json_file.close()
       viewer_url = output_json_file.get_viewer_url()
   else:
-    print("Perf results JSON file doesn't exist for benchmark %s" %
+    logging.warning("Perf results JSON file doesn't exist for benchmark %s" %
           benchmark_name)
 
   base_benchmark_name = benchmark_name.replace('.reference', '')
@@ -588,12 +596,12 @@
 
 
 def print_duration(step, start, end):
-  print('Duration of %s: %d seconds' % (step, end - start))
+  logging.info('Duration of %s: %d seconds' % (step, end - start))
 
 
 def main():
   """ See collect_task.collect_task for more on the merge script API. """
-  print(sys.argv)
+  logging.info(sys.argv)
   parser = argparse.ArgumentParser()
   # configuration-name (previously perf-id) is the name of bot the tests run on
   # For example, buildbot-test is the name of the android-go-perf bot
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc
index ba2bafa..d620303 100644
--- a/ui/accessibility/ax_node.cc
+++ b/ui/accessibility/ax_node.cc
@@ -925,4 +925,8 @@
   return false;
 }
 
+bool AXNode::IsTextOnlyObject() const {
+  return IsText();
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h
index 05d2b4b..0e69a89 100644
--- a/ui/accessibility/ax_node.h
+++ b/ui/accessibility/ax_node.h
@@ -380,6 +380,10 @@
   // of a list marker node. Returns false otherwise.
   bool IsInListMarker() const;
 
+  // Returns true if this object is used only for representing text, including
+  // inline text boxes.
+  bool IsTextOnlyObject() const;
+
  private:
   // Computes the text offset where each line starts by traversing all child
   // leaf nodes.
diff --git a/ui/accessibility/ax_node_position.cc b/ui/accessibility/ax_node_position.cc
index 0a34728..2ed49cd8 100644
--- a/ui/accessibility/ax_node_position.cc
+++ b/ui/accessibility/ax_node_position.cc
@@ -5,12 +5,20 @@
 #include "ui/accessibility/ax_node_position.h"
 
 #include "base/strings/string_util.h"
+#include "build/build_config.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_tree_manager_map.h"
 
 namespace ui {
 
+AXEmbeddedObjectBehavior g_ax_embedded_object_behavior =
+#if defined(OS_WIN)
+    AXEmbeddedObjectBehavior::kExposeCharacter;
+#else
+    AXEmbeddedObjectBehavior::kSuppressCharacter;
+#endif
+
 AXTree* AXNodePosition::tree_ = nullptr;
 
 // static
@@ -149,19 +157,24 @@
   if (IsNullPosition())
     return {};
 
+  base::string16 text;
+  if (IsEmptyObjectReplacedByCharacter()) {
+    text += kEmbeddedCharacter;
+    return text;
+  }
+
   const AXNode* anchor = GetAnchor();
   DCHECK(anchor);
-  base::string16 value = GetAnchor()->data().GetString16Attribute(
+  text = GetAnchor()->data().GetString16Attribute(
       ax::mojom::StringAttribute::kValue);
-  if (!value.empty())
-    return value;
+  if (!text.empty())
+    return text;
 
   if (anchor->IsText()) {
     return anchor->data().GetString16Attribute(
         ax::mojom::StringAttribute::kName);
   }
 
-  base::string16 text;
   for (int i = 0; i < AnchorChildCount(); ++i)
     text += CreateChildPositionAt(i)->GetText();
 
@@ -199,6 +212,9 @@
   if (IsNullPosition())
     return INVALID_OFFSET;
 
+  if (IsEmptyObjectReplacedByCharacter())
+    return 1;
+
   const AXNode* anchor = GetAnchor();
   DCHECK(anchor);
   base::string16 value = GetAnchor()->data().GetString16Attribute(
@@ -252,6 +268,12 @@
   if (IsNullPosition())
     return std::vector<int32_t>();
   DCHECK(GetAnchor());
+
+  // Embedded object replacement characters are not represented in |kWordStarts|
+  // attribute.
+  if (IsEmptyObjectReplacedByCharacter())
+    return {0};
+
   return GetAnchor()->data().GetIntListAttribute(
       ax::mojom::IntListAttribute::kWordStarts);
 }
@@ -260,6 +282,16 @@
   if (IsNullPosition())
     return std::vector<int32_t>();
   DCHECK(GetAnchor());
+
+  // Embedded object replacement characters are not represented in |kWordEnds|
+  // attribute. Since the whole text exposed inside of an embedded object is of
+  // length 1 (the embedded object replacement character), the word end offset
+  // is positioned at 1. Because we want to treat the embedded object
+  // replacement characters as ordinary characters, it wouldn't be consistent to
+  // assume they have no length and return 0 instead of 1.
+  if (IsEmptyObjectReplacedByCharacter())
+    return {1};
+
   return GetAnchor()->data().GetIntListAttribute(
       ax::mojom::IntListAttribute::kWordEnds);
 }
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc
index ea49b09e..fd34c77 100644
--- a/ui/accessibility/ax_node_position_unittest.cc
+++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -372,6 +372,9 @@
 const char* AXPositionTest::TEXT_VALUE = "Line 1\nLine 2";
 
 void AXPositionTest::SetUp() {
+  // Most tests use kSuppressCharacter behavior.
+  g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kSuppressCharacter;
+
   // root_
   //  |
   //  +------------+-----------+
@@ -6164,6 +6167,199 @@
   ASSERT_EQ(0, text_position->text_offset());
 }
 
+TEST_F(AXPositionTest, EmbeddedObjectReplacementCharacterTextNavigation) {
+  g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+
+  // ++1 kRootWebArea
+  // ++++2 kStaticText
+  // ++++++3 kInlineTextBox
+  // ++++4 kTextField
+  // ++++++5 kGenericContainer
+  // ++++6 kStaticText
+  // ++++++7 kInlineTextBox
+  AXNodeData root;
+  AXNodeData static_text1;
+  AXNodeData inline_box1;
+  AXNodeData text_field;
+  AXNodeData generic_container;
+  AXNodeData static_text2;
+  AXNodeData inline_box2;
+
+  root.id = 1;
+  static_text1.id = 2;
+  inline_box1.id = 3;
+  text_field.id = 4;
+  generic_container.id = 5;
+  static_text2.id = 6;
+  inline_box2.id = 7;
+
+  root.role = ax::mojom::Role::kRootWebArea;
+  root.child_ids = {static_text1.id, text_field.id, static_text2.id};
+
+  static_text1.role = ax::mojom::Role::kStaticText;
+  static_text1.SetName("Hello ");
+  static_text1.child_ids = {inline_box1.id};
+
+  inline_box1.role = ax::mojom::Role::kInlineTextBox;
+  inline_box1.SetName("Hello ");
+  inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
+                                  std::vector<int32_t>{0});
+  inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
+                                  std::vector<int32_t>{6});
+
+  text_field.role = ax::mojom::Role::kTextField;
+  text_field.child_ids = {generic_container.id};
+
+  generic_container.role = ax::mojom::Role::kGenericContainer;
+
+  static_text2.role = ax::mojom::Role::kStaticText;
+  static_text2.SetName(" world");
+  static_text2.child_ids = {inline_box2.id};
+
+  inline_box2.role = ax::mojom::Role::kInlineTextBox;
+  inline_box2.SetName(" world");
+  inline_box2.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
+                                  std::vector<int32_t>{1});
+  inline_box2.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
+                                  std::vector<int32_t>{6});
+
+  std::unique_ptr<AXTree> new_tree =
+      CreateAXTree({root, static_text1, inline_box1, text_field,
+                    generic_container, static_text2, inline_box2});
+
+  AXNodePosition::SetTree(new_tree.get());
+
+  // CreateStartWordStartPosition tests.
+  TestPositionType position = AXNodePosition::CreateTextPosition(
+      new_tree->data().tree_id, inline_box1.id,
+      0 /* child_index_or_text_offset */, ax::mojom::TextAffinity::kDownstream);
+
+  TestPositionType result_position =
+      position->CreateNextWordStartPosition(AXBoundaryBehavior::CrossBoundary);
+  std::string expectations =
+      "TextPosition anchor_id=5 text_offset=0 affinity=downstream "
+      "annotated_text=<\xEF\xBF\xBC>";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  position = std::move(result_position);
+  result_position =
+      position->CreateNextWordStartPosition(AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=7 text_offset=1 affinity=downstream "
+      "annotated_text= <w>orld";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  // CreatePreviousWordStartPosition tests.
+  position = std::move(result_position);
+  result_position = position->CreatePreviousWordStartPosition(
+      AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=5 text_offset=0 affinity=downstream "
+      "annotated_text=<\xEF\xBF\xBC>";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  position = std::move(result_position);
+  result_position = position->CreatePreviousWordStartPosition(
+      AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=3 text_offset=0 affinity=downstream "
+      "annotated_text=<H>ello ";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  // CreateNextWordEndPosition tests.
+  position = std::move(result_position);
+  result_position =
+      position->CreateNextWordEndPosition(AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=3 text_offset=6 affinity=downstream "
+      "annotated_text=Hello <>";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  position = std::move(result_position);
+  result_position =
+      position->CreateNextWordEndPosition(AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=5 text_offset=1 affinity=downstream "
+      "annotated_text=\xEF\xBF\xBC<>";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  position = std::move(result_position);
+  result_position =
+      position->CreateNextWordEndPosition(AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=7 text_offset=6 affinity=downstream "
+      "annotated_text= world<>";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  // CreatePreviousWordEndPosition tests.
+  position = std::move(result_position);
+  result_position = position->CreatePreviousWordEndPosition(
+      AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=5 text_offset=1 affinity=downstream "
+      "annotated_text=\xEF\xBF\xBC<>";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  position = std::move(result_position);
+  result_position = position->CreatePreviousWordEndPosition(
+      AXBoundaryBehavior::CrossBoundary);
+  expectations =
+      "TextPosition anchor_id=3 text_offset=6 affinity=downstream "
+      "annotated_text=Hello <>";
+  ASSERT_EQ(result_position->ToString(), expectations);
+
+  // GetText() with embedded object replacement character test.
+  position = AXNodePosition::CreateTextPosition(
+      new_tree->data().tree_id, generic_container.id, 0 /* text_offset */,
+      ax::mojom::TextAffinity::kDownstream);
+
+  base::string16 expected_text;
+  expected_text += AXNodePosition::kEmbeddedCharacter;
+  ASSERT_EQ(expected_text, position->GetText());
+
+  // GetText() on a node parent of text nodes and an embedded object replacement
+  // character.
+  position = AXNodePosition::CreateTextPosition(
+      new_tree->data().tree_id, root.id, 0 /* text_offset */,
+      ax::mojom::TextAffinity::kDownstream);
+
+  expected_text = base::WideToUTF16(L"Hello ") +
+                  AXNodePosition::kEmbeddedCharacter +
+                  base::WideToUTF16(L" world");
+  ASSERT_EQ(expected_text, position->GetText());
+
+  // MaxTextOffset() with an embedded object replacement character.
+  position = AXNodePosition::CreateTextPosition(
+      new_tree->data().tree_id, generic_container.id, 0 /* text_offset */,
+      ax::mojom::TextAffinity::kDownstream);
+
+  ASSERT_EQ(1, position->MaxTextOffset());
+
+  // Parent positions created from a position inside a node represented by an
+  // embedded object replacement character.
+  position = position->CreateParentPosition();
+  expectations =
+      "TextPosition anchor_id=4 text_offset=0 affinity=downstream "
+      "annotated_text=<\xEF\xBF\xBC>";
+  ASSERT_EQ(position->ToString(), expectations);
+  ASSERT_EQ(1, position->MaxTextOffset());
+
+  position = position->CreateParentPosition();
+  expectations =
+      "TextPosition anchor_id=1 text_offset=6 affinity=downstream "
+      "annotated_text=Hello <\xEF\xBF\xBC> world";
+  ASSERT_EQ(position->ToString(), expectations);
+  ASSERT_EQ(13, position->MaxTextOffset());
+
+  // MaxTextOffset() on a node parent of text nodes and an embedded object
+  // replacement character.
+  position = AXNodePosition::CreateTextPosition(
+      new_tree->data().tree_id, root.id, 0 /* text_offset */,
+      ax::mojom::TextAffinity::kDownstream);
+
+  ASSERT_EQ(13, position->MaxTextOffset());
+}
+
 //
 // Parameterized tests.
 //
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h
index ed525a2..122a4f3 100644
--- a/ui/accessibility/ax_position.h
+++ b/ui/accessibility/ax_position.h
@@ -90,6 +90,26 @@
   kRightFirst
 };
 
+// Some platforms require empty objects to be represented by a replacement
+// character in order for text navigation to work correctly. This enum controls
+// whether a replacement character will be exposed for such objects.
+//
+// When an embedded object is replaced by a real character, the expectations
+// are the same with this character as with other ordinary characters.
+// For example, with UIA on Windows, we need to be able to navigate inside and
+// outside of this character as if it was an ordinary character, using the
+// AXPlatformNodeTextRangeProvider methods. Since an embedded object character
+// is the only character in a node, we also treat this character as a word.
+enum class AXEmbeddedObjectBehavior {
+  kExposeCharacter,
+  kSuppressCharacter,
+};
+
+// Controls whether embedded objects are represented by a replacement
+// character. This is initialized to a per-platform default but can be
+// overridden for testing.
+AX_EXPORT extern AXEmbeddedObjectBehavior g_ax_embedded_object_behavior;
+
 // Forward declarations.
 template <class AXPositionType, class AXNodeType>
 class AXPosition;
@@ -149,6 +169,13 @@
   static const int INVALID_INDEX = -2;
   static const int INVALID_OFFSET = -1;
 
+  // Replacement character used to represent an empty object. See
+  // AXEmbeddedObjectBehavior for more information.
+  //
+  // Duplicate of AXPlatformNodeBase::kEmbeddedCharacter because we don't want
+  // to include platform specific code in here.
+  static constexpr base::char16 kEmbeddedCharacter = L'\xfffc';
+
   static AXPositionInstance CreateNullPosition() {
     AXPositionInstance new_position(new AXPositionType());
     new_position->Initialize(
@@ -269,9 +296,10 @@
 
     base::string16 text = GetText();
     DCHECK_GE(text_offset_, 0);
-    DCHECK_LE(text_offset_, int{text.length()});
+    int max_text_offset = MaxTextOffset();
+    DCHECK_LE(text_offset_, max_text_offset);
     base::string16 annotated_text;
-    if (text_offset_ == MaxTextOffset()) {
+    if (text_offset_ == max_text_offset) {
       annotated_text = text + base::WideToUTF16(L"<>");
     } else {
       annotated_text = text.substr(0, text_offset_) + base::WideToUTF16(L"<") +
@@ -2592,6 +2620,22 @@
                                other_tree_position_ancestor->child_index());
   }
 
+  // Returns true if this position is on an empty object node that needs to
+  // be represented by an empty object replacement character. It does when
+  // the node has no child, is not a text object and we are on a platform that
+  // enables this feature.
+  bool IsEmptyObjectReplacedByCharacter() const {
+    if (g_ax_embedded_object_behavior ==
+            AXEmbeddedObjectBehavior::kSuppressCharacter ||
+        AnchorChildCount()) {
+      return false;
+    }
+    // All unignored leaf nodes in the AXTree except the document and the text
+    // nodes should be replaced by the embedded object character.
+    return !IsIgnored() && !IsDocument(GetRole()) &&
+           !GetAnchor()->IsTextOnlyObject();
+  }
+
   void swap(AXPosition& other) {
     std::swap(kind_, other.kind_);
     std::swap(tree_id_, other.tree_id_);
@@ -2608,8 +2652,8 @@
 
   // Returns the text that is present inside the anchor node, including any text
   // found in descendant text nodes, based on the platform's text
-  // representation. Some platforms use an embedded object character that
-  // replaces the text coming from each child node.
+  // representation. Some platforms use an embedded object replacement character
+  // that replaces the text coming from each child node.
   virtual base::string16 GetText() const = 0;
 
   // Determines if the anchor containing this position is a <br> or a text
diff --git a/ui/accessibility/ax_range_unittest.cc b/ui/accessibility/ax_range_unittest.cc
index a0091fc4..d035dd9 100644
--- a/ui/accessibility/ax_range_unittest.cc
+++ b/ui/accessibility/ax_range_unittest.cc
@@ -142,6 +142,9 @@
 };
 
 void AXRangeTest::SetUp() {
+  // Most tests use kSuppressCharacter behavior.
+  g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kSuppressCharacter;
+
   root_.id = ROOT_ID;
   div1_.id = DIV1_ID;
   div2_.id = DIV2_ID;
diff --git a/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc
index f94f8797..e27e41a 100644
--- a/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc
@@ -25,6 +25,10 @@
   // nontext_child_of_root______                          text_child_of_root
   // |                          |                         |
   // nontext_child_of_nontext   text_child_of_nontext     text_child_of_text
+  //
+  // nontext leaf elements are considered as embedded objects and expose a
+  // character to allow the text pattern navigation to work with them too.
+  // Because of that, a nontext leaf element is treated as a text element.
   void SetUp() override {
     ui::AXNodeData root;
     root.id = 1;
@@ -273,7 +277,9 @@
   EXPECT_HRESULT_SUCCEEDED(
       text_range_provider->GetText(-1, text_content.Receive()));
   EXPECT_EQ(
-      0, wcscmp(static_cast<BSTR>(text_content), L"\ntext child of nontext."));
+      0,
+      wcscmp(static_cast<BSTR>(text_content),
+             (kEmbeddedCharacterAsString + L"text child of nontext.").c_str()));
 
   ComPtr<IRawElementProviderSimple> enclosing_element;
   text_range_provider->GetEnclosingElement(&enclosing_element);
@@ -310,7 +316,8 @@
   base::win::ScopedBstr text_content;
   EXPECT_HRESULT_SUCCEEDED(
       text_range_provider->GetText(-1, text_content.Receive()));
-  EXPECT_EQ(0, wcscmp(static_cast<BSTR>(text_content), L""));
+  EXPECT_EQ(0, wcscmp(static_cast<BSTR>(text_content),
+                      kEmbeddedCharacterAsString.c_str()));
 
   ComPtr<IRawElementProviderSimple> enclosing_element;
   text_range_provider->GetEnclosingElement(&enclosing_element);
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc
index b20d062..775e3f61 100644
--- a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc
@@ -261,8 +261,11 @@
   EXPECT_HRESULT_SUCCEEDED(
       text_range_provider->GetText(-1, text_content.Receive()));
   EXPECT_EQ(0, wcscmp(static_cast<BSTR>(text_content),
-                      L"Dialog label.Dialog description.ok.Some more detail "
-                      L"about dialog."));
+                      (L"Dialog label.Dialog description." +
+                       kEmbeddedCharacterAsString +
+                       "ok.Some more detail "
+                       L"about dialog.")
+                          .c_str()));
 
   // Check the reverse relationship that GetEnclosingElement on the text range
   // gives back the dialog.
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
index 102936d..5944dedc 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -169,6 +169,13 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_EXPANDTOENCLOSINGUNIT);
   UIA_VALIDATE_TEXTRANGEPROVIDER_CALL();
 
+  // Normalize the start position so that we do not incorrectly expand it
+  // backwards if it happens to be sitting at the end of a node.
+  AXPositionInstance normalized_start =
+      start_->AsLeafTextPositionBeforeCharacter();
+  if (!normalized_start->IsNullPosition())
+    start_ = std::move(normalized_start);
+
   // Determine if start is on a boundary of the specified TextUnit, if it is
   // not, move backwards until it is. Move the end forwards from start until it
   // is on the next TextUnit boundary, if one exists.
@@ -771,12 +778,14 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_SELECT);
   UIA_VALIDATE_TEXTRANGEPROVIDER_CALL();
 
-  AXNodeRange range(start_->Clone(), end_->Clone());
+  AXNodeRange new_selection_range(start_->Clone(), end_->Clone());
+  RemoveFocusFromPreviousSelectionIfNeeded(new_selection_range);
+
   AXActionData action_data;
-  action_data.anchor_node_id = range.anchor()->anchor_id();
-  action_data.anchor_offset = range.anchor()->text_offset();
-  action_data.focus_node_id = range.focus()->anchor_id();
-  action_data.focus_offset = range.focus()->text_offset();
+  action_data.anchor_node_id = new_selection_range.anchor()->anchor_id();
+  action_data.anchor_offset = new_selection_range.anchor()->text_offset();
+  action_data.focus_node_id = new_selection_range.focus()->anchor_id();
+  action_data.focus_offset = new_selection_range.focus()->text_offset();
   action_data.action = ax::mojom::Action::kSetSelection;
   owner()->GetDelegate()->AccessibilityPerformAction(action_data);
   return S_OK;
@@ -810,16 +819,9 @@
   DCHECK(common_ancestor_anchor == end_common_ancestor->GetAnchor());
 
   const AXTreeID common_ancestor_tree_id = start_common_ancestor->tree_id();
-  const AXTreeManager* ax_tree_manager =
-      AXTreeManagerMap::GetInstance().GetManager(common_ancestor_tree_id);
-  DCHECK(ax_tree_manager);
-  AXNode* root_node = ax_tree_manager->GetRootAsAXNode();
-  const AXPlatformNode* root_platform_node =
-      owner_->GetDelegate()->GetFromTreeIDAndNodeID(common_ancestor_tree_id,
-                                                    root_node->id());
-  DCHECK(root_platform_node);
   const AXPlatformNodeDelegate* root_delegate =
-      root_platform_node->GetDelegate();
+      GetRootDelegate(common_ancestor_tree_id);
+  DCHECK(root_delegate);
   const gfx::Rect root_frame_bounds = root_delegate->GetBoundsRect(
       AXCoordinateSystem::kFrame, AXClippingBehavior::kUnclipped);
   UIA_VALIDATE_BOUNDS(root_frame_bounds);
@@ -1185,4 +1187,69 @@
   DCHECK_LE(*start_, *end_);
 }
 
+AXPlatformNodeDelegate* AXPlatformNodeTextRangeProviderWin::GetRootDelegate(
+    const ui::AXTreeID tree_id) {
+  const AXTreeManager* ax_tree_manager =
+      AXTreeManagerMap::GetInstance().GetManager(tree_id);
+  DCHECK(ax_tree_manager);
+  AXNode* root_node = ax_tree_manager->GetRootAsAXNode();
+  const AXPlatformNode* root_platform_node =
+      owner_->GetDelegate()->GetFromTreeIDAndNodeID(tree_id, root_node->id());
+  DCHECK(root_platform_node);
+  return root_platform_node->GetDelegate();
+}
+
+AXNode* AXPlatformNodeTextRangeProviderWin::GetSelectionCommonAnchor() {
+  AXPlatformNodeDelegate* delegate = owner()->GetDelegate();
+  ui::AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();
+  AXPlatformNode* anchor_object =
+      delegate->GetFromNodeID(unignored_selection.anchor_object_id);
+  AXPlatformNode* focus_object =
+      delegate->GetFromNodeID(unignored_selection.focus_object_id);
+
+  if (!anchor_object || !focus_object)
+    return nullptr;
+
+  AXNodePosition::AXPositionInstance start =
+      anchor_object->GetDelegate()->CreateTextPositionAt(
+          unignored_selection.anchor_offset);
+  AXNodePosition::AXPositionInstance end =
+      focus_object->GetDelegate()->CreateTextPositionAt(
+          unignored_selection.focus_offset);
+
+  return start->LowestCommonAnchor(*end);
+}
+
+// When the current selection is inside a focusable element, the DOM focused
+// element will correspond to this element. When we update the selection to be
+// on a different element that is not focusable, the new selection won't be
+// applied unless we remove the DOM focused element. For example, with Narrator,
+// if we move by word from a text field (focusable) to a static text
+// (not focusable), the selection we stay on the textfield because the DOM
+// focused element will still be the textfield. To avoid that, we need to remove
+// the focus from this element.
+// Since |ax::mojom::Action::kBlur| is not implemented, we perform a
+// |ax::mojom::Action::focus| action on the root node. The result is the same.
+void AXPlatformNodeTextRangeProviderWin::
+    RemoveFocusFromPreviousSelectionIfNeeded(const AXNodeRange& new_selection) {
+  const AXNode* old_selection_node = GetSelectionCommonAnchor();
+  const AXNode* new_selection_node =
+      new_selection.anchor()->LowestCommonAnchor(*new_selection.focus());
+
+  if (!old_selection_node)
+    return;
+
+  if (!new_selection_node ||
+      (old_selection_node->data().HasState(ax::mojom::State::kFocusable) &&
+       !new_selection_node->data().HasState(ax::mojom::State::kFocusable))) {
+    AXPlatformNodeDelegate* root_delegate =
+        GetRootDelegate(old_selection_node->tree()->GetAXTreeID());
+    DCHECK(root_delegate);
+
+    AXActionData focus_action;
+    focus_action.action = ax::mojom::Action::kFocus;
+    root_delegate->AccessibilityPerformAction(focus_action);
+  }
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
index 549a4179..432a74df 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
@@ -148,6 +148,10 @@
 
   void NormalizeAsUnignoredTextRange();
   void NormalizeTextRange();
+  AXPlatformNodeDelegate* GetRootDelegate(const ui::AXTreeID tree_id);
+  AXNode* GetSelectionCommonAnchor();
+  void RemoveFocusFromPreviousSelectionIfNeeded(
+      const AXNodeRange& new_selection);
 
   Microsoft::WRL::ComPtr<AXPlatformNodeWin> owner_;
   AXPositionInstance start_;
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
index f3276a2..75c6427 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -568,6 +568,16 @@
   }
 
   ui::AXTreeUpdate BuildAXTreeForMoveByFormat() {
+    //                    1
+    //                    |
+    //    -------------------------------------
+    //    |       |       |    |    |    |    |
+    //    2       4       8   10   12   14   16
+    //    |       |       |    |    |    |    |
+    //    |   ---------   |    |    |    |    |
+    //    |   |   |   |   |    |    |    |    |
+    //    3   5   6   7   9   11   13   15   17
+
     ui::AXNodeData group1_data;
     group1_data.id = 2;
     group1_data.role = ax::mojom::Role::kGenericContainer;
@@ -1212,7 +1222,6 @@
   Init(BuildAXTreeForMoveByFormat());
   AXNodePosition::SetTree(tree_.get());
   AXNode* root_node = GetRootNode();
-
   ComPtr<ITextRangeProvider> text_range_provider;
   GetTextRangeProviderFromTextNode(text_range_provider, root_node);
 
@@ -1221,54 +1230,190 @@
       L"Text with formattingStandalone line with no formattingbold "
       L"textParagraph 1Paragraph 2Paragraph 3Paragraph 4");
 
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"Text with formatting");
+  // https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nf-uiautomationclient-iuiautomationtextrange-expandtoenclosingunit
+  // Consider two consecutive text units A and B.
+  // The documentation illustrates 9 cases, but cases 1 and 9 are equivalent.
+  // In each case, the expected output is a range from start of A to end of A.
 
-  // Set it up so that the text range is in the middle of a format boundary
-  // and expand by format.
+  // Create a range encompassing nodes 11-15 which will serve as text units A
+  // and B for this test.
+  ComPtr<ITextRangeProvider> units_a_b_provider;
+  ASSERT_HRESULT_SUCCEEDED(text_range_provider->Clone(&units_a_b_provider));
   int count;
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->Move(TextUnit_Character, /*count*/ 31, &count));
-  ASSERT_EQ(31, count);
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"l");
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider,
-                          L"Standalone line with no formatting");
+  ASSERT_HRESULT_SUCCEEDED(units_a_b_provider->MoveEndpointByUnit(
+      TextPatternRangeEndpoint_Start, TextUnit_Character, /*count*/ 63,
+      &count));
+  ASSERT_EQ(63, count);
+  ASSERT_HRESULT_SUCCEEDED(units_a_b_provider->MoveEndpointByUnit(
+      TextPatternRangeEndpoint_End, TextUnit_Character, /*count*/ -11, &count));
+  ASSERT_EQ(-11, count);
+  EXPECT_UIA_TEXTRANGE_EQ(units_a_b_provider,
+                          L"Paragraph 1Paragraph 2Paragraph 3");
 
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->Move(TextUnit_Character, /*count*/ 35, &count));
-  ASSERT_EQ(35, count);
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"o");
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"bold text");
-
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->Move(TextUnit_Character, /*count*/ 10, &count));
-  ASSERT_EQ(10, count);
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"a");
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"Paragraph 1");
-
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->Move(TextUnit_Character, /*count*/ 15, &count));
-  ASSERT_EQ(15, count);
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"g");
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"Paragraph 2Paragraph 3");
-
-  // Test expanding a degenerate range
-  ASSERT_HRESULT_SUCCEEDED(text_range_provider->MoveEndpointByUnit(
+  // Create a range encompassing node 11 which will serve as our expected
+  // value of a range from start of A to end of A.
+  ComPtr<ITextRangeProvider> unit_a_provider;
+  ASSERT_HRESULT_SUCCEEDED(units_a_b_provider->Clone(&unit_a_provider));
+  ASSERT_HRESULT_SUCCEEDED(unit_a_provider->MoveEndpointByUnit(
       TextPatternRangeEndpoint_End, TextUnit_Character, /*count*/ -22, &count));
   ASSERT_EQ(-22, count);
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"");
-  ASSERT_HRESULT_SUCCEEDED(
-      text_range_provider->ExpandToEnclosingUnit(TextUnit_Format));
-  EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"Paragraph 2Paragraph 3");
+  EXPECT_UIA_TEXTRANGE_EQ(unit_a_provider, L"Paragraph 1");
+
+  // Case 1: Degenerate range at start of A.
+  {
+    SCOPED_TRACE("Case 1: Degenerate range at start of A.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByRange(
+        TextPatternRangeEndpoint_End, test_case_provider.Get(),
+        TextPatternRangeEndpoint_Start));
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
+
+  // Case 2: Range from start of A to middle of A.
+  {
+    SCOPED_TRACE("Case 2: Range from start of A to middle of A.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_End, TextUnit_Character, /*count*/ -7,
+        &count));
+    ASSERT_EQ(-7, count);
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"Para");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
+
+  // Case 3: Range from start of A to end of A.
+  {
+    SCOPED_TRACE("Case 3: Range from start of A to end of A.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"Paragraph 1");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
+
+  // Case 4: Range from start of A to middle of B.
+  {
+    SCOPED_TRACE("Case 4: Range from start of A to middle of B.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_End, TextUnit_Character, /*count*/ 4, &count));
+    ASSERT_EQ(4, count);
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"Paragraph 1Para");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
+
+  // Case 5: Degenerate range in middle of A.
+  {
+    SCOPED_TRACE("Case 5: Degenerate range in middle of A.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_Start, TextUnit_Character, /*count*/ 4,
+        &count));
+    ASSERT_EQ(4, count);
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByRange(
+        TextPatternRangeEndpoint_End, test_case_provider.Get(),
+        TextPatternRangeEndpoint_Start));
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
+
+  // Case 6: Range from middle of A to middle of A.
+  {
+    SCOPED_TRACE("Case 6: Range from middle of A to middle of A.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_Start, TextUnit_Character, /*count*/ 4,
+        &count));
+    ASSERT_EQ(4, count);
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_End, TextUnit_Character, /*count*/ -2,
+        &count));
+    ASSERT_EQ(-2, count);
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"graph");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
+
+  // Case 7: Range from middle of A to end of A.
+  {
+    SCOPED_TRACE("Case 7: Range from middle of A to end of A.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_Start, TextUnit_Character, /*count*/ 4,
+        &count));
+    ASSERT_EQ(4, count);
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"graph 1");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
+
+  // Case 8: Range from middle of A to middle of B.
+  {
+    SCOPED_TRACE("Case 8: Range from middle of A to middle of B.");
+    ComPtr<ITextRangeProvider> test_case_provider;
+    ASSERT_HRESULT_SUCCEEDED(unit_a_provider->Clone(&test_case_provider));
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_Start, TextUnit_Character, /*count*/ 4,
+        &count));
+    ASSERT_EQ(4, count);
+    ASSERT_HRESULT_SUCCEEDED(test_case_provider->MoveEndpointByUnit(
+        TextPatternRangeEndpoint_End, TextUnit_Character, /*count*/ 4, &count));
+    ASSERT_EQ(4, count);
+    EXPECT_UIA_TEXTRANGE_EQ(test_case_provider, L"graph 1Para");
+
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->ExpandToEnclosingUnit(TextUnit_Format));
+    BOOL are_same;
+    ASSERT_HRESULT_SUCCEEDED(
+        test_case_provider->Compare(unit_a_provider.Get(), &are_same));
+    EXPECT_TRUE(are_same);
+  }
 }
 
 TEST_F(AXPlatformNodeTextRangeProviderTest,
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 98895ad..ad206303 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -6723,7 +6723,7 @@
   AXPlatformNodeWin* parent = static_cast<AXPlatformNodeWin*>(
       AXPlatformNode::FromNativeViewAccessible(GetParent()));
   while (parent) {
-    if (parent->ShouldHideChildren())
+    if (parent->ShouldHideChildrenForUIA())
       return true;
     parent = static_cast<AXPlatformNodeWin*>(
         FromNativeViewAccessible(parent->GetParent()));
@@ -6731,7 +6731,7 @@
   return false;
 }
 
-bool AXPlatformNodeWin::ShouldHideChildren() const {
+bool AXPlatformNodeWin::ShouldHideChildrenForUIA() const {
   switch (GetData().role) {
     case ax::mojom::Role::kButton:
     case ax::mojom::Role::kImage:
@@ -6741,6 +6741,7 @@
     case ax::mojom::Role::kProgressIndicator:
     case ax::mojom::Role::kScrollBar:
     case ax::mojom::Role::kSlider:
+    case ax::mojom::Role::kTextField:
       return true;
     default:
       return false;
@@ -7493,7 +7494,7 @@
   AXPlatformNodeWin* parent = static_cast<AXPlatformNodeWin*>(
       AXPlatformNode::FromNativeViewAccessible(GetParent()));
   while (parent) {
-    if (parent->ShouldHideChildren())
+    if (parent->ShouldHideChildrenForUIA())
       return parent;
     parent = static_cast<AXPlatformNodeWin*>(
         AXPlatformNode::FromNativeViewAccessible(parent->GetParent()));
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index 21d56fd..9b8033c 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -1080,7 +1080,7 @@
 
   bool IsInaccessibleDueToAncestor() const;
 
-  bool ShouldHideChildren() const;
+  bool ShouldHideChildrenForUIA() const;
 
   // AXPlatformNodeBase overrides.
   void Dispose() override;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index 872aa76..1dbcb3e 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -32,6 +32,9 @@
 
 namespace ui {
 
+const base::string16 AXPlatformNodeWinTest::kEmbeddedCharacterAsString = {
+    ui::AXPlatformNodeBase::kEmbeddedCharacter};
+
 namespace {
 
 // Most IAccessible functions require a VARIANT set to CHILDID_SELF as
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.h b/ui/accessibility/platform/ax_platform_node_win_unittest.h
index fced930..d2c9e0de 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.h
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.h
@@ -55,6 +55,8 @@
   void TearDown() override;
 
  protected:
+  static const base::string16 kEmbeddedCharacterAsString;
+
   AXPlatformNode* AXPlatformNodeFromNode(AXNode* node);
   template <typename T>
   Microsoft::WRL::ComPtr<T> QueryInterfaceFromNodeId(int32_t id);
diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc
index bd0ed8f9f..e5e8275 100644
--- a/ui/base/clipboard/clipboard_android.cc
+++ b/ui/base/clipboard/clipboard_android.cc
@@ -479,7 +479,7 @@
                                      size_t title_len,
                                      const char* url_data,
                                      size_t url_len) {
-  g_map.Get().Set(ClipboardFormatType::GetBookmarkType().ToString(),
+  g_map.Get().Set(ClipboardFormatType::GetUrlWType().ToString(),
                   std::string(url_data, url_len));
 }
 
diff --git a/ui/base/clipboard/clipboard_format_type.h b/ui/base/clipboard/clipboard_format_type.h
index 1880c3f..0d45d94d 100644
--- a/ui/base/clipboard/clipboard_format_type.h
+++ b/ui/base/clipboard/clipboard_format_type.h
@@ -74,10 +74,6 @@
   static const ClipboardFormatType& GetIDListType();
 #endif
 
-#if defined(OS_ANDROID)
-  static const ClipboardFormatType& GetBookmarkType();
-#endif
-
   // ClipboardFormatType can be used in a set on some platforms.
   bool operator<(const ClipboardFormatType& other) const;
 
diff --git a/ui/base/clipboard/clipboard_format_type_android.cc b/ui/base/clipboard/clipboard_format_type_android.cc
index e241d16..d4f76ba0 100644
--- a/ui/base/clipboard/clipboard_format_type_android.cc
+++ b/ui/base/clipboard/clipboard_format_type_android.cc
@@ -8,19 +8,6 @@
 
 namespace ui {
 
-namespace {
-
-// Various formats we support.
-const char kURLFormat[] = "url";
-const char kPlainTextFormat[] = "text";
-const char kHTMLFormat[] = "html";
-const char kRTFFormat[] = "rtf";
-const char kBitmapFormat[] = "bitmap";
-const char kWebKitSmartPasteFormat[] = "webkit_smart";
-const char kBookmarkFormat[] = "bookmark";
-
-}  // namespace
-
 // ClipboardFormatType implementation.
 ClipboardFormatType::ClipboardFormatType() = default;
 
@@ -57,43 +44,44 @@
 
 // static
 const ClipboardFormatType& ClipboardFormatType::GetUrlWType() {
-  static base::NoDestructor<ClipboardFormatType> type(kURLFormat);
+  static base::NoDestructor<ClipboardFormatType> type(kMimeTypeURIList);
   return *type;
 }
 
 // static
 const ClipboardFormatType& ClipboardFormatType::GetPlainTextType() {
-  static base::NoDestructor<ClipboardFormatType> type(kPlainTextFormat);
+  static base::NoDestructor<ClipboardFormatType> type(kMimeTypeText);
   return *type;
 }
 
 // static
 const ClipboardFormatType& ClipboardFormatType::GetPlainTextWType() {
-  static base::NoDestructor<ClipboardFormatType> type(kPlainTextFormat);
+  static base::NoDestructor<ClipboardFormatType> type(kMimeTypeText);
   return *type;
 }
 
 // static
 const ClipboardFormatType& ClipboardFormatType::GetWebKitSmartPasteType() {
-  static base::NoDestructor<ClipboardFormatType> type(kWebKitSmartPasteFormat);
+  static base::NoDestructor<ClipboardFormatType> type(
+      kMimeTypeWebkitSmartPaste);
   return *type;
 }
 
 // static
 const ClipboardFormatType& ClipboardFormatType::GetHtmlType() {
-  static base::NoDestructor<ClipboardFormatType> type(kHTMLFormat);
+  static base::NoDestructor<ClipboardFormatType> type(kMimeTypeHTML);
   return *type;
 }
 
 // static
 const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
-  static base::NoDestructor<ClipboardFormatType> type(kRTFFormat);
+  static base::NoDestructor<ClipboardFormatType> type(kMimeTypeRTF);
   return *type;
 }
 
 // static
 const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
-  static base::NoDestructor<ClipboardFormatType> type(kBitmapFormat);
+  static base::NoDestructor<ClipboardFormatType> type(kMimeTypePNG);
   return *type;
 }
 
@@ -110,10 +98,4 @@
   return *type;
 }
 
-// static
-const ClipboardFormatType& ClipboardFormatType::GetBookmarkType() {
-  static base::NoDestructor<ClipboardFormatType> type(kBookmarkFormat);
-  return *type;
-}
-
 }  // namespace ui
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fr.xtb b/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
index 2f278d3..508789d3 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
@@ -34,7 +34,7 @@
 <translation id="1310751437842832374">Translittération (mausam → ନମସ୍ତେ)</translation>
 <translation id="1337036551624197047">Clavier tchèque</translation>
 <translation id="1338950911836659113">Suppression en cours...</translation>
-<translation id="1346748346194534595">Vers la droite</translation>
+<translation id="1346748346194534595">À droite</translation>
 <translation id="1351692861129622852">Importation de <ph name="FILE_COUNT" /> fichiers en cours…</translation>
 <translation id="1352103415082130575">Clavier thaï (pattachote)</translation>
 <translation id="1358735829858566124">Le fichier ou le répertoire ne sont pas utilisables.</translation>
@@ -48,7 +48,7 @@
 <translation id="1441841714100794440">Clavier vietnamien (Télex)</translation>
 <translation id="1455548678241328678">Clavier norvégien</translation>
 <translation id="1464724975715666883">Une erreur.</translation>
-<translation id="1467432559032391204">Vers la gauche</translation>
+<translation id="1467432559032391204">À gauche</translation>
 <translation id="1474339897586437869">Le fichier "<ph name="FILENAME" />" n'a pas été importé, car l'espace disponible sur Google Drive est insuffisant.</translation>
 <translation id="148466539719134488">Suisse</translation>
 <translation id="1497522201463361063">Impossible de renommer "<ph name="FILE_NAME" />". <ph name="ERROR_MESSAGE" /></translation>
@@ -481,7 +481,7 @@
 <translation id="6509122719576673235">Norvégien</translation>
 <translation id="6527303717912515753">Partager</translation>
 <translation id="653019979737152879">Synchronisation de <ph name="FILE_NAME" /> en cours…</translation>
-<translation id="6549689063733911810">Activité récente</translation>
+<translation id="6549689063733911810">Récents</translation>
 <translation id="6556866813142980365">Rétablir</translation>
 <translation id="6558280019477628686">Une erreur s'est produite. Il se peut que certains éléments n'aient pas été supprimés.</translation>
 <translation id="656398493051028875">Suppression de "<ph name="FILENAME" />" en cours...</translation>
@@ -604,7 +604,7 @@
 <translation id="7898607018410277265">Clavier gujarati (nouvelle phonétique)</translation>
 <translation id="7917972308273378936">Clavier lituanien</translation>
 <translation id="7925686952655276919">Ne pas utiliser les données mobiles pour la synchronisation</translation>
-<translation id="7928710562641958568">Éjecter l'appareil</translation>
+<translation id="7928710562641958568">Éjecter le périphérique</translation>
 <translation id="7943385054491506837">Colemak américain</translation>
 <translation id="7953739707111622108">Impossible d'ouvrir ce périphérique, car son système de fichiers n'est pas reconnu.</translation>
 <translation id="7969525169268594403">Slovène</translation>
@@ -694,7 +694,7 @@
 <translation id="9035012421917565900">Les éléments ne pourront pas être redéplacés vers "<ph name="DESTINATION_NAME" />". Cette action est donc irréversible.</translation>
 <translation id="9038620279323455325">Le nom "<ph name="FILE_NAME" />" est déjà attribué à un fichier. Veuillez en choisir un autre.</translation>
 <translation id="9064939804718829769">Transfert en cours…</translation>
-<translation id="9065203028668620118">Édition</translation>
+<translation id="9065203028668620118">Modifier</translation>
 <translation id="9099674669267916096">Nombre de pages</translation>
 <translation id="9110990317705400362">Nous recherchons constamment à rendre votre navigation plus sûre. Auparavant, vous pouviez être invité à ajouter une extension dans votre navigateur par n'importe quel site Web. Dans les dernières versions de Google Chrome, vous devez explicitement indiquer que vous souhaitez installer une extension en l'ajoutant via la page "Extensions". <ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /></translation>
 <translation id="912419004897138677">Codec</translation>
@@ -714,7 +714,7 @@
 <translation id="939736085109172342">Nouveau dossier</translation>
 <translation id="942954117721265519">Pas d'image dans ce répertoire.</translation>
 <translation id="943972244133411984">Modifié par</translation>
-<translation id="945522503751344254">Envoyer le commentaire</translation>
+<translation id="945522503751344254">Envoyer un commentaire</translation>
 <translation id="947144732524271678"><ph name="ENTRY_COUNT" /> éléments sélectionnés, de <ph name="FROM_ENTRY_NAME" /> à <ph name="TO_ENTRY_NAME" />.</translation>
 <translation id="981121421437150478">Hors connexion</translation>
 <translation id="988685240266037636">Un fichier intitulé "<ph name="FILE_NAME" />" existe déjà. Voulez-vous le remplacer ?</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ko.xtb b/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
index ae24cf9f..6d29f0e0 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
@@ -180,7 +180,7 @@
 <translation id="3116361045094675131">영어(영국식) 키보드</translation>
 <translation id="3126026824346185272">Ctrl</translation>
 <translation id="3144126448740580210">완료</translation>
-<translation id="3157729859914172001">미국 국제(PC) 키보드</translation>
+<translation id="3157729859914172001">영어(미국식) 국제(PC) 키보드</translation>
 <translation id="3187212781151025377">히브리어 키보드</translation>
 <translation id="3188257591659621405">내 파일</translation>
 <translation id="3197563288998582412">영어(영국) 드보락</translation>
@@ -263,7 +263,7 @@
 <translation id="418179967336296930">러시아 표음식(YaZHert) 키보드</translation>
 <translation id="4193154014135846272">Google 문서</translation>
 <translation id="4195249722193633765">Linux(베타)로 앱 설치</translation>
-<translation id="4197674956721858839">압축 선택</translation>
+<translation id="4197674956721858839">선택항목 압축하기</translation>
 <translation id="421017592316736757">이 파일에 액세스하려면 온라인 상태여야 합니다.</translation>
 <translation id="4212740939091998969">이름이 '<ph name="FOLDER_NAME" />'인 폴더가 이미 존재합니다. 다른 이름을 선택하세요.</translation>
 <translation id="4215448920900139318">파일 <ph name="FILE_COUNT" />개 백업 중</translation>
@@ -448,7 +448,7 @@
 <translation id="6074825444536523002">Google 양식</translation>
 <translation id="6096979789310008754">검색어가 삭제되었으며, 모든 파일과 폴더가 표시됩니다.</translation>
 <translation id="6111770213269631447">음역(namaskar → নমস্কার)</translation>
-<translation id="6129953537138746214">공백</translation>
+<translation id="6129953537138746214">Space</translation>
 <translation id="6133173853026656527"><ph name="FILE_NAME" /> 이동 중...</translation>
 <translation id="6146563240635539929">동영상</translation>
 <translation id="6150853954427645995">오프라인에서 사용하기 위해 이 파일을 저장하려면 온라인으로 돌아가서 마우스 오른쪽 버튼으로 파일을 클릭한 다음 <ph name="OFFLINE_CHECKBOX_NAME" /> 옵션을 선택하세요.</translation>
@@ -516,7 +516,7 @@
     <ph name="LINE_BREAK1" />
     파일 <ph name="FILE_COUNT" />개 있음</translation>
 <translation id="6935521024859866267">180도 회전</translation>
-<translation id="6939777852457331078">미국 워크맨 키보드</translation>
+<translation id="6939777852457331078">영어(미국식) 워크맨 키보드</translation>
 <translation id="696203921837389374">모바일 데이터를 이용한 동기화 사용 설정</translation>
 <translation id="6965382102122355670">확인</translation>
 <translation id="6970230597523682626">불가리아어</translation>
@@ -535,7 +535,7 @@
 <translation id="7172053773111046550">에스토니아어 키보드</translation>
 <translation id="7180611975245234373">새로고침</translation>
 <translation id="7189874332498648577"><ph name="NUMBER_OF_GB" />GB</translation>
-<translation id="719009910964971313">US 프로그래머 드보락 키보드</translation>
+<translation id="719009910964971313">영어(미국식) 프로그래머 드보락 키보드</translation>
 <translation id="7191454237977785534">다른 이름으로 저장</translation>
 <translation id="7222624196722476520">불가리아어 표음식 키보드</translation>
 <translation id="7238097264433196391">드라이브 이름</translation>
@@ -544,7 +544,7 @@
 <translation id="7283041136720745563">Google 드라이브 용량이 부족합니다.</translation>
 <translation id="7295662345261934369">다른 사용자와 공유</translation>
 <translation id="7339898014177206373">새 창</translation>
-<translation id="7348749398828259943">미국 워크맨(국제) 키보드</translation>
+<translation id="7348749398828259943">영어(미국식) 워크맨 국제 키보드</translation>
 <translation id="7359359531237882347">항목 <ph name="NUMBER_OF_ITEMS" />개 복사 중...</translation>
 <translation id="7375951387215729722">파일 목록이 <ph name="COLUMN_NAME" /> 기준 내림차순으로 정렬되어 있습니다.</translation>
 <translation id="7389722738210761877">태국어 키보드(TIS 820-2531)</translation>
@@ -674,7 +674,7 @@
 <translation id="8698464937041809063">Google 드로잉</translation>
 <translation id="8714406895390098252">자전거</translation>
 <translation id="8719721339511222681"><ph name="ENTRY_NAME" /> 항목이 선택되었습니다.</translation>
-<translation id="8722421161699219904">미국 국제 키보드</translation>
+<translation id="8722421161699219904">영어(미국식) 국제 키보드</translation>
 <translation id="872537912056138402">크로아티아어</translation>
 <translation id="874420130893181774">번체 병음 입력 방법</translation>
 <translation id="8775404590947523323">수정 사항이 자동으로 저장됩니다.<ph name="BREAKS" />원본 이미지의 사본을 보관하려면 '원본 덮어쓰기'를 선택 해제합니다.</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_mr.xtb b/ui/chromeos/translations/ui_chromeos_strings_mr.xtb
index c357757a..e5d9d9d 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_mr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_mr.xtb
@@ -80,7 +80,7 @@
 <translation id="1847880352285315359">सेव्ह केले</translation>
 <translation id="1864756863218646478">फाइल आढळू शकली नाही.</translation>
 <translation id="1921986354447415460">तुर्की-F कीबोर्ड</translation>
-<translation id="1924372192547904021"><ph name="DRIVE_NAME" /> फॉरमॅट केला आहे</translation>
+<translation id="1924372192547904021"><ph name="DRIVE_NAME" /> फॉरमॅट केली आहे</translation>
 <translation id="1931134289871235022">स्लोव्हाक</translation>
 <translation id="1933345018156373194">हलवता आले नाही, अनपेक्षित एरर: <ph name="ERROR_MESSAGE" /></translation>
 <translation id="1936717151811561466">फिन्निश</translation>
@@ -571,7 +571,7 @@
 <translation id="7649070708921625228">मदत</translation>
 <translation id="7654209398114106148"><ph name="NUMBER_OF_ITEMS" /> आयटम हलवत आहे...</translation>
 <translation id="7658239707568436148">रद्द करा</translation>
-<translation id="7695430100978772476"><ph name="DRIVE_NAME" /> फॉरमॅट करता आला नाही</translation>
+<translation id="7695430100978772476"><ph name="DRIVE_NAME" /> फॉरमॅट करता आली नाही</translation>
 <translation id="770015031906360009">ग्रीक</translation>
 <translation id="7706319470528945664">पोर्तुगीज कीबोर्ड</translation>
 <translation id="7711920809702896782">इमेज माहिती</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
index bddf59d..98a2b62 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
@@ -349,7 +349,7 @@
 <translation id="5123433949759960244">Basketboll</translation>
 <translation id="5129662217315786329">polska</translation>
 <translation id="5144820558584035333">Hangul 3 Set (390)</translation>
-<translation id="5145331109270917438">Ändrad den</translation>
+<translation id="5145331109270917438">Ändringsdatum</translation>
 <translation id="515594325917491223">Schack</translation>
 <translation id="5158593464696388225">Det gick inte att spara bilden.</translation>
 <translation id="5159383109919732130"><ph name="BEGIN_BOLD" />Ta inte bort enheten ännu!<ph name="END_BOLD" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
index a8289c300..a4a1f37 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
@@ -80,7 +80,7 @@
 <translation id="1847880352285315359">محفوظ ہو گئی</translation>
 <translation id="1864756863218646478">فائل تلاش نہیں کی جا سکی۔</translation>
 <translation id="1921986354447415460">‏ترکی F کی بورڈ</translation>
-<translation id="1924372192547904021"><ph name="DRIVE_NAME" /> فارمیٹ کر دیا گیا</translation>
+<translation id="1924372192547904021"><ph name="DRIVE_NAME" /> کو فارمیٹ کر دیا گیا</translation>
 <translation id="1931134289871235022">سلاواکی</translation>
 <translation id="1933345018156373194">منتقلی ناکام ہو گئی، غیر متوقع خرابی: <ph name="ERROR_MESSAGE" /></translation>
 <translation id="1936717151811561466">فنّنِش</translation>
@@ -570,7 +570,7 @@
 <translation id="7649070708921625228">مدد</translation>
 <translation id="7654209398114106148"><ph name="NUMBER_OF_ITEMS" /> آئٹمز منتقل کئے جا رہے ہیں...</translation>
 <translation id="7658239707568436148">منسوخ کریں</translation>
-<translation id="7695430100978772476"><ph name="DRIVE_NAME" /> فارمیٹ نہیں کیا جا سکا</translation>
+<translation id="7695430100978772476"><ph name="DRIVE_NAME" /> کو فارمیٹ نہیں کیا جا سکا</translation>
 <translation id="770015031906360009">يونانی</translation>
 <translation id="7706319470528945664">پرتگالی کی بورڈ</translation>
 <translation id="7711920809702896782">تصویر کی معلومات</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
index 1058649..69e33dc 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
@@ -80,7 +80,7 @@
 <translation id="1847880352285315359">已保存</translation>
 <translation id="1864756863218646478">找不到该文件。</translation>
 <translation id="1921986354447415460">土耳其语 F 键盘</translation>
-<translation id="1924372192547904021">已格式化“<ph name="DRIVE_NAME" />”</translation>
+<translation id="1924372192547904021">已将“<ph name="DRIVE_NAME" />”格式化</translation>
 <translation id="1931134289871235022">斯洛伐克语</translation>
 <translation id="1933345018156373194">移动失败,出现了意外的错误:<ph name="ERROR_MESSAGE" /></translation>
 <translation id="1936717151811561466">芬兰语</translation>
@@ -164,7 +164,7 @@
 <translation id="2942290791863759244">德语Neo 2键盘</translation>
 <translation id="2943400156390503548">幻灯片</translation>
 <translation id="2943503720238418293">请使用一个较短的名称</translation>
-<translation id="2949781154072577687">正在格式化“<ph name="DRIVE_NAME" />”…</translation>
+<translation id="2949781154072577687">正在将“<ph name="DRIVE_NAME" />”格式化…</translation>
 <translation id="2951236788251446349">海蜇</translation>
 <translation id="2963783323012015985">土耳其语键盘</translation>
 <translation id="2966459079597787514">瑞典语键盘</translation>
@@ -566,7 +566,7 @@
 <translation id="7649070708921625228">帮助</translation>
 <translation id="7654209398114106148">正在移动 <ph name="NUMBER_OF_ITEMS" /> 项内容…</translation>
 <translation id="7658239707568436148">取消</translation>
-<translation id="7695430100978772476">无法格式化“<ph name="DRIVE_NAME" />”</translation>
+<translation id="7695430100978772476">无法将“<ph name="DRIVE_NAME" />”格式化</translation>
 <translation id="770015031906360009">希腊语</translation>
 <translation id="7706319470528945664">葡萄牙语键盘</translation>
 <translation id="7711920809702896782">图片信息</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
index a93ff185..18470d6 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
@@ -400,7 +400,7 @@
 <translation id="5533102081734025921"><ph name="IMAGE_TYPE" /> 圖片</translation>
 <translation id="5533555070048896610">音譯 (namaste → नमस्ते)</translation>
 <translation id="5534520101572674276">正在計算大小</translation>
-<translation id="5583640892426849032">Backspace 鍵</translation>
+<translation id="5583640892426849032">Backspace</translation>
 <translation id="5605830556594064952">Dvorak 美式配置</translation>
 <translation id="5640179856859982418">瑞士文鍵盤</translation>
 <translation id="5649768706273821470">聆聽</translation>
diff --git a/ui/events/blink/compositor_thread_event_queue.cc b/ui/events/blink/compositor_thread_event_queue.cc
index f9c2b46..8d4e064 100644
--- a/ui/events/blink/compositor_thread_event_queue.cc
+++ b/ui/events/blink/compositor_thread_event_queue.cc
@@ -76,12 +76,12 @@
 
   std::unique_ptr<EventWithCallback> scroll_event =
       std::make_unique<EventWithCallback>(
-          WebInputEventTraits::Clone(coalesced_events.first), oldest_latency,
+          coalesced_events.first.Clone(), oldest_latency,
           oldest_creation_timestamp, timestamp_now, nullptr);
 
   std::unique_ptr<EventWithCallback> pinch_event =
       std::make_unique<EventWithCallback>(
-          WebInputEventTraits::Clone(coalesced_events.second), oldest_latency,
+          coalesced_events.second.Clone(), oldest_latency,
           oldest_creation_timestamp, timestamp_now,
           std::move(combined_original_events));
 
diff --git a/ui/events/blink/event_with_callback.cc b/ui/events/blink/event_with_callback.cc
index cbed0013..c3c685d 100644
--- a/ui/events/blink/event_with_callback.cc
+++ b/ui/events/blink/event_with_callback.cc
@@ -19,7 +19,7 @@
     const LatencyInfo& latency,
     base::TimeTicks timestamp_now,
     InputHandlerProxy::EventDispositionCallback callback)
-    : event_(WebInputEventTraits::Clone(*event)),
+    : event_(event->Clone()),
       latency_(latency),
       creation_timestamp_(timestamp_now),
       last_coalesced_timestamp_(timestamp_now) {
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc
index cf89aaa4..9b2b867f 100644
--- a/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -94,7 +94,7 @@
     gesture.data.pinch_update.scale = delta_y_or_scale;
     gesture.SetPositionInWidget(gfx::PointF(x, y));
   }
-  return WebInputEventTraits::Clone(gesture);
+  return gesture.Clone();
 }
 
 class MockInputHandler : public cc::InputHandler {
@@ -2640,14 +2640,14 @@
     WebGestureEvent gesture(WebInputEvent::kGestureScrollBegin,
                             WebInputEvent::kNoModifiers, tick_clock_.NowTicks(),
                             blink::WebGestureDevice::kTouchscreen);
-    HandleGesture(WebInputEventTraits::Clone(gesture));
+    HandleGesture(gesture.Clone());
   }
 
   void HandleScrollEnd() {
     WebGestureEvent gesture(WebInputEvent::kGestureScrollEnd,
                             WebInputEvent::kNoModifiers, tick_clock_.NowTicks(),
                             blink::WebGestureDevice::kTouchscreen);
-    HandleGesture(WebInputEventTraits::Clone(gesture));
+    HandleGesture(gesture.Clone());
   }
 
   void HandleScrollUpdate(bool is_momentum) {
@@ -2659,7 +2659,7 @@
       gesture.data.scroll_update.inertial_phase =
           blink::WebGestureEvent::InertialPhaseState::kMomentum;
     }
-    HandleGesture(WebInputEventTraits::Clone(gesture));
+    HandleGesture(gesture.Clone());
   }
 
   void AdvanceClock(uint32_t milliseconds) {
diff --git a/ui/events/blink/scroll_predictor_unittest.cc b/ui/events/blink/scroll_predictor_unittest.cc
index cbf1b883..e8409d2 100644
--- a/ui/events/blink/scroll_predictor_unittest.cc
+++ b/ui/events/blink/scroll_predictor_unittest.cc
@@ -58,10 +58,10 @@
     gesture.data.scroll_update.delta_y = delta_y;
     gesture.data.scroll_update.inertial_phase = phase;
 
-    original_events_.emplace_back(WebInputEventTraits::Clone(gesture),
-                                  LatencyInfo(), base::NullCallback());
+    original_events_.emplace_back(gesture.Clone(), LatencyInfo(),
+                                  base::NullCallback());
 
-    return WebInputEventTraits::Clone(gesture);
+    return gesture.Clone();
   }
 
   void CoalesceWith(const WebScopedInputEvent& new_event,
@@ -90,7 +90,7 @@
         WebInputEvent::GetStaticTimeStampForTests() +
             base::TimeDelta::FromMillisecondsD(time_delta_in_milliseconds));
 
-    event = WebInputEventTraits::Clone(event_with_callback->event());
+    event = event_with_callback->event().Clone();
   }
 
   std::unique_ptr<ui::InputPredictor::InputData> PredictionAvailable(
@@ -203,7 +203,7 @@
                               WebInputEvent::kNoModifiers,
                               WebInputEvent::GetStaticTimeStampForTests(),
                               blink::WebGestureDevice::kTouchscreen);
-  WebScopedInputEvent event = WebInputEventTraits::Clone(gesture_end);
+  WebScopedInputEvent event = gesture_end.Clone();
   HandleResampleScrollEvents(event);
   EXPECT_FALSE(GetResamplingState());
 }
diff --git a/ui/events/blink/web_input_event_traits.cc b/ui/events/blink/web_input_event_traits.cc
index 9734e1d..19bd615 100644
--- a/ui/events/blink/web_input_event_traits.cc
+++ b/ui/events/blink/web_input_event_traits.cc
@@ -105,17 +105,6 @@
       event.rotation_angle, event.tilt_x, event.tilt_y);
 }
 
-struct WebInputEventDelete {
-  template <class EventType>
-  bool Execute(WebInputEvent* event, void*) const {
-    if (!event)
-      return false;
-    DCHECK_EQ(sizeof(EventType), event->size());
-    delete static_cast<EventType*>(event);
-    return true;
-  }
-};
-
 struct WebInputEventToString {
   template <class EventType>
   bool Execute(const WebInputEvent& event, std::string* result) const {
@@ -129,17 +118,6 @@
   }
 };
 
-struct WebInputEventClone {
-  template <class EventType>
-  bool Execute(const WebInputEvent& event,
-               WebScopedInputEvent* scoped_event) const {
-    DCHECK_EQ(sizeof(EventType), event.size());
-    *scoped_event = WebScopedInputEvent(
-        new EventType(static_cast<const EventType&>(event)));
-    return true;
-  }
-};
-
 template <typename Operator, typename ArgIn, typename ArgOut>
 bool Apply(Operator op,
            WebInputEvent::Type type,
@@ -164,25 +142,12 @@
 
 }  // namespace
 
-void WebInputEventDeleter::operator()(WebInputEvent* event) const {
-  if (!event)
-    return;
-  void* temp = nullptr;
-  Apply(WebInputEventDelete(), event->GetType(), event, temp);
-}
-
 std::string WebInputEventTraits::ToString(const WebInputEvent& event) {
   std::string result;
   Apply(WebInputEventToString(), event.GetType(), event, &result);
   return result;
 }
 
-WebScopedInputEvent WebInputEventTraits::Clone(const WebInputEvent& event) {
-  WebScopedInputEvent scoped_event;
-  Apply(WebInputEventClone(), event.GetType(), event, &scoped_event);
-  return scoped_event;
-}
-
 bool WebInputEventTraits::ShouldBlockEventStream(const WebInputEvent& event) {
   switch (event.GetType()) {
     case WebInputEvent::kContextMenu:
diff --git a/ui/events/blink/web_input_event_traits.h b/ui/events/blink/web_input_event_traits.h
index 19f9db8b..10f60ba 100644
--- a/ui/events/blink/web_input_event_traits.h
+++ b/ui/events/blink/web_input_event_traits.h
@@ -14,18 +14,12 @@
 
 namespace ui {
 
-struct WebInputEventDeleter {
-  void operator()(blink::WebInputEvent*) const;
-};
-
-using WebScopedInputEvent =
-    std::unique_ptr<blink::WebInputEvent, WebInputEventDeleter>;
+using WebScopedInputEvent = std::unique_ptr<blink::WebInputEvent>;
 
 // Utility class for performing operations on and with WebInputEvents.
 class WebInputEventTraits {
  public:
   static std::string ToString(const blink::WebInputEvent& event);
-  static WebScopedInputEvent Clone(const blink::WebInputEvent& event);
   static bool ShouldBlockEventStream(const blink::WebInputEvent& event);
 
   // Return uniqueTouchEventId for WebTouchEvent, otherwise return 0.
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index 2922c28..cced299 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1890,6 +1890,12 @@
   padding-inline-start: 32px;
 }
 
+html[dir='rtl'] #share-menu cr-menu-item,
+html[dir='rtl'] #share-sub-menu cr-menu-item,
+html[dir='rtl'] #tasks-menu cr-menu-item:not(.change-default) {
+  background-position: right 10px center;
+}
+
 #share-menu cr-menu-item[command='#share'] {
   background-image: -webkit-image-set(
       url(../images/files/ui/person_add.png) 1x,
diff --git a/ui/ozone/demo/window_manager.cc b/ui/ozone/demo/window_manager.cc
index ffea585..ed4f66c 100644
--- a/ui/ozone/demo/window_manager.cc
+++ b/ui/ozone/demo/window_manager.cc
@@ -69,8 +69,8 @@
   }
 
   is_configuring_ = true;
-  delegate_->GetDisplays(base::BindRepeating(&WindowManager::OnDisplaysAquired,
-                                             base::Unretained(this)));
+  delegate_->GetDisplays(base::BindOnce(&WindowManager::OnDisplaysAquired,
+                                        base::Unretained(this)));
 }
 
 void WindowManager::OnDisplaySnapshotsInvalidated() {}
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
index 08b2ddb..09936ef8 100644
--- a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -6,7 +6,6 @@
 #include <wayland-server.h>
 #include <memory>
 
-#include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ime/linux/linux_input_method_context.h"
diff --git a/ui/ozone/public/gpu_platform_support_host.h b/ui/ozone/public/gpu_platform_support_host.h
index 4839359e..af6da1d 100644
--- a/ui/ozone/public/gpu_platform_support_host.h
+++ b/ui/ozone/public/gpu_platform_support_host.h
@@ -12,7 +12,7 @@
 #include "base/single_thread_task_runner.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_sender.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/message_pipe.h"
 
 namespace ui {
 
diff --git a/ui/strings/translations/ui_strings_fr.xtb b/ui/strings/translations/ui_strings_fr.xtb
index c25d540..750d73b7 100644
--- a/ui/strings/translations/ui_strings_fr.xtb
+++ b/ui/strings/translations/ui_strings_fr.xtb
@@ -68,7 +68,7 @@
 <translation id="2583543531130364912">Calibrer votre écran tactile</translation>
 <translation id="2666092431469916601">En haut</translation>
 <translation id="2701330563083355633">Partagé par <ph name="DEVICE_NAME" /></translation>
-<translation id="2743387203779672305">Copier dans le Presse-papier</translation>
+<translation id="2743387203779672305">Copier dans le presse-papiers</translation>
 <translation id="2749082172777216925"><ph name="APP_NAME_INFO" />, <ph name="PRICE" /></translation>
 <translation id="2803313416453193357">Ouvrir le dossier</translation>
 <translation id="2824719307700604149">{YEARS,plural, =1{Il y a 1 an}one{Il y a # an}other{Il y a # ans}}</translation>
@@ -78,7 +78,7 @@
 <translation id="3036649622769666520">Ouvrir les fichiers</translation>
 <translation id="3049748772180311791"><ph name="QUANTITY" /> Mo</translation>
 <translation id="3068711042108640621">Étagère à gauche</translation>
-<translation id="3087734570205094154">Bas</translation>
+<translation id="3087734570205094154">En bas</translation>
 <translation id="3126026824346185272">Ctrl</translation>
 <translation id="3157931365184549694">Restaurer</translation>
 <translation id="3183922693828471536">Défilement jusqu'ici</translation>
diff --git a/ui/strings/translations/ui_strings_ko.xtb b/ui/strings/translations/ui_strings_ko.xtb
index 18a3024..814995f 100644
--- a/ui/strings/translations/ui_strings_ko.xtb
+++ b/ui/strings/translations/ui_strings_ko.xtb
@@ -108,7 +108,7 @@
 <translation id="3990502903496589789">오른쪽 모서리</translation>
 <translation id="40579289237549812">{UNREAD_NOTIFICATIONS,plural, =1{읽지 않은 알림 1개}other{읽지 않은 알림 #개}}</translation>
 <translation id="4202807286478387388">건너뛰기</translation>
-<translation id="4250229828105606438">캡처화면</translation>
+<translation id="4250229828105606438">스크린샷</translation>
 <translation id="4266252015790371705">{MONTHS,plural, =1{1개월 전}other{#개월 전}}</translation>
 <translation id="4289300219472526559">말하기 시작</translation>
 <translation id="430191667033048642"><ph name="MOVED_APP_NAME" /> 앱이 <ph name="FOLDER_NAME" /> 폴더로 이동했습니다.</translation>
@@ -152,7 +152,7 @@
 <translation id="6022924867608035986">검색창 텍스트 삭제</translation>
 <translation id="6040143037577758943">닫기</translation>
 <translation id="6119846243427417423">활성화</translation>
-<translation id="6129953537138746214">공백</translation>
+<translation id="6129953537138746214">Space</translation>
 <translation id="6135826906199951471">Del</translation>
 <translation id="6142413573757616983"><ph name="QUANTITY" />B/s</translation>
 <translation id="6156262341071374681">펼쳐서 모든 앱 보기</translation>
diff --git a/ui/strings/translations/ui_strings_nl.xtb b/ui/strings/translations/ui_strings_nl.xtb
index c0aad36..1c5c607 100644
--- a/ui/strings/translations/ui_strings_nl.xtb
+++ b/ui/strings/translations/ui_strings_nl.xtb
@@ -102,7 +102,7 @@
 <translation id="3842239759367498783">Verder lezen vanaf je mobiele apparaat <ph name="TITLE" /></translation>
 <translation id="385051799172605136">Vorige</translation>
 <translation id="3889424535448813030">Pijl-rechts</translation>
-<translation id="3892641579809465218">Interne display</translation>
+<translation id="3892641579809465218">Ingebouwd scherm</translation>
 <translation id="3897092660631435901">Menu</translation>
 <translation id="3909791450649380159">&amp;Knippen</translation>
 <translation id="3990502903496589789">Rechterzijde</translation>
diff --git a/ui/strings/translations/ui_strings_zh-TW.xtb b/ui/strings/translations/ui_strings_zh-TW.xtb
index 2fd68f0..a1dac47 100644
--- a/ui/strings/translations/ui_strings_zh-TW.xtb
+++ b/ui/strings/translations/ui_strings_zh-TW.xtb
@@ -137,7 +137,7 @@
 <translation id="5476505524087279545">取消選取</translation>
 <translation id="547979256943495781">在右側顯示檔案櫃</translation>
 <translation id="5574202486608032840"><ph name="IDS_SHORT_PRODUCT_OS_NAME" /></translation>
-<translation id="5583640892426849032">Backspace 鍵</translation>
+<translation id="5583640892426849032">Backspace</translation>
 <translation id="5613020302032141669">向左鍵</translation>
 <translation id="5675363643668471212">檔案櫃項目</translation>
 <translation id="5754277640426581776">{MINUTES,plural, =1{1 分鐘}other{# 分鐘}}</translation>
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 541a8197..609ae12b 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -1034,6 +1034,10 @@
   desktop_window_tree_host_->SizeConstraintsChanged();
 }
 
+void DesktopNativeWidgetAura::OnNativeViewHierarchyWillChange() {}
+
+void DesktopNativeWidgetAura::OnNativeViewHierarchyChanged() {}
+
 std::string DesktopNativeWidgetAura::GetName() const {
   return name_;
 }
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index 4e47c92..0a766bc 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -195,6 +195,8 @@
   bool IsTranslucentWindowOpacitySupported() const override;
   ui::GestureRecognizer* GetGestureRecognizer() override;
   void OnSizeConstraintsChanged() override;
+  void OnNativeViewHierarchyWillChange() override;
+  void OnNativeViewHierarchyChanged() override;
   std::string GetName() const override;
 
   // Overridden from aura::WindowDelegate:
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index a30e4d8..129f2f0 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -821,6 +821,10 @@
   SetResizeBehaviorFromDelegate(GetWidget()->widget_delegate(), window_);
 }
 
+void NativeWidgetAura::OnNativeViewHierarchyWillChange() {}
+
+void NativeWidgetAura::OnNativeViewHierarchyChanged() {}
+
 std::string NativeWidgetAura::GetName() const {
   return window_ ? window_->GetName() : std::string();
 }
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index b31bef1..07ccff56 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -156,6 +156,8 @@
   bool IsTranslucentWindowOpacitySupported() const override;
   ui::GestureRecognizer* GetGestureRecognizer() override;
   void OnSizeConstraintsChanged() override;
+  void OnNativeViewHierarchyWillChange() override;
+  void OnNativeViewHierarchyChanged() override;
   std::string GetName() const override;
 
   // Overridden from aura::WindowDelegate:
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h
index 11a6f25..7c2db18 100644
--- a/ui/views/widget/native_widget_mac.h
+++ b/ui/views/widget/native_widget_mac.h
@@ -177,6 +177,8 @@
   bool IsTranslucentWindowOpacitySupported() const override;
   ui::GestureRecognizer* GetGestureRecognizer() override;
   void OnSizeConstraintsChanged() override;
+  void OnNativeViewHierarchyWillChange() override;
+  void OnNativeViewHierarchyChanged() override;
   std::string GetName() const override;
 
   // Calls |callback| with the newly created NativeWidget whenever a
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index f34479e..e94c50e9 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -778,6 +778,18 @@
       widget->widget_delegate()->CanMaximize());
 }
 
+void NativeWidgetMac::OnNativeViewHierarchyWillChange() {
+  // If this is not top-level, then the FocusManager may change, so remove our
+  // listeners.
+  if (!GetWidget()->is_top_level())
+    SetFocusManager(nullptr);
+}
+
+void NativeWidgetMac::OnNativeViewHierarchyChanged() {
+  if (!GetWidget()->is_top_level())
+    SetFocusManager(GetWidget()->GetFocusManager());
+}
+
 std::string NativeWidgetMac::GetName() const {
   return name_;
 }
diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h
index 4aa5fd1..7055294 100644
--- a/ui/views/widget/native_widget_private.h
+++ b/ui/views/widget/native_widget_private.h
@@ -230,6 +230,9 @@
   virtual bool IsTranslucentWindowOpacitySupported() const = 0;
   virtual ui::GestureRecognizer* GetGestureRecognizer() = 0;
   virtual void OnSizeConstraintsChanged() = 0;
+  // Called before and after re-parenting of this or an ancestor widget.
+  virtual void OnNativeViewHierarchyWillChange() = 0;
+  virtual void OnNativeViewHierarchyChanged() = 0;
 
   // Returns an internal name that matches the name of the associated Widget.
   virtual std::string GetName() const = 0;
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 8ff27f1..9006611f 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -466,9 +466,11 @@
   // to avoid these redundant steps and to avoid accessing deleted views
   // that may have been in focus.
   ClearFocusFromWidget();
+  native_widget_->OnNativeViewHierarchyChanged();
 }
 
 void Widget::NotifyNativeViewHierarchyChanged() {
+  native_widget_->OnNativeViewHierarchyWillChange();
   root_view_->NotifyNativeViewHierarchyChanged();
 }
 
@@ -1387,12 +1389,14 @@
 
 bool Widget::SetInitialFocus(ui::WindowShowState show_state) {
   FocusManager* focus_manager = GetFocusManager();
+  if (!focus_manager)
+    return false;
   View* v = widget_delegate_->GetInitiallyFocusedView();
   if (!focus_on_creation_ || show_state == ui::SHOW_STATE_INACTIVE ||
       show_state == ui::SHOW_STATE_MINIMIZED) {
     // If not focusing the window now, tell the focus manager which view to
     // focus when the window is restored.
-    if (v && focus_manager)
+    if (v)
       focus_manager->SetStoredFocusView(v);
     return true;
   }
@@ -1401,10 +1405,8 @@
     // If the Widget is active (thus allowing its child Views to receive focus),
     // but the request for focus was unsuccessful, fall back to using the first
     // focusable View instead.
-    if (focus_manager && focus_manager->GetFocusedView() == nullptr &&
-        IsActive()) {
+    if (focus_manager->GetFocusedView() == nullptr && IsActive())
       focus_manager->AdvanceFocus(false);
-    }
   }
   return !!focus_manager->GetFocusedView();
 }
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn
index 9bd7a857..998d193 100644
--- a/weblayer/BUILD.gn
+++ b/weblayer/BUILD.gn
@@ -131,6 +131,8 @@
     "browser/ssl_host_state_delegate_impl.h",
     "browser/tab_impl.cc",
     "browser/tab_impl.h",
+    "browser/weblayer_browser_interface_binders.cc",
+    "browser/weblayer_browser_interface_binders.h",
     "browser/weblayer_content_browser_overlay_manifest.cc",
     "browser/weblayer_content_browser_overlay_manifest.h",
     "browser/webui/web_ui_controller_factory.cc",
diff --git a/weblayer/browser/OWNERS b/weblayer/browser/OWNERS
index ddc1609..c814729 100644
--- a/weblayer/browser/OWNERS
+++ b/weblayer/browser/OWNERS
@@ -2,3 +2,5 @@
 per-file weblayer_content_browser_overlay_manifest.cc=file://ipc/SECURITY_OWNERS
 per-file weblayer_content_browser_overlay_manifest.h=set noparent
 per-file weblayer_content_browser_overlay_manifest.h=file://ipc/SECURITY_OWNERS
+per-file weblayer_browser_interface_binders.cc=set noparent
+per-file weblayer_browser_interface_binders.cc=file://ipc/SECURITY_OWNERS
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java
index d5bb408..f2e51ca5 100644
--- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java
+++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java
@@ -12,6 +12,7 @@
 import android.os.Bundle;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
+import android.support.v4.app.Fragment;
 import android.text.TextUtils;
 
 import org.json.JSONException;
@@ -251,4 +252,12 @@
     public String getTestDataURL(String path) {
         return getTestServer().getURL("/weblayer/test/data/" + path);
     }
+
+    public void setRetainInstance(boolean retain) {
+        TestThreadUtils.runOnUiThreadBlocking(() -> getActivity().setRetainInstance(retain));
+    }
+
+    public Fragment getFragment() {
+        return TestThreadUtils.runOnUiThreadBlockingNoException(() -> getActivity().getFragment());
+    }
 }
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SmokeTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SmokeTest.java
index 6c3a40d7..ebcf856 100644
--- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SmokeTest.java
+++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SmokeTest.java
@@ -5,6 +5,7 @@
 package org.chromium.weblayer.test;
 
 import android.support.test.filters.SmallTest;
+import android.support.v4.app.Fragment;
 
 import org.junit.Assert;
 import org.junit.Rule;
@@ -86,4 +87,38 @@
             }
         });
     }
+
+    @Test
+    @SmallTest
+    public void testSetRetainInstance() {
+        ReferenceQueue<InstrumentationActivity> referenceQueue = new ReferenceQueue<>();
+        PhantomReference<InstrumentationActivity> reference;
+        {
+            InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");
+
+            mActivityTestRule.setRetainInstance(true);
+            Fragment firstFragment = mActivityTestRule.getFragment();
+            mActivityTestRule.recreateActivity();
+            Fragment secondFragment = mActivityTestRule.getFragment();
+            Assert.assertEquals(firstFragment, secondFragment);
+
+            boolean destroyed =
+                    TestThreadUtils.runOnUiThreadBlockingNoException(() -> activity.isDestroyed());
+            Assert.assertTrue(destroyed);
+            reference = new PhantomReference<>(activity, referenceQueue);
+        }
+
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                Reference enqueuedReference = referenceQueue.poll();
+                if (enqueuedReference == null) {
+                    Runtime.getRuntime().gc();
+                    return false;
+                }
+                Assert.assertEquals(reference, enqueuedReference);
+                return true;
+            }
+        });
+    }
 }
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc
index 39e88ed..4368e6d 100644
--- a/weblayer/browser/content_browser_client_impl.cc
+++ b/weblayer/browser/content_browser_client_impl.cc
@@ -36,8 +36,6 @@
 #include "services/service_manager/public/cpp/binder_map.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
-#include "third_party/blink/public/mojom/installedapp/installed_app_provider.mojom.h"
-#include "third_party/blink/public/mojom/installedapp/related_application.mojom.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 #include "weblayer/browser/browser_main_parts_impl.h"
@@ -45,6 +43,7 @@
 #include "weblayer/browser/profile_impl.h"
 #include "weblayer/browser/ssl_error_handler.h"
 #include "weblayer/browser/tab_impl.h"
+#include "weblayer/browser/weblayer_browser_interface_binders.h"
 #include "weblayer/browser/weblayer_content_browser_overlay_manifest.h"
 #include "weblayer/common/features.h"
 #include "weblayer/public/fullscreen_delegate.h"
@@ -108,29 +107,6 @@
       const std::string& serialized_report) override {}
 };
 
-#if defined(OS_ANDROID)
-// TODO(https://crbug.com/1037884): Remove this.
-class StubInstalledAppProvider : public blink::mojom::InstalledAppProvider {
- public:
-  StubInstalledAppProvider() {}
-  ~StubInstalledAppProvider() override = default;
-
-  // InstalledAppProvider overrides:
-  void FilterInstalledApps(
-      std::vector<blink::mojom::RelatedApplicationPtr> related_apps,
-      FilterInstalledAppsCallback callback) override {
-    std::move(callback).Run(std::vector<blink::mojom::RelatedApplicationPtr>());
-  }
-
-  static void Create(
-      content::RenderFrameHost* rfh,
-      mojo::PendingReceiver<blink::mojom::InstalledAppProvider> receiver) {
-    mojo::MakeSelfOwnedReceiver(std::make_unique<StubInstalledAppProvider>(),
-                                std::move(receiver));
-  }
-};
-#endif
-
 }  // namespace
 
 namespace weblayer {
@@ -398,11 +374,7 @@
 void ContentBrowserClientImpl::RegisterBrowserInterfaceBindersForFrame(
     content::RenderFrameHost* render_frame_host,
     service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) {
-#if defined(OS_ANDROID)
-  // TODO(https://crbug.com/1037884): Remove this.
-  map->Add<blink::mojom::InstalledAppProvider>(
-      base::BindRepeating(&StubInstalledAppProvider::Create));
-#endif
+  PopulateWebLayerFrameBinders(render_frame_host, map);
 }
 
 #if defined(OS_ANDROID)
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
index b4fb4a85..3628372 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -33,6 +33,7 @@
     private BrowserViewController mViewController;
     private FragmentWindowAndroid mWindowAndroid;
     private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
+    private TabImpl mActiveTab;
     private IBrowserClient mClient;
     private LocaleChangedBroadcastReceiver mLocaleReceiver;
 
@@ -46,22 +47,31 @@
     }
 
     public ViewGroup getViewAndroidDelegateContainerView() {
+        if (mViewController == null) return null;
         return mViewController.getContentView();
     }
 
     public void onFragmentAttached(Context context, FragmentWindowAndroid windowAndroid) {
+        assert mWindowAndroid == null;
+        assert mViewController == null;
         mWindowAndroid = windowAndroid;
         mViewController = new BrowserViewController(context, windowAndroid);
-        TabImpl tab = new TabImpl(mProfile, windowAndroid);
-        addTab(tab);
-        boolean set_active_result = setActiveTab(tab);
-        assert set_active_result;
-
         mLocaleReceiver = new LocaleChangedBroadcastReceiver(context);
+
+        if (mTabs.isEmpty()) {
+            TabImpl tab = new TabImpl(mProfile, windowAndroid);
+            addTab(tab);
+            boolean set_active_result = setActiveTab(tab);
+            assert set_active_result;
+        } else {
+            updateAllTabs();
+            mViewController.setActiveTab(mActiveTab);
+        }
     }
 
     public void onFragmentDetached() {
-        destroy(); // For now we don't retain anything between detach and attach.
+        destroyAttachmentState();
+        updateAllTabs();
     }
 
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
@@ -144,6 +154,7 @@
     public boolean setActiveTab(ITab controller) {
         StrictModeWorkaround.apply();
         TabImpl tab = (TabImpl) controller;
+        mActiveTab = tab;
         if (tab != null && tab.getBrowser() != this) return false;
         mViewController.setActiveTab(tab);
         try {
@@ -157,7 +168,7 @@
     }
 
     public TabImpl getActiveTab() {
-        return mViewController.getTab();
+        return mActiveTab;
     }
 
     @Override
@@ -190,15 +201,21 @@
     }
 
     public void destroy() {
+        setActiveTab(null);
+        for (TabImpl tab : mTabs) {
+            tab.destroy();
+        }
+        mTabs.clear();
+        destroyAttachmentState();
+    }
+
+    private void destroyAttachmentState() {
         if (mLocaleReceiver != null) {
             mLocaleReceiver.destroy();
             mLocaleReceiver = null;
         }
         if (mViewController != null) {
             mViewController.destroy();
-            for (TabImpl tab : mTabs) {
-                tab.destroy();
-            }
             mViewController = null;
         }
         if (mWindowAndroid != null) {
@@ -206,4 +223,10 @@
             mWindowAndroid = null;
         }
     }
+
+    private void updateAllTabs() {
+        for (TabImpl tab : mTabs) {
+            tab.updateFromBrowser();
+        }
+    }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
index c12c33d..4af8dbc 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
@@ -115,12 +115,16 @@
      */
     public void attachToBrowser(BrowserImpl browser) {
         mBrowser = browser;
-        mWebContents.setTopLevelNativeWindow(browser.getWindowAndroid());
-        mViewAndroidDelegate.setContainerView(browser.getViewAndroidDelegateContainerView());
+        updateFromBrowser();
         SelectionPopupController.fromWebContents(mWebContents)
                 .setActionModeCallback(new ActionModeCallback(mWebContents));
     }
 
+    public void updateFromBrowser() {
+        mWebContents.setTopLevelNativeWindow(mBrowser.getWindowAndroid());
+        mViewAndroidDelegate.setContainerView(mBrowser.getViewAndroidDelegateContainerView());
+    }
+
     public BrowserImpl getBrowser() {
         return mBrowser;
     }
diff --git a/weblayer/browser/resources/weblayer_internals/weblayer_internals.js b/weblayer/browser/resources/weblayer_internals/weblayer_internals.js
index e742ba2..48c36ea 100644
--- a/weblayer/browser/resources/weblayer_internals/weblayer_internals.js
+++ b/weblayer/browser/resources/weblayer_internals/weblayer_internals.js
@@ -10,7 +10,8 @@
 /* Main entry point. */
 document.addEventListener('DOMContentLoaded', function() {
   // Setup backend mojo.
-  const pageHandler = weblayerInternals.mojom.PageHandler.getRemote();
+  const pageHandler = weblayerInternals.mojom.PageHandler.getRemote(
+      /*useBrowserInterfaceBroker=*/ true);
   if (cr.isAndroid) {
     pageHandler.getRemoteDebuggingEnabled().then((response) => {
         let checkbox = $('remote-debug');
diff --git a/weblayer/browser/weblayer_browser_interface_binders.cc b/weblayer/browser/weblayer_browser_interface_binders.cc
new file mode 100644
index 0000000..9f31dd1
--- /dev/null
+++ b/weblayer/browser/weblayer_browser_interface_binders.cc
@@ -0,0 +1,83 @@
+// Copyright 2019 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 "weblayer/browser/weblayer_browser_interface_binders.h"
+
+#include "base/bind.h"
+#include "build/build_config.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "third_party/blink/public/mojom/installedapp/installed_app_provider.mojom.h"
+#include "third_party/blink/public/mojom/installedapp/related_application.mojom.h"
+#include "weblayer/browser/webui/weblayer_internals.mojom.h"
+#include "weblayer/browser/webui/weblayer_internals_ui.h"
+
+#if defined(OS_ANDROID)
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#endif
+
+namespace weblayer {
+namespace {
+
+void BindPageHandler(
+    content::RenderFrameHost* host,
+    mojo::PendingReceiver<weblayer_internals::mojom::PageHandler> receiver) {
+  auto* contents = content::WebContents::FromRenderFrameHost(host);
+  if (!contents)
+    return;
+
+  content::WebUI* web_ui = contents->GetWebUI();
+
+  // Performs a safe downcast to the concrete WebUIController subclass.
+  WebLayerInternalsUI* concrete_controller =
+      web_ui ? web_ui->GetController()->GetAs<WebLayerInternalsUI>() : nullptr;
+
+  // This is expected to be called only for main frames and for the right
+  // WebUI pages matching the same WebUI associated to the RenderFrameHost.
+  if (host->GetParent() || !concrete_controller)
+    return;
+
+  concrete_controller->BindInterface(std::move(receiver));
+}
+
+#if defined(OS_ANDROID)
+// TODO(https://crbug.com/1037884): Remove this.
+class StubInstalledAppProvider : public blink::mojom::InstalledAppProvider {
+ public:
+  StubInstalledAppProvider() {}
+  ~StubInstalledAppProvider() override = default;
+
+  // InstalledAppProvider overrides:
+  void FilterInstalledApps(
+      std::vector<blink::mojom::RelatedApplicationPtr> related_apps,
+      FilterInstalledAppsCallback callback) override {
+    std::move(callback).Run(std::vector<blink::mojom::RelatedApplicationPtr>());
+  }
+
+  static void Create(
+      content::RenderFrameHost* rfh,
+      mojo::PendingReceiver<blink::mojom::InstalledAppProvider> receiver) {
+    mojo::MakeSelfOwnedReceiver(std::make_unique<StubInstalledAppProvider>(),
+                                std::move(receiver));
+  }
+};
+#endif
+
+}  // namespace
+
+void PopulateWebLayerFrameBinders(
+    content::RenderFrameHost* render_frame_host,
+    service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) {
+  map->Add<weblayer_internals::mojom::PageHandler>(
+      base::BindRepeating(&BindPageHandler));
+#if defined(OS_ANDROID)
+  // TODO(https://crbug.com/1037884): Remove this.
+  map->Add<blink::mojom::InstalledAppProvider>(
+      base::BindRepeating(&StubInstalledAppProvider::Create));
+#endif
+}
+
+}  // namespace weblayer
diff --git a/weblayer/browser/weblayer_browser_interface_binders.h b/weblayer/browser/weblayer_browser_interface_binders.h
new file mode 100644
index 0000000..63ff1d8
--- /dev/null
+++ b/weblayer/browser/weblayer_browser_interface_binders.h
@@ -0,0 +1,23 @@
+// Copyright 2019 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 WEBLAYER_BROWSER_WEBLAYER_BROWSER_INTERFACE_BINDERS_H_
+#define WEBLAYER_BROWSER_WEBLAYER_BROWSER_INTERFACE_BINDERS_H_
+
+#include "services/service_manager/public/cpp/binder_map.h"
+
+namespace content {
+class RenderFrameHost;
+}
+
+namespace weblayer {
+
+void PopulateWebLayerFrameBinders(
+    content::RenderFrameHost* render_frame_host,
+    service_manager::BinderMapWithContext<content::RenderFrameHost*>*
+        binder_map);
+
+}  // namespace weblayer
+
+#endif  // WEBLAYER_BROWSER_WEBLAYER_BROWSER_INTERFACE_BINDERS_H_
diff --git a/weblayer/browser/weblayer_content_browser_overlay_manifest.cc b/weblayer/browser/weblayer_content_browser_overlay_manifest.cc
index 6b4fbc6..c121bc8 100644
--- a/weblayer/browser/weblayer_content_browser_overlay_manifest.cc
+++ b/weblayer/browser/weblayer_content_browser_overlay_manifest.cc
@@ -6,17 +6,12 @@
 
 #include "base/no_destructor.h"
 #include "services/service_manager/public/cpp/manifest_builder.h"
-#include "weblayer/browser/webui/weblayer_internals.mojom.h"
 
 namespace weblayer {
 
 const service_manager::Manifest& GetWebLayerContentBrowserOverlayManifest() {
   static base::NoDestructor<service_manager::Manifest> manifest{
       service_manager::ManifestBuilder()
-          .ExposeInterfaceFilterCapability_Deprecated(
-              "navigation:frame", "renderer",
-              service_manager::Manifest::InterfaceList<
-                  weblayer_internals::mojom::PageHandler>())
           .Build()};
   return *manifest;
 }
diff --git a/weblayer/browser/webui/weblayer_internals_ui.cc b/weblayer/browser/webui/weblayer_internals_ui.cc
index 4449b00e..0c87d2a 100644
--- a/weblayer/browser/webui/weblayer_internals_ui.cc
+++ b/weblayer/browser/webui/weblayer_internals_ui.cc
@@ -23,8 +23,6 @@
   source->SetDefaultResource(IDR_WEBLAYER_INTERNALS_HTML);
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 source);
-  AddHandlerToRegistry(base::BindRepeating(
-      &WebLayerInternalsUI::BindPageHandler, base::Unretained(this)));
 }
 
 WebLayerInternalsUI::~WebLayerInternalsUI() {}
@@ -40,7 +38,7 @@
 }
 #endif
 
-void WebLayerInternalsUI::BindPageHandler(
+void WebLayerInternalsUI::BindInterface(
     mojo::PendingReceiver<weblayer_internals::mojom::PageHandler>
         pending_receiver) {
   if (receiver_.is_bound())
@@ -49,4 +47,6 @@
   receiver_.Bind(std::move(pending_receiver));
 }
 
+WEB_UI_CONTROLLER_TYPE_IMPL(WebLayerInternalsUI)
+
 }  // namespace weblayer
diff --git a/weblayer/browser/webui/weblayer_internals_ui.h b/weblayer/browser/webui/weblayer_internals_ui.h
index 9cf7011..7300eb0 100644
--- a/weblayer/browser/webui/weblayer_internals_ui.h
+++ b/weblayer/browser/webui/weblayer_internals_ui.h
@@ -21,6 +21,12 @@
 
   ~WebLayerInternalsUI() override;
 
+  // Instantiates implementor of the mojom::PageHandler mojo interface
+  // passing the pending receiver that will be internally bound.
+  void BindInterface(
+      mojo::PendingReceiver<weblayer_internals::mojom::PageHandler>
+          pending_receiver);
+
  private:
   // weblayer_internals::mojom::PageHandler:
 #if defined(OS_ANDROID)
@@ -29,12 +35,10 @@
   void SetRemoteDebuggingEnabled(bool enabled) override;
 #endif
 
-  void BindPageHandler(
-      mojo::PendingReceiver<weblayer_internals::mojom::PageHandler>
-          pending_receiver);
-
   mojo::Receiver<weblayer_internals::mojom::PageHandler> receiver_{this};
 
+  WEB_UI_CONTROLLER_TYPE_DECL();
+
   DISALLOW_COPY_AND_ASSIGN(WebLayerInternalsUI);
 };
 
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
index 3c2b758..650901f1 100644
--- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
+++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
@@ -35,6 +35,7 @@
  */
 public class InstrumentationActivity extends FragmentActivity {
     private static final String TAG = "WLInstrumentation";
+    private static final String KEY_MAIN_VIEW_ID = "mainViewId";
 
     public static final String EXTRA_PROFILE_NAME = "EXTRA_PROFILE_NAME";
 
@@ -43,6 +44,7 @@
     public static final String EXTRA_CREATE_WEBLAYER = "EXTRA_CREATE_WEBLAYER";
 
     private Profile mProfile;
+    private Fragment mFragment;
     private Browser mBrowser;
     private Tab mTab;
     private EditText mUrlView;
@@ -51,11 +53,16 @@
     private ViewGroup mTopContentsContainer;
     private IntentInterceptor mIntentInterceptor;
     private Bundle mSavedInstanceState;
+    private TabCallback mTabCallback;
 
     public Tab getTab() {
         return mTab;
     }
 
+    public Fragment getFragment() {
+        return mFragment;
+    }
+
     public Browser getBrowser() {
         return mBrowser;
     }
@@ -88,7 +95,11 @@
         super.onCreate(savedInstanceState);
         mSavedInstanceState = savedInstanceState;
         LinearLayout mainView = new LinearLayout(this);
-        mMainViewId = View.generateViewId();
+        if (savedInstanceState == null) {
+            mMainViewId = View.generateViewId();
+        } else {
+            mMainViewId = savedInstanceState.getInt(KEY_MAIN_VIEW_ID);
+        }
         mainView.setId(mMainViewId);
         mMainView = mainView;
         setContentView(mainView);
@@ -117,6 +128,23 @@
         }
     }
 
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        // When restoring Fragments, FragmentManager tries to put them in the containers with same
+        // ids as before.
+        outState.putInt(KEY_MAIN_VIEW_ID, mMainViewId);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mTabCallback != null) {
+            mTab.unregisterTabCallback(mTabCallback);
+            mTabCallback = null;
+        }
+    }
+
     private void createWebLayerAsync() {
         try {
             WebLayer.loadAsync(getApplicationContext(), webLayer -> onWebLayerReady());
@@ -138,19 +166,20 @@
     private void onWebLayerReady() {
         if (mBrowser != null || isFinishing() || isDestroyed()) return;
 
-        Fragment fragment = getOrCreateBrowserFragment();
-        mBrowser = Browser.fromFragment(fragment);
+        mFragment = getOrCreateBrowserFragment();
+        mBrowser = Browser.fromFragment(mFragment);
         mProfile = mBrowser.getProfile();
 
         mBrowser.setTopView(mTopContentsContainer);
 
         mTab = mBrowser.getActiveTab();
-        mTab.registerTabCallback(new TabCallback() {
+        mTabCallback = new TabCallback() {
             @Override
             public void onVisibleUriChanged(Uri uri) {
                 mUrlView.setText(uri.toString());
             }
-        });
+        };
+        mTab.registerTabCallback(mTabCallback);
     }
 
     private Fragment getOrCreateBrowserFragment() {
@@ -189,6 +218,10 @@
         mUrlView.clearFocus();
     }
 
+    public void setRetainInstance(boolean retain) {
+        mFragment.setRetainInstance(retain);
+    }
+
     private static String getUrlFromIntent(Intent intent) {
         return intent != null ? intent.getDataString() : null;
     }