diff --git a/DEPS b/DEPS
index 72e89b9c..e9984c8 100644
--- a/DEPS
+++ b/DEPS
@@ -105,11 +105,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': 'b8eeb808d84f7892fad9ce8ff6ce62c7fcacb217',
+  'skia_revision': '903fb041a2f86e6273afa501e8e15335cd4e9972',
   # 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': 'd7b61abe7b48928aed739f02bf7695732d359e7e',
+  'v8_revision': '22a88d89e037d3e95dc320f09544b16e9959a407',
   # 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.
@@ -129,7 +129,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '2bfa78540c375916ec9973f0ae11271b098180bd',
+  'pdfium_revision': 'c62aa207e9acb919c33df5f3694fe159619dda86',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -165,7 +165,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': '6a1002b4d937c97a958e28b63a34ac6fd591757a',
+  'catapult_revision': '2a64e6b6d554193f50f82d9557442615457365d9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -539,7 +539,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5bc35fd6c6315985505c2ab7157aae91e1b95a9e',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b96253cab7d9acd6c40a22e1f8f192e61fbc027a',
       'condition': 'checkout_linux',
   },
 
@@ -564,7 +564,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5ba1e9caeecb40a6ec7cc045e6850dbe65f79446',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6ec6d27f2d1bd3d46eddaf469ee21cacc3e04999',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1034,7 +1034,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '21dbf06b5aa6c7dc8cf56314d4a3f96f57956c53',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'a76af0ca2e8c67db2d9d1423c2ca46dadc0aa5dd',
+    Var('webrtc_git') + '/src.git' + '@' + '25cc8ad198731ff8eee35859d82919949afbdff7',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index c72fb04..af1bab5 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -282,8 +282,6 @@
     "frame/frame_border_hit_test.h",
     "frame/frame_header.cc",
     "frame/frame_header.h",
-    "frame/frame_header_origin_text.cc",
-    "frame/frame_header_origin_text.h",
     "frame/frame_header_util.cc",
     "frame/frame_header_util.h",
     "frame/header_view.cc",
diff --git a/ash/frame/custom_frame_view_ash.h b/ash/frame/custom_frame_view_ash.h
index a593db51a..8f41f53 100644
--- a/ash/frame/custom_frame_view_ash.h
+++ b/ash/frame/custom_frame_view_ash.h
@@ -120,6 +120,8 @@
   SkColor GetActiveFrameColorForTest() const;
   SkColor GetInactiveFrameColorForTest() const;
 
+  views::Widget* frame() { return frame_; }
+
  protected:
   // Called when overview mode or split view state changed. If overview mode and
   // split view mode are both active at the same time, the header of the window
diff --git a/ash/system/tray/system_tray_item_detailed_view_delegate.cc b/ash/system/tray/system_tray_item_detailed_view_delegate.cc
index 1041ab1..57771ab69 100644
--- a/ash/system/tray/system_tray_item_detailed_view_delegate.cc
+++ b/ash/system/tray/system_tray_item_detailed_view_delegate.cc
@@ -67,7 +67,8 @@
 
   auto* label = TrayPopupUtils::CreateDefaultLabel();
   label->SetText(l10n_util::GetStringUTF16(string_id));
-  TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::TITLE);
+  TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::TITLE,
+                           false /* use_unified_theme */);
   style.SetupLabel(label);
   tri_view->AddView(TriView::Container::CENTER, label);
 
diff --git a/ash/system/tray/tray_popup_item_style.cc b/ash/system/tray/tray_popup_item_style.cc
index f038e86..50ee296 100644
--- a/ash/system/tray/tray_popup_item_style.cc
+++ b/ash/system/tray/tray_popup_item_style.cc
@@ -85,7 +85,8 @@
   const gfx::FontList& base_font_list = views::Label::GetDefaultFontList();
   switch (font_style_) {
     case FontStyle::TITLE:
-      label->SetFontList(base_font_list.Derive(1, gfx::Font::NORMAL,
+      label->SetFontList(base_font_list.Derive(use_unified_theme_ ? 8 : 1,
+                                               gfx::Font::NORMAL,
                                                gfx::Font::Weight::MEDIUM));
       break;
     case FontStyle::DEFAULT_VIEW_LABEL:
diff --git a/ash/system/unified/sign_out_button.cc b/ash/system/unified/sign_out_button.cc
index a0039f7..d061b87 100644
--- a/ash/system/unified/sign_out_button.cc
+++ b/ash/system/unified/sign_out_button.cc
@@ -26,6 +26,8 @@
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
   SetBorder(views::CreateEmptyBorder(gfx::Insets()));
   label()->SetSubpixelRenderingEnabled(false);
+  label()->SetFontList(views::Label::GetDefaultFontList().Derive(
+      1, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM));
   TrayPopupUtils::ConfigureTrayPopupButton(this);
 }
 
diff --git a/ash/system/unified/unified_detailed_view_delegate.cc b/ash/system/unified/unified_detailed_view_delegate.cc
index 9375c202..91eabcf4 100644
--- a/ash/system/unified/unified_detailed_view_delegate.cc
+++ b/ash/system/unified/unified_detailed_view_delegate.cc
@@ -13,6 +13,7 @@
 #include "ash/system/unified/collapse_button.h"
 #include "ash/system/unified/top_shortcut_button.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
+#include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/vector_icon_types.h"
@@ -124,7 +125,8 @@
 
   auto* label = TrayPopupUtils::CreateDefaultLabel();
   label->SetText(l10n_util::GetStringUTF16(string_id));
-  TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::TITLE);
+  TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::TITLE,
+                           true /* use_unified_theme */);
   style.SetupLabel(label);
   tri_view->AddView(TriView::Container::CENTER, label);
 
@@ -205,7 +207,7 @@
 
 views::Button* UnifiedDetailedViewDelegate::CreateHelpButton(
     views::ButtonListener* listener) {
-  auto* button = new TopShortcutButton(listener, kSystemMenuHelpIcon,
+  auto* button = new TopShortcutButton(listener, vector_icons::kHelpOutlineIcon,
                                        IDS_ASH_STATUS_TRAY_HELP);
   // Help opens a web page, so treat it like Web UI settings.
   if (!TrayPopupUtils::CanOpenWebUISettings())
diff --git a/base/bind_internal.h b/base/bind_internal.h
index 4ebecfa..23c4463 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -46,6 +46,15 @@
 //  BindState<> -- Stores the curried parameters, and is the main entry point
 //                 into the Bind() system.
 
+#if defined(OS_WIN)
+namespace Microsoft {
+namespace WRL {
+template <typename>
+class ComPtr;
+}  // namespace WRL
+}  // namespace Microsoft
+#endif
+
 namespace base {
 
 template <typename T>
@@ -910,6 +919,13 @@
   static T Unwrap(const internal::PassedWrapper<T>& o) { return o.Take(); }
 };
 
+#if defined(OS_WIN)
+template <typename T>
+struct BindUnwrapTraits<Microsoft::WRL::ComPtr<T>> {
+  static T* Unwrap(const Microsoft::WRL::ComPtr<T>& ptr) { return ptr.Get(); }
+};
+#endif
+
 // CallbackCancellationTraits allows customization of Callback's cancellation
 // semantics. By default, callbacks are not cancellable. A specialization should
 // set is_cancellable = true and implement an IsCancelled() that returns if the
diff --git a/chrome/VERSION b/chrome/VERSION
index 2dc3113..b190f73 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=70
 MINOR=0
-BUILD=3501
+BUILD=3502
 PATCH=0
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index d8953d8..67107b2 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-70.0.3500.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-70.0.3501.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index f5e76c5f0..3518dea 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -57,6 +57,7 @@
 #include "content/public/common/user_agent.h"
 #include "google_apis/drive/auth_service.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "net/base/network_change_notifier.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
@@ -209,7 +210,8 @@
 }  // namespace
 
 // Observes drive disable Preference's change.
-class DriveIntegrationService::PreferenceWatcher {
+class DriveIntegrationService::PreferenceWatcher
+    : public net::NetworkChangeNotifier::NetworkChangeObserver {
  public:
   explicit PreferenceWatcher(PrefService* pref_service)
       : pref_service_(pref_service),
@@ -219,12 +221,29 @@
     pref_change_registrar_.Init(pref_service);
     pref_change_registrar_.Add(
         prefs::kDisableDrive,
-        base::Bind(&PreferenceWatcher::OnPreferenceChanged,
-                   weak_ptr_factory_.GetWeakPtr()));
+        base::BindRepeating(&PreferenceWatcher::OnPreferenceChanged,
+                            weak_ptr_factory_.GetWeakPtr()));
+    pref_change_registrar_.Add(
+        prefs::kDisableDriveOverCellular,
+        base::BindRepeating(&PreferenceWatcher::UpdateSyncPauseState,
+                            weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  ~PreferenceWatcher() override {
+    if (integration_service_ && integration_service_->drivefs_holder_) {
+      net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
+    }
   }
 
   void set_integration_service(DriveIntegrationService* integration_service) {
     integration_service_ = integration_service;
+    if (integration_service_->drivefs_holder_) {
+      net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+    }
+  }
+
+  void UpdateSyncPauseState() {
+    OnNetworkChanged(net::NetworkChangeNotifier::GetConnectionType());
   }
 
  private:
@@ -234,6 +253,17 @@
         !pref_service_->GetBoolean(prefs::kDisableDrive));
   }
 
+  // net::NetworkChangeNotifier::NetworkChangeObserver
+  void OnNetworkChanged(
+      net::NetworkChangeNotifier::ConnectionType type) override {
+    if (!integration_service_->GetDriveFsInterface())
+      return;
+
+    integration_service_->GetDriveFsInterface()->SetPauseSyncing(
+        net::NetworkChangeNotifier::IsConnectionCellular(type) &&
+        pref_service_->GetBoolean(prefs::kDisableDriveOverCellular));
+  }
+
   PrefService* pref_service_;
   PrefChangeRegistrar pref_change_registrar_;
   DriveIntegrationService* integration_service_;
@@ -626,6 +656,10 @@
     for (auto& observer : observers_)
       observer.OnFileSystemMounted();
   }
+
+  if (drivefs_holder_ && preference_watcher_) {
+    preference_watcher_->UpdateSyncPauseState();
+  }
 }
 
 void DriveIntegrationService::RemoveDriveMountPoint() {
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 0ad012a..957b2763 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -557,7 +557,12 @@
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
                        MAYBE_WebRequestDeclarative2) {
   ASSERT_TRUE(StartEmbeddedTestServer());
-  ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative2.html"))
+  const char* network_service_arg =
+      base::FeatureList::IsEnabled(network::features::kNetworkService)
+          ? "NetworkServiceEnabled"
+          : "NetworkServiceDisabled";
+  ASSERT_TRUE(RunExtensionSubtestWithArg("webrequest", "test_declarative2.html",
+                                         network_service_arg))
       << message_;
 }
 
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index b47f739..d5fccec 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1553,12 +1553,6 @@
     "browser dialogs. If --top-chrome-md is effectively Material Design "
     "refresh, this option is enabled.";
 
-const char kServiceWorkerNavigationPreloadName[] =
-    "Service worker navigation preload.";
-const char kServiceWorkerNavigationPreloadDescription[] =
-    "Enable web pages to use the experimental service worker navigation "
-    "preload API.";
-
 const char kServiceWorkerPaymentAppsName[] = "Service Worker payment apps";
 const char kServiceWorkerPaymentAppsDescription[] =
     "Enable Service Worker applications to integrate as payment apps";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7562c26..dd9999c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -950,9 +950,6 @@
 extern const char kSecondaryUiMd[];
 extern const char kSecondaryUiMdDescription[];
 
-extern const char kServiceWorkerNavigationPreloadName[];
-extern const char kServiceWorkerNavigationPreloadDescription[];
-
 extern const char kServiceWorkerPaymentAppsName[];
 extern const char kServiceWorkerPaymentAppsDescription[];
 
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 4100b70..86696fb 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -722,7 +722,7 @@
           password_manager_client_bindings_.GetCurrentTargetFrame(),
           ui_data.value().bounds);
       driver->GetPasswordAutofillManager()->MaybeShowPasswordSuggestions(
-          element_bounds_in_screen_space);
+          element_bounds_in_screen_space, ui_data.value().text_direction);
     } else {
       PasswordAccessoryController::FromWebContents(web_contents())
           ->OnAutomaticGenerationStatusChanged(false, base::nullopt, nullptr);
@@ -1053,7 +1053,7 @@
   if (!is_manually_triggered &&
       driver->GetPasswordAutofillManager()
           ->MaybeShowPasswordSuggestionsWithGeneration(
-              element_bounds_in_screen_space))
+              element_bounds_in_screen_space, ui_data.text_direction))
     return;
 
   element_bounds_in_screen_space = GetBoundsInScreenSpace(ui_data.bounds);
diff --git a/chrome/browser/policy/browser_dm_token_storage.h b/chrome/browser/policy/browser_dm_token_storage.h
index 3b3d4ed..97f91f1 100644
--- a/chrome/browser/policy/browser_dm_token_storage.h
+++ b/chrome/browser/policy/browser_dm_token_storage.h
@@ -23,7 +23,8 @@
 // registry once and cached values are returned in subsequent calls.
 //
 // All calls to member functions must be sequenced. It is an error to attempt
-// concurrent store operations.
+// concurrent store operations. RetrieveClientId must be the first method
+// called.
 class BrowserDMTokenStorage {
  public:
   using StoreCallback = base::OnceCallback<void(bool success)>;
diff --git a/chrome/browser/policy/browser_dm_token_storage_mac.mm b/chrome/browser/policy/browser_dm_token_storage_mac.mm
index 0492566..f0fd5a67 100644
--- a/chrome/browser/policy/browser_dm_token_storage_mac.mm
+++ b/chrome/browser/policy/browser_dm_token_storage_mac.mm
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "base/base64url.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
@@ -18,6 +19,7 @@
 #import "base/mac/scoped_nsautorelease_pool.h"
 #include "base/no_destructor.h"
 #include "base/path_service.h"
+#include "base/sha1.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -33,12 +35,14 @@
 
 namespace {
 
-const char kDmTokenBaseDir[] = FILE_PATH_LITERAL("Policy/Enrollment/");
+const char kDmTokenBaseDir[] =
+    FILE_PATH_LITERAL("Google/Chrome Cloud Enrollment/");
 NSString* const kEnrollmentTokenPolicyName =
     @"MachineLevelUserCloudPolicyEnrollmentToken";
-const char kDmTokenFilename[] = FILE_PATH_LITERAL("token");
 
-bool GetDmTokenFilePath(base::FilePath* token_file_path, bool create_dir) {
+bool GetDmTokenFilePath(base::FilePath* token_file_path,
+                        const std::string& client_id,
+                        bool create_dir) {
   if (!base::PathService::Get(base::DIR_APP_DATA, token_file_path))
     return false;
 
@@ -47,14 +51,18 @@
   if (create_dir && !base::CreateDirectory(*token_file_path))
     return false;
 
-  *token_file_path = token_file_path->Append(kDmTokenFilename);
+  std::string filename;
+  base::Base64UrlEncode(base::SHA1HashString(client_id),
+                        base::Base64UrlEncodePolicy::OMIT_PADDING, &filename);
+  *token_file_path = token_file_path->Append(filename.c_str());
 
   return true;
 }
 
-bool StoreDMTokenInDirAppDataDir(const std::string& token) {
+bool StoreDMTokenInDirAppDataDir(const std::string& token,
+                                 const std::string& client_id) {
   base::FilePath token_file_path;
-  if (!GetDmTokenFilePath(&token_file_path, true)) {
+  if (!GetDmTokenFilePath(&token_file_path, client_id, true)) {
     NOTREACHED();
     return false;
   }
@@ -117,7 +125,7 @@
 
 std::string BrowserDMTokenStorageMac::InitDMToken() {
   base::FilePath token_file_path;
-  if (!GetDmTokenFilePath(&token_file_path, true))
+  if (!GetDmTokenFilePath(&token_file_path, RetrieveClientId(), true))
     return std::string();
 
   std::string token;
@@ -131,7 +139,7 @@
   std::string client_id = RetrieveClientId();
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE, {base::MayBlock()},
-      base::BindOnce(&StoreDMTokenInDirAppDataDir, token),
+      base::BindOnce(&StoreDMTokenInDirAppDataDir, token, client_id),
       base::BindOnce(&BrowserDMTokenStorage::OnDMTokenStored,
                      weak_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/policy/browser_dm_token_storage_mac_unittest.cc b/chrome/browser/policy/browser_dm_token_storage_mac_unittest.cc
index eb368a5..1dc9855 100644
--- a/chrome/browser/policy/browser_dm_token_storage_mac_unittest.cc
+++ b/chrome/browser/policy/browser_dm_token_storage_mac_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <iostream>
 
+#include "base/base64url.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_util.h"
@@ -13,6 +14,7 @@
 #include "base/macros.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/sha1.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_path_override.h"
 #include "chrome/common/chrome_paths.h"
@@ -26,8 +28,8 @@
 
 namespace {
 
-const char kDmTokenBaseDir[] = FILE_PATH_LITERAL("Policy/Enrollment/");
-const char kDmTokenFilename[] = FILE_PATH_LITERAL("token");
+const char kDmTokenBaseDir[] =
+    FILE_PATH_LITERAL("Google/Chrome Cloud Enrollment/");
 
 constexpr char kDMToken[] = "fake-dm-token";
 
@@ -92,8 +94,12 @@
   base::FilePath app_data_dir_path;
   ASSERT_TRUE(base::PathService::Get(base::DIR_APP_DATA, &app_data_dir_path));
   base::FilePath dm_token_dir_path = app_data_dir_path.Append(kDmTokenBaseDir);
-  base::FilePath dm_token_file_path =
-      dm_token_dir_path.Append(kDmTokenFilename);
+
+  std::string filename;
+  base::Base64UrlEncode(base::SHA1HashString(storage.InitClientId()),
+                        base::Base64UrlEncodePolicy::OMIT_PADDING, &filename);
+
+  base::FilePath dm_token_file_path = dm_token_dir_path.Append(filename);
 
   std::string dm_token;
   ASSERT_TRUE(base::ReadFileToString(dm_token_file_path, &dm_token));
diff --git a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
index e8f0cfb..26f45ee 100644
--- a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
+++ b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
@@ -16,6 +16,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/containers/span.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -341,8 +342,10 @@
     std::string pdf_data;
 
     ASSERT_TRUE(base::ReadFileToString(pdf_file_save_path_, &pdf_data));
-    ASSERT_TRUE(chrome_pdf::GetPDFDocInfo(pdf_data.data(), pdf_data.size(),
-                                          &num_pages, &max_width_in_points));
+
+    auto pdf_span = base::as_bytes(base::make_span(pdf_data));
+    ASSERT_TRUE(
+        chrome_pdf::GetPDFDocInfo(pdf_span, &num_pages, &max_width_in_points));
 
     ASSERT_GT(num_pages, 0);
     double max_width_in_pixels =
@@ -351,8 +354,7 @@
     for (int i = 0; i < num_pages; ++i) {
       double width_in_points, height_in_points;
       ASSERT_TRUE(chrome_pdf::GetPDFPageSizeByIndex(
-          pdf_data.data(), pdf_data.size(), i, &width_in_points,
-          &height_in_points));
+          pdf_span, i, &width_in_points, &height_in_points));
 
       double width_in_pixels = ConvertUnitDouble(
           width_in_points, kPointsPerInch, kDpi);
@@ -386,10 +388,9 @@
                                             settings.area.size().GetArea());
 
       ASSERT_TRUE(chrome_pdf::RenderPDFPageToBitmap(
-          pdf_data.data(), pdf_data.size(), i, page_bitmap_data.data(),
-          settings.area.size().width(), settings.area.size().height(),
-          settings.dpi.width(), settings.dpi.height(), settings.autorotate,
-          settings.use_color));
+          pdf_span, i, page_bitmap_data.data(), settings.area.size().width(),
+          settings.area.size().height(), settings.dpi.width(),
+          settings.dpi.height(), settings.autorotate, settings.use_color));
       FillPng(&page_bitmap_data, width_in_pixels, max_width_in_pixels,
               settings.area.size().height());
       bitmap_data.insert(bitmap_data.end(),
diff --git a/chrome/browser/resources/chromeos/zip_archiver/manifest.json b/chrome/browser/resources/chromeos/zip_archiver/manifest.json
index 828fa95..82619de 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/manifest.json
+++ b/chrome/browser/resources/chromeos/zip_archiver/manifest.json
@@ -68,6 +68,6 @@
         "js/volume.js"
       ]
     },
-    "content_security_policy": "default-src 'none'; script-src chrome://resources; style-src 'unsafe-inline' chrome://resources;"
+    "content_security_policy": "default-src 'none'; script-src 'self' chrome://resources; style-src 'unsafe-inline' chrome://resources;"
   }
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index 3fc07a1a..a4f5126 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -96,7 +96,7 @@
         <include name="IDR_PDF_INDEX_HTML" file="pdf/index.html" allowexternalscript="true" type="BINDATA" />
         <include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" allowexternalscript="true" type="BINDATA" />
         <include name="IDR_PDF_MAIN_JS" file="pdf/main.js" type="BINDATA" />
-        <include name="IDR_PDF_PDF_JS" file="pdf/pdf.js" type="BINDATA" />
+        <include name="IDR_PDF_PDF_VIEWER_JS" file="pdf/pdf_viewer.js" type="BINDATA" />
         <include name="IDR_PDF_UI_MANAGER_JS" file="pdf/toolbar_manager.js" type="BINDATA" />
         <include name="IDR_PDF_PDF_FITTING_TYPE_JS" file="pdf/pdf_fitting_type.js" type="BINDATA" />
         <include name="IDR_PDF_VIEWPORT_JS" file="pdf/viewport.js" type="BINDATA" />
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html
index dcec3cc..f509a2d6 100644
--- a/chrome/browser/resources/pdf/index.html
+++ b/chrome/browser/resources/pdf/index.html
@@ -40,6 +40,6 @@
 <script src="browser_api.js"></script>
 <script src="coords_transformer.js"></script>
 <script src="metrics.js"></script>
-<script src="pdf.js"></script>
+<script src="pdf_viewer.js"></script>
 <script src="main.js"></script>
 </html>
diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf_viewer.js
similarity index 100%
rename from chrome/browser/resources/pdf/pdf.js
rename to chrome/browser/resources/pdf/pdf_viewer.js
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index 952dba95..0efe913d 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -387,6 +387,17 @@
             </paper-icon-button-light>
           </a>
 
+          <a class$="inherit-color no-outline
+              [[getListItemClass_(unifiedConsentEnabled)]]" tabindex="-1"
+              target="_blank" href="$i18n{syncDashboardUrl}">
+            <div class="start">
+              $i18n{manageSyncedDataTitle}
+            </div>
+            <paper-icon-button-light actionable class="icon-external">
+              <button aria-label="$i18n{manageSyncedDataTitle}"></button>
+            </paper-icon-button-light>
+          </a>
+
           <div id="encryptionDescription"
               hidden="[[syncPrefs.passphraseRequired]]"
               class$="two-line single-column
@@ -452,17 +463,6 @@
             </div>
           </template>
 
-          <a class$="inherit-color no-outline
-              [[getListItemClass_(unifiedConsentEnabled)]]" tabindex="-1"
-              target="_blank" href="$i18n{syncDashboardUrl}">
-            <div class="start">
-              $i18n{manageSyncedDataTitle}
-            </div>
-            <paper-icon-button-light actionable class="icon-external">
-              <button aria-label="$i18n{manageSyncedDataTitle}"></button>
-            </paper-icon-button-light>
-          </a>
-
         </div>
       </div>
     </iron-collapse>
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.html b/chrome/browser/resources/settings/privacy_page/personalization_options.html
index c3e2807..e50aef0 100644
--- a/chrome/browser/resources/settings/privacy_page/personalization_options.html
+++ b/chrome/browser/resources/settings/privacy_page/personalization_options.html
@@ -85,27 +85,12 @@
       </settings-toggle-button>
     </template>
 <if expr="_google_chrome">
-    <template is="dom-if" if="[[!unifiedConsentEnabled]]">
-      <settings-toggle-button id="spellCheckControl"
-          pref="{{prefs.spellcheck.use_spelling_service}}"
-          label="$i18n{spellingPref}"
-          sub-label="$i18n{spellingDescription}"
-          disabled="[[unifiedConsentGiven]]">
-      </settings-toggle-button>
-    </template>
-    <template is="dom-if" if="[[unifiedConsentEnabled]]">
-      <div class="settings-box two-line" id="spellCheckLinkBox">
-        <div class="start">
-          $i18n{spellingPref}
-          <div class="secondary" on-click="onLanguageLinkBoxClick_">
-            $i18nRaw{spellingDescription}
-          </div>
-        </div>
-        <cr-toggle checked="[[prefs.spellcheck.use_spelling_service]]"
-            disabled="[[unifiedConsentGiven]]">
-        </cr-toggle>
-      </div>
-    </template>
+    <settings-toggle-button
+        pref="{{prefs.spellcheck.use_spelling_service}}"
+        label="$i18n{spellingPref}"
+        sub-label="$i18n{spellingDescription}"
+        disabled="[[unifiedConsentGiven]]">
+    </settings-toggle-button>
 </if><!-- _google_chrome -->
   </template>
   <script src="personalization_options.js"></script>
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.js b/chrome/browser/resources/settings/privacy_page/personalization_options.js
index 8ba2842..27b0823 100644
--- a/chrome/browser/resources/settings/privacy_page/personalization_options.js
+++ b/chrome/browser/resources/settings/privacy_page/personalization_options.js
@@ -102,6 +102,7 @@
   },
 
   /**
+   * TODO(crbug.com/855945): Use this function for the spell check error hint
    * @param {!Event} e
    * @private
    */
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index e555fe0..4aa7746 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -40,7 +40,6 @@
 #include "components/signin/core/browser/profile_management_switches.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_buildflags.h"
-#include "components/signin/core/browser/signin_cookie_change_subscription.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "components/signin/core/browser/signin_switches.h"
@@ -249,18 +248,6 @@
       ->RemoveObserver(observer);
 }
 
-std::unique_ptr<SigninClient::CookieChangeSubscription>
-ChromeSigninClient::AddCookieChangeCallback(
-    const GURL& url,
-    const std::string& name,
-    net::CookieChangeCallback callback) {
-  scoped_refptr<net::URLRequestContextGetter> context_getter =
-      profile_->GetRequestContext();
-  DCHECK(context_getter.get());
-  return std::make_unique<SigninCookieChangeSubscription>(
-      context_getter, url, name, std::move(callback));
-}
-
 void ChromeSigninClient::OnSignedIn(const std::string& account_id,
                                     const std::string& gaia_id,
                                     const std::string& username,
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h
index c8c74d1..520a6c1c 100644
--- a/chrome/browser/signin/chrome_signin_client.h
+++ b/chrome/browser/signin/chrome_signin_client.h
@@ -71,10 +71,6 @@
   // <Build Info> <OS> <Version number> (<Last change>)<channel or "-devel">
   // If version information is unavailable, returns "invalid."
   std::string GetProductVersion() override;
-  std::unique_ptr<CookieChangeSubscription> AddCookieChangeCallback(
-      const GURL& url,
-      const std::string& name,
-      net::CookieChangeCallback callback) override;
   void OnSignedIn(const std::string& account_id,
                   const std::string& gaia_id,
                   const std::string& username,
diff --git a/chrome/browser/themes/OWNERS b/chrome/browser/themes/OWNERS
index 328894a..8bbbf35 100644
--- a/chrome/browser/themes/OWNERS
+++ b/chrome/browser/themes/OWNERS
@@ -1,4 +1,5 @@
 estade@chromium.org
+pkasting@chromium.org
 pkotwicz@chromium.org
 
 # COMPONENT: UI>Browser>Themes
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 1af09eba..2e5deaba4 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3212,6 +3212,8 @@
         "views/frame/hosted_app_button_container.h",
         "views/frame/hosted_app_menu_button.cc",
         "views/frame/hosted_app_menu_button.h",
+        "views/frame/hosted_app_origin_text.cc",
+        "views/frame/hosted_app_origin_text.h",
         "views/frame/immersive_mode_controller.cc",
         "views/frame/immersive_mode_controller.h",
         "views/frame/immersive_mode_controller_factory_views.cc",
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
index 07be8a5..c3e2131 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -849,12 +849,12 @@
     // and drop checking state.
     ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
         loc.x() + 10, loc.y(),
-        base::BindOnce(&BookmarkBarViewTest7::Step3A, this)));
+        base::BindOnce(&BookmarkBarViewTest7::Step3A, base::Unretained(this))));
 #else
     // Start a drag.
     ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
         loc.x() + 10, loc.y(),
-        base::BindOnce(&BookmarkBarViewTest7::Step4, this)));
+        base::BindOnce(&BookmarkBarViewTest7::Step4, base::Unretained(this))));
 
     // See comment above this method as to why we do this.
     ScheduleMouseMoveInBackground(loc.x(), loc.y());
@@ -868,7 +868,8 @@
     views::View::ConvertPointToScreen(other_button, &loc);
 
     ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
-        loc.x(), loc.y(), base::BindOnce(&BookmarkBarViewTest7::Step4, this)));
+        loc.x(), loc.y(),
+        base::BindOnce(&BookmarkBarViewTest7::Step4, base::Unretained(this))));
   }
 
   void Step4() {
@@ -956,11 +957,11 @@
     // and drop checking state.
     ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
         loc.x() + 10, loc.y(),
-        base::BindOnce(&BookmarkBarViewTest8::Step3A, this)));
+        base::BindOnce(&BookmarkBarViewTest8::Step3A, base::Unretained(this))));
 #else
     ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
         loc.x() + 10, loc.y(),
-        base::BindOnce(&BookmarkBarViewTest8::Step4, this)));
+        base::BindOnce(&BookmarkBarViewTest8::Step4, base::Unretained(this))));
     // See comment above this method as to why we do this.
     ScheduleMouseMoveInBackground(loc.x(), loc.y());
 #endif
@@ -974,7 +975,7 @@
 
     ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
         loc.x() + 10, loc.y(),
-        base::BindOnce(&BookmarkBarViewTest8::Step4, this)));
+        base::BindOnce(&BookmarkBarViewTest8::Step4, base::Unretained(this))));
   }
 
   void Step4() {
@@ -987,7 +988,8 @@
     gfx::Point loc(button->width() / 2, button->height() / 2);
     views::View::ConvertPointToScreen(button, &loc);
     ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
-        loc.x(), loc.y(), base::BindOnce(&BookmarkBarViewTest8::Step5, this)));
+        loc.x(), loc.y(),
+        base::BindOnce(&BookmarkBarViewTest8::Step5, base::Unretained(this))));
   }
 
   void Step5() {
@@ -1066,7 +1068,8 @@
 
   void Step3() {
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE, base::BindOnce(&BookmarkBarViewTest9::Step4, this),
+        FROM_HERE,
+        base::BindOnce(&BookmarkBarViewTest9::Step4, base::Unretained(this)),
         base::TimeDelta::FromMilliseconds(200));
   }
 
@@ -1082,7 +1085,8 @@
     // which can interfere with Done. We need to run Done in the
     // next execution loop.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&ViewEventTestBase::Done, this));
+        FROM_HERE,
+        base::BindOnce(&ViewEventTestBase::Done, base::Unretained(this)));
   }
 
   int start_y_;
@@ -1338,11 +1342,9 @@
     // Click and wait until the dialog box appears.
     std::unique_ptr<DialogWaiter> dialog_waiter(new DialogWaiter());
     ui_test_utils::MoveMouseToCenterAndPress(
-        child_menu,
-        ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        base::Bind(
-            &BookmarkBarViewTest12::Step4, this, base::Passed(&dialog_waiter)));
+        child_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
+        base::Bind(&BookmarkBarViewTest12::Step4, base::Unretained(this),
+                   base::Passed(&dialog_waiter)));
   }
 
   void Step4(std::unique_ptr<DialogWaiter> waiter) {
@@ -1359,7 +1361,7 @@
     // For some reason return isn't processed correctly unless we delay.
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE,
-        base::BindOnce(&BookmarkBarViewTest12::Step5, this,
+        base::BindOnce(&BookmarkBarViewTest12::Step5, base::Unretained(this),
                        base::Unretained(dialog)),
         base::TimeDelta::FromSeconds(1));
   }
@@ -2308,7 +2310,8 @@
         WM_CANCELMODE, 0, 0);
 
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&BookmarkBarViewTest26::Step3, this));
+        FROM_HERE,
+        base::Bind(&BookmarkBarViewTest26::Step3, base::Unretained(this)));
   }
 
   void Step3() {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 8d73777..1ac25c4 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -10,7 +10,6 @@
 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"  // mash-ok
 #include "ash/frame/default_frame_header.h"      // mash-ok
 #include "ash/frame/frame_border_hit_test.h"     // mash-ok
-#include "ash/frame/frame_header_origin_text.h"  // mash-ok
 #include "ash/frame/frame_header_util.h"         // mash-ok
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_types.h"
@@ -25,9 +24,6 @@
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task_runner.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
@@ -39,6 +35,7 @@
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
+#include "chrome/browser/ui/views/frame/hosted_app_origin_text.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/frame/top_container_view.h"
 #include "chrome/browser/ui/views/profiles/profile_indicator_icon.h"
@@ -133,9 +130,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserNonClientFrameViewAsh, public:
 
-const base::TimeDelta BrowserNonClientFrameViewAsh::kTitlebarAnimationDelay =
-    base::TimeDelta::FromMilliseconds(750);
-
 BrowserNonClientFrameViewAsh::BrowserNonClientFrameViewAsh(
     BrowserFrame* frame,
     BrowserView* browser_view)
@@ -523,8 +517,8 @@
   if (hosted_app_button_container_)
     hosted_app_button_container_->SetPaintAsActive(should_paint_as_active);
 
-  if (frame_header_origin_text_)
-    frame_header_origin_text_->SetPaintAsActive(should_paint_as_active);
+  if (hosted_app_origin_text_)
+    hosted_app_origin_text_->SetPaintAsActive(should_paint_as_active);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -596,11 +590,11 @@
       (tab_strip_visible || immersive) ? 0 : GetTopInset(/*restored=*/false);
   frame()->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, inset);
 
-  if (frame_header_origin_text_) {
+  if (hosted_app_origin_text_) {
     // Align the right side of the text with the left side of the caption
     // buttons.
     gfx::Size origin_text_preferred_size =
-        frame_header_origin_text_->GetPreferredSize();
+        hosted_app_origin_text_->GetPreferredSize();
     int origin_text_width =
         std::min(width() - caption_button_container_->width(),
                  origin_text_preferred_size.width());
@@ -608,7 +602,7 @@
                           origin_text_preferred_size.height());
     SetRightSide(&text_bounds, caption_button_container_->x());
     AlignVerticalCenterWith(&text_bounds, caption_button_container_->bounds());
-    frame_header_origin_text_->SetBoundsRect(text_bounds);
+    hosted_app_origin_text_->SetBoundsRect(text_bounds);
   }
 
   // The top right corner must be occupied by a caption button for easy mouse
@@ -1020,17 +1014,17 @@
         ash::FrameCaptionButton::ColorMode::kThemed, *theme_color);
   }
 
-  // Add the container for extra hosted app buttons (e.g app menu button).
+  // Add the origin text.
   const float inactive_alpha_ratio =
       ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio();
   SkColor inactive_color =
       SkColorSetA(active_color, 255 * inactive_alpha_ratio);
-  hosted_app_button_container_ = new HostedAppButtonContainer(
-      browser_view(), active_color, inactive_color);
+  hosted_app_origin_text_ =
+      new HostedAppOriginText(browser, active_color, inactive_color);
 
-  // Add the origin text.
-  frame_header_origin_text_ = new ash::FrameHeaderOriginText(
-      browser->hosted_app_controller()->GetFormattedUrlOrigin(), active_color,
+  // Add the container for extra hosted app buttons (e.g app menu button).
+  hosted_app_button_container_ = new HostedAppButtonContainer(
+      frame(), browser_view(), hosted_app_origin_text_, active_color,
       inactive_color);
 
   if (IsMash()) {
@@ -1044,25 +1038,12 @@
     hosted_app_extras_container_->SetLayoutManager(std::move(layout));
     AddChildView(hosted_app_extras_container_);
 
-    hosted_app_extras_container_->AddChildView(frame_header_origin_text_);
+    hosted_app_extras_container_->AddChildView(hosted_app_origin_text_);
     hosted_app_extras_container_->AddChildView(hosted_app_button_container_);
   } else {
     caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0);
-    AddChildView(frame_header_origin_text_);
+    AddChildView(hosted_app_origin_text_);
   }
-
-  // Schedule the title bar animation.
-  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation,
-                     weak_factory_.GetWeakPtr()),
-      kTitlebarAnimationDelay);
-}
-
-void BrowserNonClientFrameViewAsh::StartHostedAppAnimation() {
-  frame_header_origin_text_->StartSlideAnimation();
-  hosted_app_button_container_->StartTitlebarAnimation(
-      frame_header_origin_text_->AnimationDuration());
 }
 
 void BrowserNonClientFrameViewAsh::UpdateFrameColors() {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index fb8247e..95045cf 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -28,6 +28,7 @@
 class HostedAppNonClientFrameViewAshTest;
 }
 
+class HostedAppOriginText;
 class HostedAppButtonContainer;
 class TabIconView;
 
@@ -35,7 +36,6 @@
 class DefaultFrameHeader;
 class FrameCaptionButton;
 class FrameCaptionButtonContainerView;
-class FrameHeaderOriginText;
 }
 
 // Provides the BrowserNonClientFrameView for Chrome OS.
@@ -50,9 +50,6 @@
       public aura::WindowObserver,
       public ImmersiveModeController::Observer {
  public:
-  // How long to delay the hosted app origin text animation from starting.
-  static const base::TimeDelta kTitlebarAnimationDelay;
-
   BrowserNonClientFrameViewAsh(BrowserFrame* frame, BrowserView* browser_view);
   ~BrowserNonClientFrameViewAsh() override;
 
@@ -216,10 +213,10 @@
 
   // URL origin text for hosted app windows.
   // Owned by views hierarchy.
-  ash::FrameHeaderOriginText* frame_header_origin_text_ = nullptr;
+  HostedAppOriginText* hosted_app_origin_text_ = nullptr;
 
   // A view that contains the extra views used for hosted apps
-  // (|hosted_app_button_container_| and |frame_header_origin_text_|).
+  // (|hosted_app_button_container_| and |hosted_app_origin_text_|).
   // Only used in Mash.
   views::View* hosted_app_extras_container_ = nullptr;
 
@@ -248,8 +245,6 @@
   scoped_refptr<ImageRegistration> active_frame_overlay_image_registration_;
   scoped_refptr<ImageRegistration> inactive_frame_overlay_image_registration_;
 
-  base::WeakPtrFactory<BrowserNonClientFrameViewAsh> weak_factory_{this};
-
   DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh);
 };
 
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index 49ad2216..d6f8d41 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -118,11 +118,10 @@
     // here and call it on demand in
     // HostedAppButtonContainer::UpdateIconsColor() via a delegate interface.
     hosted_app_button_container_ = new HostedAppButtonContainer(
-        browser_view, GetTitlebarFeatureColor(true),
+        frame, browser_view, nullptr, GetTitlebarFeatureColor(true),
         GetTitlebarFeatureColor(false));
     AddChildView(hosted_app_button_container_);
     // TODO(https://crbug.com/854479): Add FrameHeaderOriginText animation here.
-    hosted_app_button_container_->StartTitlebarAnimation(base::TimeDelta());
   }
 
   minimize_button_ =
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
index ac44295..7a8d36c9 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
@@ -8,8 +8,11 @@
 #include "chrome/browser/extensions/browsertest_util.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/views/frame/app_menu_button.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/web_application_info.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -80,7 +83,7 @@
   if (!InstallAndLaunchHostedApp())
     return;
 
-  DCHECK_EQ(glass_frame_view_->GetTitlebarColor(), *theme_color_);
+  EXPECT_EQ(glass_frame_view_->GetTitlebarColor(), *theme_color_);
 }
 
 IN_PROC_BROWSER_TEST_F(HostedAppGlassBrowserFrameViewTest, NoThemeColor) {
@@ -88,7 +91,48 @@
   if (!InstallAndLaunchHostedApp())
     return;
 
-  DCHECK_EQ(
+  EXPECT_EQ(
       glass_frame_view_->GetTitlebarColor(),
       ThemeProperties::GetDefaultColor(ThemeProperties::COLOR_FRAME, false));
 }
+
+IN_PROC_BROWSER_TEST_F(HostedAppGlassBrowserFrameViewTest, SpaceConstrained) {
+  theme_color_ = base::nullopt;
+  if (!InstallAndLaunchHostedApp())
+    return;
+
+  views::View* page_action_icon_container =
+      browser_view_->toolbar_button_provider()
+          ->GetPageActionIconContainerView();
+  EXPECT_EQ(page_action_icon_container->parent(), hosted_app_button_container_);
+
+  views::View* menu_button =
+      browser_view_->toolbar_button_provider()->GetAppMenuButton();
+  EXPECT_EQ(menu_button->parent(), hosted_app_button_container_);
+
+  // Initially the page action icons are not visible, just the menu button has
+  // width.
+  EXPECT_EQ(page_action_icon_container->width(), 0);
+  int original_menu_button_width = menu_button->width();
+  EXPECT_GT(original_menu_button_width, 0);
+
+  // Cause the zoom page action icon to be visible.
+  chrome::Zoom(app_browser_, content::PAGE_ZOOM_IN);
+
+  // The page action icons should now take up width.
+  EXPECT_GT(page_action_icon_container->width(), 0);
+  EXPECT_EQ(menu_button->width(), original_menu_button_width);
+
+  // Resize the HostedAppButtonContainer just enough to clip out the page action
+  // icons.
+  hosted_app_button_container_->SetSize(
+      gfx::Size(hosted_app_button_container_->width() -
+                    page_action_icon_container->bounds().right(),
+                hosted_app_button_container_->height()));
+  hosted_app_button_container_->Layout();
+
+  // The page action icons should be clipped to 0 width while the app menu
+  // button retains its full width.
+  EXPECT_EQ(page_action_icon_container->width(), 0);
+  EXPECT_EQ(menu_button->width(), original_menu_button_width);
+}
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
index c14d14d..d0c1e87 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -5,12 +5,15 @@
 #include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
 
 #include "base/metrics/histogram_macros.h"
+#include "base/task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h"
 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
 #include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/hosted_app_menu_button.h"
+#include "chrome/browser/ui/views/frame/hosted_app_origin_text.h"
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h"
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
@@ -65,6 +68,9 @@
 
 }  // namespace
 
+const base::TimeDelta HostedAppButtonContainer::kTitlebarAnimationDelay =
+    base::TimeDelta::FromMilliseconds(750);
+
 class HostedAppButtonContainer::ContentSettingsContainer
     : public views::View,
       public ContentSettingImageView::Delegate {
@@ -83,7 +89,16 @@
       v->SetIconColor(icon_color);
   }
 
+  void SetUpForFadeIn() {
+    SetVisible(false);
+    SetPaintToLayer();
+    layer()->SetFillsBoundsOpaquely(false);
+    layer()->SetOpacity(0);
+  }
+
   void FadeIn() {
+    if (visible())
+      return;
     SetVisible(true);
     DCHECK_EQ(layer()->opacity(), 0);
     ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
@@ -91,6 +106,12 @@
     layer()->SetOpacity(1);
   }
 
+  void EnsureVisible() {
+    SetVisible(true);
+    if (layer())
+      layer()->SetOpacity(1);
+  }
+
   const std::vector<ContentSettingImageView*>&
   GetContentSettingViewsForTesting() const {
     return content_setting_views_;
@@ -125,10 +146,6 @@
   DISALLOW_COPY_AND_ASSIGN(ContentSettingsContainer);
 };
 
-void HostedAppButtonContainer::DisableAnimationForTesting() {
-  g_animation_disabled_for_testing = true;
-}
-
 views::View* HostedAppButtonContainer::GetContentSettingContainerForTesting() {
   return content_settings_container_;
 }
@@ -145,17 +162,13 @@
       extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser(
           browser_view->browser()));
 
-  SetLayoutManager(std::make_unique<views::BoxLayout>(
-      views::BoxLayout::kHorizontal, gfx::Insets(),
-      views::LayoutProvider::Get()->GetDistanceMetric(
-          views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
-
-  if (!g_animation_disabled_for_testing) {
-    SetVisible(false);
-    SetPaintToLayer();
-    layer()->SetFillsBoundsOpaquely(false);
-    layer()->SetOpacity(0);
-  }
+  views::BoxLayout& layout =
+      *SetLayoutManager(std::make_unique<views::BoxLayout>(
+          views::BoxLayout::kHorizontal, gfx::Insets(),
+          views::LayoutProvider::Get()->GetDistanceMetric(
+              views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
+  // Right align to clip the leftmost items first when not enough space.
+  layout.set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
 
   std::vector<std::unique_ptr<ContentSettingImageModel>> models =
       ContentSettingImageModel::GenerateContentSettingImageModels();
@@ -173,10 +186,15 @@
   }
 }
 
-HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view,
-                                                   SkColor active_icon_color,
-                                                   SkColor inactive_icon_color)
-    : browser_view_(browser_view),
+HostedAppButtonContainer::HostedAppButtonContainer(
+    views::Widget* widget,
+    BrowserView* browser_view,
+    HostedAppOriginText* hosted_app_origin_text,
+    SkColor active_icon_color,
+    SkColor inactive_icon_color)
+    : scoped_widget_observer_(this),
+      browser_view_(browser_view),
+      hosted_app_origin_text_(hosted_app_origin_text),
       active_icon_color_(active_icon_color),
       inactive_icon_color_(inactive_icon_color),
       content_settings_container_(new ContentSettingsContainer(browser_view)),
@@ -194,13 +212,15 @@
                                       false /* interactive */)),
       app_menu_button_(new HostedAppMenuButton(browser_view)) {
   DCHECK(browser_view_);
-  auto layout = std::make_unique<views::BoxLayout>(
-      views::BoxLayout::kHorizontal,
-      gfx::Insets(0, HorizontalPaddingBetweenItems()),
-      HorizontalPaddingBetweenItems());
-  layout->set_cross_axis_alignment(
+  views::BoxLayout& layout =
+      *SetLayoutManager(std::make_unique<views::BoxLayout>(
+          views::BoxLayout::kHorizontal,
+          gfx::Insets(0, HorizontalPaddingBetweenItems()),
+          HorizontalPaddingBetweenItems()));
+  // Right align to clip the leftmost items first when not enough space.
+  layout.set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
+  layout.set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
-  SetLayoutManager(std::move(layout));
 
   AddChildView(content_settings_container_);
   AddChildView(page_action_icon_container_view_);
@@ -211,6 +231,7 @@
 
   browser_view_->SetToolbarButtonProvider(this);
   browser_view_->immersive_mode_controller()->AddObserver(this);
+  scoped_widget_observer_.Add(widget);
 }
 
 HostedAppButtonContainer::~HostedAppButtonContainer() {
@@ -231,6 +252,31 @@
   UpdateIconsColor();
 }
 
+bool HostedAppButtonContainer::ShouldAnimate() const {
+  return !g_animation_disabled_for_testing && hosted_app_origin_text_ &&
+         !browser_view_->immersive_mode_controller()->IsEnabled();
+}
+
+void HostedAppButtonContainer::StartTitlebarAnimation() {
+  if (!ShouldAnimate())
+    return;
+
+  hosted_app_origin_text_->StartSlideAnimation();
+  app_menu_button_->StartHighlightAnimation(
+      HostedAppOriginText::AnimationDuration());
+  icon_fade_in_delay_.Start(
+      FROM_HERE, HostedAppOriginText::AnimationDuration(), this,
+      &HostedAppButtonContainer::FadeInContentSettingIcons);
+}
+
+void HostedAppButtonContainer::FadeInContentSettingIcons() {
+  content_settings_container_->FadeIn();
+}
+
+void HostedAppButtonContainer::DisableAnimationForTesting() {
+  g_animation_disabled_for_testing = true;
+}
+
 void HostedAppButtonContainer::UpdateIconsColor() {
   SkColor icon_color =
       paint_as_active_ ? active_icon_color_ : inactive_icon_color_;
@@ -239,31 +285,14 @@
   app_menu_button_->SetIconColor(icon_color);
 }
 
-void HostedAppButtonContainer::StartTitlebarAnimation(
-    base::TimeDelta origin_text_slide_duration) {
-  if (g_animation_disabled_for_testing ||
-      browser_view_->immersive_mode_controller()->IsEnabled()) {
-    return;
-  }
-
-  app_menu_button_->StartHighlightAnimation(origin_text_slide_duration);
-
-  fade_in_content_setting_buttons_timer_.Start(
-      FROM_HERE, origin_text_slide_duration, content_settings_container_,
-      &ContentSettingsContainer::FadeIn);
-}
-
 void HostedAppButtonContainer::ChildPreferredSizeChanged(views::View* child) {
   PreferredSizeChanged();
 }
 
 void HostedAppButtonContainer::OnImmersiveRevealStarted() {
-  // Cancel the content setting animation as icons need immediately show in
-  // immersive mode.
-  if (fade_in_content_setting_buttons_timer_.IsRunning()) {
-    fade_in_content_setting_buttons_timer_.AbandonAndStop();
-    content_settings_container_->SetVisible(true);
-  }
+  // Don't wait for the fade in animation to make content setting icons visible
+  // once in immersive mode.
+  content_settings_container_->EnsureVisible();
 }
 
 void HostedAppButtonContainer::ChildVisibilityChanged(views::View* child) {
@@ -339,3 +368,16 @@
 views::AccessiblePaneView* HostedAppButtonContainer::GetAsAccessiblePaneView() {
   return this;
 }
+
+void HostedAppButtonContainer::OnWidgetVisibilityChanged(views::Widget* widget,
+                                                         bool visibility) {
+  if (!visibility || !pending_widget_visibility_)
+    return;
+  pending_widget_visibility_ = false;
+  if (ShouldAnimate()) {
+    content_settings_container_->SetUpForFadeIn();
+    animation_start_delay_.Start(
+        FROM_HERE, kTitlebarAnimationDelay, this,
+        &HostedAppButtonContainer::StartTitlebarAnimation);
+  }
+}
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.h b/chrome/browser/ui/views/frame/hosted_app_button_container.h
index 3409425..f39a9cd 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.h
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.h
@@ -8,6 +8,9 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/scoped_observer.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
@@ -17,6 +20,7 @@
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/button/menu_button_listener.h"
 #include "ui/views/view.h"
+#include "ui/views/widget/widget_observer.h"
 
 namespace {
 class HostedAppNonClientFrameViewAshTest;
@@ -24,10 +28,12 @@
 
 class AppMenuButton;
 class BrowserView;
+class HostedAppOriginText;
 class HostedAppMenuButton;
 
 namespace views {
 class MenuButton;
+class Widget;
 }
 
 // A container for hosted app buttons in the title bar.
@@ -35,11 +41,14 @@
                                  public BrowserActionsContainer::Delegate,
                                  public PageActionIconView::Delegate,
                                  public ToolbarButtonProvider,
-                                 public ImmersiveModeController::Observer {
+                                 public ImmersiveModeController::Observer,
+                                 public views::WidgetObserver {
  public:
   // |active_icon_color| and |inactive_icon_color| indicate the colors to use
   // for button icons when the window is focused and blurred respectively.
-  HostedAppButtonContainer(BrowserView* browser_view,
+  HostedAppButtonContainer(views::Widget* widget,
+                           BrowserView* browser_view,
+                           HostedAppOriginText* hosted_app_origin_text,
                            SkColor active_icon_color,
                            SkColor inactive_icon_color);
   ~HostedAppButtonContainer() override;
@@ -49,15 +58,19 @@
   // Sets the container to paints its buttons the active/inactive color.
   void SetPaintAsActive(bool active);
 
-  // Animates the menu button and content setting icons. Intended to run in sync
-  // with a FrameHeaderOriginText slide animation.
-  void StartTitlebarAnimation(base::TimeDelta origin_text_slide_duration);
-
  private:
   friend class HostedAppNonClientFrameViewAshTest;
   friend class HostedAppGlassBrowserFrameViewTest;
   friend class ImmersiveModeControllerAshHostedAppBrowserTest;
 
+  // Duration to wait before starting the opening animation.
+  static const base::TimeDelta kTitlebarAnimationDelay;
+
+  // Methods for coordinate the titlebar animation (origin text slide, menu
+  // highlight and icon fade in).
+  bool ShouldAnimate() const;
+  void StartTitlebarAnimation();
+  void FadeInContentSettingIcons();
   static void DisableAnimationForTesting();
 
   class ContentSettingsContainer;
@@ -67,8 +80,6 @@
   const std::vector<ContentSettingImageView*>&
   GetContentSettingViewsForTesting() const;
 
-  void FadeInContentSettingButtons();
-
   void UpdateIconsColor();
 
   // views::View:
@@ -98,24 +109,35 @@
   // ImmersiveModeController::Observer:
   void OnImmersiveRevealStarted() override;
 
+  // views::WidgetObserver:
+  void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override;
+
+  // Whether we're waiting for the widget to become visible.
+  bool pending_widget_visibility_ = true;
+
+  ScopedObserver<views::Widget, views::WidgetObserver> scoped_widget_observer_;
+
+  // Timers for synchronising their respective parts of the titlebar animation.
+  base::OneShotTimer animation_start_delay_;
+  base::OneShotTimer icon_fade_in_delay_;
+
   // The containing browser view.
   BrowserView* browser_view_;
 
+  // The origin text to coordinate the titlebar animation with.
+  HostedAppOriginText* hosted_app_origin_text_ = nullptr;
+
   // Button colors.
   bool paint_as_active_ = true;
   const SkColor active_icon_color_;
   const SkColor inactive_icon_color_;
 
-  base::OneShotTimer fade_in_content_setting_buttons_timer_;
-
   // Owned by the views hierarchy.
   ContentSettingsContainer* content_settings_container_ = nullptr;
   PageActionIconContainerView* page_action_icon_container_view_ = nullptr;
   BrowserActionsContainer* browser_actions_container_ = nullptr;
   HostedAppMenuButton* app_menu_button_ = nullptr;
 
-  base::OneShotTimer opening_animation_timer_;
-
   DISALLOW_COPY_AND_ASSIGN(HostedAppButtonContainer);
 };
 
diff --git a/ash/frame/frame_header_origin_text.cc b/chrome/browser/ui/views/frame/hosted_app_origin_text.cc
similarity index 79%
rename from ash/frame/frame_header_origin_text.cc
rename to chrome/browser/ui/views/frame/hosted_app_origin_text.cc
index a2f0beb..6b7073d 100644
--- a/ash/frame/frame_header_origin_text.cc
+++ b/chrome/browser/ui/views/frame/hosted_app_origin_text.cc
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/frame/frame_header_origin_text.h"
+#include "chrome/browser/ui/views/frame/hosted_app_origin_text.h"
 
 #include "base/i18n/rtl.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/compositor/layer_animation_element.h"
 #include "ui/compositor/layer_animation_sequence.h"
@@ -12,8 +14,6 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/fill_layout.h"
 
-namespace ash {
-
 namespace {
 
 constexpr base::TimeDelta kOriginSlideInDuration =
@@ -27,13 +27,19 @@
 
 }  // namespace
 
-FrameHeaderOriginText::FrameHeaderOriginText(const base::string16& origin,
-                                             SkColor active_color,
-                                             SkColor inactive_color)
+HostedAppOriginText::HostedAppOriginText(Browser* browser,
+                                         SkColor active_color,
+                                         SkColor inactive_color)
     : active_color_(active_color), inactive_color_(inactive_color) {
+  DCHECK(
+      extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser(
+          browser));
+
   SetLayoutManager(std::make_unique<views::FillLayout>());
 
-  label_ = std::make_unique<views::Label>(origin).release();
+  label_ = std::make_unique<views::Label>(
+               browser->hosted_app_controller()->GetFormattedUrlOrigin())
+               .release();
   label_->SetElideBehavior(gfx::ELIDE_HEAD);
   label_->SetSubpixelRenderingEnabled(false);
   label_->SetEnabledColor(active_color);
@@ -51,13 +57,13 @@
   layer()->SetMasksToBounds(true);
 }
 
-FrameHeaderOriginText::~FrameHeaderOriginText() = default;
+HostedAppOriginText::~HostedAppOriginText() = default;
 
-void FrameHeaderOriginText::SetPaintAsActive(bool active) {
+void HostedAppOriginText::SetPaintAsActive(bool active) {
   label_->SetEnabledColor(active ? active_color_ : inactive_color_);
 }
 
-void FrameHeaderOriginText::StartSlideAnimation() {
+void HostedAppOriginText::StartSlideAnimation() {
   ui::Layer* label_layer = label_->layer();
 
   // Current state will become the first animation keyframe.
@@ -104,14 +110,12 @@
   NotifyAccessibilityEvent(ax::mojom::Event::kValueChanged, true);
 }
 
-base::TimeDelta FrameHeaderOriginText::AnimationDuration() {
+base::TimeDelta HostedAppOriginText::AnimationDuration() {
   return kOriginSlideInDuration + kOriginPauseDuration +
          kOriginSlideOutDuration;
 }
 
-void FrameHeaderOriginText::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+void HostedAppOriginText::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ax::mojom::Role::kApplication;
   node_data->SetName(label_->text());
 }
-
-}  // namespace ash
diff --git a/ash/frame/frame_header_origin_text.h b/chrome/browser/ui/views/frame/hosted_app_origin_text.h
similarity index 63%
rename from ash/frame/frame_header_origin_text.h
rename to chrome/browser/ui/views/frame/hosted_app_origin_text.h
index 2b7248f..8b10fa3 100644
--- a/ash/frame/frame_header_origin_text.h
+++ b/chrome/browser/ui/views/frame/hosted_app_origin_text.h
@@ -2,28 +2,27 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
-#define ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
+#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_HOSTED_APP_ORIGIN_TEXT_H_
+#define CHROME_BROWSER_UI_VIEWS_FRAME_HOSTED_APP_ORIGIN_TEXT_H_
 
-#include "ash/ash_export.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/views/view.h"
 
+class Browser;
+
 namespace views {
 class Label;
 }
 
-namespace ash {
-
 // A URL's origin text with a slide in/out animation.
-class ASH_EXPORT FrameHeaderOriginText : public views::View {
+class HostedAppOriginText : public views::View {
  public:
-  FrameHeaderOriginText(const base::string16& origin,
-                        SkColor active_color,
-                        SkColor inactive_color);
-  ~FrameHeaderOriginText() override;
+  HostedAppOriginText(Browser* browser,
+                      SkColor active_color,
+                      SkColor inactive_color);
+  ~HostedAppOriginText() override;
 
   // Sets whether to paint the text with the active/inactive color.
   void SetPaintAsActive(bool active);
@@ -44,9 +43,7 @@
   const SkColor active_color_;
   const SkColor inactive_color_;
 
-  DISALLOW_COPY_AND_ASSIGN(FrameHeaderOriginText);
+  DISALLOW_COPY_AND_ASSIGN(HostedAppOriginText);
 };
 
-}  // namespace ash
-
-#endif  // ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
+#endif  // CHROME_BROWSER_UI_VIEWS_FRAME_HOSTED_APP_ORIGIN_TEXT_H_
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
index 34a1fad..95a649d 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
@@ -133,6 +133,9 @@
     return BrowserView::GetBrowserViewForBrowser(browser_);
   }
   ImmersiveModeController* controller() { return controller_; }
+  base::TimeDelta titlebar_animation_delay() {
+    return HostedAppButtonContainer::kTitlebarAnimationDelay;
+  }
 
  private:
   // Not owned.
@@ -331,8 +334,7 @@
     frame_view = static_cast<BrowserNonClientFrameViewAsh*>(
         browser_view->GetWidget()->non_client_view()->frame_view());
 
-    task_runner->FastForwardBy(
-        BrowserNonClientFrameViewAsh::kTitlebarAnimationDelay);
+    task_runner->FastForwardBy(titlebar_animation_delay());
 
     VerifyButtonsInImmersiveMode(frame_view);
   }
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
index 06b50d0..b5d733c 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
@@ -18,8 +18,11 @@
     PageActionIconView::Delegate* page_action_icon_delegate,
     LocationBarView::Delegate* location_bar_delegate)
     : zoom_observer_(this) {
-  SetLayoutManager(std::make_unique<views::BoxLayout>(
-      views::BoxLayout::kHorizontal, gfx::Insets(), between_icon_spacing));
+  views::BoxLayout& layout =
+      *SetLayoutManager(std::make_unique<views::BoxLayout>(
+          views::BoxLayout::kHorizontal, gfx::Insets(), between_icon_spacing));
+  // Right align to clip the leftmost items first when not enough space.
+  layout.set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
 
   for (PageActionIconType type : types_enabled) {
     switch (type) {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index 4d571af9..745683d 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -431,7 +431,7 @@
   source->AddResourcePath("pdf/index.html", IDR_PDF_INDEX_HTML);
   source->AddResourcePath("pdf/index.css", IDR_PDF_INDEX_CSS);
   source->AddResourcePath("pdf/main.js", IDR_PDF_MAIN_JS);
-  source->AddResourcePath("pdf/pdf.js", IDR_PDF_PDF_JS);
+  source->AddResourcePath("pdf/pdf_viewer.js", IDR_PDF_PDF_VIEWER_JS);
   source->AddResourcePath("pdf/toolbar_manager.js", IDR_PDF_UI_MANAGER_JS);
   source->AddResourcePath("pdf/pdf_fitting_type.js",
                           IDR_PDF_PDF_FITTING_TYPE_JS);
diff --git a/chrome/chrome_cleaner/BUILD.gn b/chrome/chrome_cleaner/BUILD.gn
index 040bc97..59124b9 100644
--- a/chrome/chrome_cleaner/BUILD.gn
+++ b/chrome/chrome_cleaner/BUILD.gn
@@ -22,14 +22,10 @@
     "//chrome/chrome_cleaner/pup_data:unittest_sources",
     "//chrome/chrome_cleaner/settings:unittest_sources",
     "//chrome/chrome_cleaner/strings:unittest_sources",
-    "//chrome/chrome_cleaner/test:unittest_sources",
 
     # Dependencies of the test harness.
     "//base",
     "//base/test:test_support",
-    "//chrome/chrome_cleaner/os:cleaner_os",
-    "//chrome/chrome_cleaner/os:common_os",
-    "//chrome/chrome_cleaner/test:test_util",
     "//sandbox/win:sandbox",
     "//testing/gtest",
   ]
diff --git a/chrome/chrome_cleaner/DEPS b/chrome/chrome_cleaner/DEPS
index 16f67f85..aa45b14 100644
--- a/chrome/chrome_cleaner/DEPS
+++ b/chrome/chrome_cleaner/DEPS
@@ -1,4 +1,3 @@
 include_rules = [
-  "+sandbox/win/src",
   "+testing/gtest",
 ]
diff --git a/chrome/chrome_cleaner/os/BUILD.gn b/chrome/chrome_cleaner/os/BUILD.gn
index fe0dbf45..ee87e0ff 100644
--- a/chrome/chrome_cleaner/os/BUILD.gn
+++ b/chrome/chrome_cleaner/os/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("common_os") {
+static_library("common_os") {
   sources = [
     "digest_verifier.cc",
     "digest_verifier.h",
@@ -74,6 +74,7 @@
     "ntdll.lib",  # For NtQueryKey
     "secur32.lib",  # For GetUserNameEx
     "taskschd.lib",  # For CLSID_TaskScheduler
+    "wintrust.lib",  # For WinVerifyTrust
   ]
 
   defines = [ "SECURITY_WIN32" ]  # For secur32.lib
@@ -90,7 +91,7 @@
   ]
 }
 
-source_set("cleaner_os") {
+static_library("cleaner_os") {
   sources = [
     "file_removal_status_updater.cc",
     "file_removal_status_updater.h",
@@ -123,27 +124,11 @@
 
   sources = [
     # TODO(joenotcharles): Copy unit tests from the internal repo.
-    "digest_verifier_unittest.cc",
-    "disk_util_unittest.cc",
-    "file_path_sanitization_unittest.cc",
-    "file_path_set_unittest.cc",
-    "file_removal_status_updater_unittest.cc",
-    "file_remover_unittest.cc",
   ]
 
   deps = [
     ":cleaner_os",
     ":common_os",
     ":file_remover_api",
-    "//base",
-    "//base/test:test_config",
-    "//base/test:test_support",
-    "//chrome/chrome_cleaner/logging/proto:removal_status_proto",
-    "//chrome/chrome_cleaner/strings",
-    "//chrome/chrome_cleaner/test:test_executables",
-    "//chrome/chrome_cleaner/test:test_strings",
-    "//chrome/chrome_cleaner/test:test_util",
-    "//chrome/chrome_cleaner/test/resources:test_resources",
-    "//testing/gtest",
   ]
 }
diff --git a/chrome/chrome_cleaner/os/digest_verifier_unittest.cc b/chrome/chrome_cleaner/os/digest_verifier_unittest.cc
deleted file mode 100644
index 2be0340..0000000
--- a/chrome/chrome_cleaner/os/digest_verifier_unittest.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/os/digest_verifier.h"
-
-#include "base/base_paths.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
-#include "chrome/chrome_cleaner/os/system_util.h"
-#include "chrome/chrome_cleaner/test/resources/grit/test_resources.h"
-#include "chrome/chrome_cleaner/test/test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-TEST(DigestVerifier, KnownFile) {
-  std::shared_ptr<DigestVerifier> digest_verifier =
-      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST);
-  ASSERT_TRUE(digest_verifier);
-
-  base::FilePath dll_path = GetSampleDLLPath();
-  ASSERT_TRUE(base::PathExists(dll_path)) << dll_path.value();
-
-  EXPECT_TRUE(digest_verifier->IsKnownFile(dll_path));
-}
-
-TEST(DigestVerifier, UnknownFile) {
-  std::shared_ptr<DigestVerifier> digest_verifier =
-      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST);
-  ASSERT_TRUE(digest_verifier);
-
-  const base::FilePath self_path =
-      PreFetchedPaths::GetInstance()->GetExecutablePath();
-
-  EXPECT_FALSE(digest_verifier->IsKnownFile(self_path));
-}
-
-TEST(DigestVerifier, InexistentFile) {
-  std::shared_ptr<DigestVerifier> digest_verifier =
-      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST);
-  ASSERT_TRUE(digest_verifier);
-
-  base::FilePath invalid_path(L"this_file_should_not_exist.dll");
-  ASSERT_FALSE(base::PathExists(invalid_path));
-
-  EXPECT_FALSE(digest_verifier->IsKnownFile(invalid_path));
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/disk_util.cc b/chrome/chrome_cleaner/os/disk_util.cc
index 6b8e4b2..5e0534a 100644
--- a/chrome/chrome_cleaner/os/disk_util.cc
+++ b/chrome/chrome_cleaner/os/disk_util.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/chrome_cleaner/os/disk_util.h"
 
+#include <softpub.h>
 #include <stdint.h>
 
 #include <algorithm>
@@ -134,6 +135,22 @@
   }
 }
 
+// Return whether an executable is whitelisted. On success, |file_information|
+// receives the file version information. |file_information| is not modified by
+// this function but cannot be const because of the accessors prototype in base.
+bool IsExecutableWhiteListed(FileVersionInfo* file_information) {
+  DCHECK(file_information);
+  bool white_listed = false;
+  base::string16 company_name = file_information->company_name();
+  for (const base::string16& white_listed_name : company_white_list) {
+    if (company_name.compare(white_listed_name) == 0) {
+      white_listed = true;
+      break;
+    }
+  }
+  return white_listed;
+}
+
 void AppendFileInformationField(const wchar_t* field_name,
                                 const base::string16& field,
                                 base::string16* information) {
@@ -503,28 +520,10 @@
   return content;
 }
 
-bool IsExecutableOnDefaultReportingWhiteList(const base::FilePath& file_path) {
-  std::unique_ptr<FileVersionInfo> file_information(
-      FileVersionInfo::CreateFileVersionInfo(file_path));
-  if (!file_information)
-    return false;
-
-  bool white_listed = false;
-  base::string16 company_name = file_information->company_name();
-  for (const base::string16& white_listed_name : company_white_list) {
-    if (company_name.compare(white_listed_name) == 0) {
-      white_listed = true;
-      break;
-    }
-  }
-  return white_listed;
-}
-
 bool RetrieveDetailedFileInformation(
     const base::FilePath& file_path,
     internal::FileInformation* file_information,
-    bool* white_listed,
-    ReportingWhiteListCallback white_list_callback) {
+    bool* white_listed) {
   DCHECK(file_information);
   DCHECK(white_listed);
 
@@ -532,7 +531,9 @@
   if (!TryToExpandPath(file_path, &expanded_path))
     return false;
 
-  if (std::move(white_list_callback).Run(file_path)) {
+  std::unique_ptr<FileVersionInfo> version(
+      FileVersionInfo::CreateFileVersionInfo(expanded_path));
+  if (version.get() && IsExecutableWhiteListed(version.get())) {
     *white_listed = true;
     return false;
   }
@@ -549,9 +550,7 @@
   }
 
   // Set the executable version information, when available.
-  std::unique_ptr<FileVersionInfo> version(
-      FileVersionInfo::CreateFileVersionInfo(expanded_path));
-  if (version) {
+  if (version.get()) {
     file_information->company_name = version->company_name();
     file_information->company_short_name = version->company_short_name();
     file_information->product_name = version->product_name();
diff --git a/chrome/chrome_cleaner/os/disk_util.h b/chrome/chrome_cleaner/os/disk_util.h
index 4285c1e8..201c5dcc 100644
--- a/chrome/chrome_cleaner/os/disk_util.h
+++ b/chrome/chrome_cleaner/os/disk_util.h
@@ -14,8 +14,6 @@
 #include <string>
 #include <vector>
 
-#include "base/bind.h"
-#include "base/callback.h"
 #include "base/strings/string16.h"
 #include "base/win/scoped_handle.h"
 #include "chrome/chrome_cleaner/os/disk_util_types.h"
@@ -29,9 +27,6 @@
 
 class LayeredServiceProviderAPI;
 
-typedef base::OnceCallback<bool(const base::FilePath&)>
-    ReportingWhiteListCallback;
-
 // Return the full path of the relative path |input_path| when expanded to the
 // 64 bits program files path. Return an empty path when not running on 64 bits
 // OS.
@@ -97,20 +92,13 @@
 base::string16 FileInformationToString(
     const internal::FileInformation& file_information);
 
-// Returns true if the given |path| refers to an executable which is
-// whitelisted so that its details should not be reported.
-bool IsExecutableOnDefaultReportingWhiteList(const base::FilePath& file_path);
-
 // Retrieve the detailed information for the executable |file_path| and append
-// the fields to |file_information|. If the executable is |white_listed|
-// according to the given |white_list_callback|, |file_information| stays
-// unchanged.
+// the fields to |file_information|. If the executable is |white_listed|,
+// |file_information| stay unchanged.
 bool RetrieveDetailedFileInformation(
     const base::FilePath& file_path,
     internal::FileInformation* file_information,
-    bool* white_listed,
-    ReportingWhiteListCallback white_list_callback =
-        base::BindOnce(&IsExecutableOnDefaultReportingWhiteList));
+    bool* white_listed);
 
 // Retrieve the file information path, dates and size into |file_information|.
 bool RetrieveBasicFileInformation(const base::FilePath& file_path,
diff --git a/chrome/chrome_cleaner/os/disk_util_unittest.cc b/chrome/chrome_cleaner/os/disk_util_unittest.cc
deleted file mode 100644
index 4d8741a..0000000
--- a/chrome/chrome_cleaner/os/disk_util_unittest.cc
+++ /dev/null
@@ -1,1233 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/os/disk_util.h"
-
-#include <windows.h>
-
-#include <shlobj.h>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/path_service.h"
-#include "base/process/launch.h"
-#include "base/stl_util.h"
-#include "base/strings/strcat.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_path_override.h"
-#include "base/test/test_shortcut_win.h"
-#include "base/test/test_timeouts.h"
-#include "base/win/windows_version.h"
-#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
-#include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h"
-#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
-#include "chrome/chrome_cleaner/strings/string_util.h"
-#include "chrome/chrome_cleaner/test/test_executables.h"
-#include "chrome/chrome_cleaner/test/test_file_util.h"
-#include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
-#include "chrome/chrome_cleaner/test/test_strings.h"
-#include "chrome/chrome_cleaner/test/test_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-namespace {
-
-// A path name under program files.
-const wchar_t kProgramFilesBaseName[] = L"Foo";
-
-// Keep these digests in sorted order.
-const char* const kFileContentDigests[] = {
-    "02544E052F29BBA79C81243EC63B43B6CD85B185461928E65BFF501346C62A75",
-    "04614470DDF4939091F5EC4A13C92A9EAAACF07CA5C3F713E792E2D21CD24075",
-    // Hash for content: |kFileContent2|.
-    "82E0B92772BC0DA59AAB0B9231AA006FB37B4F99EC3E853C5A62786A1C7215BD",
-    "94F7BDF53CDFDE7AA5E5C90BCDA6793B7377CE39E2591ABC758EBAE8072A275C",
-    // Hash for content: |kFileContent1|.
-    "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371"};
-
-const wchar_t kFileName1[] = L"Filename one";
-const wchar_t kFileName2[] = L"Filename two";
-const wchar_t kFileName3[] = L"Third filename";
-const wchar_t kLongFileName1[] = L"Long File Name.bla";
-const wchar_t kLongFileName2[] = L"Other Long File Name.bla";
-const wchar_t kLongFileName2Subset[] = L"Long File";
-const char kFileContent1[] = "This is the file content.";
-const char kFileContent2[] = "Hi!";
-const char kFileContent3[] = "Hello World!";
-
-const internal::FileInformation kFileInformation1(L"some/path/something.tmp",
-                                                  "3/1/2016",
-                                                  "3/3/2016",
-                                                  "somedigest1234",
-                                                  9876,
-                                                  L"Company Name",
-                                                  L"CNShort",
-                                                  L"Product Name",
-                                                  L"PNShort",
-                                                  L"Internal Name",
-                                                  L"Something_Original.tmp",
-                                                  L"Very descriptive",
-                                                  L"42.1.2");
-
-const wchar_t kFileInformation1ExpectedString[] =
-    L"path = 'some/path/something.tmp', file_creation_date = "
-    L"'3/1/2016', file_last_modified_date = '3/3/2016', digest = "
-    L"'somedigest1234', size = '9876', company_name = 'Company Name', "
-    L"company_short_name = 'CNShort', product_name = 'Product Name', "
-    L"product_short_name = 'PNShort', internal_name = 'Internal Name', "
-    L"original_filename = 'Something_Original.tmp', file_description = 'Very "
-    L"descriptive', file_version = '42.1.2', active_file = '0'";
-
-// All potential format of content that get from registry. %ls will be replaced
-// by the executable path.
-// clang-format off
-const wchar_t* kMockRegistryContents[] = {
-    // Straight path as is.
-    L"%ls",
-    L"\"%ls\"",
-    // With command line arguments.
-    L"%ls -s",
-    L"\"%ls\" -s",
-    L"\"%ls -s\"",
-    // Using rundll.
-    L"C:\\Windows\\SysWow64\\rundll32 %ls",
-    L"C:\\Windows\\SysWow64\\rundll32 \"%ls\"",
-    // Using rundll with args.
-    L"C:\\Windows\\SysWow64\\rundll32.exe %ls,OpenAs_RunDLL %%1",
-    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\",OpenAs_RunDLL %%1",
-    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls,OpenAs_RunDLL\" %%1",
-    L"C:\\Windows\\SysWow64\\rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
-    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\" a1,OpenAs_RunDLL %%1",
-    L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls a1,OpenAs_RunDLL\" %%1",
-    L"C:\\Windows\\System32\\rundll32 %ls",
-    // Rundll without a path.
-    L"rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
-    L"rundll32.exe \"%ls\" -s %%1",
-    L"rundll32.exe \"%ls -s\" %%1",
-    // Rundll without extension.
-    L"C:\\Windows\\SysWow64\\rundll32 %ls a1 a2,OpenAs_RunDLL %%1",
-    L"C:\\Windows\\SysWow64\\rundll32 \"%ls\" -s %%1",
-    L"C:\\Windows\\SysWow64\\rundll32 \"%ls -s\" %%1"};
-// clang-format on
-
-bool LaunchTestProcess(const wchar_t* executable,
-                       const char* action,
-                       bool wait) {
-  base::FilePath executable_path(executable);
-  base::CommandLine command_line(executable_path);
-  command_line.AppendSwitch(action);
-  base::LaunchOptions options = base::LaunchOptions();
-  options.wait = wait;
-  return base::LaunchProcess(command_line, options).IsValid();
-}
-
-bool DoesVolumeSupportNamedStreams(const base::FilePath& path) {
-  std::vector<base::string16> components;
-  path.GetComponents(&components);
-  DCHECK(!components.empty());
-  base::string16& drive = components[0];
-  drive += L'\\';
-  DWORD system_flags = 0;
-  if (::GetVolumeInformation(drive.c_str(), nullptr, 0, nullptr, nullptr,
-                             &system_flags, nullptr, 0) != TRUE) {
-    PLOG(ERROR) << "Cannot retrieve drive information: '" << path.value()
-                << "'.";
-    return false;
-  }
-
-  return (system_flags & FILE_NAMED_STREAMS) != 0;
-}
-
-void CreateProgramPathsAndFiles(const base::FilePath& temp_dir_path,
-                                base::FilePath* program_path,
-                                base::FilePath* spaced_program_path) {
-  DCHECK(program_path);
-  DCHECK(spaced_program_path);
-  base::FilePath folder;
-  base::FilePath file_path;
-  base::FilePath spaced_folder;
-  base::FilePath spaced_file_path;
-
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L"folder", &folder));
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L"  spaced folder",
-                                            &spaced_folder));
-
-  ASSERT_TRUE(CreateTemporaryFileInDir(folder, &file_path));
-  ASSERT_TRUE(CreateTemporaryFileInDir(spaced_folder, &spaced_file_path));
-
-  *program_path = file_path;
-  *spaced_program_path = spaced_file_path;
-}
-
-// Substitutes |registry_path| into each entry in the mock registry in turn
-// and passes the result to ExtractExecutablePathFromRegistryContent to get a
-// file path. Returns success if every file path matches |expected_path|.
-::testing::AssertionResult ExtractExecutablePathFromMockRegistryAndExpect(
-    const base::string16& registry_path,
-    const base::FilePath& expected_path) {
-  for (const base::string16& registry_content : kMockRegistryContents) {
-    base::string16 full_registry_content =
-        base::StringPrintf(registry_content.c_str(), registry_path.c_str());
-    base::FilePath extracted_path =
-        ExtractExecutablePathFromRegistryContent(full_registry_content);
-    if (!PathEqual(expected_path, extracted_path)) {
-      return ::testing::AssertionFailure()
-             << expected_path.value() << " != " << extracted_path.value()
-             << ", full_registry_content = " << full_registry_content;
-    }
-  }
-  return ::testing::AssertionSuccess();
-}
-
-// Return that the sample DLL is whitelisted and all other files are not.
-bool WhitelistSampleDLL(const base::FilePath& path) {
-  return PathEqual(path, GetSampleDLLPath());
-}
-
-}  // namespace
-
-TEST(DiskUtilTests, GetX64ProgramFilePath) {
-  base::FilePath x64_program_files =
-      GetX64ProgramFilesPath(base::FilePath(kProgramFilesBaseName));
-  if (base::win::OSInfo::GetInstance()->architecture() ==
-      base::win::OSInfo::X86_ARCHITECTURE) {
-    EXPECT_TRUE(x64_program_files.empty());
-    return;
-  }
-
-  EXPECT_FALSE(x64_program_files.empty());
-  EXPECT_NE(x64_program_files,
-            ExpandSpecialFolderPath(CSIDL_PROGRAM_FILES,
-                                    base::FilePath(kProgramFilesBaseName)));
-}
-
-TEST(DiskUtilTests, PathContainsWildcards) {
-  EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\foo.txt")));
-  EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\bar\\foo.txt")));
-  EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t?t")));
-  EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t*t")));
-  EXPECT_TRUE(
-      PathContainsWildcards(base::FilePath(L"c:\\"
-                                           LR"(???)"
-                                           L"*\\foo.txt")));
-  EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"*:\\")));
-  EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"foo.txt")));
-  EXPECT_TRUE(PathContainsWildcards(base::FilePath(LR"(foo.???)")));
-}
-
-TEST(DiskUtilTests, CollectMatchingPathsMultipleWildcards) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  // Create files and folders under |temp_dir| and add them to |expected_files|.
-  std::set<base::FilePath> expected_files;
-
-  base::ScopedTempDir sub_dir1;
-  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::ScopedTempDir sub_dir2;
-  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
-  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
-
-  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
-  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
-
-  base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
-  base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
-
-  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
-  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
-
-  base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
-  base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
-
-  expected_files.insert(sub_dir1_file_path1);
-  expected_files.insert(sub_dir1_file_path2);
-  expected_files.insert(sub_dir2_file_path1);
-  expected_files.insert(sub_dir2_file_path2);
-
-  base::FilePath wildcard_path1(
-      temp_dir.GetPath().Append(L"*").Append(L"Filename*"));
-  std::vector<base::FilePath> matches;
-  CollectMatchingPaths(wildcard_path1, &matches);
-  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
-}
-
-TEST(DiskUtilTests, CollectMatchingPathsDriveWildcard) {
-  std::vector<base::FilePath> matches;
-
-  // The drive could not be enumerated, thus no file will exists..
-  base::FilePath wildcard_path1(L"*:\\test");
-  CollectMatchingPaths(wildcard_path1, &matches);
-  EXPECT_TRUE(matches.empty());
-
-  base::FilePath wildcard_path2(L"*:\\");
-  CollectMatchingPaths(wildcard_path2, &matches);
-  EXPECT_TRUE(matches.empty());
-}
-
-TEST(DiskUtilTests, CollectMatchingPathsDirectoryWildcard) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  // Create files and folders under |temp_dir| and add them to |expected_files|.
-  std::set<base::FilePath> expected_files;
-
-  base::ScopedTempDir sub_dir1;
-  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::ScopedTempDir sub_dir2;
-  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
-  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
-
-  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
-  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
-
-  base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
-  base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
-
-  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
-  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
-
-  base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
-  base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
-
-  expected_files.insert(sub_dir1_file_path1);
-  expected_files.insert(sub_dir2_file_path1);
-  base::FilePath wildcard_path3(
-      temp_dir.GetPath().Append(L"*").Append(kFileName1));
-  std::vector<base::FilePath> matches;
-  CollectMatchingPaths(wildcard_path3, &matches);
-  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
-}
-
-TEST(DiskUtilTests, CollectMatchingPathsMultipleFileWildcards) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  base::ScopedTempDir sub_dir1;
-  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::ScopedTempDir sub_dir2;
-  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
-  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
-
-  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
-  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
-
-  base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
-  base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
-
-  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
-  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
-
-  base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
-  base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
-
-  // Create files and folders under |temp_dir| and add them to |expected_files|.
-  std::set<base::FilePath> expected_files;
-  expected_files.insert(sub_dir1_file_path3);
-  base::FilePath wildcard_path4(
-      temp_dir.GetPath().Append(L"*").Append(L"*Third*"));
-  std::vector<base::FilePath> matches;
-  CollectMatchingPaths(wildcard_path4, &matches);
-  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
-}
-
-TEST(DiskUtilTests, CollectMatchingPathsNoWildcards) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  base::ScopedTempDir sub_dir;
-  ASSERT_TRUE(sub_dir.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::FilePath sub_dir_file_path1(sub_dir.GetPath().Append(kFileName1));
-  base::File sub_dir_file1(sub_dir_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir_file_path1));
-
-  base::FilePath sub_dir_file_path2(sub_dir.GetPath().Append(kFileName2));
-  base::File sub_dir_file2(sub_dir_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir_file_path2));
-
-  base::FilePath sub_dir_file_path3(sub_dir.GetPath().Append(kFileName3));
-  base::File sub_dir_file3(sub_dir_file_path3, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir_file_path3));
-
-  // Create files and folders under |temp_dir| and add them to |expected_files|.
-  std::vector<base::FilePath> matches;
-
-  base::FilePath no_wildcard_path(sub_dir.GetPath());
-  CollectMatchingPaths(no_wildcard_path, &matches);
-  EXPECT_EQ(1UL, matches.size());
-  EXPECT_NE(matches.end(),
-            std::find(matches.begin(), matches.end(), sub_dir.GetPath()));
-}
-
-TEST(DiskUtilTests, CollectExecutableMatchingPaths) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  base::FilePath subfolder1_path;
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
-                                            &subfolder1_path));
-
-  base::FilePath subfolder2_path;
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
-                                            &subfolder2_path));
-
-  base::FilePath subfolder3_path(subfolder2_path.Append(L"folder.exe"));
-  ASSERT_TRUE(base::CreateDirectory(subfolder3_path));
-
-  base::FilePath file_path1(subfolder1_path.Append(L"dummy1.exe"));
-  base::FilePath file_path2(subfolder1_path.Append(L"dummy2.exe"));
-  base::FilePath file_path3(subfolder2_path.Append(L"dummy3.exe"));
-  base::FilePath file_path4(subfolder2_path.Append(L"dummy4.exe"));
-  base::FilePath file_path5(subfolder2_path.Append(L"info.exe.txt"));
-  base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
-
-  CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
-  CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
-  CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
-  CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
-  CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
-  CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
-
-  base::FilePath wildcard_path(temp_dir.GetPath().Append(L"*\\*.exe"));
-  std::vector<base::FilePath> executable_matches;
-  CollectMatchingPaths(wildcard_path, &executable_matches);
-
-  EXPECT_THAT(executable_matches,
-              testing::ElementsAre(file_path1, file_path2, file_path3,
-                                   file_path4, subfolder3_path));
-}
-
-TEST(DiskUtilTests, CollectMultipleDotWildcardsMatchingPaths) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  base::FilePath subfolder1_path;
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
-                                            &subfolder1_path));
-
-  base::FilePath subfolder2_path;
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
-                                            &subfolder2_path));
-
-  base::FilePath subfolder3_path;
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(subfolder2_path, L"folder.exe",
-                                            &subfolder3_path));
-
-  base::FilePath file_path1(subfolder1_path.Append(L"dummy1.tar.gz"));
-  base::FilePath file_path2(subfolder1_path.Append(L"dummy2.12.exe"));
-  base::FilePath file_path3(subfolder2_path.Append(L"dummy3.tar.gz"));
-  base::FilePath file_path4(subfolder2_path.Append(L"dummy4.12.exe"));
-  base::FilePath file_path5(subfolder2_path.Append(L"info.tar.gz.txt"));
-  base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
-
-  CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
-  CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
-  CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
-  CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
-  CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
-  CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
-
-  base::FilePath wildcard_path_tar_gz(
-      temp_dir.GetPath().Append(L"*\\*.tar.gz"));
-  std::vector<base::FilePath> executable_matches_tar_gz;
-  CollectMatchingPaths(wildcard_path_tar_gz, &executable_matches_tar_gz);
-
-  EXPECT_THAT(executable_matches_tar_gz,
-              testing::ElementsAre(file_path1, file_path3));
-
-  base::FilePath wildcard_path_all(temp_dir.GetPath().Append(L"*\\*.*.*"));
-  std::vector<base::FilePath> executable_matches_all;
-  CollectMatchingPaths(wildcard_path_all, &executable_matches_all);
-
-  EXPECT_THAT(executable_matches_all,
-              testing::ElementsAre(file_path1, file_path2, file_path3,
-                                   file_path4, file_path5));
-}
-
-TEST(DiskUtilTests, CollectEmptyDirMatchingPaths) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  base::FilePath subfolder1_path;
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
-                                            &subfolder1_path));
-
-  base::FilePath subfolder2_path;
-  ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
-                                            &subfolder2_path));
-
-  base::FilePath wildcard_path1(temp_dir.GetPath().Append(L"*\\dummy.exe"));
-  std::vector<base::FilePath> executable_matches;
-  CollectMatchingPaths(wildcard_path1, &executable_matches);
-  EXPECT_TRUE(executable_matches.empty());
-}
-
-TEST(DiskUtilTests, CollectCumulativeMatchingPaths) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  base::ScopedTempDir sub_dir1;
-  ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  // Create files and folders under |sub_dirX| and add them to |expected_files|.
-  std::set<base::FilePath> expected_files;
-  base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
-  base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
-  expected_files.insert(sub_dir1_file_path1);
-
-  base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
-  base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
-  expected_files.insert(sub_dir1_file_path2);
-
-  base::ScopedTempDir sub_dir2;
-  ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
-
-  base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
-  base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
-  ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
-  expected_files.insert(sub_dir2_file_path1);
-
-  base::FilePath wildcard_path1(sub_dir1.GetPath().Append(L"*"));
-  std::vector<base::FilePath> matches;
-  CollectMatchingPaths(wildcard_path1, &matches);
-  base::FilePath wildcard_path2(sub_dir2.GetPath().Append(L"*"));
-  CollectMatchingPaths(wildcard_path2, &matches);
-  EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
-}
-
-TEST(DiskUtilTests, PathHasActiveExtension) {
-  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe")));
-  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe  ")));
-  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg.exe")));
-  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.lnk")));
-  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file")));
-  EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\file.lnk::$DATA")));
-
-  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.wvm")));
-  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg")));
-  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg ")));
-  EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\file.txt::$DATA")));
-}
-
-TEST(DiskUtilTests, HasDosExecutableHeader) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-  base::FilePath executable = temp.GetPath().Append(L"executable.txt");
-  const char kExecutableFileContents[] = "MZ I am executable";
-  chrome_cleaner::CreateFileWithContent(executable, kExecutableFileContents,
-                                        sizeof(kExecutableFileContents));
-  EXPECT_TRUE(HasDosExecutableHeader(executable));
-
-  base::FilePath non_executable = temp.GetPath().Append(L"text.exe");
-  const char kTextFileContents[] = "I am benign text";
-  chrome_cleaner::CreateFileWithContent(non_executable, kTextFileContents,
-                                        sizeof(kTextFileContents));
-  EXPECT_FALSE(HasDosExecutableHeader(non_executable));
-}
-
-TEST(DiskUtilTests, HasAlternateFileStream) {
-  EXPECT_FALSE(HasAlternateFileStream(base::FilePath(L"C:\\file.txt")));
-  EXPECT_FALSE(HasAlternateFileStream(base::FilePath(L"C:\\file.txt::$DATA")));
-
-  EXPECT_TRUE(HasAlternateFileStream(base::FilePath(L"C:\\file.txt:stream")));
-  EXPECT_TRUE(
-      HasAlternateFileStream(base::FilePath(L"C:\\file.txt:stream:$TYPE")));
-}
-
-TEST(DiskUtilTests, ExpandEnvPath) {
-  ASSERT_TRUE(
-      ::SetEnvironmentVariable(L"CLEANER_TEST_VAR", L"CLEANER_TEST_VALUE"));
-  ASSERT_TRUE(::SetEnvironmentVariable(L"ROOT_TEST_VAR", L"c:\\root"));
-  base::FilePath test_path1(L"C:\\%CLEANER_TEST_VAR%\\test\\foo");
-  base::FilePath test_path2(L"%ROOT_TEST_VAR%\\test\\foo");
-  base::FilePath test_path3(
-      L"C:\\aa%CLEANER_TEST_VAR%bb\\test\\%%CLEANER_TEST_VAR%%");
-
-  base::FilePath expanded_path;
-  ExpandEnvPath(test_path1, &expanded_path);
-  EXPECT_EQ(L"C:\\CLEANER_TEST_VALUE\\test\\foo", expanded_path.value());
-
-  ExpandEnvPath(test_path2, &expanded_path);
-  EXPECT_EQ(L"c:\\root\\test\\foo", expanded_path.value());
-
-  ExpandEnvPath(test_path3, &expanded_path);
-  EXPECT_EQ(L"C:\\aaCLEANER_TEST_VALUEbb\\test\\%CLEANER_TEST_VALUE%",
-            expanded_path.value());
-}
-
-TEST(DiskUtilTests, ExpandWow64Path) {
-  base::ScopedPathOverride windows_override(
-      CsidlToPathServiceKey(CSIDL_WINDOWS));
-  base::FilePath windows_folder;
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_WINDOWS),
-                                     &windows_folder));
-
-  base::FilePath system_folder(windows_folder.Append(L"system32"));
-  base::ScopedPathOverride system_override(CsidlToPathServiceKey(CSIDL_SYSTEM),
-                                           system_folder, true, true);
-
-  base::FilePath native_folder(windows_folder.Append(L"sysnative"));
-  ASSERT_TRUE(base::CreateDirectory(native_folder));
-
-  base::FilePath file_path1(system_folder.Append(kFileName1));
-  base::FilePath file_path2(native_folder.Append(kFileName2));
-  base::FilePath file_path3_system(system_folder.Append(kFileName3));
-  base::FilePath file_path3_native(native_folder.Append(kFileName3));
-  CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
-  CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
-  CreateFileWithContent(file_path3_system, kFileContent3,
-                        sizeof(kFileContent3));
-  CreateFileWithContent(file_path3_native, kFileContent3,
-                        sizeof(kFileContent3));
-
-  base::FilePath expanded_file1;
-  ExpandWow64Path(file_path1, &expanded_file1);
-  ASSERT_TRUE(PathEqual(expanded_file1, file_path1));
-
-  base::FilePath expanded_file2;
-  ExpandWow64Path(file_path2, &expanded_file2);
-  ASSERT_TRUE(PathEqual(expanded_file2, file_path2));
-
-  base::FilePath expanded_file3;
-  ExpandWow64Path(file_path3_system, &expanded_file3);
-  ASSERT_TRUE(PathEqual(expanded_file3, file_path3_native));
-}
-
-TEST(DiskUtilTests, ComputeDigestSHA256) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  // Check the digest of an non-existing file.
-  base::FilePath file_path1(temp_dir.GetPath().Append(kFileName1));
-  std::string digest1;
-  EXPECT_FALSE(ComputeDigestSHA256(file_path1, &digest1));
-  EXPECT_TRUE(digest1.empty());
-
-  // Create an empty file and validate the digest.
-  base::FilePath file_path2(temp_dir.GetPath().Append(kFileName2));
-  base::File empty_file(file_path2, base::File::FLAG_CREATE);
-  empty_file.Close();
-
-  std::string digest2;
-  EXPECT_TRUE(ComputeDigestSHA256(file_path2, &digest2));
-  EXPECT_STREQ(
-      "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
-      digest2.c_str());
-
-  // Create a file with some content and validate the digest.
-  base::FilePath file_path3(temp_dir.GetPath().Append(kFileName3));
-  base::File valid_file(
-      file_path3, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
-  ASSERT_EQ(sizeof(kFileContent),
-            static_cast<size_t>(valid_file.WriteAtCurrentPos(
-                kFileContent, sizeof(kFileContent))));
-  valid_file.Close();
-
-  std::string digest3;
-  EXPECT_TRUE(ComputeDigestSHA256(file_path3, &digest3));
-  EXPECT_STREQ(
-      "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371",
-      digest3.c_str());
-}
-
-TEST(DiskUtilTests, ComputeDigestSHA256OnBigFile) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  struct DigestInfo {
-    size_t size;
-    const char* digest;
-  } digests[] = {
-      {1, "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB"},
-      {2, "FB8E20FC2E4C3F248C60C39BD652F3C1347298BB977B8B4D5903B85055620603"},
-      {3, "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"},
-      {100, "2AC123DCD759EEBABFA1B17C0332B88B3815EF3F95FBFCCEB5FAC07E233235BD"},
-      {128, "6C05BE2C4268843AE47E68E611277CE62C02153F2F4D2E1E2A1A4B44F766CF74"},
-      {1000,
-       "915E53A44C18B19BB06BA5B3F5FCAF1DC4651E8404C63425CFC6174E74659D87"},
-      {1023,
-       "6A6EE128AAC6B98D2697EED0A912AE264603D046B3CBFD5E7EA1D01C865474D9"},
-      {1024,
-       "DBA4A6315B76548B7A4DD079EF6AA29A7B34FA8B92C11668473441715C5F0AF5"},
-      {1025,
-       "2B4B65474580781B4DC0AB66B9A0F39B869DE5A44CF26DBA22AC0496760D4230"},
-      {4095,
-       "7413609B553226A9A8A3203A82062111DC1F98C24163E303774F27E4F615BFB2"},
-      {4096,
-       "BC45051AC426475F459EC0B0C88A6646D037B8DFB1B9FA3CA3EF9203CE33E283"},
-      {4097,
-       "A9145EB3812CA8F11A014029FEE1854FABB76D2FFEA680D0875F78FA786F58B8"},
-      {10000,
-       "5B92F844F0ED521B75688F4B6FF58E127711709613589EB6EC88FDFBBDC7DC63"}};
-
-  for (size_t offset = 0; offset < base::size(digests); ++offset) {
-    DigestInfo* info = &digests[offset];
-    DCHECK(info);
-
-    // Create a file and write some content into it.
-    base::FilePath file_path(temp_dir.GetPath().Append(kFileName1));
-    base::File valid_file(
-        file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
-    for (size_t position = 0; position < info->size; ++position) {
-      char c = 'a' + (position % 26);
-      ASSERT_EQ(1, valid_file.WriteAtCurrentPos(&c, 1));
-    }
-    valid_file.Close();
-
-    std::string digest;
-    EXPECT_TRUE(ComputeDigestSHA256(file_path, &digest));
-    EXPECT_STREQ(info->digest, digest.c_str());
-  }
-}
-
-TEST(DiskUtilTests, GetLayeredServiceProviders) {
-  // Make sure that running the OS implementation doesn't crash/dcheck.
-  LSPPathToGUIDs providers;
-  GetLayeredServiceProviders(LayeredServiceProviderWrapper(), &providers);
-  providers.clear();
-
-  // Make sure an empty test provider returns nothing
-  TestLayeredServiceProvider lsp;
-  GetLayeredServiceProviders(lsp, &providers);
-  EXPECT_TRUE(providers.empty());
-
-  // Now try with a couple of providers
-  base::FilePath file_path1 = base::FilePath(kFileName1);
-  base::FilePath file_path2 = base::FilePath(kFileName2);
-  lsp.AddProvider(kGUID1, file_path1);
-  lsp.AddProvider(kGUID2, file_path2);
-  lsp.AddProvider(kGUID3, file_path2);
-
-  GetLayeredServiceProviders(lsp, &providers);
-
-  EXPECT_EQ(2UL, providers.size());
-  EXPECT_NE(providers.end(), providers.find(file_path1));
-  EXPECT_NE(providers.end(), providers.find(file_path2));
-  EXPECT_EQ(1UL, providers.find(file_path1)->second.size());
-  EXPECT_NE(providers.find(file_path1)->second.end(),
-            providers.find(file_path1)->second.find(kGUID1));
-  EXPECT_EQ(2UL, providers.find(file_path2)->second.size());
-  EXPECT_NE(providers.find(file_path2)->second.end(),
-            providers.find(file_path2)->second.find(kGUID2));
-  EXPECT_NE(providers.find(file_path2)->second.end(),
-            providers.find(file_path2)->second.find(kGUID3));
-}
-
-TEST(DiskUtilTests, DeleteFileFromTempProcess) {
-  base::FilePath test_file;
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::CreateTemporaryFileInDir(test_dir.GetPath(), &test_file);
-  ASSERT_TRUE(base::PathExists(test_file));
-  base::WriteFile(test_file, "foo", 3);
-  base::win::ScopedHandle process_handle;
-  EXPECT_TRUE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
-  ASSERT_NE(static_cast<HANDLE>(nullptr), process_handle.Get());
-  DWORD wait_result = ::WaitForSingleObject(
-      process_handle.Get(),
-      TestTimeouts::action_max_timeout().InMilliseconds());
-  process_handle.Close();
-  EXPECT_EQ(WAIT_OBJECT_0, wait_result);
-  EXPECT_FALSE(base::PathExists(test_file));
-  EXPECT_FALSE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
-  EXPECT_FALSE(process_handle.IsValid());
-}
-
-TEST(DiskUtilTests, ShortPathContainsCaseInsensitive) {
-  base::ScopedTempDir scoped_temp_dir;
-  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
-  base::FilePath short_name_path;
-  CreateFileAndGetShortName(scoped_temp_dir.GetPath().Append(kLongFileName1),
-                            &short_name_path);
-
-  // Make sure the test strings would fail with the previous API.
-  ASSERT_FALSE(
-      String16ContainsCaseInsensitive(short_name_path.value(), kLongFileName1));
-
-  // Find the long name from the shorten version.
-  EXPECT_TRUE(ShortPathContainsCaseInsensitive(short_name_path.value(),
-                                               kLongFileName1));
-
-  // Make sure the shorten version can also be found.
-  EXPECT_TRUE(ShortPathContainsCaseInsensitive(short_name_path.value(),
-                                               short_name_path.value()));
-
-  // Validate the not found case.
-  EXPECT_FALSE(ShortPathContainsCaseInsensitive(short_name_path.value(),
-                                                kLongFileName2));
-
-  // Validate a non shorten case.
-  EXPECT_TRUE(
-      ShortPathContainsCaseInsensitive(kLongFileName2, kLongFileName2Subset));
-}
-
-TEST(DiskUtilTests, PathEqual) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath long_path1(temp_dir.GetPath().Append(kLongFileName1));
-  base::FilePath long_path2(temp_dir.GetPath().Append(kLongFileName2));
-  base::FilePath long_path1_upper(base::ToUpperASCII(long_path1.value()));
-
-  base::FilePath short_path1;
-  CreateFileAndGetShortName(long_path1, &short_path1);
-
-  // Same paths are equal.
-  EXPECT_TRUE(PathEqual(long_path1, long_path1));
-  EXPECT_TRUE(PathEqual(long_path2, long_path2));
-  // Same paths with different case are equal.
-  EXPECT_TRUE(PathEqual(long_path1, long_path1_upper));
-  // Different path are not equal.
-  EXPECT_FALSE(PathEqual(long_path1, long_path2));
-
-  // Short and long path to the same file are equal.
-  EXPECT_TRUE(PathEqual(short_path1, long_path1));
-  // Short and long path to different files are not equal.
-  EXPECT_FALSE(PathEqual(short_path1, long_path2));
-}
-
-TEST(DiskUtilTests, GetAppDataProductDirectory) {
-  base::ScopedPathOverride appdata_override(
-      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
-  base::FilePath appdata_dir;
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
-                                     &appdata_dir));
-
-  base::FilePath product_folder;
-  EXPECT_TRUE(GetAppDataProductDirectory(&product_folder));
-  EXPECT_TRUE(base::DirectoryExists(product_folder));
-  EXPECT_TRUE(PathEqual(appdata_dir, product_folder.DirName().DirName()));
-}
-
-TEST(DiskUtilTests, ZoneIdentifier) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath path(temp_dir.GetPath().Append(kTestProcessExecutableName));
-
-  if (!DoesVolumeSupportNamedStreams(temp_dir.GetPath())) {
-    LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
-    return;
-  }
-
-  // Copy the test_process executable in a temporary folder.
-  base::FilePath executable_path;
-  ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
-  base::FilePath source_path =
-      executable_path.Append(kTestProcessExecutableName);
-  ASSERT_TRUE(base::CopyFile(source_path, path));
-
-  // Overwrite the ZoneIdentifier.
-  EXPECT_FALSE(HasZoneIdentifier(path));
-  EXPECT_TRUE(OverwriteZoneIdentifier(path));
-  EXPECT_TRUE(HasZoneIdentifier(path));
-
-  // Validate the content of the Zone.Identifier stream.
-  base::FilePath stream_path(path.value() + L":Zone.Identifier");
-  std::string content;
-  ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
-  EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
-}
-
-TEST(DiskUtilTests, ZoneIdentifierWhenProcessIsRunning) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  if (!DoesVolumeSupportNamedStreams(temp_dir.GetPath())) {
-    LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
-    return;
-  }
-
-  // Copy the test_process executable in a temporary folder.
-  base::FilePath executable_path;
-  ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
-  base::FilePath source_exe_path(
-      executable_path.Append(kTestProcessExecutableName));
-  base::FilePath target_exe_path(
-      temp_dir.GetPath().Append(kTestProcessExecutableName));
-  ASSERT_TRUE(base::CopyFile(source_exe_path, target_exe_path));
-
-  // Launch the test_process and wait it's completion. The process must set its
-  // zone identifier.
-  EXPECT_FALSE(HasZoneIdentifier(target_exe_path));
-  ASSERT_FALSE(IsProcessRunning(kTestProcessExecutableName));
-  ASSERT_TRUE(LaunchTestProcess(target_exe_path.value().c_str(),
-                                kTestForceOverwriteZoneIdentifier, false));
-  EXPECT_TRUE(WaitForProcessesStopped(kTestProcessExecutableName));
-  EXPECT_TRUE(HasZoneIdentifier(target_exe_path));
-
-  // Validate the content of the Zone.Identifier stream.
-  base::FilePath stream_path(target_exe_path.value() + L":Zone.Identifier");
-  std::string content;
-  ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
-  EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
-}
-
-TEST(DiskUtilTests,
-     ExtractExecutablePathFromRegistryContentWithSysnativeReplacement) {
-  base::FilePath system_folder;
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_SYSTEM),
-                                     &system_folder));
-
-  base::FilePath native_folder(system_folder.DirName().Append(L"sysnative"));
-  // Only run this test on 64-bits Windows with 32-bits process.
-  if (base::PathExists(native_folder)) {
-    base::ScopedTempDir temp_dir;
-    ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(native_folder));
-
-    base::FilePath program_path, spaced_program_path;
-    CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
-                               &spaced_program_path);
-    const base::FilePath program_paths[] = {program_path, spaced_program_path};
-    for (const auto& program_path : program_paths) {
-      // convert C:\\Windows\sysnative\scoped_folder\folder1234\file1 into
-      // C:\\Windows\system32\scoped_folder\folder1234\file1
-      base::FilePath program_path_system =
-          system_folder.Append(program_path.DirName().DirName().BaseName())
-              .Append(program_path.DirName().BaseName())
-              .Append(program_path.BaseName());
-      EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
-          program_path_system.value(), program_path));
-    }
-  }
-}
-
-TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContentWithEnvVariable) {
-  // This test expects files to be placed in %TEMP% and not anywhere else
-  // ScopedTempDir might decide to put them.
-  base::string16 temp_str;
-  ASSERT_NE(0U, ::GetEnvironmentVariableW(
-                    L"TEMP", ::base::WriteInto(&temp_str, MAX_PATH), MAX_PATH))
-      << logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
-  base::FilePath temp_path(temp_str);
-  ASSERT_TRUE(base::PathExists(temp_path));
-
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(temp_path));
-
-  base::FilePath program_path, spaced_program_path;
-  CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
-                             &spaced_program_path);
-  const base::FilePath program_paths[] = {program_path, spaced_program_path};
-
-  for (const auto& program_path : program_paths) {
-    // Convert
-    // "C:\Users\$USER\AppData\Local\Temp\scoped_dir1234\folder6788\A111.tmp"
-    // into "scoped_dir1234\folder6789\A111.tmp"
-    base::FilePath relative_program_path =
-        program_path.DirName()
-            .DirName()
-            .BaseName()
-            .Append(program_path.DirName().BaseName())
-            .Append(program_path.BaseName());
-    const auto program_path_with_var =
-        base::StrCat({L"%TEMP%\\", relative_program_path.value()});
-
-    EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
-        program_path_with_var, program_path));
-  }
-}
-
-TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContent) {
-  // Create the executable to be recognized.
-  base::ScopedTempDir temp_dir;
-
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath program_path, spaced_program_path;
-  CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
-                             &spaced_program_path);
-  const base::FilePath program_paths[] = {program_path, spaced_program_path};
-
-  for (const auto& program_path : program_paths) {
-    EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
-        program_path.value(), program_path));
-  }
-}
-
-TEST(DiskUtilTests, FilePathLess) {
-  base::FilePath path_a(L"c:\\a");
-  base::FilePath path_upper_a(L"c:\\A");
-  base::FilePath path_b(L"c:\\b");
-  FilePathLess file_path_less;
-  EXPECT_TRUE(file_path_less(path_a, path_b));
-  EXPECT_TRUE(file_path_less(path_upper_a, path_b));
-  EXPECT_FALSE(file_path_less(path_b, path_a));
-  EXPECT_FALSE(file_path_less(path_a, path_upper_a));
-  EXPECT_FALSE(file_path_less(path_upper_a, path_a));
-
-  std::map<base::FilePath, int, FilePathLess> collection;
-  collection[path_a] = 0;
-  EXPECT_NE(collection.find(path_a), collection.end());
-  EXPECT_NE(collection.find(path_upper_a), collection.end());
-  EXPECT_EQ(collection.find(path_b), collection.end());
-}
-
-TEST(DiskUtilTests, RetrieveDetailedFileInformation) {
-  base::ScopedPathOverride appdata_override(
-      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
-  base::FilePath appdata_folder;
-
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
-                                     &appdata_folder));
-
-  base::FilePath temp_file(appdata_folder.Append(L"DUMMY.inactive"));
-  CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
-
-  bool whitelisted = false;
-  internal::FileInformation file_information;
-  RetrieveDetailedFileInformation(temp_file, &file_information, &whitelisted);
-
-  EXPECT_FALSE(whitelisted);
-
-  base::string16 sanitized_path = SanitizePath(temp_file);
-
-  EXPECT_EQ(sanitized_path, file_information.path);
-  EXPECT_FALSE(file_information.creation_date.empty());
-  EXPECT_FALSE(file_information.last_modified_date.empty());
-  EXPECT_FALSE(file_information.active_file);
-  EXPECT_EQ(kFileContentDigests[4], file_information.sha256);
-  EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
-  // The next fields are parsed from PE headers so they won't exist.
-  EXPECT_TRUE(file_information.company_name.empty());
-  EXPECT_TRUE(file_information.company_short_name.empty());
-  EXPECT_TRUE(file_information.product_name.empty());
-  EXPECT_TRUE(file_information.product_short_name.empty());
-  EXPECT_TRUE(file_information.internal_name.empty());
-  EXPECT_TRUE(file_information.original_filename.empty());
-  EXPECT_TRUE(file_information.file_description.empty());
-  EXPECT_TRUE(file_information.file_version.empty());
-}
-
-TEST(DiskUtilTests, RetrieveDetailedFileInformationNoFile) {
-  base::FilePath appdata_folder;
-
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
-                                     &appdata_folder));
-
-  base::FilePath non_existent_file(
-      appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
-
-  bool whitelisted = false;
-  internal::FileInformation file_information;
-  RetrieveDetailedFileInformation(non_existent_file, &file_information,
-                                  &whitelisted);
-
-  EXPECT_FALSE(whitelisted);
-  EXPECT_TRUE(file_information.path.empty());
-  EXPECT_TRUE(file_information.creation_date.empty());
-  EXPECT_TRUE(file_information.last_modified_date.empty());
-  EXPECT_FALSE(file_information.active_file);
-  EXPECT_TRUE(file_information.sha256.empty());
-  EXPECT_EQ(0, file_information.size);
-  EXPECT_TRUE(file_information.company_name.empty());
-  EXPECT_TRUE(file_information.company_short_name.empty());
-  EXPECT_TRUE(file_information.product_name.empty());
-  EXPECT_TRUE(file_information.product_short_name.empty());
-  EXPECT_TRUE(file_information.internal_name.empty());
-  EXPECT_TRUE(file_information.original_filename.empty());
-  EXPECT_TRUE(file_information.file_description.empty());
-  EXPECT_TRUE(file_information.file_version.empty());
-}
-
-TEST(DiskUtilTests, RetrieveDetailedFileInformationWhitelisted) {
-  bool whitelisted = false;
-  internal::FileInformation file_information;
-
-  RetrieveDetailedFileInformation(GetSampleDLLPath(), &file_information,
-                                  &whitelisted,
-                                  base::BindOnce(&WhitelistSampleDLL));
-
-  EXPECT_TRUE(whitelisted);
-  EXPECT_TRUE(file_information.path.empty());
-  EXPECT_TRUE(file_information.creation_date.empty());
-  EXPECT_TRUE(file_information.last_modified_date.empty());
-  EXPECT_FALSE(file_information.active_file);
-  EXPECT_TRUE(file_information.sha256.empty());
-  EXPECT_EQ(0, file_information.size);
-  EXPECT_TRUE(file_information.company_name.empty());
-  EXPECT_TRUE(file_information.company_short_name.empty());
-  EXPECT_TRUE(file_information.product_name.empty());
-  EXPECT_TRUE(file_information.product_short_name.empty());
-  EXPECT_TRUE(file_information.internal_name.empty());
-  EXPECT_TRUE(file_information.original_filename.empty());
-  EXPECT_TRUE(file_information.file_description.empty());
-  EXPECT_TRUE(file_information.file_version.empty());
-}
-
-TEST(DiskUtilTests, RetrieveBasicFileInformation) {
-  base::ScopedPathOverride appdata_override(
-      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
-  base::FilePath appdata_folder;
-
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
-                                     &appdata_folder));
-
-  base::FilePath temp_file(appdata_folder.Append(L"DUMMY.exe"));
-  CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
-
-  internal::FileInformation file_information;
-  RetrieveBasicFileInformation(temp_file, &file_information);
-
-  // The expected file path value should be sanitized.
-  EXPECT_EQ(SanitizePath(temp_file), file_information.path);
-  EXPECT_FALSE(file_information.creation_date.empty());
-  EXPECT_FALSE(file_information.last_modified_date.empty());
-  EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
-  EXPECT_TRUE(file_information.active_file);
-  // The next fields are not included in basic file information.
-  EXPECT_TRUE(file_information.sha256.empty());
-  EXPECT_TRUE(file_information.company_name.empty());
-  EXPECT_TRUE(file_information.company_short_name.empty());
-  EXPECT_TRUE(file_information.product_name.empty());
-  EXPECT_TRUE(file_information.product_short_name.empty());
-  EXPECT_TRUE(file_information.internal_name.empty());
-  EXPECT_TRUE(file_information.original_filename.empty());
-  EXPECT_TRUE(file_information.file_description.empty());
-  EXPECT_TRUE(file_information.file_version.empty());
-}
-
-TEST(DiskUtilTests, RetrieveBasicFileInformationNoFile) {
-  base::FilePath appdata_folder;
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
-                                     &appdata_folder));
-
-  base::FilePath non_existent_file(
-      appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
-
-  internal::FileInformation file_information;
-  RetrieveBasicFileInformation(non_existent_file, &file_information);
-
-  EXPECT_TRUE(file_information.path.empty());
-  EXPECT_TRUE(file_information.creation_date.empty());
-  EXPECT_TRUE(file_information.last_modified_date.empty());
-  EXPECT_FALSE(file_information.active_file);
-  EXPECT_TRUE(file_information.sha256.empty());
-  EXPECT_EQ(0, file_information.size);
-  EXPECT_TRUE(file_information.company_name.empty());
-  EXPECT_TRUE(file_information.company_short_name.empty());
-  EXPECT_TRUE(file_information.product_name.empty());
-  EXPECT_TRUE(file_information.product_short_name.empty());
-  EXPECT_TRUE(file_information.internal_name.empty());
-  EXPECT_TRUE(file_information.original_filename.empty());
-  EXPECT_TRUE(file_information.file_description.empty());
-  EXPECT_TRUE(file_information.file_version.empty());
-}
-
-TEST(DiskUtilTests, FileInformationToString) {
-  base::string16 display_str = FileInformationToString(kFileInformation1);
-  EXPECT_EQ(kFileInformation1ExpectedString, display_str);
-}
-
-TEST(DiskUtilTests, FileInformationToStringEmpty) {
-  internal::FileInformation file_information;
-  EXPECT_TRUE(FileInformationToString(file_information).empty());
-}
-
-TEST(DiskUtilTests, TryToExpandPath_NonSystemNativePath) {
-  base::ScopedPathOverride appdata_override(
-      CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
-  base::FilePath appdata_folder;
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
-                                     &appdata_folder));
-
-  base::FilePath non_existing_file(
-      appdata_folder.DirName().Append(L"non-existing-file.tmp"));
-  base::FilePath unused_expanded_path;
-  ASSERT_FALSE(TryToExpandPath(non_existing_file, &unused_expanded_path));
-
-  base::FilePath existing_file(appdata_folder.Append(L"existing-file.tmp"));
-  CreateFileWithContent(existing_file, kFileContent1, sizeof(kFileContent1));
-  base::FilePath expanded_path;
-  ASSERT_TRUE(TryToExpandPath(existing_file, &expanded_path));
-  ASSERT_EQ(existing_file.value(), expanded_path.value());
-
-  // TODO: Figure out how to test paths in C:\Windows\System32.
-}
-
-TEST(DiskUtilTests, TruncateLogFileToTail_FindsNewline) {
-  const char kFileContents[] = "File with utf8 \n\xe2\x82\xac \ntail";
-  const int kFileSize = strlen(kFileContents);
-  const char kTailContents[] = "\ntail";
-  const int kTailSize = strlen(kTailContents);
-
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
-  ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
-
-  // The tail threshold lands in the middle of a multi-byte character.
-  TruncateLogFileToTail(file_path, kTailSize + 3);
-
-  int64_t file_size;
-  ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
-  EXPECT_EQ(kTailSize, file_size);
-  std::string tail;
-  ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
-  EXPECT_EQ(kTailContents, tail);
-}
-
-TEST(DiskUtilTests, TruncateLogFileToTail_FileSmallerThanLimit) {
-  const char kFileContents[] = "I am file";
-  const int kFileSize = strlen(kFileContents);
-
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
-  ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
-
-  TruncateLogFileToTail(file_path, kFileSize * 2);
-
-  int64_t file_size;
-  ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
-  EXPECT_EQ(kFileSize, file_size);
-  std::string tail;
-  ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
-  EXPECT_EQ(kFileContents, tail);
-}
-
-TEST(DiskUtilTests, TruncateLogFileToTail_NotExisting) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
-
-  TruncateLogFileToTail(file_path, 42);
-
-  EXPECT_FALSE(base::PathExists(file_path));
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_path_sanitization_unittest.cc b/chrome/chrome_cleaner/os/file_path_sanitization_unittest.cc
deleted file mode 100644
index 8b46d8c2..0000000
--- a/chrome/chrome_cleaner/os/file_path_sanitization_unittest.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
-
-#include <shlobj.h>
-
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-namespace {
-
-base::string16 FirstComponent(const base::string16& original) {
-  return original.substr(0, original.find(L"\\"));
-}
-
-TEST(FilePathSanitizationTests, NormalizePath) {
-  base::FilePath expected_path =
-      base::FilePath(L"c:\\program files\\desktop.ini");
-  EXPECT_EQ(NormalizePath(base::FilePath(L"C:\\PROGRA~1\\DESKTOP.INI")),
-            expected_path);
-  EXPECT_EQ(NormalizePath(base::FilePath(L"c:\\pRoGrAm FiLeS\\desktop.INI")),
-            expected_path);
-  base::FilePath empty_path;
-  EXPECT_EQ(NormalizePath(empty_path), empty_path);
-}
-
-TEST(FilePathSanitizationTests, NormalizePathUnicode) {
-  EXPECT_EQ(
-      NormalizePath(
-          base::FilePath(L"C:\\\u03b1\u03c1\u03c7\u03b5\u03b9\u03b1 "
-                         L"\u03c0\u03c1\u03bf\u03b3\u03c1"
-                         L"\u03b1\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2\\u03b5"
-                         L"\u03c0\u03b9\u03c6"
-                         L"\u03ac\u03bd\u03b5\u03b9\u03b1 "
-                         L"\u03b5\u03c1\u03b3\u03b1\u03c3\u03af"
-                         L"\u03b1\u03c2.iNi"))
-          .value(),
-      L"c:\\\u03b1\u03c1\u03c7\u03b5\u03b9\u03b1 \u03c0\u03c1\u03bf\u03b3\u03c1"
-      L"\u03b1\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2\\u03b5\u03c0\u03b9\u03c6"
-      L"\u03ac\u03bd\u03b5\u03b9\u03b1 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af"
-      L"\u03b1\u03c2.ini");
-}
-TEST(FilePathSanitizationTests, SanitizePath) {
-  base::FilePath programfiles_folder;
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_PROGRAM_FILES),
-                                     &programfiles_folder));
-
-  base::FilePath absolute(L"C:\\Dummy\\Dummy.exe");
-  base::string16 result = SanitizePath(absolute);
-  EXPECT_EQ(NormalizePath(absolute).value(), result);
-
-  base::FilePath relative(programfiles_folder.Append(L"Dummy\\Dummy.exe"));
-  base::string16 sanitized_relative = SanitizePath(relative);
-  EXPECT_NE(sanitized_relative, relative.value());
-  EXPECT_EQ(L"CSIDL_PROGRAM_FILES\\dummy\\dummy.exe", sanitized_relative);
-
-  base::FilePath empty_path;
-  EXPECT_EQ(L"", SanitizePath(empty_path));
-}
-
-TEST(FilePathSanitizationTests, SanitizePathConsistency) {
-  // Loop over all the rewrite rules used by sanitize path to make sure all the
-  // rules work correctly. In particular this test verifies each rule is not
-  // masked by another.
-  base::FilePath arbitrary_path = NormalizePath(base::FilePath(L"Desktop.ini"));
-  for (auto* rule = sanitization_internal::rewrite_rules; rule->path != nullptr;
-       ++rule) {
-    base::FilePath expanded_path;
-    base::PathService::Get(rule->id, &expanded_path);
-    expanded_path = expanded_path.Append(arbitrary_path);
-    const auto sanitized_path = chrome_cleaner::SanitizePath(expanded_path);
-
-    // The FirstComponent here is the label string used to sanitize the path. It
-    // is extracted to verify the correct label string is being used.
-    //
-    // For example:
-    // C:\Program Files (x86)\Common Files\Desktop.ini
-    // maps to
-    // CSIDL_PROGRAM_FILES_COMMON (CSIDL_PROGRAM_FILES_COMMON\Desktop.ini)
-    // and shouldn't map to
-    // CSIDL_PROGRAM_FILES        (CSIDL_PROGRAM_FILES\Common Files\Desktop.ini)
-    // or it will clash with
-    // C:\Program Files (x86)\Desktop.ini
-    // which maps to
-    // CSIDL_PROGRAM_FILES        (CSIDL_PROGRAM_FILES\desktop.ini)
-    const auto first_dir = FirstComponent(sanitized_path);
-    if (first_dir != rule->path) {
-      ADD_FAILURE() << base::WideToUTF8(expanded_path.value())
-                    << " is being Sanitized to "
-                    << base::WideToUTF8(sanitized_path) << " instead of using "
-                    << rule->path;
-    }
-  }
-}
-
-TEST(FilePathSanitizationTests, SanitizeCommandLine) {
-  base::CommandLine switches =
-      base::CommandLine::FromString(L"dummy.exe --flag --arg=value");
-
-  base::CommandLine already_sanitized(switches);
-  already_sanitized.SetProgram(base::FilePath(L"c:\\dummy\\dummy.exe"));
-  base::string16 result = SanitizeCommandLine(already_sanitized);
-  EXPECT_EQ(already_sanitized.GetCommandLineString(), result);
-
-  base::FilePath programfiles_folder;
-  ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_PROGRAM_FILES),
-                                     &programfiles_folder));
-  base::FilePath exe_in_programfiles =
-      programfiles_folder.Append(L"dummy\\dummy.exe");
-
-  base::CommandLine to_sanitize(switches);
-  to_sanitize.SetProgram(exe_in_programfiles);
-  base::string16 sanitized_cmd = SanitizeCommandLine(to_sanitize);
-  EXPECT_NE(to_sanitize.GetCommandLineString(), sanitized_cmd);
-  EXPECT_NE(sanitized_cmd.find(SanitizePath(exe_in_programfiles)),
-            base::string16::npos);
-}
-
-TEST(FilePathSanitizationTests, ExpandSpecialFolderPath) {
-  base::FilePath arbitrary_path(L"Desktop.ini");
-  for (auto* rule = sanitization_internal::rewrite_rules; rule->path != nullptr;
-       ++rule) {
-    // Skip non-CSIDL entries.
-    if (rule->id < sanitization_internal::PATH_CSIDL_START ||
-        rule->id >= sanitization_internal::PATH_CSIDL_END) {
-      continue;
-    }
-
-    // Fetch and validate expected path.
-    base::FilePath expected_path;
-    ASSERT_TRUE(base::PathService::Get(rule->id, &expected_path));
-    ASSERT_FALSE(expected_path.empty());
-    expected_path = expected_path.Append(arbitrary_path);
-
-    int csidl = rule->id - sanitization_internal::PATH_CSIDL_START;
-    base::FilePath expanded_path =
-        ExpandSpecialFolderPath(csidl, arbitrary_path);
-    EXPECT_EQ(expected_path, expanded_path)
-        << "Failed special folder path expansion. Got: \""
-        << base::WideToUTF8(expanded_path.value())
-        << "\", but expected: " << base::WideToUTF8(expected_path.value());
-  }
-}
-
-}  // namespace
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_path_set_unittest.cc b/chrome/chrome_cleaner/os/file_path_set_unittest.cc
deleted file mode 100644
index ddb0ab8..0000000
--- a/chrome/chrome_cleaner/os/file_path_set_unittest.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/os/file_path_set.h"
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/strings/string_util.h"
-#include "chrome/chrome_cleaner/test/test_file_util.h"
-#include "chrome/chrome_cleaner/test/test_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-namespace {
-const wchar_t kFileNameFull[] = L"C:\\Filename";
-const wchar_t kLongFileName[] = L"Long File Name.bla";
-const wchar_t kLongFileNameFull[] = L"C:\\Long File Name.bla";
-}  // namespace
-
-TEST(FilePathSetTests, Empty) {
-  FilePathSet file_paths;
-  // Start empty.
-  EXPECT_TRUE(file_paths.empty());
-  // Clear should be callable on empty sets.
-  file_paths.clear();
-}
-
-TEST(FilePathSetTests, InsertedOnce) {
-  FilePathSet file_paths;
-  // Same path should be inserted only once.
-  base::FilePath file_path1(kFileNameFull);
-  EXPECT_TRUE(file_paths.Insert(file_path1));
-  EXPECT_FALSE(file_paths.Insert(file_path1));
-  EXPECT_EQ(1UL, file_paths.size());
-  // But still should be found.
-  EXPECT_TRUE(file_paths.Contains(file_path1));
-}
-
-TEST(FilePathSetTests, EqualOperator) {
-  FilePathSet file_paths1;
-  base::FilePath file_path(kFileNameFull);
-  EXPECT_TRUE(file_paths1.Insert(file_path));
-  EXPECT_EQ(file_paths1, file_paths1);
-
-  FilePathSet file_paths2;
-  EXPECT_TRUE(file_paths2.Insert(file_path));
-  EXPECT_EQ(file_paths1, file_paths2);
-
-  base::FilePath long_file_path(kLongFileNameFull);
-  EXPECT_TRUE(file_paths1.Insert(long_file_path));
-  EXPECT_TRUE(file_paths2.Insert(long_file_path));
-  EXPECT_EQ(file_paths1, file_paths2);
-
-  base::FilePath other_path(L"C:\\other_path.txt");
-  EXPECT_TRUE(file_paths2.Insert(other_path));
-  // To avoid implementing operator!=();
-  EXPECT_FALSE(file_paths1 == file_paths2);
-}
-
-TEST(FilePathSetTests, LongName) {
-  FilePathSet file_paths;
-  // Long paths should also be found, even by their short version.
-  base::ScopedTempDir scoped_temp_dir;
-  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
-  base::FilePath short_name_path;
-  base::FilePath long_name_path(
-      scoped_temp_dir.GetPath().Append(kLongFileName));
-  CreateFileAndGetShortName(long_name_path, &short_name_path);
-  EXPECT_TRUE(file_paths.Insert(long_name_path));
-  EXPECT_FALSE(file_paths.Insert(long_name_path));
-  EXPECT_FALSE(file_paths.Insert(short_name_path));
-  base::FilePath long_name_path_upper(
-      base::ToUpperASCII(long_name_path.value()));
-  EXPECT_FALSE(file_paths.Insert(long_name_path_upper));
-
-  // And they should be found-able in all its different forms.
-  EXPECT_TRUE(file_paths.Contains(long_name_path));
-  EXPECT_TRUE(file_paths.Contains(short_name_path));
-  EXPECT_TRUE(file_paths.Contains(long_name_path_upper));
-}
-
-TEST(FilePathSetTests, ShortName) {
-  FilePathSet file_paths;
-  // Short paths should also be found, even by their long version.
-  base::ScopedTempDir scoped_temp_dir;
-  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
-  base::FilePath short_name_path;
-  base::FilePath long_name_path(
-      scoped_temp_dir.GetPath().Append(kLongFileName));
-  CreateFileAndGetShortName(long_name_path, &short_name_path);
-  EXPECT_TRUE(file_paths.Insert(short_name_path));
-  EXPECT_FALSE(file_paths.Insert(short_name_path));
-  EXPECT_FALSE(file_paths.Insert(long_name_path));
-  base::FilePath long_name_path_upper(
-      base::ToUpperASCII(long_name_path.value()));
-  EXPECT_FALSE(file_paths.Insert(long_name_path_upper));
-
-  // And they should be found-able in all its different forms.
-  EXPECT_TRUE(file_paths.Contains(long_name_path));
-  EXPECT_TRUE(file_paths.Contains(short_name_path));
-  EXPECT_TRUE(file_paths.Contains(long_name_path_upper));
-}
-
-TEST(FilePathSetTests, ProperOrder) {
-  // Ensure that all the items in a folder are listed before the folder.
-  const base::FilePath folder(L"C:\\folder");
-  base::FilePath file = folder.Append(L"file.exe");
-  base::FilePath sub_folder = folder.Append(L"sub_folder");
-  base::FilePath sub_file = sub_folder.Append(L"sub_file.txt");
-
-  FilePathSet file_paths;
-  EXPECT_TRUE(file_paths.Insert(folder));
-  EXPECT_TRUE(file_paths.Insert(file));
-  EXPECT_TRUE(file_paths.Insert(sub_folder));
-  EXPECT_TRUE(file_paths.Insert(sub_file));
-
-  const auto sorted_files = file_paths.ReverseSorted();
-  ASSERT_EQ(4UL, sorted_files.size());
-  EXPECT_EQ(sub_file, sorted_files[0]);
-  EXPECT_EQ(sub_folder, sorted_files[1]);
-  EXPECT_EQ(file, sorted_files[2]);
-  EXPECT_EQ(folder, sorted_files[3]);
-}
-
-TEST(FilePathMap, Find) {
-  // Long paths should also be found, even by their short version.
-  base::ScopedTempDir scoped_temp_dir;
-  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
-  base::FilePath short_name_path;
-  base::FilePath long_name_path(
-      scoped_temp_dir.GetPath().Append(kLongFileName));
-  CreateFileAndGetShortName(long_name_path, &short_name_path);
-
-  FilePathMap<int> map;
-  EXPECT_TRUE(map.Insert(short_name_path, 42));
-
-  const int* found_value = nullptr;
-  ASSERT_NE(nullptr, found_value = map.Find(short_name_path));
-  EXPECT_EQ(42, *found_value);
-
-  ASSERT_NE(nullptr, found_value = map.Find(long_name_path));
-  EXPECT_EQ(42, *found_value);
-
-  EXPECT_EQ(nullptr, map.Find(base::FilePath(kFileNameFull)));
-}
-
-TEST(FilePathMap, DoNotInsertDuplicates) {
-  base::ScopedTempDir scoped_temp_dir;
-  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
-  base::FilePath short_name_path;
-  base::FilePath long_name_path(
-      scoped_temp_dir.GetPath().Append(kLongFileName));
-  CreateFileAndGetShortName(long_name_path, &short_name_path);
-
-  FilePathMap<int> map;
-  EXPECT_TRUE(map.Insert(long_name_path, 42));
-  EXPECT_FALSE(map.Insert(long_name_path, 43));
-  EXPECT_FALSE(map.Insert(short_name_path, 44));
-  EXPECT_EQ(1u, map.map().size());
-
-  const int* found_value = nullptr;
-  EXPECT_NE(nullptr, found_value = map.Find(short_name_path));
-  EXPECT_EQ(42, *found_value);
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_removal_status_updater_unittest.cc b/chrome/chrome_cleaner/os/file_removal_status_updater_unittest.cc
deleted file mode 100644
index 54642931..0000000
--- a/chrome/chrome_cleaner/os/file_removal_status_updater_unittest.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/os/file_removal_status_updater.h"
-
-#include "base/base_paths.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-namespace {
-
-constexpr wchar_t kFile1[] = L"file_one";
-constexpr wchar_t kFile2[] = L"file_two";
-
-class FileRemovalStatusUpdaterTest : public ::testing::Test {
- protected:
-  FileRemovalStatusUpdaterTest() {
-    // Start each test with an empty map.
-    FileRemovalStatusUpdater::GetInstance()->Clear();
-  }
-
-  // Convenience accessors
-  FileRemovalStatusUpdater* instance_ = FileRemovalStatusUpdater::GetInstance();
-  const base::FilePath file_1_ = base::FilePath(kFile1);
-  const base::FilePath file_2_ = base::FilePath(kFile2);
-};
-
-}  // namespace
-
-TEST_F(FileRemovalStatusUpdaterTest, Clear) {
-  // Map should start empty.
-  EXPECT_TRUE(instance_->GetAllRemovalStatuses().empty());
-  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_1_));
-  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_2_));
-
-  instance_->UpdateRemovalStatus(file_1_, REMOVAL_STATUS_MATCHED_ONLY);
-
-  // Only file_1_ should be in the map.
-  EXPECT_EQ(1U, instance_->GetAllRemovalStatuses().size());
-  EXPECT_EQ(REMOVAL_STATUS_MATCHED_ONLY, instance_->GetRemovalStatus(file_1_));
-  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_2_));
-
-  instance_->Clear();
-
-  // Map should be empty again.
-  EXPECT_TRUE(instance_->GetAllRemovalStatuses().empty());
-  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_1_));
-  EXPECT_EQ(REMOVAL_STATUS_UNSPECIFIED, instance_->GetRemovalStatus(file_2_));
-}
-
-TEST_F(FileRemovalStatusUpdaterTest, UpdateRemovalStatus) {
-  // This function uses GetRemovalStatusOfSanitizedPath to cut down on the
-  // number of times it calls SanitizePath on the same paths, which is slow.
-  const base::string16 file_1_sanitized = SanitizePath(file_1_);
-  const base::string16 file_2_sanitized = SanitizePath(file_2_);
-
-  // Creates a vector of all RemovalStatus enum values to improve readability
-  // of loops in this test and ensure that all RemovalStatus enumerators are
-  // checked.
-  std::vector<RemovalStatus> all_removal_status;
-  for (int i = RemovalStatus_MIN; i <= RemovalStatus_MAX; ++i) {
-    // Status cannot be set to REMOVAL_STATUS_UNSPECIFIED - this is guarded by
-    // an assert.
-    RemovalStatus status = static_cast<RemovalStatus>(i);
-    if (status != REMOVAL_STATUS_UNSPECIFIED)
-      all_removal_status.push_back(status);
-  }
-
-  for (RemovalStatus removal_status : all_removal_status) {
-    // Repeatedly update the removal status of file_2_. file_1_'s status should
-    // not be touched.
-    for (RemovalStatus new_removal_status : all_removal_status) {
-      SCOPED_TRACE(::testing::Message()
-                   << "removal_status " << removal_status
-                   << ", new_removal_status " << new_removal_status);
-
-      // Initially, files should have removal status "unspecified".
-      ASSERT_TRUE(instance_->GetAllRemovalStatuses().empty());
-      ASSERT_EQ(REMOVAL_STATUS_UNSPECIFIED,
-                instance_->GetRemovalStatusOfSanitizedPath(file_1_sanitized));
-      ASSERT_EQ(REMOVAL_STATUS_UNSPECIFIED,
-                instance_->GetRemovalStatusOfSanitizedPath(file_2_sanitized));
-
-      // Any removal status can override "unspecified".
-      instance_->UpdateRemovalStatus(file_1_, removal_status);
-      instance_->UpdateRemovalStatus(file_2_, removal_status);
-      EXPECT_EQ(removal_status,
-                instance_->GetRemovalStatusOfSanitizedPath(file_1_sanitized));
-      EXPECT_EQ(removal_status,
-                instance_->GetRemovalStatusOfSanitizedPath(file_2_sanitized));
-
-      // Tests if attempts to override removal status obey the rules specified
-      // by GetRemovalStatusOfSanitizedPathOverridePermissionMap().
-      instance_->UpdateRemovalStatus(file_2_, new_removal_status);
-      const internal::RemovalStatusOverridePermissionMap& decisions_map =
-          internal::GetRemovalStatusOverridePermissionMap();
-      const bool can_override = decisions_map.find(removal_status)
-                                    ->second.find(new_removal_status)
-                                    ->second == internal::kOkToOverride;
-      EXPECT_EQ(can_override ? new_removal_status : removal_status,
-                instance_->GetRemovalStatusOfSanitizedPath(file_2_sanitized));
-
-      // Updating file_2_ should not have touched file_1_.
-      EXPECT_EQ(removal_status,
-                instance_->GetRemovalStatusOfSanitizedPath(file_1_sanitized));
-
-      // GetAllRemovalStatuses should agree with GetRemovalStatusOfSanitizedPath
-      // for all files.
-      FileRemovalStatusUpdater::SanitizedPathToRemovalStatusMap all_statuses =
-          instance_->GetAllRemovalStatuses();
-      EXPECT_EQ(2U, all_statuses.size());
-      for (const auto& path_and_status : all_statuses) {
-        base::string16 sanitized_path = path_and_status.first;
-        FileRemovalStatusUpdater::FileRemovalStatus status =
-            path_and_status.second;
-        EXPECT_EQ(instance_->GetRemovalStatusOfSanitizedPath(sanitized_path),
-                  status.removal_status);
-      }
-
-      // Empty the map for the next loop.
-      instance_->Clear();
-    }
-  }
-}
-
-TEST_F(FileRemovalStatusUpdaterTest, PathSanitization) {
-  base::FilePath home_dir;
-  ASSERT_TRUE(base::PathService::Get(base::DIR_HOME, &home_dir));
-  base::FilePath path = home_dir.Append(L"UPPER_CASE_FILENAME");
-
-  instance_->UpdateRemovalStatus(path, REMOVAL_STATUS_REMOVED);
-
-  // Path should be accessible with any capitalization, sanitized or
-  // unsanitized.
-  base::string16 lowercase_path = base::ToLowerASCII(path.value());
-  EXPECT_EQ(REMOVAL_STATUS_REMOVED, instance_->GetRemovalStatus(path));
-  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
-            instance_->GetRemovalStatus(base::FilePath(lowercase_path)));
-
-  base::string16 sanitized_path = SanitizePath(path);
-  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
-            instance_->GetRemovalStatusOfSanitizedPath(sanitized_path));
-
-  FileRemovalStatusUpdater::SanitizedPathToRemovalStatusMap all_statuses =
-      instance_->GetAllRemovalStatuses();
-  EXPECT_EQ(1U, all_statuses.size());
-  EXPECT_EQ(sanitized_path, all_statuses.begin()->first);
-  EXPECT_EQ(path, all_statuses.begin()->second.path);
-  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
-            all_statuses.begin()->second.removal_status);
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/file_remover_unittest.cc b/chrome/chrome_cleaner/os/file_remover_unittest.cc
deleted file mode 100644
index dad51e1b..0000000
--- a/chrome/chrome_cleaner/os/file_remover_unittest.cc
+++ /dev/null
@@ -1,405 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/os/file_remover.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "base/base_paths.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/test/scoped_path_override.h"
-#include "chrome/chrome_cleaner/logging/proto/removal_status.pb.h"
-#include "chrome/chrome_cleaner/os/disk_util.h"
-#include "chrome/chrome_cleaner/os/file_removal_status_updater.h"
-#include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h"
-#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
-#include "chrome/chrome_cleaner/os/system_util.h"
-#include "chrome/chrome_cleaner/os/whitelisted_directory.h"
-#include "chrome/chrome_cleaner/test/reboot_deletion_helper.h"
-#include "chrome/chrome_cleaner/test/resources/grit/test_resources.h"
-#include "chrome/chrome_cleaner/test/test_file_util.h"
-#include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
-#include "chrome/chrome_cleaner/test/test_strings.h"
-#include "chrome/chrome_cleaner/test/test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-namespace {
-
-using testing::_;
-using testing::Eq;
-using testing::Return;
-using ValidationStatus = FileRemoverAPI::DeletionValidationStatus;
-
-const wchar_t kRemoveFile1[] = L"remove_one.exe";
-const wchar_t kRemoveFile2[] = L"remove_two.exe";
-const wchar_t kRemoveFolder[] = L"remove";
-
-class FileRemoverTest : public ::testing::Test {
- protected:
-  FileRemoverTest()
-      : default_file_remover_(
-            nullptr,
-            LayeredServiceProviderWrapper(),
-            /*deletion_allowed_paths=*/{},
-            base::BindRepeating(&FileRemoverTest::RebootRequired,
-                                base::Unretained(this))) {
-    FileRemovalStatusUpdater::GetInstance()->Clear();
-  }
-
-  void RebootRequired() { reboot_required_ = true; }
-
-  void TestBlacklistedRemoval(FileRemover* remover,
-                              const base::FilePath& path) {
-    DCHECK(remover);
-
-    EXPECT_EQ(ValidationStatus::FORBIDDEN, remover->CanRemove(path));
-
-    FileRemovalStatusUpdater* removal_status_updater =
-        FileRemovalStatusUpdater::GetInstance();
-
-    EXPECT_FALSE(remover->RemoveNow(path));
-    EXPECT_EQ(removal_status_updater->GetRemovalStatus(path),
-              REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
-
-    removal_status_updater->Clear();
-    EXPECT_FALSE(remover->RegisterPostRebootRemoval(path));
-    EXPECT_EQ(removal_status_updater->GetRemovalStatus(path),
-              REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
-
-    EXPECT_TRUE(base::PathExists(path));
-    EXPECT_FALSE(IsFileRegisteredForPostRebootRemoval(path));
-  }
-
-  FileRemover default_file_remover_;
-  bool reboot_required_ = false;
-};
-
-}  // namespace
-
-TEST_F(FileRemoverTest, RemoveNowValidFile) {
-  // Create a temporary empty file.
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-
-  const base::FilePath file_path = temp.GetPath().Append(kRemoveFile1);
-  EXPECT_TRUE(CreateEmptyFile(file_path));
-
-  // Removing it must succeed.
-  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path));
-  EXPECT_FALSE(base::PathExists(file_path));
-  EXPECT_EQ(
-      FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(file_path),
-      REMOVAL_STATUS_REMOVED);
-}
-
-TEST_F(FileRemoverTest, RemoveNowAbsentFile) {
-  // Create a non-existing file name.
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-
-  FileRemovalStatusUpdater* removal_status_updater =
-      FileRemovalStatusUpdater::GetInstance();
-
-  const base::FilePath file_path = temp.GetPath().Append(kRemoveFile1);
-  EXPECT_FALSE(base::PathExists(file_path));
-
-  // Removing it must not generate an error.
-  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path),
-            REMOVAL_STATUS_NOT_FOUND);
-
-  // Ensure the non-existant files with non-existant parents don't generate an
-  // error.
-  base::FilePath file_path_deeper = file_path.Append(kRemoveFile2);
-  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path_deeper));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path_deeper),
-            REMOVAL_STATUS_NOT_FOUND);
-}
-
-TEST_F(FileRemoverTest, NoKnownFileRemoval) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
-  FileRemover remover(
-      DigestVerifier::CreateFromResource(IDS_TEST_SAMPLE_DLL_DIGEST),
-      LayeredServiceProviderWrapper(), /*deletion_allowed_paths=*/{},
-      base::DoNothing::Repeatedly());
-
-  // Copy the sample DLL to the temp folder.
-  base::FilePath dll_path = GetSampleDLLPath();
-  ASSERT_TRUE(base::PathExists(dll_path)) << dll_path.value();
-
-  base::FilePath target_dll_path(
-      temp_dir.GetPath().Append(dll_path.BaseName()));
-  ASSERT_TRUE(base::CopyFile(dll_path, target_dll_path));
-
-  TestBlacklistedRemoval(&remover, target_dll_path);
-}
-
-TEST_F(FileRemoverTest, NoSelfRemoval) {
-  base::FilePath exe_path = PreFetchedPaths::GetInstance()->GetExecutablePath();
-  TestBlacklistedRemoval(&default_file_remover_, exe_path);
-}
-
-TEST_F(FileRemoverTest, NoWhitelistedFileRemoval) {
-  base::FilePath program_files_dir =
-      PreFetchedPaths::GetInstance()->GetProgramFilesFolder();
-  TestBlacklistedRemoval(&default_file_remover_, program_files_dir);
-}
-
-TEST_F(FileRemoverTest, NoWhitelistFileTempRemoval) {
-  base::FilePath temp_dir;
-  ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &temp_dir));
-  TestBlacklistedRemoval(&default_file_remover_, temp_dir);
-}
-
-TEST_F(FileRemoverTest, NoLSPRemoval) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-  base::FilePath provider_path = temp.GetPath().Append(kRemoveFile1);
-  ASSERT_TRUE(CreateEmptyFile(provider_path));
-
-  TestLayeredServiceProvider lsp;
-  lsp.AddProvider(kGUID1, provider_path);
-
-  FileRemover remover(nullptr, lsp, /*deletion_allowed_paths=*/{},
-                      base::DoNothing::Repeatedly());
-
-  TestBlacklistedRemoval(&remover, provider_path);
-}
-
-TEST_F(FileRemoverTest, CanRemoveAbsolutePath) {
-  EXPECT_EQ(ValidationStatus::ALLOWED,
-            default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\bar")));
-}
-
-TEST_F(FileRemoverTest, NoRelativePathRemoval) {
-  EXPECT_EQ(ValidationStatus::FORBIDDEN,
-            default_file_remover_.CanRemove(base::FilePath(L"bar.txt")));
-}
-
-TEST_F(FileRemoverTest, NoDriveRemoval) {
-  EXPECT_EQ(ValidationStatus::FORBIDDEN,
-            default_file_remover_.CanRemove(base::FilePath(L"C:")));
-  EXPECT_EQ(ValidationStatus::FORBIDDEN,
-            default_file_remover_.CanRemove(base::FilePath(L"C:\\")));
-}
-
-TEST_F(FileRemoverTest, NoPathTraversal) {
-  EXPECT_EQ(
-      ValidationStatus::FORBIDDEN,
-      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\..\\bar")));
-  EXPECT_EQ(
-      ValidationStatus::FORBIDDEN,
-      default_file_remover_.CanRemove(base::FilePath(L"..\\foo\\bar.dll")));
-}
-
-TEST_F(FileRemoverTest, CorrectPathTraversalDetection) {
-  EXPECT_EQ(
-      ValidationStatus::ALLOWED,
-      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\..bar.dll")));
-  EXPECT_EQ(
-      ValidationStatus::ALLOWED,
-      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo\\bar..dll")));
-  EXPECT_EQ(
-      ValidationStatus::ALLOWED,
-      default_file_remover_.CanRemove(base::FilePath(L"C:\\foo..\\bar.dll")));
-}
-
-TEST_F(FileRemoverTest, RemoveNowDoesNotDeleteFolders) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-
-  // Create the folder and the files.
-  base::FilePath subfolder_path = temp.GetPath().Append(kRemoveFolder);
-  base::CreateDirectory(subfolder_path);
-  base::FilePath file_path1 = subfolder_path.Append(kRemoveFile1);
-  ASSERT_TRUE(CreateEmptyFile(file_path1));
-
-  // The folder should not be removed.
-  EXPECT_FALSE(default_file_remover_.RemoveNow(subfolder_path));
-  EXPECT_EQ(
-      FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(subfolder_path),
-      REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
-  EXPECT_TRUE(base::PathExists(subfolder_path));
-  EXPECT_TRUE(base::PathExists(file_path1));
-}
-
-TEST_F(FileRemoverTest, RemoveNowDeletesEmptyFolders) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-
-  // Create the folder and the files.
-  base::FilePath subfolder_path = temp.GetPath().Append(kRemoveFolder);
-  base::CreateDirectory(subfolder_path);
-  base::FilePath file_path1 = subfolder_path.Append(kRemoveFile1);
-  ASSERT_TRUE(CreateEmptyFile(file_path1));
-  base::FilePath subsubfolder_path = subfolder_path.Append(kRemoveFolder);
-  base::CreateDirectory(subsubfolder_path);
-  base::FilePath file_path2 = subsubfolder_path.Append(kRemoveFile2);
-  ASSERT_TRUE(CreateEmptyFile(file_path2));
-
-  FileRemovalStatusUpdater* removal_status_updater =
-      FileRemovalStatusUpdater::GetInstance();
-
-  // Delete a file in a folder with other stuff, so the folder isn't deleted.
-  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path1));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path1),
-            REMOVAL_STATUS_REMOVED);
-  EXPECT_TRUE(base::PathExists(subfolder_path));
-  EXPECT_FALSE(base::PathExists(file_path1));
-  EXPECT_TRUE(base::PathExists(subsubfolder_path));
-  EXPECT_TRUE(base::PathExists(file_path2));
-
-  // Delete the file and ensure the two parent folders are deleted since they
-  // are now empty.
-  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path2));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path2),
-            REMOVAL_STATUS_REMOVED);
-  EXPECT_FALSE(base::PathExists(subfolder_path));
-  EXPECT_FALSE(base::PathExists(subsubfolder_path));
-  EXPECT_FALSE(base::PathExists(file_path2));
-}
-
-TEST_F(FileRemoverTest, RemoveNowDeletesEmptyFoldersNotTemp) {
-  base::ScopedPathOverride temp_override(base::DIR_TEMP);
-
-  base::FilePath scoped_temp_dir;
-  ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &scoped_temp_dir));
-
-  // Create a file in temp.
-  base::FilePath file_path = scoped_temp_dir.Append(kRemoveFile1);
-  ASSERT_TRUE(CreateEmptyFile(file_path));
-
-  // Delete the file and ensure Temp isn't deleted since it is whitelisted.
-  EXPECT_TRUE(default_file_remover_.RemoveNow(file_path));
-  EXPECT_EQ(
-      FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(file_path),
-      REMOVAL_STATUS_REMOVED);
-  EXPECT_FALSE(base::PathExists(file_path));
-  base::FilePath temp_dir;
-  ASSERT_TRUE(base::GetTempDir(&temp_dir));
-  EXPECT_TRUE(base::PathExists(temp_dir));
-}
-
-TEST_F(FileRemoverTest, RegisterPostRebootRemoval) {
-  FileRemovalStatusUpdater* removal_status_updater =
-      FileRemovalStatusUpdater::GetInstance();
-
-  // When trying to delete a whitelisted file, we should fail to register the
-  // file for removal, and no reboot should be required.
-  base::FilePath exe_path = PreFetchedPaths::GetInstance()->GetExecutablePath();
-  EXPECT_FALSE(default_file_remover_.RegisterPostRebootRemoval(exe_path));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(exe_path),
-            REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
-  EXPECT_FALSE(reboot_required_);
-
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-  base::FilePath file_path = temp.GetPath().Append(kRemoveFile2);
-
-  // When trying to delete an non-existant file, we should return success, but
-  // not require a reboot.
-  EXPECT_TRUE(default_file_remover_.RegisterPostRebootRemoval(file_path));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path),
-            REMOVAL_STATUS_NOT_FOUND);
-  EXPECT_FALSE(reboot_required_);
-
-  // When trying to delete a real file, we should return success and require a
-  // reboot.
-  ASSERT_TRUE(CreateEmptyFile(file_path));
-  EXPECT_TRUE(default_file_remover_.RegisterPostRebootRemoval(file_path));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(file_path),
-            REMOVAL_STATUS_SCHEDULED_FOR_REMOVAL);
-  EXPECT_TRUE(reboot_required_);
-  EXPECT_TRUE(IsFileRegisteredForPostRebootRemoval(file_path));
-}
-
-TEST_F(FileRemoverTest, RegisterPostRebootRemoval_Directories) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-
-  // Create an empty directory.
-  base::FilePath subfolder_path = temp.GetPath().Append(kRemoveFolder);
-  ASSERT_TRUE(base::CreateDirectory(subfolder_path));
-
-  FileRemovalStatusUpdater* removal_status_updater =
-      FileRemovalStatusUpdater::GetInstance();
-
-  // Directories shouldn't be registered for deletion.
-  EXPECT_FALSE(default_file_remover_.RegisterPostRebootRemoval(subfolder_path));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(subfolder_path),
-            REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
-
-  // Put a file into the directory and ensure the non-empty directory still
-  // isn't registered for removal.
-  removal_status_updater->Clear();
-  base::FilePath file_path1 = subfolder_path.Append(kRemoveFile1);
-  ASSERT_TRUE(CreateEmptyFile(file_path1));
-  EXPECT_FALSE(default_file_remover_.RegisterPostRebootRemoval(subfolder_path));
-  EXPECT_EQ(removal_status_updater->GetRemovalStatus(subfolder_path),
-            REMOVAL_STATUS_BLACKLISTED_FOR_REMOVAL);
-}
-
-TEST_F(FileRemoverTest, NotActiveFileType) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-  base::FilePath path = temp.GetPath().Append(L"temp_file.txt");
-  ASSERT_TRUE(
-      CreateFileInFolder(path.DirName(), path.BaseName().value().c_str()));
-
-  EXPECT_EQ(ValidationStatus::INACTIVE,
-            FileRemover::IsFileRemovalAllowed(path, {}, {}));
-  EXPECT_TRUE(default_file_remover_.RemoveNow(path));
-  EXPECT_EQ(REMOVAL_STATUS_NOT_REMOVED_INACTIVE_EXTENSION,
-            FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(path));
-  EXPECT_TRUE(base::PathExists(path));
-}
-
-TEST_F(FileRemoverTest, NotActiveFileAllowed) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-  base::FilePath path = temp.GetPath().Append(L"temp_file.txt");
-  ASSERT_TRUE(
-      CreateFileInFolder(path.DirName(), path.BaseName().value().c_str()));
-
-  FileRemover remover(nullptr, LayeredServiceProviderWrapper(),
-                      {path.value().c_str()}, base::DoNothing::Repeatedly());
-
-  EXPECT_EQ(ValidationStatus::ALLOWED, FileRemover::IsFileRemovalAllowed(
-                                           path, {path.value().c_str()}, {}));
-  EXPECT_TRUE(remover.RemoveNow(path));
-  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
-            FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(path));
-  EXPECT_FALSE(base::PathExists(path));
-}
-
-TEST_F(FileRemoverTest, DosMzExecutable) {
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-  base::FilePath path = temp.GetPath().Append(L"temp_file.txt");
-  constexpr char kMzExecutable[] = "MZ executable";
-  CreateFileWithContent(path, kMzExecutable, sizeof(kMzExecutable));
-  ASSERT_TRUE(base::PathExists(path));
-
-  FileRemover remover(nullptr, LayeredServiceProviderWrapper(),
-                      {path.value().c_str()}, base::DoNothing::Repeatedly());
-
-  EXPECT_EQ(ValidationStatus::ALLOWED,
-            FileRemover::IsFileRemovalAllowed(path, {}, {}));
-  EXPECT_TRUE(remover.RemoveNow(path));
-  EXPECT_EQ(REMOVAL_STATUS_REMOVED,
-            FileRemovalStatusUpdater::GetInstance()->GetRemovalStatus(path));
-  EXPECT_FALSE(base::PathExists(path));
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/settings/BUILD.gn b/chrome/chrome_cleaner/settings/BUILD.gn
index 6dd920a..adc94eb06 100644
--- a/chrome/chrome_cleaner/settings/BUILD.gn
+++ b/chrome/chrome_cleaner/settings/BUILD.gn
@@ -8,7 +8,7 @@
   ]
 }
 
-source_set("settings") {
+static_library("settings") {
   sources = [
     "settings.cc",
     "settings.h",
@@ -28,14 +28,14 @@
   ]
 }
 
-source_set("matching_options") {
+static_library("matching_options") {
   sources = [
     "matching_options.cc",
     "matching_options.h",
   ]
 }
 
-source_set("default_matching_options") {
+static_library("default_matching_options") {
   sources = [
     "default_matching_options.cc",
     "default_matching_options.h",
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn
index 421d318..e4609bb 100644
--- a/chrome/chrome_cleaner/test/BUILD.gn
+++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -28,69 +28,23 @@
   ]
 }
 
-source_set("test_executables") {
+static_library("test_util") {
   testonly = true
 
   sources = [
-    "test_executables.cc",
-    "test_executables.h",
-  ]
-
-  # Assume that every target that uses the test_executables header will run one
-  # of the executables, so make sure they are built.
-  data_deps = [
-    ":test_process",
-    ":test_service",
-  ]
-
-  deps = [
-    ":test_strings",
-    ":test_util",
-    "//base:base",
-    "//chrome/chrome_cleaner/constants:common_strings",
-  ]
-}
-
-source_set("test_util") {
-  testonly = true
-
-  sources = [
-    "reboot_deletion_helper.cc",
-    "reboot_deletion_helper.h",
     "test_file_util.cc",
     "test_file_util.h",
-    "test_layered_service_provider.cc",
-    "test_layered_service_provider.h",
     "test_name_helper.cc",
-    "test_name_helper.h",
     "test_registry_util.cc",
     "test_registry_util.h",
-    "test_util.cc",
-    "test_util.h",
   ]
 
   deps = [
-    ":test_pup_data",
-    ":test_strings",
     "//base:base",
-    "//base/test:test_support",
-    "//chrome/chrome_cleaner/constants:common_strings",
-    "//chrome/chrome_cleaner/os:cleaner_os",
-    "//chrome/chrome_cleaner/os:common_os",
-    "//chrome/chrome_cleaner/pup_data:pup_data_base",
-    "//chrome/chrome_cleaner/strings",
-    "//components/chrome_cleaner/public/constants:constants",
-    "//sandbox/win:sandbox",
-  ]
-
-  data_deps = [
-    ":empty_dll",
-    "//chrome/chrome_cleaner/test/resources:signed_empty_dll",
-  ]
-
-  public_deps = [
     "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
+    "//chrome/chrome_cleaner/os:common_os",
     "//chrome/chrome_cleaner/proto:shared_pup_enums_proto",
+    "//chrome/chrome_cleaner/pup_data:pup_data_base",
     "//testing/gmock",
     "//testing/gtest",
   ]
@@ -126,52 +80,3 @@
     "//testing/gtest",
   ]
 }
-
-source_set("unittest_sources") {
-  testonly = true
-
-  sources = [
-    "reboot_deletion_helper_unittest.cc",
-    "test_util_unittest.cc",
-  ]
-
-  deps = [
-    ":test_util",
-    "//base",
-    "//base/test:test_support",
-    "//chrome/chrome_cleaner/os:common_os",
-    "//testing/gtest",
-  ]
-}
-
-executable("test_process") {
-  testonly = true
-
-  sources = [
-    "test_process_main.cc",
-  ]
-
-  deps = [
-    ":test_strings",
-    ":test_util",
-    "//base:base",
-    "//base/test:test_support",
-    "//build/win:default_exe_manifest",
-    "//chrome/chrome_cleaner/os:common_os",
-  ]
-}
-
-executable("test_service") {
-  testonly = true
-
-  sources = [
-    "test_service_main.cc",
-  ]
-
-  deps = [
-    ":test_strings",
-    "//base:base",
-    "//base/test:test_support",
-    "//build/win:default_exe_manifest",
-  ]
-}
diff --git a/chrome/chrome_cleaner/test/reboot_deletion_helper.cc b/chrome/chrome_cleaner/test/reboot_deletion_helper.cc
deleted file mode 100644
index 7792cb1..0000000
--- a/chrome/chrome_cleaner/test/reboot_deletion_helper.cc
+++ /dev/null
@@ -1,306 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/test/reboot_deletion_helper.h"
-
-#include <windows.h>
-
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "base/win/registry.h"
-#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
-#include "chrome/chrome_cleaner/os/registry_util.h"
-
-namespace chrome_cleaner {
-
-namespace {
-
-// The moves-pending-reboot is a MULTISZ registry value in the HKLM part of the
-// registry.
-const wchar_t kSessionManagerKey[] =
-    L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
-const wchar_t kPendingFileRenameOps[] = L"PendingFileRenameOperations";
-
-const wchar_t kDoubleNullEntry[] = L"\0\0";
-
-// Convert the strings found in |buffer| to a list of string16s that is returned
-// in |value|. |buffer| is a string which contains a series of pairs of
-// null-terminated string16s followed by a terminating null character. |value|
-// is a pointer to an empty vector of pending moves. On success, this vector
-// contains all of the strings extracted from |buffer|.
-// Returns false if buffer does not meet the above specification.
-bool MultiSZToStringArray(const base::string16& buffer,
-                          std::vector<PendingMove>* value) {
-  DCHECK(value);
-  DCHECK(value->empty());
-
-  const base::char16* data = buffer.c_str();
-  const base::char16* data_end = data + buffer.size();
-
-  // Put null-terminated strings into the sequence.
-  while (data < data_end) {
-    // Parse the source path.
-    base::string16 str_from(data);
-    data += str_from.length() + 1;
-
-    // Parse the destination path. If the offset is at the end of the string,
-    // we assume the destination is empty. This may happen with corrupt registry
-    // values where there are missing trailing null characters.
-    base::string16 str_to;
-    if (data > data_end)
-      return false;
-    if (data < data_end)
-      str_to = data;
-
-    // Move to the next entry.
-    data += str_to.length() + 1;
-    value->push_back(std::make_pair(str_from, str_to));
-  }
-  return true;
-}
-
-// The inverse of MultiSZToStringArray, this function converts a list
-// of string pairs into a byte array format suitable for writing to the
-// kPendingFileRenameOps registry value. It concatenates the strings and
-// appends an additional terminating null character.
-void StringArrayToMultiSZ(const std::vector<PendingMove>& pending_moves,
-                          base::string16* buffer) {
-  DCHECK(buffer);
-  buffer->clear();
-
-  if (pending_moves.empty()) {
-    // Leave buffer empty if there are no strings.
-    return;
-  }
-
-  size_t total_wchars = 0;
-  std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
-  for (; iter != pending_moves.end(); ++iter) {
-    total_wchars += iter->first.length();
-    ++total_wchars;  // Space for the null char.
-    total_wchars += iter->second.length();
-    ++total_wchars;  // Space for the null char.
-  }
-  ++total_wchars;  // Space for the extra terminating null char.
-
-  buffer->resize(total_wchars);
-  base::char16* write_pointer =
-      reinterpret_cast<base::char16*>(&((*buffer)[0]));
-  // Keep an end pointer around for sanity checking.
-  base::char16* end_pointer = write_pointer + total_wchars;
-
-  std::vector<PendingMove>::const_iterator copy_iter(pending_moves.begin());
-  for (; copy_iter != pending_moves.end() && write_pointer < end_pointer;
-       ++copy_iter) {
-    // First copy the source string.
-    size_t string_length = copy_iter->first.length() + 1;
-    ::memcpy(write_pointer, copy_iter->first.c_str(),
-             string_length * sizeof(base::char16));
-    write_pointer += string_length;
-    // Now copy the destination string.
-    string_length = copy_iter->second.length() + 1;
-    ::memcpy(write_pointer, copy_iter->second.c_str(),
-             string_length * sizeof(base::char16));
-    write_pointer += string_length;
-
-    // We should never run off the end while in this loop.
-    DCHECK(write_pointer < end_pointer);
-  }
-  *write_pointer = L'\0';  // Explicitly set the final null char.
-  DCHECK(++write_pointer == end_pointer);
-}
-
-// A helper function for the win32 GetShortPathName that more conveniently
-// returns a FilePath. Note that if |path| is not present on the file system
-// then GetShortPathName will return |path| unchanged, unlike the win32
-// GetShortPathName which will return an error.
-base::FilePath GetShortPathName(const base::FilePath& path) {
-  base::string16 short_path;
-  DWORD length = ::GetShortPathName(
-      path.value().c_str(), base::WriteInto(&short_path, MAX_PATH), MAX_PATH);
-  DPLOG_IF(WARNING, length == 0 && ::GetLastError() != ERROR_PATH_NOT_FOUND)
-      << "GetShortPathName an unexpected result.";
-  if (length == 0) {
-    // GetShortPathName fails if the path is no longer present. Instead of
-    // returning an empty string, just return the original string. This will
-    // serve our purpose.
-    return path;
-  }
-
-  short_path.resize(length);
-  return base::FilePath(short_path);
-}
-
-base::FilePath GetShortPathNameWithoutPrefix(const base::FilePath& reg_path) {
-  // Stores the path stored in each entry.
-  base::string16 match_path(reg_path.value());
-
-  // First chomp the prefix since that will mess up GetShortPathName.
-  base::string16 prefix(L"\\??\\");
-  if (base::StartsWith(match_path, prefix,
-                       base::CompareCase::INSENSITIVE_ASCII))
-    match_path = match_path.substr(4);
-
-  // Get the short path name of the entry.
-  return GetShortPathName(base::FilePath(match_path));
-}
-
-}  // namespace
-
-bool IsFileRegisteredForPostRebootRemoval(const base::FilePath& file_path) {
-  base::FilePath short_path = GetShortPathName(NormalizePath(file_path));
-
-  PendingMoveVector pending_moves;
-  // This can only be called in tests, so CHECKing is ok since that ensures the
-  // test fails.
-  CHECK(GetPendingMoves(&pending_moves)) << "Unable to get pending moves";
-
-  for (PendingMoveVector::const_iterator iter(pending_moves.begin());
-       iter != pending_moves.end(); ++iter) {
-    if (!iter->second.empty()) {
-      // If the destination string is not empty, the pending operation is a move
-      // so this isn't a removal.
-      continue;
-    }
-
-    base::FilePath pending_path(
-        GetShortPathName(NormalizePath(base::FilePath(iter->first))));
-    pending_path = GetShortPathNameWithoutPrefix(pending_path);
-    if (base::FilePath::CompareEqualIgnoreCase(pending_path.value(),
-                                               short_path.value())) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool UnregisterPostRebootRemovals(const FilePathSet& paths) {
-  // Retrieve pending moves from the registry.
-  PendingMoveVector pending_moves;
-  if (!GetPendingMoves(&pending_moves))
-    return false;
-
-  // Build an index of short paths to remove.
-  UnorderedFilePathSet short_paths;
-  for (const auto& path : paths.file_paths()) {
-    short_paths.insert(GetShortPathName(path));
-  }
-
-  // Filter paths pending for deletion with the short paths index.
-  PendingMoveVector moves_to_keep;
-  for (PendingMoveVector::const_iterator iter(pending_moves.begin());
-       iter != pending_moves.end(); ++iter) {
-    if (!iter->second.empty()) {
-      // If the destination string is not empty, the pending operation is a move
-      // and must not be removed.
-      moves_to_keep.push_back(*iter);
-      continue;
-    }
-    base::FilePath pending_path(
-        GetShortPathName(NormalizePath(base::FilePath(iter->first))));
-    pending_path = GetShortPathNameWithoutPrefix(pending_path);
-    if (short_paths.find(pending_path) == short_paths.end())
-      moves_to_keep.push_back(*iter);
-  }
-
-  // Update the remaining pending moves to the registry.
-  if (!SetPendingMoves(moves_to_keep))
-    return false;
-
-  return true;
-}
-
-// Retrieves the list of pending moves from the registry and returns a vector
-// containing pairs of strings that represent the operations. If the list
-// contains only deletes then every other element will be an empty string
-// as per http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx.
-bool GetPendingMoves(PendingMoveVector* pending_moves) {
-  DCHECK(pending_moves);
-  pending_moves->clear();
-
-  // Get the current value of the key.
-  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
-                                        KEY_QUERY_VALUE);
-  HKEY session_manager_handle = session_manager_key.Handle();
-  if (!session_manager_handle ||
-      !session_manager_key.HasValue(kPendingFileRenameOps)) {
-    // If the key or the value is missing, that's totally acceptable.
-    return true;
-  }
-
-  // Read the content of the registry value to retrieve the pending moves.
-  base::string16 pending_moves_value;
-  uint32_t pending_moves_value_type;
-  if (!ReadRegistryValue(session_manager_key, kPendingFileRenameOps,
-                         &pending_moves_value, &pending_moves_value_type,
-                         nullptr)) {
-    DLOG(ERROR) << "Cannot read PendingRename registry value.";
-    return false;
-  }
-
-  if (pending_moves_value_type != REG_MULTI_SZ) {
-    DLOG(ERROR) << "Found PendingRename value of unexpected type.";
-    return false;
-  }
-
-  // We now have a buffer of bytes that is actually a sequence of
-  // null-terminated char16 strings terminated by an additional null character.
-  // Stick this into a vector of strings for clarity.
-  if (!MultiSZToStringArray(pending_moves_value, pending_moves)) {
-    DLOG(ERROR) << "Cannot decode PendingRename registry value.";
-    return false;
-  }
-
-  // Remove the last pending moves entry if it is empty. This entry is found on
-  // Vista+ but not on XP.
-  if (!pending_moves->empty() && pending_moves->back().first.empty() &&
-      pending_moves->back().second.empty()) {
-    pending_moves->pop_back();
-  }
-
-  return true;
-}
-
-bool SetPendingMoves(const PendingMoveVector& pending_moves) {
-  // Retrieve the key content into a buffer.
-  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
-                                        KEY_CREATE_SUB_KEY | KEY_SET_VALUE);
-  if (!session_manager_key.Handle()) {
-    // Couldn't open / create the key.
-    LOG(ERROR) << "Failed to open session manager key for writing.";
-    return false;
-  }
-
-  if (pending_moves.empty()) {
-    // No remaining moves. Don't bother writing that.
-    LONG delete_result = session_manager_key.DeleteValue(kPendingFileRenameOps);
-    return (delete_result == ERROR_SUCCESS ||
-            delete_result == ERROR_FILE_NOT_FOUND);
-  }
-
-  // Serialize pending moves as a sequence of bytes.
-  base::string16 buffer;
-  StringArrayToMultiSZ(pending_moves, &buffer);
-  if (buffer.empty())
-    return false;
-
-  // The pending moves format needs a null entry at the end which consists of
-  // two MULTISZ empty string.
-  base::string16 last_entry(kDoubleNullEntry, base::size(kDoubleNullEntry) - 1);
-  buffer = buffer + last_entry;
-
-  // Write back the serialized values into the registry key.
-  uint32_t size_in_bytes = buffer.size() * sizeof(base::char16);
-  if (session_manager_key.WriteValue(kPendingFileRenameOps, buffer.c_str(),
-                                     size_in_bytes,
-                                     REG_MULTI_SZ) != ERROR_SUCCESS) {
-    LOG(ERROR) << "Failed to update the " << kPendingFileRenameOps << " key.";
-    return false;
-  }
-
-  return true;
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/reboot_deletion_helper.h b/chrome/chrome_cleaner/test/reboot_deletion_helper.h
deleted file mode 100644
index 1a9165e9..0000000
--- a/chrome/chrome_cleaner/test/reboot_deletion_helper.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-#ifndef CHROME_CHROME_CLEANER_TEST_REBOOT_DELETION_HELPER_H_
-#define CHROME_CHROME_CLEANER_TEST_REBOOT_DELETION_HELPER_H_
-
-#include <utility>
-#include <vector>
-
-#include "chrome/chrome_cleaner/os/file_path_set.h"
-
-namespace chrome_cleaner {
-
-// Holds the (source, destination) paths of a pending move. An empty
-// destination string means deletion instead of move.
-typedef std::pair<base::string16, base::string16> PendingMove;
-typedef std::vector<PendingMove> PendingMoveVector;
-
-// Returns true if the given file is registered to be deleted on the next
-// reboot.
-bool IsFileRegisteredForPostRebootRemoval(const base::FilePath& file_path);
-
-// Unregister all of the given files from being registered to be deleted after
-// the next reboot.
-bool UnregisterPostRebootRemovals(const FilePathSet& paths);
-
-// Get the list of all the pending post reboot moves.
-bool GetPendingMoves(PendingMoveVector* pending_moves);
-
-// Set all the pending moves for the nest reboot.
-bool SetPendingMoves(const PendingMoveVector& pending_moves);
-
-}  // namespace chrome_cleaner
-
-#endif  // CHROME_CHROME_CLEANER_TEST_REBOOT_DELETION_HELPER_H_
diff --git a/chrome/chrome_cleaner/test/reboot_deletion_helper_unittest.cc b/chrome/chrome_cleaner/test/reboot_deletion_helper_unittest.cc
deleted file mode 100644
index 76f3742..0000000
--- a/chrome/chrome_cleaner/test/reboot_deletion_helper_unittest.cc
+++ /dev/null
@@ -1,322 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/test/reboot_deletion_helper.h"
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/test/test_reg_util_win.h"
-#include "base/win/registry.h"
-#include "chrome/chrome_cleaner/os/disk_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-namespace {
-
-// The moves-pending-reboot is a MULTISZ registry value in the HKLM part of the
-// registry.
-const wchar_t kSessionManagerKey[] =
-    L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
-const wchar_t kPendingFileRenameOps[] = L"PendingFileRenameOperations";
-
-const uint32_t kMaxRegistryValueLength = 1024;
-
-const wchar_t kRemoveFile1[] = L"remove_one";
-const wchar_t kRemoveFile2[] = L"remove_two";
-const wchar_t kRemoveFile3[] = L"remove_three";
-const wchar_t kRemoveFile4[] = L"remove_four";
-const wchar_t kRemoveFile5[] = L"remove_five";
-const wchar_t kDeleteFile[] = L"";
-const BYTE kNoNullInvalidString[] = {12, 13};
-const BYTE kMissingNullEntryString[] = {65, 0, 0, 0};
-const BYTE kOddSizeEntryString[] = {0, 65, 0, 66, 0xFF, 0, 0, 0, 0};
-const wchar_t kRemoveRawMultipleFiles[] =
-    L"remove_one\0\0remove_two\0remove_three\0\0\0";
-const wchar_t kRemoveRawEmpty0[] = L"";
-const wchar_t kRemoveRawEmpty1[] = L"\0";
-const wchar_t kRemoveRawEmpty2[] = L"\0\0";
-const wchar_t kRemoveRawCorrupt[] = L"file_with_no_ending_null";
-
-bool TestPendingFileRenameOperations(const wchar_t* content,
-                                     size_t content_size,
-                                     PendingMoveVector* pending_moves) {
-  DCHECK(content);
-  DCHECK(pending_moves);
-  pending_moves->clear();
-
-  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
-                                        KEY_ALL_ACCESS);
-  if (!session_manager_key.Handle()) {
-    PLOG(ERROR) << "Can't open session manager.";
-    return false;
-  }
-
-  // Write raw content of the registry value.
-  if (session_manager_key.WriteValue(kPendingFileRenameOps, content,
-                                     content_size,
-                                     REG_MULTI_SZ) != ERROR_SUCCESS) {
-    PLOG(ERROR) << "Can't write to registry value '" << kPendingFileRenameOps
-                << "' value: '" << content << "'.";
-    return false;
-  }
-
-  // Read back the pending moves.
-  if (!GetPendingMoves(pending_moves)) {
-    PLOG(ERROR) << "Can't read back or parse the registry value '"
-                << kPendingFileRenameOps << "'.";
-    return false;
-  }
-
-  return true;
-}
-
-}  // namespace
-
-TEST(RebootDeletionHelper, GetPendingMovesRawValue) {
-  registry_util::RegistryOverrideManager registry_override;
-  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
-
-  PendingMoveVector pending_moves;
-  EXPECT_TRUE(
-      TestPendingFileRenameOperations(kRemoveRawEmpty0, 0, &pending_moves));
-  EXPECT_TRUE(pending_moves.empty());
-
-  EXPECT_TRUE(TestPendingFileRenameOperations(
-      kRemoveRawEmpty0, sizeof(kRemoveRawEmpty0), &pending_moves));
-  EXPECT_TRUE(pending_moves.empty());
-
-  EXPECT_TRUE(TestPendingFileRenameOperations(
-      kRemoveRawEmpty1, sizeof(kRemoveRawEmpty1), &pending_moves));
-  EXPECT_TRUE(pending_moves.empty());
-
-  EXPECT_TRUE(TestPendingFileRenameOperations(
-      kRemoveRawEmpty2, sizeof(kRemoveRawEmpty2), &pending_moves));
-  EXPECT_TRUE(pending_moves.empty());
-
-  EXPECT_TRUE(TestPendingFileRenameOperations(kRemoveRawMultipleFiles,
-                                              sizeof(kRemoveRawMultipleFiles),
-                                              &pending_moves));
-  EXPECT_THAT(pending_moves,
-              testing::ElementsAre(std::make_pair(kRemoveFile1, kDeleteFile),
-                                   std::make_pair(kRemoveFile2, kRemoveFile3)));
-
-  const wchar_t kRemoveRawSingleFile[] = L"remove_one\0\0";
-  EXPECT_TRUE(TestPendingFileRenameOperations(
-      kRemoveRawSingleFile, sizeof(kRemoveRawSingleFile), &pending_moves));
-  EXPECT_THAT(pending_moves,
-              testing::ElementsAre(std::make_pair(kRemoveFile1, kDeleteFile)));
-
-  const wchar_t kRemoveRawRename0[] = L"remove_one\0remove_two";
-  EXPECT_TRUE(TestPendingFileRenameOperations(
-      kRemoveRawRename0, sizeof(kRemoveRawRename0), &pending_moves));
-  EXPECT_THAT(pending_moves,
-              testing::ElementsAre(std::make_pair(kRemoveFile1, kRemoveFile2)));
-
-  const wchar_t kRemoveRawRename1[] = L"remove_one\0remove_two\0";
-  EXPECT_TRUE(TestPendingFileRenameOperations(
-      kRemoveRawRename1, sizeof(kRemoveRawRename1), &pending_moves));
-  EXPECT_THAT(pending_moves,
-              testing::ElementsAre(std::make_pair(kRemoveFile1, kRemoveFile2)));
-
-  const wchar_t kRemoveRawRename2[] = L"remove_one\0remove_two\0\0";
-  EXPECT_TRUE(TestPendingFileRenameOperations(
-      kRemoveRawRename2, sizeof(kRemoveRawRename2), &pending_moves));
-  EXPECT_THAT(pending_moves,
-              testing::ElementsAre(std::make_pair(kRemoveFile1, kRemoveFile2)));
-
-  EXPECT_FALSE(TestPendingFileRenameOperations(
-      kRemoveRawCorrupt, sizeof(kRemoveRawCorrupt), &pending_moves));
-}
-
-TEST(RebootDeletionHelper, SetPendingMovesRawValue) {
-  registry_util::RegistryOverrideManager registry_override;
-  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
-
-  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
-                                        KEY_ALL_ACCESS);
-  EXPECT_TRUE(session_manager_key.Handle());
-
-  // Write some pending moves.
-  PendingMoveVector pending_moves;
-  pending_moves.push_back(std::make_pair(kRemoveFile1, kDeleteFile));
-  pending_moves.push_back(std::make_pair(kRemoveFile2, kRemoveFile3));
-
-  EXPECT_TRUE(SetPendingMoves(pending_moves));
-
-  wchar_t buffer[kMaxRegistryValueLength];
-  DWORD buffer_size = kMaxRegistryValueLength;
-  DWORD buffer_type = REG_NONE;
-
-  // Validate the raw content of the registry value.
-  EXPECT_EQ(ERROR_SUCCESS,
-            session_manager_key.ReadValue(kPendingFileRenameOps, &buffer[0],
-                                          &buffer_size, &buffer_type));
-
-  EXPECT_EQ(buffer_size, sizeof(kRemoveRawMultipleFiles));
-  EXPECT_EQ(0, ::memcmp(kRemoveRawMultipleFiles, buffer, buffer_size));
-  EXPECT_EQ(REG_MULTI_SZ, buffer_type);
-}
-
-TEST(RebootDeletionHelper, SetPendingMovesValueWithEmptyInput) {
-  registry_util::RegistryOverrideManager registry_override;
-  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
-
-  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
-                                        KEY_ALL_ACCESS);
-  EXPECT_TRUE(session_manager_key.Handle());
-
-  // Write raw content of the registry value.
-  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
-                               kPendingFileRenameOps, kRemoveRawMultipleFiles,
-                               sizeof(kRemoveRawMultipleFiles), REG_MULTI_SZ));
-
-  // Write an empty pending moves vector.
-  PendingMoveVector pending_moves;
-  SetPendingMoves(pending_moves);
-
-  // The registry value must be removed.
-  EXPECT_FALSE(session_manager_key.HasValue(kPendingFileRenameOps));
-}
-
-TEST(RebootDeletionHelper, GetAndSetPendingMoves) {
-  // Declare the scoped temp dir before the registry override manager because
-  // the recursive deletion of folders fail when running elevated while a
-  // registry override is active.
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-
-  registry_util::RegistryOverrideManager registry_override;
-  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
-
-  // Expect the registry key to be empty.
-  PendingMoveVector pending_moves;
-  EXPECT_TRUE(GetPendingMoves(&pending_moves));
-  ASSERT_TRUE(pending_moves.empty());
-
-  // Write back some moves into the registry key.
-  base::FilePath file_path1 = temp.GetPath().Append(kRemoveFile1);
-  base::FilePath file_path2 = temp.GetPath().Append(kRemoveFile2);
-  base::FilePath file_path3 = temp.GetPath().Append(kRemoveFile3);
-
-  pending_moves.push_back(
-      std::make_pair(file_path1.value(), file_path2.value()));
-  pending_moves.push_back(std::make_pair(file_path3.value(), kDeleteFile));
-
-  EXPECT_TRUE(SetPendingMoves(pending_moves));
-
-  // Read back the written moves.
-  PendingMoveVector written_moves;
-  EXPECT_TRUE(GetPendingMoves(&written_moves));
-
-  // Validate that moves before and after serialisation are the same.
-  EXPECT_THAT(written_moves, testing::ElementsAreArray(pending_moves));
-
-  // Write back an empty set of moves.
-  pending_moves.clear();
-  EXPECT_TRUE(SetPendingMoves(pending_moves));
-  EXPECT_TRUE(GetPendingMoves(&written_moves));
-  EXPECT_TRUE(written_moves.empty());
-}
-
-TEST(RebootDeletionHelper, GetInvalidPendingMoves) {
-  // Open the pending registry key to write into invalid data.
-  registry_util::RegistryOverrideManager registry_override;
-  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
-
-  base::win::RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
-                                        KEY_CREATE_SUB_KEY | KEY_SET_VALUE);
-  EXPECT_TRUE(session_manager_key.Handle());
-
-  // Write an invalid pending moves registry key with a wrong type.
-  EXPECT_EQ(ERROR_SUCCESS,
-            session_manager_key.WriteValue(kPendingFileRenameOps, 0xCCCCCCCC));
-  PendingMoveVector pending_moves;
-  EXPECT_FALSE(GetPendingMoves(&pending_moves));
-
-  // Write an invalid pending moves registry key with an invalid string format.
-  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
-                               kPendingFileRenameOps, kNoNullInvalidString,
-                               sizeof(kNoNullInvalidString), REG_MULTI_SZ));
-  EXPECT_FALSE(GetPendingMoves(&pending_moves));
-
-  // Write an invalid string without the ending empty entry.
-  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
-                               kPendingFileRenameOps, kMissingNullEntryString,
-                               sizeof(kMissingNullEntryString), REG_MULTI_SZ));
-  EXPECT_FALSE(GetPendingMoves(&pending_moves));
-
-  // Write an invalid string with an odd number of bytes.
-  EXPECT_EQ(ERROR_SUCCESS, session_manager_key.WriteValue(
-                               kPendingFileRenameOps, kOddSizeEntryString,
-                               sizeof(kOddSizeEntryString), REG_MULTI_SZ));
-  EXPECT_TRUE(GetPendingMoves(&pending_moves));
-}
-
-TEST(RebootDeletionHelper, UnregisterPostRebootRemovals) {
-  // Declare the scoped temp dir before the registry override manager because
-  // the recursive deletion of folders fail when running elevated while a
-  // registry override is active.
-  base::ScopedTempDir temp;
-  ASSERT_TRUE(temp.CreateUniqueTempDir());
-
-  registry_util::RegistryOverrideManager registry_override;
-  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
-
-  // Write some moves and renamings into the registry key.
-  base::FilePath file_path1 = temp.GetPath().Append(kRemoveFile1);
-  base::FilePath file_path2 = temp.GetPath().Append(kRemoveFile2);
-  base::FilePath file_path3 = temp.GetPath().Append(kRemoveFile3);
-  base::FilePath file_path4 = temp.GetPath().Append(kRemoveFile4);
-  base::FilePath file_path5 = temp.GetPath().Append(kRemoveFile5);
-
-  PendingMoveVector pending_moves;
-  pending_moves.push_back(std::make_pair(file_path1.value(), kDeleteFile));
-  pending_moves.push_back(std::make_pair(file_path2.value(), kDeleteFile));
-  pending_moves.push_back(std::make_pair(file_path3.value(), kDeleteFile));
-  pending_moves.push_back(
-      std::make_pair(file_path4.value(), file_path5.value()));
-
-  EXPECT_TRUE(SetPendingMoves(pending_moves));
-
-  // Unregister paths from the pending moves.
-  FilePathSet paths;
-  paths.Insert(file_path2);
-  paths.Insert(file_path3);
-  // A file renaming action must not be removed, even if a unregister is
-  // requested.
-  paths.Insert(file_path4);
-  EXPECT_TRUE(UnregisterPostRebootRemovals(paths));
-
-  // Read back the pending moves.
-  PendingMoveVector written_moves;
-  EXPECT_TRUE(GetPendingMoves(&written_moves));
-  EXPECT_THAT(written_moves,
-              testing::ElementsAre(
-                  std::make_pair(file_path1.value(), kDeleteFile),
-                  std::make_pair(file_path4.value(), file_path5.value())));
-}
-
-TEST(RebootDeletionHelper, UnregisterPostRebootRemovalsOfQualifiedPath) {
-  registry_util::RegistryOverrideManager registry_override;
-  registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
-
-  // Add a pending deletion with a qualified path.
-  PendingMoveVector pending_moves;
-  pending_moves.push_back(
-      std::make_pair(L"\\??\\C:\\this_file_doesnt_exist", kDeleteFile));
-  EXPECT_TRUE(SetPendingMoves(pending_moves));
-
-  // Try to remove it with an unqualified path.
-  FilePathSet paths;
-  paths.Insert(base::FilePath(FILE_PATH_LITERAL("C:\\this_file_doesnt_exist")));
-  EXPECT_TRUE(UnregisterPostRebootRemovals(paths));
-
-  // Read back the pending moves.
-  PendingMoveVector written_moves;
-  EXPECT_TRUE(GetPendingMoves(&written_moves));
-  EXPECT_TRUE(written_moves.empty());
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/resources/BUILD.gn b/chrome/chrome_cleaner/test/resources/BUILD.gn
index f363a360..aa31e346 100644
--- a/chrome/chrome_cleaner/test/resources/BUILD.gn
+++ b/chrome/chrome_cleaner/test/resources/BUILD.gn
@@ -53,13 +53,3 @@
     ":compute_sample_dll_digest",
   ]
 }
-
-copy("signed_empty_dll") {
-  sources = [
-    "signed_dll/signed_empty_dll.dll",
-  ]
-
-  outputs = [
-    "$root_out_dir/signed_empty_dll.dll",
-  ]
-}
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/README.md b/chrome/chrome_cleaner/test/resources/signed_dll/README.md
deleted file mode 100644
index fa57d67d..0000000
--- a/chrome/chrome_cleaner/test/resources/signed_dll/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-### Signed test files
-
-This directory contains a self-signed test certificate and its private key.
-
-1. cleaner_test_cert.crt and cleaner_test_key.key were generated with:
-
-   ```
-   openssl req -new -newkey rsa:4096 -x509 -sha256 -days 1095 -nodes -out cleaner_test_cert.crt -keyout cleaner_test_key.key
-   ```
-
-   Leave every entry blank except CN set to "Cleaner Test Cert".
-
-   openssl is bundled with Windows Git. A copy can be found in
-   depot_tools/win_tools-2_7_6_bin/git.
-
-1. cleaner_test_cert.pfx was generated with:
-
-   ```
-   openssl pkcs12 -in cleaner_test_cert.crt -inkey cleaner_test_key.key -export -out cleaner_test_cert.pfx
-   ```
-
-   Under Windows Git's bash shell, you need to use the "winpty" wrapper because
-   it asks for user input. Leave the password blank.
-
-1. signed_empty_dll.dll was generated using the
-   //chrome/chrome_cleaner/test:empty_dll target, and then signed with
-
-   ```
-   signtool.exe sign /fd sha256 /f cleaner_test_cert.pfx signed_empty_dll.dll
-   ```
-
-   A copy of signtool.exe can be found in depot_tools/win_toolchain/vs_files.
-
-   Under Windows Git's bash shell, don't forget to escape the arguments (use
-   "//fd" and "//f"). The error message if you don't escape them is cryptic.
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.crt b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.crt
deleted file mode 100644
index a43b1e04..0000000
--- a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.crt
+++ /dev/null
@@ -1,29 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFCzCCAvOgAwIBAgIJANsfwJbhowz8MA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNV
-BAMMEUNsZWFuZXIgVGVzdCBDZXJ0MB4XDTE4MDcyMDE1MjcxN1oXDTIxMDcxOTE1
-MjcxN1owHDEaMBgGA1UEAwwRQ2xlYW5lciBUZXN0IENlcnQwggIiMA0GCSqGSIb3
-DQEBAQUAA4ICDwAwggIKAoICAQDDJXXzVyMjVU9IaufYZnbcfm+iDuKdIIStGIkP
-KVlT22cnUtSVDKykJy+SAmnzFN0tsMWyYPzTj3onfPQ6y+qAW+AhDpKCASHeMUJC
-VmPAa2mW06hEJpSRLLsBkUFV8jQgvgA0EZlBzIE9tTJXj3kTGry41Fb+Yh/RHRuV
-VXCVK5aYRtbZznLJOSkGri8k8dIqiVBOzI3Z83JD1RmfGisRSgvtg7SoQ8l+ZfQz
-bycw1wP4XJO+/NysksBW10Q5bB4XjwuPFURk+OGVlm/7WoaR6nFoQ0G9Z1YYh+pH
-FGlIYuoFngCznrwxXEAFtOVTXWVrumWhOKnHMEYkdiNPujzYekeu7ch8si/ThTH4
-m8Aphw8QAFQ2lKr9gAM/6fxSXhFUfo4juXtJF3Lz7CeLe7fY76e2NPaEwY7MyEuo
-vx6KXvemHFDJtqix2HCQCH/03TrAZNYavxWxAaH6DYpAuQRw9yUWdALFoSYVykQV
-vZ715yMtLRfT7Fi7UBK73G9G65rVbXPlDuB5uxwK48QA42PHT+u7QUY7BSKiJJBF
-6+C8BLnzVgH0ew0hFtGIUba2AYhV94RDkfTRUUq3ZuK1OmKtyC2XuHv7UXvrurlm
-BqhKl0yoACZnl3Jf3Fjouiq+Wh3IgzKvWCglYQUKQMvEHFnVk5Yu4Oh1s9xD5Mep
-PQ2JWQIDAQABo1AwTjAdBgNVHQ4EFgQUiRfCjDp9ApRzG2WbBPG/1z0jiIwwHwYD
-VR0jBBgwFoAUiRfCjDp9ApRzG2WbBPG/1z0jiIwwDAYDVR0TBAUwAwEB/zANBgkq
-hkiG9w0BAQsFAAOCAgEARRS1G7qAzz5wN8X6CSKFsBf3XXlw/De4fm8Z2Hs13GdP
-TMq8ASUgX3v+rlg/rKIiRov7sbPiaS3BpCwPfV/cCl5QVr3NWr/uqa5TPwYfb/y9
-vIWsHffD3HMp9wE7lxJLlbWQ1gX7CGYPbSJ4z+WnXg4f3KYu9Cjk1hUktpANT8gj
-p9vR7/kL9pEH70LWwTk8zDm6ibqkvSfEHP6wJpQBT6CiBfEB8x29F0klqQJ7jkh5
-wp4gFHQOTGmAdARvQOb788L1EWBIjuRgG0AmB2CoS+VwXl72xTMEWtMkitKtx0oP
-yvSXaGpW3/DcnxuWS7t0mtvNZMKmGj9rASeQcbqzGkpUmZkOHtB2msAsHVBakugb
-JsDnuwrYX5C7D8fIdDzHQPXXrZUjqb6qjOy58EVqYtqINcYzA9j766Cx4SJujmbR
-KrHU/9MAH39hcGrU/NW6mE8IYQ1SFpl8v2g7KdG0Er+ToTiCkOPrVJIst53G+0TG
-K6l81JfQ58J7ilFlcF0GWKaTZY+7d7889PgAvlfazxsUuioM48vQYUlA/ucbbyBN
-4nb/0q9kpY+tCiTZlFxCrmLNlspJHUvWUwbelUVtp+pjppbniMXXNwbOKvZltcoC
-K/Ownd8Z+5hsqDJcJdZmqO1bFNEI1RD8Oz4kFOso5LU8nItB78/lz3WnNLKHeS4=
------END CERTIFICATE-----
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.pfx b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.pfx
deleted file mode 100644
index c92f146..0000000
--- a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_cert.pfx
+++ /dev/null
Binary files differ
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_key.key b/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_key.key
deleted file mode 100644
index e79bee9..0000000
--- a/chrome/chrome_cleaner/test/resources/signed_dll/cleaner_test_key.key
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDDJXXzVyMjVU9I
-aufYZnbcfm+iDuKdIIStGIkPKVlT22cnUtSVDKykJy+SAmnzFN0tsMWyYPzTj3on
-fPQ6y+qAW+AhDpKCASHeMUJCVmPAa2mW06hEJpSRLLsBkUFV8jQgvgA0EZlBzIE9
-tTJXj3kTGry41Fb+Yh/RHRuVVXCVK5aYRtbZznLJOSkGri8k8dIqiVBOzI3Z83JD
-1RmfGisRSgvtg7SoQ8l+ZfQzbycw1wP4XJO+/NysksBW10Q5bB4XjwuPFURk+OGV
-lm/7WoaR6nFoQ0G9Z1YYh+pHFGlIYuoFngCznrwxXEAFtOVTXWVrumWhOKnHMEYk
-diNPujzYekeu7ch8si/ThTH4m8Aphw8QAFQ2lKr9gAM/6fxSXhFUfo4juXtJF3Lz
-7CeLe7fY76e2NPaEwY7MyEuovx6KXvemHFDJtqix2HCQCH/03TrAZNYavxWxAaH6
-DYpAuQRw9yUWdALFoSYVykQVvZ715yMtLRfT7Fi7UBK73G9G65rVbXPlDuB5uxwK
-48QA42PHT+u7QUY7BSKiJJBF6+C8BLnzVgH0ew0hFtGIUba2AYhV94RDkfTRUUq3
-ZuK1OmKtyC2XuHv7UXvrurlmBqhKl0yoACZnl3Jf3Fjouiq+Wh3IgzKvWCglYQUK
-QMvEHFnVk5Yu4Oh1s9xD5MepPQ2JWQIDAQABAoICAQCRoADXKK12DpFtjymYWU5V
-2JxhqQ3/B2c67NZK1CZu54mg1LUCzUR/8yYSpW5/EZDEKeg95xaEocsccKiov8ct
-JmKpCIDYNxQZBVVWv7UMwJs5DJXC1a+EbobW8ph5FJdF38OzF3bwnTXM4MzCfrRx
-R0CSBRMuHfd0S25sEChFiROGa0alnuQVuWweKhnQTgzx5Spiw08P2BXq/Llz+0ks
-S79+7QwBjSRuCJMlVss+LRYvXpZ6raPXvGN/6oBlAYOrPPn5OnuhhgCBapQCVFmb
-xgH/NkF2oAilobd4d4jhlb7hljkb0VbK1vaHy6hef5HRxHVWzDwWArY1O1u6gVYp
-PtN1ut/gFqEQRewwgZnN+rZP0Z2v1nL4s/0Nb8Y6BNtgEYHOnQZqHlq82JRCOlP8
-ezo+JkoZNZ9Aog/FVf85zkj02jxg0IIPYULQY66S3EWFT9mIHT+S+fiyKu3Y2Rra
-9h5/FlAhNcQY2uuOuKAXmS0Qz1pmv5mpgSrWmMDuYWGXsJ+Eq91IWR1bwSTdIztO
-jKfxzqNrhS1W8CfUHyAXan+yxaCni9AW9Qa7ADbSx49rhP+ihLd1PrXq1V+6LMGc
-MZ2rCL4xYgiZiFuYi89tqSUfJNVpzx0dQSDjOFv5yxGTf10rSxLAXmlN8wk466Ub
-SLLUQmcdwEqcnZT3fG26AQKCAQEA8oVNVM6zcaSyx64iC8ZfamlR/IZB4ARe9EY8
-3Im9D/Q7Z8qPcU2u4ZFDuynyxVhY24TfRKZhV7/Gv21eVbP/ChuobpEz7JaPEZhV
-GPIiTf8uKmvJ/YaQxJrx7MHDntL3SQForexo8cvfd8s7ZCge4hb4QgfxdESRGK7n
-EpaCrbNCMdSERSIA2HKswhypczdygKwVwm0XPae/YZeTP73/T8RdruD89NZcToTG
-vSTi6O6fdmVYGxkKb9TM49o4LJvm00AzlsV6hhoVGUJcqqFDrirxjOWJyWMFmJxb
-d7ZH3sHnX0Z6l91abSAwlUNoMg+ucPdQo+B+c7SPxKz9UQq64QKCAQEAzf4YB5q4
-1YBx2XRaJi8puSCCmnJKp+080pVxHrPOe0JqVa8HH4rVeMju34vFzLEk8Glvjc7u
-iRkqBTkU38wjTY70H+rj35njhrXMnuKDrmBMgezQAONZLpej44SjzSyF6djnBlxs
-a6cP9UuWKdts7hiUyqzGA55nMb7PAE8tG9lPh0FWktAnQYtT0Rn58D/WF5uy0c8h
-aPtUgrgExAvBNJpPAtnq7XOG75Iny5s91i8EXFDkIlTXYQp+0f+U6Qf75yE7BHzB
-TbuKI4Qo9/w3GMW1hMlBBydFwSJckmlP/fwVpfHog5+rHDZG2aHcphK23bO/tvJV
-/6yahwx1nz7VeQKCAQAN6QVxetWiDA9RErTTNhKc+OOB93Vp0vZbTngJMkFM2/ZY
-Uq79kbYZLArVfmd1WEboeGuR9XUZ4l8U9cH2aneTbdiwVtXCmTQljzY6UxESpjNQ
-rZQNXZ2KGVUM/mQpBPK4FkOZzjiKveXYaijC6uYyk5yztN7ti01DPCz2zPk7209N
-qmHX0UZ5I8Ky84/okuKXbMdmunkdyTRZ9aa1fkFZouq4sCDyLiVnP4hiqu307FLr
-KI7wJvSJS4xg+VBFhr+rmEAdQsBvVqmlJEBKbSuDnuTx7uyDR5G3mihI6oSey0Jp
-HZLEiSa5oaIHvbEJRgr8YcMXUzYNjuq8Hiv9bP8hAoIBAQCuDuOdIVbHSSZqWY+H
-LljyDg9tk9+Tb7nyMsaH6+Uwb9lMF35MX9KrohV+HSwBHzoYTu8tA0q52+KO0UHb
-LTIzafTMN31fRjhkbp+9LaeZI9PiAQlthq2n2ghoyn5icxmglF/6FwSiHmM0oS78
-pWWw9mJbs4wKKMIH3bQqDb0PCBvULRiLK4nQL3ued3WjVT2Ba1W5RW10uNIbNoUI
-ZupVmYHj5eFFzVWaf4RS3hVtMwNbQhrTC5+GZwjsRys7kTyAe6rTytrH5Qz/n7/C
-c4LW0tDjp+7jrYKahH92U7h845IjS3puJe+/AfnyEXxRdATC5wy6+KBET0Ovk46c
-Bcr5AoIBAEFA+NHs3omya+XLjed6fxRg6Bi14wIpMLCQbg7H+P4SXfSZLUk3e+zh
-gUjMG7vwzHGp7a5CJcL+Q7y4S5dcmwrgV4JNr4211P6HmehqaVjX3GJa79qe6wuB
-tD60Fh2cYg0DRZ555E60T/kxerwPQ5JEwr8tVkK6hcEyMIWPFmSB90E+cmIGmrzM
-kEvAEqlPVWc3uzFymH60yVbdUDAF8nSlBwjXa4RuXlLePflI4sAD3xSb+DRn/k0B
-cDKIrwpL+lCuIdWs1ARzQ1KKNQ80tKCAy8pPd4ZtVEgTdxiJfbpi+dlW65mLL/G5
-wU4oaRK0RLzuQ79pYtXPcXBbIBRm7Zo=
------END PRIVATE KEY-----
diff --git a/chrome/chrome_cleaner/test/resources/signed_dll/signed_empty_dll.dll b/chrome/chrome_cleaner/test/resources/signed_dll/signed_empty_dll.dll
deleted file mode 100755
index c9fa53b..0000000
--- a/chrome/chrome_cleaner/test/resources/signed_dll/signed_empty_dll.dll
+++ /dev/null
Binary files differ
diff --git a/chrome/chrome_cleaner/test/test_executables.cc b/chrome/chrome_cleaner/test/test_executables.cc
deleted file mode 100644
index f92500559..0000000
--- a/chrome/chrome_cleaner/test/test_executables.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/test/test_executables.h"
-
-#include "base/base_paths.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/process/launch.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/win/win_util.h"
-#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
-#include "chrome/chrome_cleaner/test/test_strings.h"
-#include "chrome/chrome_cleaner/test/test_util.h"
-
-namespace chrome_cleaner {
-
-// If you add another test executable here, also add it to the data_deps in
-// the "test_executables" target of chrome_cleaner/test/BUILD.gn.
-
-const base::char16 kTestServiceExecutableName[] = L"test_service.exe";
-const base::char16 kTestProcessExecutableName[] = L"test_process.exe";
-
-base::Process LongRunningProcess(base::CommandLine* cmd) {
-  base::FilePath exe_dir;
-  if (!base::PathService::Get(base::DIR_EXE, &exe_dir)) {
-    LOG(ERROR) << "Failed to get the executable path, unable to create always "
-                  "running process";
-    return base::Process();
-  }
-
-  base::FilePath exe_path =
-      exe_dir.Append(chrome_cleaner::kTestProcessExecutableName);
-  base::CommandLine command_line(exe_path);
-  // This will ensure this new process will run for one minute before dying.
-  command_line.AppendSwitchASCII(chrome_cleaner::kTestSleepMinutesSwitch, "1");
-
-  std::unique_ptr<base::WaitableEvent> init_done_event =
-      chrome_cleaner::CreateInheritableEvent(
-          base::WaitableEvent::ResetPolicy::AUTOMATIC,
-          base::WaitableEvent::InitialState::NOT_SIGNALED);
-  command_line.AppendSwitchNative(
-      chrome_cleaner::kInitDoneNotifierSwitch,
-      base::UintToString16(
-          base::win::HandleToUint32(init_done_event->handle())));
-
-  if (cmd)
-    *cmd = command_line;
-
-  base::LaunchOptions launch_options;
-  launch_options.handles_to_inherit.push_back(init_done_event->handle());
-  base::Process result = base::LaunchProcess(command_line, launch_options);
-
-  if (!init_done_event->TimedWait(base::TimeDelta::FromSeconds(10))) {
-    LOG(ERROR) << "Process did not signal";
-    result.Terminate(/*exit_code=*/1, /*wait=*/false);
-    return base::Process();
-  }
-
-  return result;
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_executables.h b/chrome/chrome_cleaner/test/test_executables.h
deleted file mode 100644
index ca6a2af1..0000000
--- a/chrome/chrome_cleaner/test/test_executables.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-#ifndef CHROME_CHROME_CLEANER_TEST_TEST_EXECUTABLES_H_
-#define CHROME_CHROME_CLEANER_TEST_TEST_EXECUTABLES_H_
-
-#include "base/command_line.h"
-#include "base/process/process.h"
-#include "base/strings/string16.h"
-
-namespace chrome_cleaner {
-
-// The name of the service executable used for tests.
-extern const base::char16 kTestServiceExecutableName[];
-
-// The name of the executable used for tests.
-extern const base::char16 kTestProcessExecutableName[];
-
-// Creates a process that will run for a minute, which is long enough to be
-// killed by a reasonably fast unit or integration test.
-// Populates |command_line| with the used command line if it is not nullptr.
-base::Process LongRunningProcess(base::CommandLine* command_line);
-
-}  // namespace chrome_cleaner
-
-#endif  // CHROME_CHROME_CLEANER_TEST_TEST_EXECUTABLES_H_
diff --git a/chrome/chrome_cleaner/test/test_layered_service_provider.cc b/chrome/chrome_cleaner/test/test_layered_service_provider.cc
deleted file mode 100644
index a792fc6..0000000
--- a/chrome/chrome_cleaner/test/test_layered_service_provider.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
-
-namespace chrome_cleaner {
-
-TestLayeredServiceProvider::TestLayeredServiceProvider() = default;
-
-TestLayeredServiceProvider::~TestLayeredServiceProvider() = default;
-
-int TestLayeredServiceProvider::EnumProtocols(int* protocols,
-                                              WSAPROTOCOL_INFOW* protocol_info,
-                                              DWORD* nb_protocol_info,
-                                              int* error) const {
-  // We don't use the protocols argument yet.
-  DCHECK(!protocols);
-  DCHECK(nb_protocol_info);
-  DCHECK(error);
-  size_t bytes_needed = protocol_info_.size() * sizeof(WSAPROTOCOL_INFOW);
-  if (*nb_protocol_info < bytes_needed) {
-    *nb_protocol_info = bytes_needed;
-    *error = WSAENOBUFS;
-    return SOCKET_ERROR;
-  }
-  *nb_protocol_info = bytes_needed;
-  std::map<GUID, base::FilePath, GUIDLess>::const_iterator iter =
-      protocol_info_.begin();
-  for (size_t i = 0; iter != protocol_info_.end(); ++iter, ++i) {
-    protocol_info[i].ProviderId = iter->first;
-  }
-  return protocol_info_.size();
-}
-
-int TestLayeredServiceProvider::GetProviderPath(GUID* provider_id,
-                                                wchar_t* provider_dll_path,
-                                                int* provider_dll_path_len,
-                                                int* error) const {
-  DCHECK(provider_id);
-  DCHECK(provider_dll_path);
-  DCHECK(provider_dll_path_len);
-  DCHECK(error);
-  std::map<GUID, base::FilePath, GUIDLess>::const_iterator iter =
-      protocol_info_.find(*provider_id);
-  if (iter == protocol_info_.end()) {
-    *error = WSAEINVAL;
-    return SOCKET_ERROR;
-  }
-  if (*provider_dll_path_len <
-      static_cast<int>(iter->second.value().size() + 1)) {
-    *error = WSAEFAULT;
-    return SOCKET_ERROR;
-  }
-  ::wcsncpy(provider_dll_path, iter->second.value().c_str(),
-            iter->second.value().size());
-  provider_dll_path[iter->second.value().size()] = L'\0';
-  return 0;
-}
-
-void TestLayeredServiceProvider::AddProvider(const GUID& provider_id,
-                                             const base::FilePath& path) {
-  protocol_info_[provider_id] = path;
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_layered_service_provider.h b/chrome/chrome_cleaner/test/test_layered_service_provider.h
deleted file mode 100644
index dc32939..0000000
--- a/chrome/chrome_cleaner/test/test_layered_service_provider.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.
-
-#ifndef CHROME_CHROME_CLEANER_TEST_TEST_LAYERED_SERVICE_PROVIDER_H_
-#define CHROME_CHROME_CLEANER_TEST_TEST_LAYERED_SERVICE_PROVIDER_H_
-
-#include <map>
-
-#include "base/files/file_path.h"
-#include "chrome/chrome_cleaner/os/disk_util.h"
-#include "chrome/chrome_cleaner/os/layered_service_provider_api.h"
-
-namespace chrome_cleaner {
-
-class TestLayeredServiceProvider : public LayeredServiceProviderAPI {
- public:
-  TestLayeredServiceProvider();
-  ~TestLayeredServiceProvider() override;
-
-  int EnumProtocols(int* protocols,
-                    WSAPROTOCOL_INFOW* protocol_info,
-                    DWORD* nb_protocol_info,
-                    int* error) const override;
-
-  int GetProviderPath(GUID* provider_id,
-                      wchar_t* provider_dll_path,
-                      int* provider_dll_path_len,
-                      int* error) const override;
-
-  void AddProvider(const GUID& provider_id, const base::FilePath& path);
-
- private:
-  std::map<GUID, base::FilePath, GUIDLess> protocol_info_;
-};
-
-}  // namespace chrome_cleaner
-
-#endif  // CHROME_CHROME_CLEANER_TEST_TEST_LAYERED_SERVICE_PROVIDER_H_
diff --git a/chrome/chrome_cleaner/test/test_main.cc b/chrome/chrome_cleaner/test/test_main.cc
index f551a25..316aba8 100644
--- a/chrome/chrome_cleaner/test/test_main.cc
+++ b/chrome/chrome_cleaner/test/test_main.cc
@@ -2,76 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <memory>
-
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
-#include "base/win/scoped_com_initializer.h"
-#include "chrome/chrome_cleaner/os/rebooter.h"
-#include "chrome/chrome_cleaner/os/secure_dll_loading.h"
-#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
-#include "chrome/chrome_cleaner/os/task_scheduler.h"
-#include "chrome/chrome_cleaner/test/test_util.h"
-#include "sandbox/win/src/sandbox_factory.h"
-
-namespace {
-
-bool IsSandboxedProcess() {
-  static const bool is_sandboxed_process =
-      (sandbox::SandboxFactory::GetTargetServices() != nullptr);
-  return is_sandboxed_process;
-}
-
-}  // namespace
+#include "chrome/chrome_cleaner/os/initializer.h"
+#include "chrome/chrome_cleaner/pup_data/pup_data.h"
+#include "chrome/chrome_cleaner/test/test_uws_catalog.h"
 
 int main(int argc, char** argv) {
-  // This must be executed as soon as possible to reduce the number of dlls that
-  // the code might try to load before we can lock things down.
-  //
-  // We enable secure DLL loading in the test suite to be sure that it doesn't
-  // affect the behaviour of functionality that's tested.
-  chrome_cleaner::EnableSecureDllLoading();
-
   base::TestSuite test_suite(argc, argv);
 
-  if (!chrome_cleaner::SetupTestConfigs())
-    return 1;
+  chrome_cleaner::PUPData::InitializePUPData(
+      {&chrome_cleaner::TestUwSCatalog::GetInstance()});
+  chrome_cleaner::InitializeOSUtils();
 
-  if (!chrome_cleaner::CheckTestPrivileges())
-    return 1;
-
-  // Make sure tests will not end up in an infinite reboot loop.
-  if (chrome_cleaner::Rebooter::IsPostReboot())
-    return 0;
-
-  // ScopedCOMInitializer keeps COM initialized in a specific scope. We don't
-  // want to initialize it for sandboxed processes, so manage its lifetime with
-  // a unique_ptr, which will call ScopedCOMInitializer's destructor when it
-  // goes out of scope below.
-  std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer;
-
-  if (!IsSandboxedProcess()) {
-    scoped_com_initializer = std::make_unique<base::win::ScopedCOMInitializer>(
-        base::win::ScopedCOMInitializer::kMTA);
-    bool success = chrome_cleaner::InitializeCOMSecurity();
-    DCHECK(success) << "InitializeCOMSecurity() failed.";
-
-    success = chrome_cleaner::TaskScheduler::Initialize();
-    DCHECK(success) << "TaskScheduler::Initialize() failed.";
-  }
-
-  // Some tests will fail if two tests try to launch test_process.exe
-  // simultaneously, so run the tests serially. This will still shard them and
-  // distribute the shards to different swarming bots, but tests will run
-  // serially on each bot.
-  const int result = base::LaunchUnitTestsSerially(
+  return base::LaunchUnitTests(
       argc, argv,
       base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
-
-  if (!IsSandboxedProcess())
-    chrome_cleaner::TaskScheduler::Terminate();
-
-  return result;
 }
diff --git a/chrome/chrome_cleaner/test/test_process_main.cc b/chrome/chrome_cleaner/test/test_process_main.cc
deleted file mode 100644
index de664d6..0000000
--- a/chrome/chrome_cleaner/test/test_process_main.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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.
-
-#include <windows.h>
-
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/time/time.h"
-#include "chrome/chrome_cleaner/os/disk_util.h"
-#include "chrome/chrome_cleaner/os/initializer.h"
-#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
-#include "chrome/chrome_cleaner/os/secure_dll_loading.h"
-#include "chrome/chrome_cleaner/test/test_strings.h"
-#include "chrome/chrome_cleaner/test/test_util.h"
-
-namespace {
-
-constexpr base::char16 kLogFileExtension[] = L"log";
-
-}  // namespace
-
-int APIENTRY wWinMain(HINSTANCE, HINSTANCE, wchar_t*, int) {
-  // This must be executed as soon as possible to reduce the number of dlls that
-  // the code might try to load before we can lock things down.
-  chrome_cleaner::EnableSecureDllLoading();
-
-  base::AtExitManager at_exit;
-
-  bool success = base::CommandLine::Init(0, nullptr);
-  DCHECK(success);
-
-  if (!chrome_cleaner::SetupTestConfigs())
-    return 1;
-
-  // Initialize the logging settings to set a specific log file name.
-  base::FilePath exe_file_path =
-      chrome_cleaner::PreFetchedPaths::GetInstance()->GetExecutablePath();
-
-  base::FilePath log_file_path(
-      exe_file_path.ReplaceExtension(kLogFileExtension));
-  logging::LoggingSettings logging_settings;
-  logging_settings.logging_dest = logging::LOG_TO_FILE;
-  logging_settings.log_file = log_file_path.value().c_str();
-  success = logging::InitLogging(logging_settings);
-  DCHECK(success);
-
-  LOG(INFO) << "Process Started.";
-
-  chrome_cleaner::NotifyInitializationDoneForTesting();
-
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(
-          chrome_cleaner::kTestForceOverwriteZoneIdentifier)) {
-    LOG(INFO) << "Process is overwriting the zone identifier.";
-    chrome_cleaner::OverwriteZoneIdentifier(exe_file_path);
-  }
-
-  if (command_line->HasSwitch(chrome_cleaner::kTestSleepMinutesSwitch)) {
-    std::string value = command_line->GetSwitchValueASCII(
-        chrome_cleaner::kTestSleepMinutesSwitch);
-    int sleep_minutes = 0;
-    if (base::StringToInt(value, &sleep_minutes) && sleep_minutes > 0) {
-      LOG(INFO) << "Process is sleeping for " << sleep_minutes << " minutes";
-      ::Sleep(base::TimeDelta::FromMinutes(sleep_minutes).InMilliseconds());
-    } else {
-      LOG(ERROR) << "Invalid sleep delay value " << value;
-    }
-    NOTREACHED();
-    return 1;
-  }
-
-  if (command_line->HasSwitch(chrome_cleaner::kTestEventToSignal)) {
-    LOG(INFO) << "Process is signaling event '"
-              << chrome_cleaner::kTestEventToSignal << "'";
-    base::string16 event_name =
-        command_line->GetSwitchValueNative(chrome_cleaner::kTestEventToSignal);
-    base::win::ScopedHandle handle(
-        ::OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name.c_str()));
-    PLOG_IF(ERROR, !handle.IsValid())
-        << "Cannot create event '" << chrome_cleaner::kTestEventToSignal << "'";
-    base::WaitableEvent event(std::move(handle));
-    event.Signal();
-  }
-
-  // TODO(pmbureau): Add more behavior to test processes termination.
-
-  LOG(INFO) << "Process ended.";
-  return 0;
-}
diff --git a/chrome/chrome_cleaner/test/test_service_main.cc b/chrome/chrome_cleaner/test/test_service_main.cc
deleted file mode 100644
index 20afd27..0000000
--- a/chrome/chrome_cleaner/test/test_service_main.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-// 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.
-
-#include <windows.h>
-
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/strings/string16.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/thread_checker.h"
-#include "chrome/chrome_cleaner/test/test_strings.h"
-
-namespace {
-
-class TestService {
- public:
-  TestService() {
-    service_status_.dwCurrentState = SERVICE_START_PENDING;
-    service_status_.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
-    service_status_.dwWaitHint =
-        TestTimeouts::action_max_timeout().InMilliseconds();
-    service_stop_event_ = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
-  }
-
-  void SignalStopEvent() { ::SetEvent(service_stop_event_); }
-  void WaitForStopEvent() {
-    ::WaitForSingleObject(service_stop_event_, INFINITE);
-  }
-
-  void SetControlsAccepted(DWORD control) {
-    DCHECK_CALLED_ON_VALID_THREAD(service_status_thread_checker_);
-    service_status_.dwControlsAccepted = control;
-  }
-
-  void SetStatusHandle(SERVICE_STATUS_HANDLE status_handle) {
-    CHECK(status_handle);
-    status_handle_ = status_handle;
-  }
-
-  DWORD GetServiceStatusState() {
-    DCHECK_CALLED_ON_VALID_THREAD(service_status_thread_checker_);
-    return service_status_.dwCurrentState;
-  }
-
-  void SetServiceStatusState(DWORD state) {
-    DCHECK_CALLED_ON_VALID_THREAD(service_status_thread_checker_);
-    DCHECK(status_handle_);
-    service_status_.dwCurrentState = state;
-    if (::SetServiceStatus(status_handle_, &service_status_) == FALSE)
-      LOG(ERROR) << "Cannot set service status state.";
-  }
-
- private:
-  SERVICE_STATUS_HANDLE status_handle_ = 0;
-  SERVICE_STATUS service_status_ = {};
-  HANDLE service_stop_event_ = INVALID_HANDLE_VALUE;
-  THREAD_CHECKER(service_status_thread_checker_);
-};
-
-DWORD WINAPI ServiceCtrlHandler(DWORD control,
-                                DWORD /* event_type */,
-                                LPVOID /* event_data */,
-                                LPVOID context) {
-  TestService* service = reinterpret_cast<TestService*>(context);
-  DCHECK(service);
-  if (control == SERVICE_CONTROL_STOP)
-    service->SignalStopEvent();
-  return 0;
-}
-
-void WINAPI ServiceMain(DWORD argc, LPTSTR* argv) {
-  TestService service;
-
-  // Registers a function to handle extended service control requests.
-  SERVICE_STATUS_HANDLE status_handle =
-      RegisterServiceCtrlHandlerEx(L"", ServiceCtrlHandler, &service);
-  service.SetStatusHandle(status_handle);
-
-  // Tell the service controller the current service has started.
-  service.SetServiceStatusState(SERVICE_START_PENDING);
-  LOG(INFO) << "Service status is 'start pending'.";
-
-  // Tell the service controller the current service is running.
-  service.SetControlsAccepted(SERVICE_ACCEPT_STOP);
-  service.SetServiceStatusState(SERVICE_RUNNING);
-  LOG(INFO) << "Service status is 'running'.";
-
-  // The body of the service wait until a stop signal is received.
-  LOG(INFO) << "Service is waiting to be stopped.";
-  service.WaitForStopEvent();
-
-  // TODO(pmbureau): Add more kind of worker that may protect against service
-  //     termination and validate service termination.
-
-  // Tell the service controller the current service is stopped.
-  service.SetServiceStatusState(SERVICE_STOP_PENDING);
-  LOG(INFO) << "Service status is 'stop pending'.";
-
-  service.SetServiceStatusState(SERVICE_STOPPED);
-  // Do not attempt to perform any additional work after calling
-  // SetServiceStatus with SERVICE_STOPPED, because the service process can be
-  // terminated at any time.
-}
-
-constexpr base::char16 kLogFileExtension[] = L"log";
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  base::AtExitManager at_exit;
-
-  bool success = base::CommandLine::Init(0, nullptr);
-  DCHECK(success);
-
-  TestTimeouts::Initialize();
-
-  // Initialize the logging settings to set a specific log file name.
-  base::FilePath exe_file_path;
-  success = base::PathService::Get(base::FILE_EXE, &exe_file_path);
-  DCHECK(success);
-
-  base::FilePath log_file_path(
-      exe_file_path.ReplaceExtension(kLogFileExtension));
-  logging::LoggingSettings logging_settings;
-  logging_settings.logging_dest = logging::LOG_TO_FILE;
-  logging_settings.log_file = log_file_path.value().c_str();
-  success = logging::InitLogging(logging_settings);
-  DCHECK(success);
-
-  LOG(INFO) << "Service Started.";
-
-  // Service main.
-
-  // SERVICE_TABLE_ENTRY::lpServiceName takes a non-const string.
-  base::char16 empty_string[] = L"";
-
-  SERVICE_TABLE_ENTRY dispatch_table[] = {{empty_string, ServiceMain},
-                                          {nullptr, nullptr}};
-
-  if (::StartServiceCtrlDispatcher(dispatch_table) == FALSE) {
-    LOG(ERROR) << "StartServiceCtrlDispatcher failed.";
-    return 1;
-  }
-
-  LOG(INFO) << "Service ended.";
-  return 0;
-}
diff --git a/chrome/chrome_cleaner/test/test_util.cc b/chrome/chrome_cleaner/test/test_util.cc
deleted file mode 100644
index ac643fd..0000000
--- a/chrome/chrome_cleaner/test/test_util.cc
+++ /dev/null
@@ -1,314 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/test/test_util.h"
-
-#include <stdint.h>
-#include <windows.h>
-
-#include <algorithm>
-#include <iterator>
-#include <set>
-#include <utility>
-
-#include "base/base_paths.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
-#include "chrome/chrome_cleaner/os/disk_util.h"
-#include "chrome/chrome_cleaner/os/initializer.h"
-#include "chrome/chrome_cleaner/os/post_reboot_registration.h"
-#include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
-#include "chrome/chrome_cleaner/os/scoped_disable_wow64_redirection.h"
-#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
-#include "chrome/chrome_cleaner/os/whitelisted_directory.h"
-#include "chrome/chrome_cleaner/proto/shared_pup_enums.pb.h"
-#include "chrome/chrome_cleaner/strings/string_util.h"
-#include "chrome/chrome_cleaner/test/test_file_util.h"
-#include "chrome/chrome_cleaner/test/test_strings.h"
-#include "chrome/chrome_cleaner/test/test_uws_catalog.h"
-#include "sandbox/win/src/sandbox_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chrome_cleaner {
-
-bool SetupTestConfigs() {
-  return SetupTestConfigsWithCatalogs({&TestUwSCatalog::GetInstance()});
-}
-
-bool SetupTestConfigsWithCatalogs(const PUPData::UwSCatalogs& catalogs) {
-  if (!InitializeOSUtils())
-    return false;
-
-  PUPData::InitializePUPData(catalogs);
-
-  PreFetchedPaths::GetInstance()->DisableForTesting();
-  base::PathService::DisableCache();
-
-  WhitelistedDirectory::GetInstance()->DisableCache();
-
-  return true;
-}
-
-ScopedIsPostReboot::ScopedIsPostReboot() {
-  // This switch will be removed by scoped_command_line_'s destructor when it
-  // goes out of scope.
-  scoped_command_line_.GetProcessCommandLine()->AppendSwitch(kPostRebootSwitch);
-}
-
-bool RunOnceCommandLineContains(const base::string16& product_shortname,
-                                const wchar_t* sub_string) {
-  DCHECK(sub_string);
-  PostRebootRegistration post_reboot(product_shortname);
-  base::string16 run_once_value = post_reboot.RunOnceOnRestartRegisteredValue();
-  return String16ContainsCaseInsensitive(run_once_value, sub_string);
-}
-
-bool RunOnceOverrideCommandLineContains(const std::string& cleanup_id,
-                                        const wchar_t* sub_string) {
-  DCHECK(sub_string);
-
-  base::string16 reg_value;
-  base::win::RegKey run_once_key(
-      HKEY_CURRENT_USER,
-      PostRebootRegistration::GetPostRebootSwitchKeyPath().c_str(), KEY_READ);
-  if (run_once_key.Valid()) {
-    // There is no need to check the return value, since ReadValue will leave
-    // |reg_value| empty on error.
-    run_once_key.ReadValue(base::UTF8ToUTF16(cleanup_id).c_str(), &reg_value);
-  }
-
-  return String16ContainsCaseInsensitive(reg_value, sub_string);
-}
-
-bool RegisterTestTask(TaskScheduler* task_scheduler,
-                      TaskScheduler::TaskInfo* task_info) {
-  const wchar_t name[] = L"Chrome Cleaner Test task";
-  const wchar_t description[] =
-      L"Chrome Cleaner Test Task Used Just For Testing";
-
-  const base::FilePath exe_path =
-      PreFetchedPaths::GetInstance()->GetExecutablePath();
-
-  TaskScheduler::TaskExecAction action{
-      exe_path, base::FilePath(), L"argument",
-  };
-
-  base::CommandLine command_line(action.application_path);
-  command_line.AppendArgNative(action.arguments);
-  if (!task_scheduler->RegisterTask(
-          name, description, command_line,
-          chrome_cleaner::TaskScheduler::TRIGGER_TYPE_HOURLY, false)) {
-    LOG(ERROR) << "Failed to register test task";
-    return false;
-  }
-
-  task_info->name = name;
-  task_info->description = description;
-  task_info->exec_actions.push_back(action);
-  return true;
-}
-
-void AppendTestSwitches(base::CommandLine* command_line) {
-  command_line->AppendSwitch(kNoRecoveryComponentSwitch);
-  command_line->AppendSwitch(kNoCrashUploadSwitch);
-  command_line->AppendSwitch(kNoReportUploadSwitch);
-  command_line->AppendSwitch(kNoSelfDeleteSwitch);
-}
-
-void ExpectDiskFootprint(const PUPData::PUP& pup,
-                         const base::FilePath& expected_path) {
-  for (const auto& path : pup.expanded_disk_footprints.file_paths()) {
-    if (PathEqual(expected_path, path))
-      return;
-  }
-  ADD_FAILURE() << "Expected file: " << expected_path.value();
-}
-
-// Expect the scheduled task footprint to be found in |pup|.
-void ExpectScheduledTaskFootprint(const PUPData::PUP& pup,
-                                  const wchar_t* task_name) {
-  DCHECK(task_name);
-  for (const auto& footprint : pup.expanded_scheduled_tasks) {
-    if (footprint == task_name)
-      return;
-  }
-  ADD_FAILURE() << "Expected schedule task not found: '" << task_name << "'.";
-}
-
-bool StringContainsCaseInsensitive(const std::string& value,
-                                   const std::string& substring) {
-  return std::search(
-             value.begin(), value.end(), substring.begin(), substring.end(),
-             base::CaseInsensitiveCompareASCII<std::string::value_type>()) !=
-         value.end();
-}
-
-LoggingOverride::LoggingOverride() {
-  DCHECK(!active_logging_messages_);
-  active_logging_messages_ = &logging_messages_;
-  logging::SetLogMessageHandler(&LogMessageHandler);
-}
-
-LoggingOverride::~LoggingOverride() {
-  logging::SetLogMessageHandler(nullptr);
-  logging_messages_.clear();
-  DCHECK_EQ(active_logging_messages_, &logging_messages_);
-  active_logging_messages_ = nullptr;
-}
-
-bool LoggingOverride::LoggingMessagesContain(const std::string& sub_string) {
-  for (const auto& line : logging_messages_) {
-    if (StringContainsCaseInsensitive(line, sub_string))
-      return true;
-  }
-  return false;
-}
-
-bool LoggingOverride::LoggingMessagesContain(const std::string& sub_string1,
-                                             const std::string& sub_string2) {
-  for (const auto& line : logging_messages_) {
-    if (StringContainsCaseInsensitive(line, sub_string1) &&
-        StringContainsCaseInsensitive(line, sub_string2))
-      return true;
-  }
-  return false;
-}
-
-std::vector<std::string>* LoggingOverride::active_logging_messages_ = nullptr;
-
-bool IsSubsetOf(const FilePathSet& set1,
-                const FilePathSet& set2,
-                const std::string& unexpected_path_log_message) {
-  bool is_subset = true;
-  for (const base::FilePath& file_path : set1.file_paths()) {
-    if (!set2.Contains(file_path)) {
-      LOG(ERROR) << unexpected_path_log_message << ": '" << file_path.value()
-                 << "'";
-      is_subset = false;
-    }
-  }
-  return is_subset;
-}
-
-void ExpectEqualFilePathSets(const FilePathSet& matched_files,
-                             const FilePathSet& expected_files) {
-  EXPECT_TRUE(IsSubsetOf(matched_files, expected_files,
-                         "Unexpected file in matched footprints"));
-  EXPECT_TRUE(
-      IsSubsetOf(expected_files, matched_files, "Missing expected footprint"));
-}
-
-base::FilePath GetWow64RedirectedSystemPath() {
-  std::vector<wchar_t> buffer;
-  size_t size_needed = MAX_PATH;
-  while (size_needed > buffer.size()) {
-    buffer.resize(size_needed);
-    size_needed = ::GetSystemWow64DirectoryW(buffer.data(), buffer.size());
-    if (size_needed == 0) {
-      PLOG(ERROR) << "Could not get system Wow64 directory";
-      return base::FilePath();
-    }
-  }
-  buffer.push_back(L'\0');
-  return base::FilePath(buffer.data());
-}
-
-base::FilePath GetSampleDLLPath() {
-  // The sample DLL should be next to the executable because it is generated at
-  // build time.
-  base::FilePath exe_dir;
-  base::PathService::Get(base::DIR_EXE, &exe_dir);
-  return exe_dir.Append(L"empty_dll.dll");
-}
-
-base::FilePath GetSignedSampleDLLPath() {
-  // The signed sample DLL should be next to the executable because it's copied
-  // there at build time.
-  base::FilePath exe_dir;
-  base::PathService::Get(base::DIR_EXE, &exe_dir);
-  return exe_dir.Append(L"signed_empty_dll.dll");
-}
-
-ScopedTempDirNoWow64::ScopedTempDirNoWow64() = default;
-
-ScopedTempDirNoWow64::~ScopedTempDirNoWow64() {
-  // Since the temp dir was created with Wow64 disabled, it must be deleted
-  // with Wow64 disabled.
-  ScopedDisableWow64Redirection disable_wow64_redirection;
-  ANALYZER_ALLOW_UNUSED(Delete());
-
-  // The parent's destructor will call Delete again, without disabling Wow64,
-  // which could delete a directory with the same name in SysWOW64. So make
-  // sure the path is cleared even if the Delete call above failed.
-  Take();
-}
-
-bool ScopedTempDirNoWow64::CreateUniqueSystem32TempDir() {
-  ScopedDisableWow64Redirection disable_wow64_redirection;
-  base::FilePath system_path;
-  if (!base::PathService::Get(base::DIR_SYSTEM, &system_path)) {
-    PLOG(ERROR) << "Unable to get system32 path";
-    return false;
-  }
-  // Note that on 32-bit Windows this check will always succeed because
-  // GetWow64RedirectedSystemPath returns an empty string. This is correct
-  // because Wow64 redirection isn't supported on 32-bit Windows, so the system
-  // path is guaranteed not to be redirected.
-  DCHECK(system_path != GetWow64RedirectedSystemPath());
-  return CreateUniqueTempDirUnderPath(system_path);
-}
-
-bool ScopedTempDirNoWow64::CreateEmptyFileInUniqueSystem32TempDir(
-    const base::string16& file_name) {
-  if (!CreateUniqueSystem32TempDir())
-    return false;
-  ScopedDisableWow64Redirection disable_wow64_redirection;
-  return CreateEmptyFile(GetPath().Append(file_name));
-}
-
-std::unique_ptr<base::WaitableEvent> CreateInheritableEvent(
-    base::WaitableEvent::ResetPolicy reset_policy,
-    base::WaitableEvent::InitialState initial_state) {
-  SECURITY_ATTRIBUTES attributes = {sizeof(SECURITY_ATTRIBUTES)};
-  attributes.bInheritHandle = true;
-
-  HANDLE handle = ::CreateEvent(
-      &attributes, reset_policy == base::WaitableEvent::ResetPolicy::MANUAL,
-      initial_state == base::WaitableEvent::InitialState::SIGNALED, nullptr);
-  if (handle == nullptr || handle == INVALID_HANDLE_VALUE) {
-    PLOG(ERROR) << "Could not create inheritable event";
-    return std::unique_ptr<base::WaitableEvent>();
-  }
-  base::win::ScopedHandle event_handle(handle);
-  return std::make_unique<base::WaitableEvent>(std::move(event_handle));
-}
-
-bool CheckTestPrivileges() {
-  // Check for administrator privileges, unless running in the sandbox.
-  const bool is_sandboxed_process =
-      (sandbox::SandboxFactory::GetTargetServices() != nullptr);
-  if (!is_sandboxed_process && !chrome_cleaner::HasAdminRights()) {
-    LOG(ERROR) << "Some Chrome Cleanup tests need administrator privileges.";
-    return false;
-  }
-
-  // All programs run under the msys git shell have debug privileges (!), which
-  // breaks the assumptions of some of the tests. So drop that privilege unless
-  // actually running under a debugger.
-  if (!::IsDebuggerPresent() &&
-      !chrome_cleaner::ReleaseDebugRightsPrivileges()) {
-    PLOG(ERROR) << "Failed to release debug privileges";
-    return false;
-  }
-
-  return true;
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_util.h b/chrome/chrome_cleaner/test/test_util.h
deleted file mode 100644
index c0cd0139..0000000
--- a/chrome/chrome_cleaner/test/test_util.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// 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.
-
-#ifndef CHROME_CHROME_CLEANER_TEST_TEST_UTIL_H_
-#define CHROME_CHROME_CLEANER_TEST_TEST_UTIL_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/process/process.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/scoped_command_line.h"
-#include "base/win/registry.h"
-#include "base/win/scoped_handle.h"
-#include "chrome/chrome_cleaner/os/task_scheduler.h"
-#include "chrome/chrome_cleaner/proto/shared_pup_enums.pb.h"
-#include "chrome/chrome_cleaner/pup_data/pup_data.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-class FilePath;
-}  // namespace base
-
-namespace chrome_cleaner {
-
-// Setup all configs required by tests (like disabling path caching). This
-// should be done in the main function of the test binary, not by individual
-// tests.
-//
-// Returns false if setup fails. Tests shouldn't be run if the setup fails.
-bool SetupTestConfigs();
-
-// Sets up all test configs, as SetupTestConfigs, using the given list of
-// |catalogs| instead of TestUwSCatalog.
-bool SetupTestConfigsWithCatalogs(const PUPData::UwSCatalogs& catalogs);
-
-// While this class is in scope, Rebooter::IsPostReboot will return true.
-class ScopedIsPostReboot {
- public:
-  ScopedIsPostReboot();
-
- private:
-  base::test::ScopedCommandLine scoped_command_line_;
-};
-
-class LoggingOverride {
- public:
-  LoggingOverride();
-  ~LoggingOverride();
-
-  // Intercepts all log messages.
-  static bool LogMessageHandler(int severity,
-                                const char* file,
-                                int line,
-                                size_t message_start,
-                                const std::string& str) {
-    DCHECK(active_logging_messages_);
-    active_logging_messages_->push_back(str);
-    return false;
-  }
-
-  // Returns true if one of the messages contains |sub_string|.
-  bool LoggingMessagesContain(const std::string& sub_string);
-
-  // Returns true if one of the messages contains both |sub_string| and
-  // |sub_string2|.
-  bool LoggingMessagesContain(const std::string& sub_string1,
-                              const std::string& sub_string2);
-
-  // Remove all the log messages.
-  void FlushMessages() { logging_messages_.clear(); }
-
-  std::vector<std::string> logging_messages_;
-  static std::vector<std::string>* active_logging_messages_;
-};
-
-// Validate that the run once on restart registry value contains the given
-// |sub_string|.
-bool RunOnceCommandLineContains(const base::string16& product_shortname,
-                                const wchar_t* sub_string);
-
-// Validate that the run once on restart switch-containing registry value
-// contains the given |sub_string|.
-bool RunOnceOverrideCommandLineContains(const std::string& cleanup_id,
-                                        const wchar_t* sub_string);
-
-// Register a task with the given task scheduler. If the task is successfully
-// added, |task_info| will contain all the information about the task.
-// Callers are responsible for deleting the test task.
-bool RegisterTestTask(TaskScheduler* task_scheduler,
-                      TaskScheduler::TaskInfo* task_info);
-
-// Append switches to the command line that is used to run cleaner or reporter
-// in tests. Switches will disable logs upload, profile reset and other side
-// effects.
-void AppendTestSwitches(base::CommandLine* command_line);
-
-// Expect the |expected_path| to be found in expanded disk footprint of |pup|.
-void ExpectDiskFootprint(const PUPData::PUP& pup,
-                         const base::FilePath& expected_path);
-
-// Expect the scheduled task footprint to be found in |pup|.
-void ExpectScheduledTaskFootprint(const PUPData::PUP& pup,
-                                  const wchar_t* task_name);
-
-// This function is the 8 bits version of String16ContainsCaseInsensitive in
-// chrome_cleaner/string_util. Since it's only used in tests, we decided not to
-// move it to the main lib.
-bool StringContainsCaseInsensitive(const std::string& value,
-                                   const std::string& substring);
-
-// Expect two FilePathSets to be equal. Log files that are matched in excess
-// or expected files that are missing.
-void ExpectEqualFilePathSets(const FilePathSet& matched_files,
-                             const FilePathSet& expected_files);
-
-// Returns the path that base::DIR_SYSTEM is transparently redirected to under
-// Wow64. Note that on 32-bit Windows this will always return the empty string
-// because base::DIR_SYSTEM is not redirected.
-base::FilePath GetWow64RedirectedSystemPath();
-
-// Returns the path to a sample DLL file that can be used in tests.
-base::FilePath GetSampleDLLPath();
-
-// Returns the path to a signed sample DLL file that can be used in tests.
-base::FilePath GetSignedSampleDLLPath();
-
-// A ScopedTempDir with the ability to create and delete subdirs of
-// c:\windows\system32, which are Wow64-redirected by default. This turns off
-// Wow64 redirection so the subdir is created in the real c:\windows\system32
-// even in binaries that would normally be redirected to c:\windows\SysWOW64.
-class ScopedTempDirNoWow64 : protected base::ScopedTempDir {
- public:
-  ScopedTempDirNoWow64();
-  ~ScopedTempDirNoWow64();
-
-  // Creates a unique subdirectory under system32, bypassing Wow64 redirection,
-  // and takes ownership of it.
-  bool CreateUniqueSystem32TempDir() WARN_UNUSED_RESULT;
-
-  // Convenience function to call CreateUniqueSystem32TempDir and create an
-  // empty file with the given |file_name| in the resulting directory.
-  bool CreateEmptyFileInUniqueSystem32TempDir(const base::string16& file_name)
-      WARN_UNUSED_RESULT;
-
-  using base::ScopedTempDir::Delete;
-  using base::ScopedTempDir::GetPath;
-  using base::ScopedTempDir::IsValid;
-  using base::ScopedTempDir::Take;
-
-  // Do not give access to CreateUniqueTempDir, CreateUniqueTempDirUnderPath,
-  // or Set because they can set the temp dir path to a non-Wow64-redirected
-  // directory.
-};
-
-std::unique_ptr<base::WaitableEvent> CreateInheritableEvent(
-    base::WaitableEvent::ResetPolicy reset_policy,
-    base::WaitableEvent::InitialState initial_state);
-
-// Check that the test has administrator privileges, but not debug privileges.
-// This function drops unneeded privileges if possible, but won't try to raise
-// privileges. Returns false if the privileges could not be made correct.
-bool CheckTestPrivileges();
-
-// Accepts PUPData::PUP parameters with id equals to |expected_id|.
-MATCHER_P(PupHasId, expected_id, "") {
-  return arg->signature().id == expected_id;
-}
-
-// Accepts PUPData::PUP parameters with |size| expanded disk footprints.
-MATCHER_P(PupHasFileListSize, size, "") {
-  return arg->expanded_disk_footprints.size() == static_cast<size_t>(size);
-}
-
-}  // namespace chrome_cleaner
-
-#endif  // CHROME_CHROME_CLEANER_TEST_TEST_UTIL_H_
diff --git a/chrome/chrome_cleaner/test/test_util_unittest.cc b/chrome/chrome_cleaner/test/test_util_unittest.cc
deleted file mode 100644
index b893c47cd..0000000
--- a/chrome/chrome_cleaner/test/test_util_unittest.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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.
-
-#include "chrome/chrome_cleaner/test/test_util.h"
-
-#include "chrome/chrome_cleaner/os/disk_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-// The following include is needed to use EXPECT_NONFATAL_FAILURE.
-#include "testing/gtest/include/gtest/gtest-spi.h"
-
-namespace chrome_cleaner {
-
-namespace {
-const wchar_t kFileName1[] = L"test_path1";
-const wchar_t kFileName2[] = L"test_path2";
-
-}  // namespace
-
-TEST(TestUtilTest, ExpectEqualFilePathSets) {
-  // Messages are logged to a vector for testing.
-  LoggingOverride logger;
-  FilePathSet matched_files;
-  FilePathSet expected_files;
-
-  matched_files.Insert(base::FilePath(kFileName1));
-  EXPECT_NONFATAL_FAILURE(
-      ExpectEqualFilePathSets(matched_files, expected_files), "");
-  EXPECT_TRUE(logger.LoggingMessagesContain(
-      "Unexpected file in matched footprints: 'test_path1'"));
-
-  logger.FlushMessages();
-  expected_files.Insert(base::FilePath(kFileName1));
-  ExpectEqualFilePathSets(matched_files, expected_files);
-
-  logger.FlushMessages();
-  expected_files.Insert(base::FilePath(kFileName2));
-  EXPECT_NONFATAL_FAILURE(
-      ExpectEqualFilePathSets(matched_files, expected_files), "");
-  EXPECT_TRUE(logger.LoggingMessagesContain(
-      "Missing expected footprint: 'test_path2'"));
-}
-
-}  // namespace chrome_cleaner
diff --git a/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc b/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc
index 38fd116a..65e3827d 100644
--- a/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc
+++ b/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc
@@ -53,7 +53,7 @@
       url.host_piece() == extension_misc::kPdfExtensionId;
   if (inside_print_preview || inside_pdf_extension) {
     // <object> with id="plugin" is created in
-    // chrome/browser/resources/pdf/pdf.js.
+    // chrome/browser/resources/pdf/pdf_viewer.js.
     auto plugin_element = frame->GetDocument().GetElementById("plugin");
     if (!plugin_element.IsNull()) {
       return plugin_element;
@@ -79,7 +79,7 @@
       extensions::MimeHandlerViewContainer::FromRenderFrame(
           content::RenderFrame::FromWebFrame(frame));
   if (!mime_handlers.empty()) {
-    // This message is handled in chrome/browser/resources/pdf/pdf.js and
+    // This message is handled in chrome/browser/resources/pdf/pdf_viewer.js and
     // instructs the PDF plugin to print. This is to make window.print() on a
     // PDF plugin document correctly print the PDF. See
     // https://crbug.com/448720.
diff --git a/chrome/services/printing/pdf_to_emf_converter.cc b/chrome/services/printing/pdf_to_emf_converter.cc
index 45d5738..3500b9d 100644
--- a/chrome/services/printing/pdf_to_emf_converter.cc
+++ b/chrome/services/printing/pdf_to_emf_converter.cc
@@ -8,6 +8,7 @@
 #include <limits>
 #include <utility>
 
+#include "base/containers/span.h"
 #include "base/lazy_instance.h"
 #include "base/stl_util.h"
 #include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_utils.h"
@@ -111,7 +112,9 @@
     return;
 
   int page_count = 0;
-  chrome_pdf::GetPDFDocInfo(pdf_mapping_.memory(), size, &page_count, nullptr);
+  auto pdf_span = base::make_span(
+      reinterpret_cast<const uint8_t*>(pdf_mapping_.memory()), size);
+  chrome_pdf::GetPDFDocInfo(pdf_span, &page_count, nullptr);
   total_page_count_ = page_count;
 }
 
@@ -149,10 +152,12 @@
   int offset_y = postscript ? pdf_render_settings_.offsets.y() : 0;
 
   base::ReadOnlySharedMemoryRegion invalid_emf_region;
+  auto pdf_span =
+      base::make_span(reinterpret_cast<const uint8_t*>(pdf_mapping_.memory()),
+                      pdf_mapping_.size());
   if (!chrome_pdf::RenderPDFPageToDC(
-          pdf_mapping_.memory(), pdf_mapping_.size(), page_number,
-          metafile.context(), pdf_render_settings_.dpi.width(),
-          pdf_render_settings_.dpi.height(),
+          pdf_span, page_number, metafile.context(),
+          pdf_render_settings_.dpi.width(), pdf_render_settings_.dpi.height(),
           pdf_render_settings_.area.x() - offset_x,
           pdf_render_settings_.area.y() - offset_y,
           pdf_render_settings_.area.width(), pdf_render_settings_.area.height(),
diff --git a/chrome/services/printing/pdf_to_pwg_raster_converter.cc b/chrome/services/printing/pdf_to_pwg_raster_converter.cc
index d23b7ce3..7d06ca0 100644
--- a/chrome/services/printing/pdf_to_pwg_raster_converter.cc
+++ b/chrome/services/printing/pdf_to_pwg_raster_converter.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "base/containers/span.h"
 #include "components/pwg_encoder/bitmap_image.h"
 #include "components/pwg_encoder/pwg_encoder.h"
 #include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_utils.h"
@@ -29,13 +30,16 @@
   if (!pdf_mapping.IsValid())
     return invalid_pwg_region;
 
+  auto pdf_data =
+      base::make_span(reinterpret_cast<const uint8_t*>(pdf_mapping.memory()),
+                      pdf_mapping.size());
+
   // Get the page count and reserve 64 KB per page in |pwg_data| below.
   static constexpr size_t kEstimatedSizePerPage = 64 * 1024;
   static constexpr size_t kMaxPageCount =
       std::numeric_limits<size_t>::max() / kEstimatedSizePerPage;
   int total_page_count = 0;
-  if (!chrome_pdf::GetPDFDocInfo(pdf_mapping.memory(), pdf_mapping.size(),
-                                 &total_page_count, nullptr) ||
+  if (!chrome_pdf::GetPDFDocInfo(pdf_data, &total_page_count, nullptr) ||
       total_page_count <= 0 ||
       static_cast<size_t>(total_page_count) >= kMaxPageCount) {
     return invalid_pwg_region;
@@ -53,10 +57,9 @@
       page_number = total_page_count - 1 - page_number;
 
     if (!chrome_pdf::RenderPDFPageToBitmap(
-            pdf_mapping.memory(), pdf_mapping.size(), page_number,
-            image.pixel_data(), image.size().width(), image.size().height(),
-            settings.dpi.width(), settings.dpi.height(), settings.autorotate,
-            settings.use_color)) {
+            pdf_data, page_number, image.pixel_data(), image.size().width(),
+            image.size().height(), settings.dpi.width(), settings.dpi.height(),
+            settings.autorotate, settings.use_color)) {
       return invalid_pwg_region;
     }
 
diff --git a/chrome/test/base/view_event_test_base.cc b/chrome/test/base/view_event_test_base.cc
index c7b9730f..19ab40f 100644
--- a/chrome/test/base/view_event_test_base.cc
+++ b/chrome/test/base/view_event_test_base.cc
@@ -152,7 +152,8 @@
   // Schedule a task that starts the test. Need to do this as we're going to
   // run the message loop.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&ViewEventTestBase::DoTestOnMessageLoop, this));
+      FROM_HERE, base::Bind(&ViewEventTestBase::DoTestOnMessageLoop,
+                            base::Unretained(this)));
 
   content::RunThisRunLoop(&run_loop_);
 }
diff --git a/chrome/test/base/view_event_test_base.h b/chrome/test/base/view_event_test_base.h
index 1f7fa83a6..b9ccf41e 100644
--- a/chrome/test/base/view_event_test_base.h
+++ b/chrome/test/base/view_event_test_base.h
@@ -100,10 +100,6 @@
   const views::Widget* GetWidget() const override;
   views::Widget* GetWidget() override;
 
-  // Overridden to do nothing so that this class can be used in runnable tasks.
-  void AddRef() {}
-  void Release() {}
-
  protected:
   ~ViewEventTestBase() override;
 
@@ -122,8 +118,8 @@
   // Done is invoked.
   template <class T, class Method>
   base::Closure CreateEventTask(T* target, Method method) {
-    return base::Bind(&ViewEventTestBase::RunTestMethod, this,
-                      base::Bind(method, target));
+    return base::Bind(&ViewEventTestBase::RunTestMethod, base::Unretained(this),
+                      base::Bind(method, base::Unretained(target)));
   }
 
   // Spawns a new thread posts a MouseMove in the background.
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js b/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js
index 3d957b2..e58c3599 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js
@@ -27,6 +27,8 @@
 var EditResponseCookie = chrome.declarativeWebRequest.EditResponseCookie;
 var RemoveRequestCookie = chrome.declarativeWebRequest.RemoveRequestCookie;
 var RemoveResponseCookie = chrome.declarativeWebRequest.RemoveResponseCookie;
+var headerName = 'Foo';
+var headerValue = 'Bar';
 
 // Constants as functions, not to be called until after runTests.
 function getURLEchoUserAgent() {
@@ -37,14 +39,8 @@
   return getServerURL("extensions/api_test/webrequest/simpleLoad/a.html");
 }
 
-function getURLOfHTMLWithThirdParty() {
-  // Returns the URL of a HTML document with a third-party resource.
-  return getServerURL(
-      "extensions/api_test/webrequest/declarative/third-party.html");
-}
-
-function getURLSetCookie() {
-  return getServerURL('set-cookie?Foo=Bar');
+function getURLSetHeader() {
+  return getServerURL('set-header?' + headerName + ': ' + headerValue);
 }
 
 function getURLSetCookie2() {
@@ -56,11 +52,6 @@
   return getServerURL('echoheader?Cookie');
 }
 
-function getURLHttpXHRData() {
-  return getServerURL("extensions/api_test/webrequest/xhr/data.json",
-                      "b.com");
-}
-
 runTests([
 
   function testSetRequestHeader() {
@@ -90,21 +81,21 @@
     expect();  // Used for initialization.
     onRequest.addRules(
       [{conditions: [new RequestMatcher()],
-        actions: [new RemoveRequestHeader({name: "user-AGENT"})]
+        actions: [new RemoveRequestHeader({name: headerName})]
        }],
-      function() {
-        // Check the page content for our modified User-Agent string.
-        navigateAndWait(getURLEchoUserAgent(), function() {
-          chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
-            chrome.test.assertTrue(request.pass, "User-Agent was not removed.");
-          });
-          chrome.tabs.executeScript(tabId,
-            {
-              code: "chrome.extension.sendRequest(" +
-                    "{pass: document.body.innerText.indexOf('Mozilla') == -1});"
-            });
+      chrome.test.callbackPass(function() {
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', getServerURL('echoheader?' + headerName));
+        xhr.setRequestHeader(headerName, headerValue);
+        xhr.onload = chrome.test.callbackPass(function() {
+          chrome.test.assertTrue(xhr.responseText.indexOf(headerValue) == -1,
+              'Header was not removed.');
         });
-      });
+        xhr.onerror = function() {
+          chrome.test.fail();
+        }
+        xhr.send();
+      }));
   },
 
   function testAddResponseHeader() {
@@ -112,20 +103,20 @@
     expect();  // Used for initialization.
     onRequest.addRules(
       [{conditions: [new RequestMatcher()],
-        actions: [new AddResponseHeader({name: "Set-Cookie", value: "Bar=baz"})]
+        actions: [new AddResponseHeader({name: headerName, value: headerValue})]
        }],
-      function() {
-        navigateAndWait(getURLEchoUserAgent(), function() {
-          chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
-            chrome.test.assertTrue(request.pass, "Cookie was not added.");
-          });
-          chrome.tabs.executeScript(tabId,
-            {
-              code: "chrome.extension.sendRequest(" +
-                    "{pass: document.cookie.indexOf('Bar') != -1});"
-            });
+      chrome.test.callbackPass(function() {
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', getServerURL('echo'));
+        xhr.onload = chrome.test.callbackPass(function() {
+          chrome.test.assertTrue(xhr.getResponseHeader(headerName) == 'Bar',
+              'Header was not added.');
         });
-      });
+        xhr.onerror = function() {
+          chrome.test.fail();
+        }
+        xhr.send();
+      }));
   },
 
   function testRemoveResponseHeader() {
@@ -133,21 +124,21 @@
     expect();  // Used for initialization.
     onRequest.addRules(
       [{conditions: [new RequestMatcher()],
-        actions: [new RemoveResponseHeader({name: "Set-Cookie",
-                                            value: "FoO=bAR"})]
+        actions: [new RemoveResponseHeader({name: headerName,
+                                            value: 'Bar'})]
        }],
-      function() {
-        navigateAndWait(getURLSetCookie(), function() {
-          chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
-            chrome.test.assertTrue(request.pass, "Cookie was not removed.");
-          });
-          chrome.tabs.executeScript(tabId,
-            {
-              code: "chrome.extension.sendRequest(" +
-                    "{pass: document.cookie.indexOf('Foo') == -1});"
-            });
+      chrome.test.callbackPass(function() {
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', getURLSetHeader());
+        xhr.onload = chrome.test.callbackPass(function() {
+          chrome.test.assertTrue(xhr.getResponseHeader(headerName) == null,
+              'Header was not removed.');
         });
-      });
+        xhr.onerror = function() {
+          chrome.test.fail();
+        }
+        xhr.send();
+      }));
   },
 
   function testPriorities() {
@@ -219,6 +210,13 @@
   },
 
   function testEditResponseCookies() {
+    // TODO(crbug.com/827582): Editing response cookies through
+    // declarativeWebRequest is not supported with the network service.
+    if (networkServiceState == 'enabled') {
+      chrome.test.succeed();
+      return;
+    }
+
     ignoreUnexpected = true;
     expect();
     onRequest.addRules(
diff --git a/chrome/test/data/webui/settings/personalization_options_test.js b/chrome/test/data/webui/settings/personalization_options_test.js
index 15ccf8e..1495b4c 100644
--- a/chrome/test/data/webui/settings/personalization_options_test.js
+++ b/chrome/test/data/webui/settings/personalization_options_test.js
@@ -93,12 +93,6 @@
             testElement.root.querySelectorAll('settings-toggle-button').length);
         testElement.unifiedConsentEnabled = true;
         Polymer.dom.flush();
-        // #spellCheckControl should be set to display: none by false dom-if.
-        assertTrue(
-            testElement.$$('#spellCheckControl').style.display === 'none');
-        assertTrue(!!testElement.$$('#spellCheckLinkBox'));
-        assertTrue(
-            testElement.$$('#spellCheckLinkBox').style.display !== 'none');
       });
     });
   }
diff --git a/chromeos/components/drivefs/fake_drivefs.cc b/chromeos/components/drivefs/fake_drivefs.cc
index 27c5f3e..34a34de 100644
--- a/chromeos/components/drivefs/fake_drivefs.cc
+++ b/chromeos/components/drivefs/fake_drivefs.cc
@@ -183,4 +183,6 @@
   std::move(callback).Run(drive::FILE_ERROR_OK);
 }
 
+void FakeDriveFs::SetPauseSyncing(bool pause) {}
+
 }  // namespace drivefs
diff --git a/chromeos/components/drivefs/fake_drivefs.h b/chromeos/components/drivefs/fake_drivefs.h
index db89bd4..42668c8c 100644
--- a/chromeos/components/drivefs/fake_drivefs.h
+++ b/chromeos/components/drivefs/fake_drivefs.h
@@ -55,6 +55,8 @@
                  bool pinned,
                  SetPinnedCallback callback) override;
 
+  void SetPauseSyncing(bool pause) override;
+
   const base::FilePath mount_path_;
 
   std::map<base::FilePath, FileMetadata> metadata_;
diff --git a/chromeos/components/drivefs/mojom/drivefs.mojom b/chromeos/components/drivefs/mojom/drivefs.mojom
index 1e75a03..b054416c 100644
--- a/chromeos/components/drivefs/mojom/drivefs.mojom
+++ b/chromeos/components/drivefs/mojom/drivefs.mojom
@@ -29,6 +29,9 @@
   // Sets the file at |path| to pinned or unpinned depending on the value of
   // |pinned|.
   SetPinned(mojo_base.mojom.FilePath path, bool pinned) => (FileError error);
+
+  // Set whether syncing should be paused.
+  SetPauseSyncing(bool pause);
 };
 
 // Implemented by Chrome, used from DriveFS.
diff --git a/chromeos/services/ime/BUILD.gn b/chromeos/services/ime/BUILD.gn
index c7c2e3a..f86e622 100644
--- a/chromeos/services/ime/BUILD.gn
+++ b/chromeos/services/ime/BUILD.gn
@@ -45,9 +45,9 @@
     ":lib",
     "//base",
     "//mojo/public/cpp/bindings",
-    "//services/identity/public/mojom",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp:service_test_support",
+    "//testing/gmock",
   ]
   sources = [
     "ime_service_unittest.cc",
diff --git a/chromeos/services/ime/decoder/decoder_engine.cc b/chromeos/services/ime/decoder/decoder_engine.cc
index 5e9fc47..f47986a 100644
--- a/chromeos/services/ime/decoder/decoder_engine.cc
+++ b/chromeos/services/ime/decoder/decoder_engine.cc
@@ -43,15 +43,26 @@
 
 DecoderEngine::~DecoderEngine() {}
 
-void DecoderEngine::BindRequest(const std::string& ime_spec,
+bool DecoderEngine::BindRequest(const std::string& ime_spec,
                                 mojom::InputChannelRequest request,
                                 mojom::InputChannelPtr client,
                                 const std::vector<uint8_t>& extra) {
-  // TODO(https://crbug.com/837156): Build a ClientWrapper with the clientPtr,
-  // inside we ensure the clientPtr will run in the correct SequencedTaskRunner,
-  // then pass the wrapper to the native library instead of the clientPtr.
+  if (!IsImeSupported(ime_spec))
+    return false;
+  // TODO(https://crbug.com/837156): Notify the input logic loaded from the
+  // shared library about the change by forwarding the information received.
+  // Moreover, in order to make safe calls on the clientPtr inside the input
+  // logic with multiple threads, we will send a wrapper of the clientPtr,
+  // where we make sure it runs in the correct SequencedTaskRunner.
   channel_bindings_.AddBinding(this, std::move(request));
   // TODO(https://crbug.com/837156): Registry connection error handler.
+  return true;
+}
+
+bool DecoderEngine::IsImeSupported(const std::string& ime_spec) {
+  // TODO(https://crbug.com/837156): Check the capability of the loaded shared
+  // library first.
+  return InputEngine::IsImeSupported(ime_spec);
 }
 
 void DecoderEngine::ProcessMessage(const std::vector<uint8_t>& message,
diff --git a/chromeos/services/ime/decoder/decoder_engine.h b/chromeos/services/ime/decoder/decoder_engine.h
index de23cd22..86b32cc 100644
--- a/chromeos/services/ime/decoder/decoder_engine.h
+++ b/chromeos/services/ime/decoder/decoder_engine.h
@@ -28,10 +28,11 @@
   ~DecoderEngine() override;
 
   // InputEngine overrides:
-  void BindRequest(const std::string& ime_spec,
+  bool BindRequest(const std::string& ime_spec,
                    mojom::InputChannelRequest request,
                    mojom::InputChannelPtr client,
                    const std::vector<uint8_t>& extra) override;
+  bool IsImeSupported(const std::string& ime_spec) override;
   void ProcessMessage(const std::vector<uint8_t>& message,
                       ProcessMessageCallback callback) override;
 
diff --git a/chromeos/services/ime/ime_service.cc b/chromeos/services/ime/ime_service.cc
index 4137a06..8c58500 100644
--- a/chromeos/services/ime/ime_service.cc
+++ b/chromeos/services/ime/ime_service.cc
@@ -50,8 +50,9 @@
     const std::vector<uint8_t>& extra,
     ConnectToImeEngineCallback callback) {
   DCHECK(input_engine_);
-  input_engine_->BindRequest(ime_spec, std::move(to_engine_request),
-                             std::move(from_engine), extra);
+  bool bound = input_engine_->BindRequest(
+      ime_spec, std::move(to_engine_request), std::move(from_engine), extra);
+  std::move(callback).Run(bound);
 }
 
 void ImeService::BindInputEngineManagerRequest(
diff --git a/chromeos/services/ime/ime_service.h b/chromeos/services/ime/ime_service.h
index 3428c63..567768d9 100644
--- a/chromeos/services/ime/ime_service.h
+++ b/chromeos/services/ime/ime_service.h
@@ -23,7 +23,7 @@
   ~ImeService() override;
 
  private:
-  // service_manager::Service:
+  // service_manager::Service overrides:
   void OnStart() override;
   void OnBindInterface(const service_manager::BindSourceInfo& source_info,
                        const std::string& interface_name,
diff --git a/chromeos/services/ime/ime_service_unittest.cc b/chromeos/services/ime/ime_service_unittest.cc
index 7e32332b..6e60ac5 100644
--- a/chromeos/services/ime/ime_service_unittest.cc
+++ b/chromeos/services/ime/ime_service_unittest.cc
@@ -4,45 +4,35 @@
 
 #include "base/bind.h"
 
+#include "chromeos/services/ime/ime_service.h"
 #include "chromeos/services/ime/public/mojom/constants.mojom.h"
 #include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
 
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/service_manager/public/cpp/service_test.h"
+#include "services/service_manager/public/mojom/service_factory.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::_;
 
 namespace chromeos {
 namespace ime {
 
 namespace {
-
 const char kTestServiceName[] = "ime_unittests";
+const char kInvalidImeSpec[] = "ime_spec_never_support";
 const std::vector<uint8_t> extra{0x66, 0x77, 0x88};
 
-void RunCallback(bool* success, bool result) {
+void ConnectCallback(bool* success, bool result) {
   *success = result;
 }
 
-class ImeServiceTest : public service_manager::test::ServiceTest {
+class TestClientChannel : mojom::InputChannel {
  public:
-  ImeServiceTest() : service_manager::test::ServiceTest(kTestServiceName) {}
-  ~ImeServiceTest() override {}
-
-  void SetUp() override {
-    ServiceTest::SetUp();
-    // TODO(https://crbug.com/837156): Start or bind other services used.
-    // Eg.  connector()->StartService(kServiceName) or
-    //      connector()->BindInterface(kServiceName, &ptr);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ImeServiceTest);
-};
-
-class FakeClient : mojom::InputChannel {
- public:
-  FakeClient() : binding_(this) {}
+  TestClientChannel() : binding_(this) {}
 
   mojom::InputChannelPtr CreateInterfacePtrAndBind() {
     mojom::InputChannelPtr ptr;
@@ -50,35 +40,108 @@
     return ptr;
   }
 
- private:
-  // mojom::InputEngineClient:
-  void ProcessText(const std::string& message,
-                   ProcessTextCallback callback) override{};
-  void ProcessMessage(const std::vector<uint8_t>& message,
-                      ProcessMessageCallback callback) override{};
+  // mojom::InputChannel implementation.
+  MOCK_METHOD2(ProcessText, void(const std::string&, ProcessTextCallback));
+  MOCK_METHOD2(ProcessMessage,
+               void(const std::vector<uint8_t>& message,
+                    ProcessMessageCallback));
 
+ private:
   mojo::Binding<mojom::InputChannel> binding_;
 
-  DISALLOW_COPY_AND_ASSIGN(FakeClient);
+  DISALLOW_COPY_AND_ASSIGN(TestClientChannel);
+};
+
+class ImeServiceTestClient : public service_manager::test::ServiceTestClient,
+                             public service_manager::mojom::ServiceFactory {
+ public:
+  ImeServiceTestClient(service_manager::test::ServiceTest* test)
+      : service_manager::test::ServiceTestClient(test) {
+    registry_.AddInterface<service_manager::mojom::ServiceFactory>(
+        base::BindRepeating(&ImeServiceTestClient::Create,
+                            base::Unretained(this)));
+  }
+
+ protected:
+  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override {
+    registry_.BindInterface(interface_name, std::move(interface_pipe));
+  }
+
+  // service_manager::mojom::ServiceFactory
+  void CreateService(
+      service_manager::mojom::ServiceRequest request,
+      const std::string& name,
+      service_manager::mojom::PIDReceiverPtr pid_receiver) override {
+    if (name == mojom::kServiceName) {
+      service_context_.reset(new service_manager::ServiceContext(
+          CreateImeService(), std::move(request)));
+    }
+  }
+
+  void Create(service_manager::mojom::ServiceFactoryRequest request) {
+    service_factory_bindings_.AddBinding(this, std::move(request));
+  }
+
+ private:
+  service_manager::BinderRegistry registry_;
+  mojo::BindingSet<service_manager::mojom::ServiceFactory>
+      service_factory_bindings_;
+
+  std::unique_ptr<service_manager::ServiceContext> service_context_;
+  DISALLOW_COPY_AND_ASSIGN(ImeServiceTestClient);
+};
+
+class ImeServiceTest : public service_manager::test::ServiceTest {
+ public:
+  ImeServiceTest() : service_manager::test::ServiceTest(kTestServiceName) {}
+  ~ImeServiceTest() override {}
+
+  MOCK_METHOD1(SentTextCallback, void(const std::string&));
+  MOCK_METHOD1(SentMessageCallback, void(const std::vector<uint8_t>&));
+
+ protected:
+  void SetUp() override {
+    ServiceTest::SetUp();
+    connector()->BindInterface(mojom::kServiceName,
+                               mojo::MakeRequest(&ime_manager_));
+
+    // TODO(https://crbug.com/837156): Start or bind other services used.
+    // Eg.  connector()->StartService(mojom::kSomeServiceName);
+  }
+
+  // service_manager::test::ServiceTest
+  std::unique_ptr<service_manager::Service> CreateService() override {
+    return std::make_unique<ImeServiceTestClient>(this);
+  }
+
+  void TearDown() override {
+    ime_manager_.reset();
+    ServiceTest::TearDown();
+  }
+
+  mojom::InputEngineManagerPtr ime_manager_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ImeServiceTest);
 };
 
 }  // namespace
 
-// Tests activating an IME and set its delegate.
-TEST_F(ImeServiceTest, ConnectImeEngine) {
-  connector()->StartService(mojom::kServiceName);
-
-  mojom::InputEngineManagerPtr manager;
-  connector()->BindInterface(mojom::kServiceName, &manager);
-
-  bool success = false;
-  FakeClient client;
-
+// Tests that the service is instantiated and it will return false when
+// activating an IME engine with an invalid IME spec.
+TEST_F(ImeServiceTest, ConnectInvalidImeEngine) {
+  bool success = true;
+  TestClientChannel test_channel;
   mojom::InputChannelPtr to_engine_ptr;
 
-  manager->ConnectToImeEngine("FakeIME", mojo::MakeRequest(&to_engine_ptr),
-                              client.CreateInterfacePtrAndBind(), extra,
-                              base::BindOnce(&RunCallback, &success));
+  ime_manager_->ConnectToImeEngine(
+      kInvalidImeSpec, mojo::MakeRequest(&to_engine_ptr),
+      test_channel.CreateInterfacePtrAndBind(), extra,
+      base::BindOnce(&ConnectCallback, &success));
+  ime_manager_.FlushForTesting();
+  EXPECT_FALSE(success);
 }
 
 }  // namespace ime
diff --git a/chromeos/services/ime/input_engine.cc b/chromeos/services/ime/input_engine.cc
index e919992..de26200 100644
--- a/chromeos/services/ime/input_engine.cc
+++ b/chromeos/services/ime/input_engine.cc
@@ -14,14 +14,23 @@
 
 InputEngine::~InputEngine() {}
 
-void InputEngine::BindRequest(const std::string& ime_spec,
+bool InputEngine::BindRequest(const std::string& ime_spec,
                               mojom::InputChannelRequest request,
                               mojom::InputChannelPtr client,
                               const std::vector<uint8_t>& extra) {
+  if (!IsImeSupported(ime_spec))
+    return false;
+
   channel_bindings_.AddBinding(this, std::move(request), ime_spec);
+  return true;
   // TODO(https://crbug.com/837156): Registry connection error handler.
 }
 
+bool InputEngine::IsImeSupported(const std::string& ime_spec) {
+  // TODO(https://crbug.com/837156): Add all supported IME tpyes.
+  return false;
+}
+
 void InputEngine::ProcessText(const std::string& message,
                               ProcessTextCallback callback) {
   auto& ime_spec = channel_bindings_.dispatch_context();
@@ -31,7 +40,7 @@
 
 void InputEngine::ProcessMessage(const std::vector<uint8_t>& message,
                                  ProcessMessageCallback callback) {
-  NOTREACHED() << "No defined protobuf message in this implementation";
+  NOTIMPLEMENTED();  // Protobuf message is not used in the basic engine.
 }
 
 const std::string& InputEngine::Process(const std::string& message,
diff --git a/chromeos/services/ime/input_engine.h b/chromeos/services/ime/input_engine.h
index 2b42d8f..73d4558 100644
--- a/chromeos/services/ime/input_engine.h
+++ b/chromeos/services/ime/input_engine.h
@@ -17,12 +17,16 @@
   InputEngine();
   ~InputEngine() override;
 
-  // Binds the mojom::InputChannel interface to this object.
-  virtual void BindRequest(const std::string& ime_spec,
+  // Binds the mojom::InputChannel interface to this object and returns true if
+  // the given ime_spec is supported by the engine.
+  virtual bool BindRequest(const std::string& ime_spec,
                            mojom::InputChannelRequest request,
                            mojom::InputChannelPtr client,
                            const std::vector<uint8_t>& extra);
 
+  // Returns whether the given ime_spec is supported by this engine.
+  virtual bool IsImeSupported(const std::string& ime_spec);
+
   // mojom::MessageChannel overrides:
   void ProcessText(const std::string& message,
                    ProcessTextCallback callback) override;
diff --git a/chromeos/services/ime/manifest.json b/chromeos/services/ime/manifest.json
index ed51c97..02baef6 100644
--- a/chromeos/services/ime/manifest.json
+++ b/chromeos/services/ime/manifest.json
@@ -4,7 +4,10 @@
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
-        "input_engine" : [ "chromeos.ime.mojom.InputEngine" ]
+        "input_engine" : [
+          "chromeos.ime.mojom.InputEngineManager",
+          "chromeos.ime.mojom.InputChannel"
+        ]
       },
       "requires": {
         "service_manager": [ "service_manager:all_users" ]
diff --git a/chromeos/services/ime/public/mojom/constants.mojom b/chromeos/services/ime/public/mojom/constants.mojom
index 9bcb91cb..a049e48 100644
--- a/chromeos/services/ime/public/mojom/constants.mojom
+++ b/chromeos/services/ime/public/mojom/constants.mojom
@@ -4,4 +4,4 @@
 
 module chromeos.ime.mojom;
 
-const string kServiceName = "ime_service";
+const string kServiceName = "ime";
diff --git a/chromeos/services/ime/test_manifest.json b/chromeos/services/ime/test_manifest.json
index 4e5963c..b387433e 100644
--- a/chromeos/services/ime/test_manifest.json
+++ b/chromeos/services/ime/test_manifest.json
@@ -3,6 +3,11 @@
   "display_name": "IME Unittests",
   "interface_provider_specs": {
     "service_manager:connector": {
+      "provides": {
+        "service_manager:service_factory": [
+          "service_manager.mojom.ServiceFactory"
+        ]
+      },
       "requires": {
         "ime": [ "input_engine" ]
       }
diff --git a/components/autofill/content/common/autofill_types.mojom b/components/autofill/content/common/autofill_types.mojom
index 58ca06b..c9ecc57 100644
--- a/components/autofill/content/common/autofill_types.mojom
+++ b/components/autofill/content/common/autofill_types.mojom
@@ -206,6 +206,7 @@
   gfx.mojom.RectF bounds;
   int32 max_length;
   mojo_base.mojom.String16 generation_element;
+  mojo_base.mojom.TextDirection text_direction;
   PasswordForm password_form;
 };
 
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc
index ef9a2c1..fad95ddd 100644
--- a/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -6,7 +6,6 @@
 
 #include "base/i18n/rtl.h"
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
-#include "mojo/public/cpp/base/text_direction_mojom_traits.h"
 #include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
 #include "url/mojom/origin_mojom_traits.h"
@@ -758,6 +757,7 @@
   out->max_length = data.max_length();
 
   if (!data.ReadGenerationElement(&out->generation_element) ||
+      !data.ReadTextDirection(&out->text_direction) ||
       !data.ReadPasswordForm(&out->password_form))
     return false;
 
diff --git a/components/autofill/content/common/autofill_types_struct_traits.h b/components/autofill/content/common/autofill_types_struct_traits.h
index 7d6b10e..68d03e0 100644
--- a/components/autofill/content/common/autofill_types_struct_traits.h
+++ b/components/autofill/content/common/autofill_types_struct_traits.h
@@ -23,6 +23,7 @@
 #include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "components/autofill/core/common/submission_source.h"
+#include "mojo/public/cpp/base/text_direction_mojom_traits.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "url/origin.h"
@@ -464,6 +465,11 @@
     return r.generation_element;
   }
 
+  static base::i18n::TextDirection text_direction(
+      const autofill::password_generation::PasswordGenerationUIData& r) {
+    return r.text_direction;
+  }
+
   static const autofill::PasswordForm& password_form(
       const autofill::password_generation::PasswordGenerationUIData& r) {
     return r.password_form;
diff --git a/components/autofill/content/common/autofill_types_struct_traits_unittest.cc b/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
index ea65d12..f0f8abf 100644
--- a/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
+++ b/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
@@ -145,6 +145,15 @@
       PasswordFormFieldPredictionType::PREDICTION_CURRENT_PASSWORD;
 }
 
+void CreatePasswordGenerationUIData(
+    password_generation::PasswordGenerationUIData* data) {
+  data->bounds = gfx::RectF(1, 1, 200, 100);
+  data->max_length = 20;
+  data->generation_element = base::ASCIIToUTF16("generation_element");
+  data->text_direction = base::i18n::RIGHT_TO_LEFT;
+  CreateTestPasswordForm(&data->password_form);
+}
+
 void CheckEqualPasswordFormFillData(const PasswordFormFillData& expected,
                                     const PasswordFormFillData& actual) {
   EXPECT_EQ(expected.form_renderer_id, actual.form_renderer_id);
@@ -187,6 +196,16 @@
             actual.confirmation_field_signature.value());
 }
 
+void CheckEqualPassPasswordGenerationUIData(
+    const password_generation::PasswordGenerationUIData& expected,
+    const password_generation::PasswordGenerationUIData& actual) {
+  EXPECT_EQ(expected.bounds, actual.bounds);
+  EXPECT_EQ(expected.max_length, actual.max_length);
+  EXPECT_EQ(expected.generation_element, actual.generation_element);
+  EXPECT_EQ(expected.text_direction, actual.text_direction);
+  EXPECT_EQ(expected.password_form, actual.password_form);
+}
+
 }  // namespace
 
 class AutofillTypeTraitsTestImpl : public testing::Test,
@@ -300,6 +319,14 @@
   closure.Run();
 }
 
+void ExpectPasswordGenerationUIData(
+    const password_generation::PasswordGenerationUIData& expected,
+    base::OnceClosure closure,
+    const password_generation::PasswordGenerationUIData& passed) {
+  CheckEqualPassPasswordGenerationUIData(expected, passed);
+  std::move(closure).Run();
+}
+
 void ExpectPasswordForm(const PasswordForm& expected,
                         const base::Closure& closure,
                         const PasswordForm& passed) {
@@ -412,6 +439,18 @@
   loop.Run();
 }
 
+TEST_F(AutofillTypeTraitsTestImpl, PassPasswordGenerationUIData) {
+  password_generation::PasswordGenerationUIData input;
+  CreatePasswordGenerationUIData(&input);
+
+  base::RunLoop loop;
+  mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
+  proxy->PassPasswordGenerationUIData(
+      input, base::BindOnce(&ExpectPasswordGenerationUIData, input,
+                            loop.QuitClosure()));
+  loop.Run();
+}
+
 TEST_F(AutofillTypeTraitsTestImpl, PassPasswordForm) {
   PasswordForm input;
   CreateTestPasswordForm(&input);
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index 454e4c6..5981dc4 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1420,6 +1420,10 @@
          IsSelectElement(element) || IsTextAreaElement(element);
 }
 
+bool IsWebElementVisible(const blink::WebElement& element) {
+  return element.IsFocusable();
+}
+
 const base::string16 GetFormIdentifier(const WebFormElement& form) {
   base::string16 identifier = form.GetName().Utf16();
   CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id"));
@@ -1429,8 +1433,18 @@
   return identifier;
 }
 
-bool IsWebElementVisible(const blink::WebElement& element) {
-  return element.IsFocusable();
+base::i18n::TextDirection GetTextDirectionForElement(
+    const blink::WebFormControlElement& element) {
+  // Use 'text-align: left|right' if set or 'direction' otherwise.
+  // See https://crbug.com/482339
+  base::i18n::TextDirection direction = element.DirectionForFormData() == "rtl"
+                                            ? base::i18n::RIGHT_TO_LEFT
+                                            : base::i18n::LEFT_TO_RIGHT;
+  if (element.AlignmentForFormData() == "left")
+    direction = base::i18n::LEFT_TO_RIGHT;
+  else if (element.AlignmentForFormData() == "right")
+    direction = base::i18n::RIGHT_TO_LEFT;
+  return direction;
 }
 
 std::vector<blink::WebFormControlElement> ExtractAutofillableElementsFromSet(
@@ -1511,15 +1525,7 @@
     field->is_focusable = IsWebElementVisible(element);
     field->should_autocomplete = element.AutoComplete();
 
-    // Use 'text-align: left|right' if set or 'direction' otherwise.
-    // See crbug.com/482339
-    field->text_direction = element.DirectionForFormData() == "rtl"
-                                ? base::i18n::RIGHT_TO_LEFT
-                                : base::i18n::LEFT_TO_RIGHT;
-    if (element.AlignmentForFormData() == "left")
-      field->text_direction = base::i18n::LEFT_TO_RIGHT;
-    else if (element.AlignmentForFormData() == "right")
-      field->text_direction = base::i18n::RIGHT_TO_LEFT;
+    field->text_direction = GetTextDirectionForElement(element);
     field->is_enabled = element.IsEnabled();
     field->is_readonly = element.IsReadOnly();
     field->is_default = element.GetAttribute("value") == element.Value();
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index 34f79ca..ab69b3fb 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -123,6 +123,10 @@
 // attribute.
 const base::string16 GetFormIdentifier(const blink::WebFormElement& form);
 
+// Returns text alignment for |element|.
+base::i18n::TextDirection GetTextDirectionForElement(
+    const blink::WebFormControlElement& element);
+
 // Returns all the auto-fillable form control elements in |control_elements|.
 std::vector<blink::WebFormControlElement> ExtractAutofillableElementsFromSet(
     const blink::WebVector<blink::WebFormControlElement>& control_elements);
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc
index d2c7e51..8f9dcc93 100644
--- a/components/autofill/content/renderer/password_generation_agent.cc
+++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -42,6 +42,7 @@
 
 namespace {
 
+using autofill::form_util::GetTextDirectionForElement;
 using Logger = autofill::SavePasswordProgressLogger;
 
 // Returns pairs of |PasswordForm| and corresponding |WebFormElement| for all
@@ -451,6 +452,25 @@
   DetermineGenerationElement();
 }
 
+void PasswordGenerationAgent::UserTriggeredGeneratePassword() {
+  if (SetUpUserTriggeredGeneration()) {
+    LogMessage(Logger::STRING_GENERATION_RENDERER_SHOW_MANUAL_GENERATION_POPUP);
+    autofill::password_generation::PasswordGenerationUIData
+        password_generation_ui_data(
+            render_frame()->GetRenderView()->ElementBoundsInWindow(
+                generation_element_),
+            generation_element_.MaxLength(),
+            generation_element_.NameForAutofill().Utf16(),
+            GetTextDirectionForElement(generation_element_),
+            *generation_form_data_->form);
+    // TODO(crbug.com/845458): remove it. The renderer should never invoke the
+    // prompt directly.
+    GetPasswordManagerClient()->ShowManualPasswordGenerationPopup(
+        password_generation_ui_data);
+    generation_popup_shown_ = true;
+  }
+}
+
 void PasswordGenerationAgent::DetermineGenerationElement() {
   if (generation_form_data_) {
     LogMessage(Logger::STRING_GENERATION_RENDERER_FORM_ALREADY_FOUND);
@@ -655,37 +675,27 @@
 void PasswordGenerationAgent::MaybeOfferAutomaticGeneration() {
   // TODO(crbug.com/852309): Add this check to the generation element class.
   if (!is_manually_triggered_) {
-    ShowGenerationPopup(false /* is_manual_generation */);
-  }
-}
-
-void PasswordGenerationAgent::ShowGenerationPopup(bool is_manual_generation) {
-  if (!render_frame() || generation_element_.IsNull())
-    return;
-  LogMessage(
-      is_manual_generation
-          ? Logger::STRING_GENERATION_RENDERER_SHOW_MANUAL_GENERATION_POPUP
-          : Logger::STRING_GENERATION_RENDERER_AUTOMATIC_GENERATION_AVAILABLE);
-  autofill::password_generation::PasswordGenerationUIData
-      password_generation_ui_data(
-          render_frame()->GetRenderView()->ElementBoundsInWindow(
-              generation_element_),
-          generation_element_.MaxLength(),
-          generation_element_.NameForAutofill().Utf16(),
-          *generation_form_data_->form);
-  generation_popup_shown_ = true;
-  if (is_manual_generation) {
-    GetPasswordManagerClient()->ShowManualPasswordGenerationPopup(
-        password_generation_ui_data);
-  } else {
-    GetPasswordManagerClient()->AutomaticGenerationStatusChanged(
-        true, password_generation_ui_data);
+    AutomaticGenerationStatusChanged(true /* available */);
   }
 }
 
 void PasswordGenerationAgent::AutomaticGenerationStatusChanged(bool available) {
   if (available) {
-    ShowGenerationPopup(false /* is_manual_generation */);
+    if (!render_frame() || generation_element_.IsNull())
+      return;
+    LogMessage(
+        Logger::STRING_GENERATION_RENDERER_AUTOMATIC_GENERATION_AVAILABLE);
+    autofill::password_generation::PasswordGenerationUIData
+        password_generation_ui_data(
+            render_frame()->GetRenderView()->ElementBoundsInWindow(
+                generation_element_),
+            generation_element_.MaxLength(),
+            generation_element_.NameForAutofill().Utf16(),
+            GetTextDirectionForElement(generation_element_),
+            *generation_form_data_->form);
+    generation_popup_shown_ = true;
+    GetPasswordManagerClient()->AutomaticGenerationStatusChanged(
+        true, password_generation_ui_data);
   } else {
     // Hide the generation popup.
     GetPasswordManagerClient()->AutomaticGenerationStatusChanged(false,
@@ -725,11 +735,6 @@
     GetPasswordManagerClient()->PasswordNoLongerGenerated(*presaved_form);
 }
 
-void PasswordGenerationAgent::UserTriggeredGeneratePassword() {
-  if (SetUpUserTriggeredGeneration())
-    ShowGenerationPopup(true /* is_manual_generation */);
-}
-
 const mojom::PasswordManagerDriverAssociatedPtr&
 PasswordGenerationAgent::GetPasswordManagerDriver() {
   DCHECK(password_agent_);
diff --git a/components/autofill/content/renderer/password_generation_agent.h b/components/autofill/content/renderer/password_generation_agent.h
index e6fa40a..cf9beef 100644
--- a/components/autofill/content/renderer/password_generation_agent.h
+++ b/components/autofill/content/renderer/password_generation_agent.h
@@ -132,9 +132,6 @@
   // not be offered.
   void MaybeOfferAutomaticGeneration();
 
-  // Shows a generation popup.
-  void ShowGenerationPopup(bool is_manual_generation);
-
   // Signals the browser that it should offer or rescind automatic password
   // generation depending whether the user has just focused a form field
   // suitable for generation or has changed focus from such a field.
diff --git a/components/autofill/core/common/password_generation_util.cc b/components/autofill/core/common/password_generation_util.cc
index 518c265..c040a3e 100644
--- a/components/autofill/core/common/password_generation_util.cc
+++ b/components/autofill/core/common/password_generation_util.cc
@@ -27,10 +27,12 @@
     const gfx::RectF& bounds,
     int max_length,
     const base::string16& generation_element,
+    base::i18n::TextDirection text_direction,
     const autofill::PasswordForm& password_form)
     : bounds(bounds),
       max_length(max_length),
       generation_element(generation_element),
+      text_direction(text_direction),
       password_form(password_form) {}
 
 PasswordGenerationUIData::PasswordGenerationUIData() = default;
diff --git a/components/autofill/core/common/password_generation_util.h b/components/autofill/core/common/password_generation_util.h
index bc2e3d0..5543655f 100644
--- a/components/autofill/core/common/password_generation_util.h
+++ b/components/autofill/core/common/password_generation_util.h
@@ -97,6 +97,7 @@
   PasswordGenerationUIData(const gfx::RectF& bounds,
                            int max_length,
                            const base::string16& generation_element,
+                           base::i18n::TextDirection text_direction,
                            const autofill::PasswordForm& password_form);
   PasswordGenerationUIData();
   ~PasswordGenerationUIData();
@@ -112,6 +113,9 @@
   // Name of the password field to which the generation popup is attached.
   base::string16 generation_element;
 
+  // Direction of the text for |generation_element|.
+  base::i18n::TextDirection text_direction;
+
   // The form associated with the password field.
   autofill::PasswordForm password_form;
 };
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc
index 8073d3c8..76219d6 100644
--- a/components/exo/shell_surface_base.cc
+++ b/components/exo/shell_surface_base.cc
@@ -112,9 +112,16 @@
     SetVisible(enabled);
     if (!enabled)
       CustomFrameViewAsh::SetShouldPaintHeader(false);
+
+    frame()->GetNativeWindow()->AddObserver(this);
   }
 
-  ~CustomFrameView() override {}
+  ~CustomFrameView() override {
+    if (frame() && frame()->GetNativeWindow() &&
+        frame()->GetNativeWindow()->HasObserver(this)) {
+      frame()->GetNativeWindow()->RemoveObserver(this);
+    }
+  }
 
   // Overridden from ash::CustomFrameViewAsh:
   void SetShouldPaintHeader(bool paint) override {
@@ -156,9 +163,15 @@
     // the window mask layer bounds can be set correctly in function
     // SetShouldPaintHeader(). Note: this can be removed if the layer mask in
     // CustomFrameView becomes unnecessary.
+    // TODO(oshima): Investigate if we can eliminate this.
     CustomFrameViewAsh::UpdateHeaderView();
   }
 
+  void OnWindowDestroying(aura::Window* window) override {
+    DCHECK_EQ(frame()->GetNativeWindow(), window);
+    window->RemoveObserver(this);
+  }
+
   // Overridden from views::NonClientFrameView:
   gfx::Rect GetBoundsForClientView() const override {
     if (visible())
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index b4223ea..d04bdcf1 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -65,6 +65,8 @@
 #if defined(OS_IOS)
 const base::Feature kIPHBottomToolbarTipFeature{
     "IPH_BottomToolbarTip", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHLongPressToolbarTipFeature{
+    "IPH_LongPressToolbarTip", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHNewTabTipFeature{"IPH_NewTabTip",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHNewIncognitoTabTipFeature{
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index b06d08c..cd8c766 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -49,6 +49,7 @@
 
 #if defined(OS_IOS)
 extern const base::Feature kIPHBottomToolbarTipFeature;
+extern const base::Feature kIPHLongPressToolbarTipFeature;
 extern const base::Feature kIPHNewTabTipFeature;
 extern const base::Feature kIPHNewIncognitoTabTipFeature;
 extern const base::Feature kIPHBadgedReadingListFeature;
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index 445695d..3b59190e4 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -42,6 +42,7 @@
 #endif  // BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
 #if defined(OS_IOS)
     &kIPHBottomToolbarTipFeature,
+    &kIPHLongPressToolbarTipFeature,
     &kIPHNewTabTipFeature,
     &kIPHNewIncognitoTabTipFeature,
     &kIPHBadgedReadingListFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index a9c8186b25..69e73a2 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -81,6 +81,8 @@
 #endif  // BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
 #if defined(OS_IOS)
 DEFINE_VARIATION_PARAM(kIPHBottomToolbarTipFeature, "IPH_BottomToolbarTip");
+DEFINE_VARIATION_PARAM(kIPHLongPressToolbarTipFeature,
+                       "IPH_LongPressToolbarTip");
 DEFINE_VARIATION_PARAM(kIPHNewTabTipFeature, "IPH_NewTabTip");
 DEFINE_VARIATION_PARAM(kIPHNewIncognitoTabTipFeature, "IPH_NewIncognitoTabTip");
 DEFINE_VARIATION_PARAM(kIPHBadgedReadingListFeature, "IPH_BadgedReadingList");
@@ -118,6 +120,7 @@
         VARIATION_ENTRY(kIPHNewTabFeature),
 #elif defined(OS_IOS)
         VARIATION_ENTRY(kIPHBottomToolbarTipFeature),
+        VARIATION_ENTRY(kIPHLongPressToolbarTipFeature),
         VARIATION_ENTRY(kIPHNewTabTipFeature),
         VARIATION_ENTRY(kIPHNewIncognitoTabTipFeature),
         VARIATION_ENTRY(kIPHBadgedReadingListFeature),
diff --git a/components/gcm_driver/account_tracker_unittest.cc b/components/gcm_driver/account_tracker_unittest.cc
index c8613ea..7f8a821 100644
--- a/components/gcm_driver/account_tracker_unittest.cc
+++ b/components/gcm_driver/account_tracker_unittest.cc
@@ -31,7 +31,8 @@
 using SigninManagerForTest = FakeSigninManager;
 #endif  // OS_CHROMEOS
 
-const char kPrimaryAccountKey[] = "primary_account@example.com";
+const char kPrimaryAccountEmail[] = "primary_account@example.com";
+const char kPrimaryAccountGaiaId[] = "primary_account";
 
 enum TrackingEventType { SIGN_IN, SIGN_OUT };
 
@@ -288,13 +289,17 @@
 
   // Sets the primary account info but carries no guarantee of firing the
   // callback that signin occurred (see NotifyLogin() below if exercising a
-  // true signin flow in a non-ChromeOS context).
-  void SetActiveAccount(const std::string& account_key) {
+  // true signin flow in a non-ChromeOS context). Returns the account ID of the
+  // newly-set account.
+  std::string SetActiveAccount(const std::string& gaia_id,
+                               const std::string& email) {
 #if defined(OS_CHROMEOS)
-    fake_signin_manager_->SignIn(account_key);
+    fake_signin_manager_->SignIn(email);
 #else
-    fake_signin_manager_->SignIn(account_key, account_key, "" /* password */);
+    fake_signin_manager_->SignIn(gaia_id, email, "" /* password */);
 #endif
+
+    return fake_signin_manager_->GetAuthenticatedAccountId();
   }
 
 // NOTE: On ChromeOS, the login callback is never fired in production (since the
@@ -302,8 +307,12 @@
 // exercise functionality dependent on that callback firing are not relevant
 // on ChromeOS and should simply not run on that platform.
 #if !defined(OS_CHROMEOS)
-  void NotifyLogin(const std::string& account_key) {
-    fake_signin_manager_->SignIn(account_key, account_key, "" /* password */);
+  // Sets the primary account info and fires the callback that signin occurred.
+  // Returns the account ID of the newly-set account.
+  std::string NotifyLogin(const std::string& gaia_id,
+                          const std::string& email) {
+    fake_signin_manager_->SignIn(gaia_id, email, "" /* password */);
+    return fake_signin_manager_->GetAuthenticatedAccountId();
   }
 
   void NotifyLogoutOfPrimaryAccountOnly() {
@@ -319,23 +328,32 @@
   }
 #endif
 
-  void NotifyTokenAvailable(const std::string& username) {
-    fake_oauth2_token_service_->UpdateCredentials(username,
+  std::string AddAccountWithToken(const std::string& gaia,
+                                  const std::string& email) {
+    std::string account_id =
+        account_tracker_service_.SeedAccountInfo(gaia, email);
+    fake_oauth2_token_service_->UpdateCredentials(account_id,
+                                                  "fake_refresh_token");
+    return account_id;
+  }
+
+  void NotifyTokenAvailable(const std::string& account_id) {
+    fake_oauth2_token_service_->UpdateCredentials(account_id,
                                                   "fake_refresh_token");
   }
 
-  void NotifyTokenRevoked(const std::string& username) {
-    fake_oauth2_token_service_->RevokeCredentials(username);
+  void NotifyTokenRevoked(const std::string& account_id) {
+    fake_oauth2_token_service_->RevokeCredentials(account_id);
   }
 
   // Helpers to fake access token and user info fetching
-  void IssueAccessToken(const std::string& username) {
+  void IssueAccessToken(const std::string& account_id) {
     fake_oauth2_token_service_->IssueAllTokensForAccount(
-        username, "access_token-" + username, base::Time::Max());
+        account_id, "access_token-" + account_id, base::Time::Max());
   }
 
-  std::string GetValidTokenInfoResponse(const std::string& account_key) {
-    return std::string("{ \"id\": \"") + AccountKeyToObfuscatedId(account_key) +
+  std::string GetValidTokenInfoResponse(const std::string& account_id) {
+    return std::string("{ \"id\": \"") + AccountKeyToObfuscatedId(account_id) +
            "\" }";
   }
 
@@ -346,12 +364,15 @@
   void ReturnOAuthUrlFetchSuccess(const std::string& account_key);
   void ReturnOAuthUrlFetchFailure(const std::string& account_key);
 
-  void SetupPrimaryLogin() {
+  std::string SetupPrimaryLogin() {
     // Initial setup for tests that start with a signed in profile.
-    SetActiveAccount(kPrimaryAccountKey);
-    NotifyTokenAvailable(kPrimaryAccountKey);
-    ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
+    std::string primary_account_id =
+        SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+    NotifyTokenAvailable(primary_account_id);
+    ReturnOAuthUrlFetchSuccess(primary_account_id);
     observer()->Clear();
+
+    return primary_account_id;
   }
 
  private:
@@ -380,15 +401,15 @@
 }
 
 void AccountTrackerTest::ReturnOAuthUrlFetchSuccess(
-    const std::string& account_key) {
-  IssueAccessToken(account_key);
+    const std::string& account_id) {
+  IssueAccessToken(account_id);
   ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK,
-                             GetValidTokenInfoResponse(account_key));
+                             GetValidTokenInfoResponse(account_id));
 }
 
 void AccountTrackerTest::ReturnOAuthUrlFetchFailure(
-    const std::string& account_key) {
-  IssueAccessToken(account_key);
+    const std::string& account_id) {
+  IssueAccessToken(account_id);
   ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId,
                              net::HTTP_BAD_REQUEST, "");
 }
@@ -396,8 +417,8 @@
 // Primary tests just involve the Active account
 
 TEST_F(AccountTrackerTest, PrimaryNoEventsBeforeLogin) {
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenAvailable("dummy_account_id");
+  NotifyTokenRevoked("dummy_account_id");
 
 // Logout is not possible on ChromeOS.
 #if !defined(OS_CHROMEOS)
@@ -408,101 +429,108 @@
 }
 
 TEST_F(AccountTrackerTest, PrimaryLoginThenTokenAvailable) {
-  SetActiveAccount(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
+  std::string primary_account_id =
+      SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
   EXPECT_TRUE(observer()->CheckEvents());
 
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
 }
 
-// These tests exercise true login/logout, which are not possible on ChromeOS.
 #if !defined(OS_CHROMEOS)
 TEST_F(AccountTrackerTest, PrimaryTokenAvailableThenLogin) {
-  NotifyTokenAvailable(kPrimaryAccountKey);
+  AddAccountWithToken(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
   EXPECT_TRUE(observer()->CheckEvents());
 
-  NotifyLogin(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
+  std::string primary_account_id =
+      NotifyLogin(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
 }
 
 TEST_F(AccountTrackerTest, PrimaryTokenAvailableAndRevokedThenLogin) {
-  NotifyTokenAvailable(kPrimaryAccountKey);
+  std::string primary_account_id =
+      AddAccountWithToken(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
   EXPECT_TRUE(observer()->CheckEvents());
 
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenRevoked(primary_account_id);
   EXPECT_TRUE(observer()->CheckEvents());
 
-  NotifyLogin(kPrimaryAccountKey);
+  NotifyLogin(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
   EXPECT_TRUE(observer()->CheckEvents());
 }
 #endif
 
 TEST_F(AccountTrackerTest, PrimaryRevoke) {
-  SetActiveAccount(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
+  std::string primary_account_id =
+      SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
   observer()->Clear();
 
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenRevoked(primary_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id)));
 }
 
 TEST_F(AccountTrackerTest, PrimaryRevokeThenLogin) {
-  SetActiveAccount(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  std::string primary_account_id =
+      SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
+  NotifyTokenRevoked(primary_account_id);
   observer()->Clear();
 
-  SetActiveAccount(kPrimaryAccountKey);
+  SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
   EXPECT_TRUE(observer()->CheckEvents());
 }
 
 TEST_F(AccountTrackerTest, PrimaryRevokeThenTokenAvailable) {
-  SetActiveAccount(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  std::string primary_account_id =
+      SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
+  NotifyTokenRevoked(primary_account_id);
   observer()->Clear();
 
-  NotifyTokenAvailable(kPrimaryAccountKey);
+  NotifyTokenAvailable(primary_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
 }
 
 // These tests exercise true login/logout, which are not possible on ChromeOS.
 #if !defined(OS_CHROMEOS)
 TEST_F(AccountTrackerTest, PrimaryLogoutThenRevoke) {
-  NotifyLogin(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
+  std::string primary_account_id =
+      NotifyLogin(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
   observer()->Clear();
 
   NotifyLogoutOfAllAccounts();
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id)));
 
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenRevoked(primary_account_id);
   EXPECT_TRUE(observer()->CheckEvents());
 }
 
 TEST_F(AccountTrackerTest, PrimaryLogoutFetchCancelAvailable) {
-  NotifyLogin(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
+  std::string primary_account_id =
+      NotifyLogin(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
   // TokenAvailable kicks off a fetch. Logout without satisfying it.
   NotifyLogoutOfAllAccounts();
   EXPECT_TRUE(observer()->CheckEvents());
 
-  SetActiveAccount(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
+  SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
 }
 #endif
 
@@ -511,162 +539,156 @@
 TEST_F(AccountTrackerTest, Available) {
   SetupPrimaryLogin();
 
-  NotifyTokenAvailable("user@example.com");
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
   EXPECT_TRUE(observer()->CheckEvents());
 
-  ReturnOAuthUrlFetchSuccess("user@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com")));
+  ReturnOAuthUrlFetchSuccess(account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
 }
 
 TEST_F(AccountTrackerTest, AvailableRevokeAvailable) {
   SetupPrimaryLogin();
 
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchSuccess("user@example.com");
-  NotifyTokenRevoked("user@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"),
-                              TrackingEvent(SIGN_OUT, "user@example.com")));
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  ReturnOAuthUrlFetchSuccess(account_id);
+  NotifyTokenRevoked(account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id),
+                                      TrackingEvent(SIGN_OUT, account_id)));
 
-  NotifyTokenAvailable("user@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com")));
+  NotifyTokenAvailable(account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
 }
 
 TEST_F(AccountTrackerTest, AvailableRevokeAvailableWithPendingFetch) {
   SetupPrimaryLogin();
 
-  NotifyTokenAvailable("user@example.com");
-  NotifyTokenRevoked("user@example.com");
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  NotifyTokenRevoked(account_id);
   EXPECT_TRUE(observer()->CheckEvents());
 
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchSuccess("user@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com")));
+  NotifyTokenAvailable(account_id);
+  ReturnOAuthUrlFetchSuccess(account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
 }
 
 TEST_F(AccountTrackerTest, AvailableRevokeRevoke) {
   SetupPrimaryLogin();
 
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchSuccess("user@example.com");
-  NotifyTokenRevoked("user@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"),
-                              TrackingEvent(SIGN_OUT, "user@example.com")));
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  ReturnOAuthUrlFetchSuccess(account_id);
+  NotifyTokenRevoked(account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id),
+                                      TrackingEvent(SIGN_OUT, account_id)));
 
-  NotifyTokenRevoked("user@example.com");
+  NotifyTokenRevoked(account_id);
   EXPECT_TRUE(observer()->CheckEvents());
 }
 
 TEST_F(AccountTrackerTest, AvailableAvailable) {
   SetupPrimaryLogin();
 
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchSuccess("user@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com")));
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  ReturnOAuthUrlFetchSuccess(account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
 
-  NotifyTokenAvailable("user@example.com");
+  NotifyTokenAvailable(account_id);
   EXPECT_TRUE(observer()->CheckEvents());
 }
 
 TEST_F(AccountTrackerTest, TwoAccounts) {
   SetupPrimaryLogin();
 
-  NotifyTokenAvailable("alpha@example.com");
-  ReturnOAuthUrlFetchSuccess("alpha@example.com");
+  std::string alpha_account_id =
+      AddAccountWithToken("alpha", "alpha@example.com");
+  ReturnOAuthUrlFetchSuccess(alpha_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "alpha@example.com")));
+      observer()->CheckEvents(TrackingEvent(SIGN_IN, alpha_account_id)));
 
-  NotifyTokenAvailable("beta@example.com");
-  ReturnOAuthUrlFetchSuccess("beta@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "beta@example.com")));
+  std::string beta_account_id = AddAccountWithToken("beta", "beta@example.com");
+  ReturnOAuthUrlFetchSuccess(beta_account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, beta_account_id)));
 
-  NotifyTokenRevoked("alpha@example.com");
+  NotifyTokenRevoked(alpha_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, "alpha@example.com")));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, alpha_account_id)));
 
-  NotifyTokenRevoked("beta@example.com");
+  NotifyTokenRevoked(beta_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, "beta@example.com")));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, beta_account_id)));
 }
 
 TEST_F(AccountTrackerTest, AvailableTokenFetchFailAvailable) {
   SetupPrimaryLogin();
 
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchFailure("user@example.com");
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  ReturnOAuthUrlFetchFailure(account_id);
   EXPECT_TRUE(observer()->CheckEvents());
 
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchSuccess("user@example.com");
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com")));
+  NotifyTokenAvailable(account_id);
+  ReturnOAuthUrlFetchSuccess(account_id);
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
 }
 
 // These tests exercise true login/logout, which are not possible on ChromeOS.
 #if !defined(OS_CHROMEOS)
 TEST_F(AccountTrackerTest, MultiSignOutSignIn) {
-  SetupPrimaryLogin();
+  std::string primary_account_id = SetupPrimaryLogin();
 
-  NotifyTokenAvailable("alpha@example.com");
-  ReturnOAuthUrlFetchSuccess("alpha@example.com");
-  NotifyTokenAvailable("beta@example.com");
-  ReturnOAuthUrlFetchSuccess("beta@example.com");
+  std::string alpha_account_id =
+      AddAccountWithToken("alpha", "alpha@example.com");
+  ReturnOAuthUrlFetchSuccess(alpha_account_id);
+  std::string beta_account_id = AddAccountWithToken("beta", "beta@example.com");
+  ReturnOAuthUrlFetchSuccess(beta_account_id);
 
   observer()->SortEventsByUser();
-  EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "alpha@example.com"),
-                              TrackingEvent(SIGN_IN, "beta@example.com")));
+  EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, alpha_account_id),
+                                      TrackingEvent(SIGN_IN, beta_account_id)));
 
   // Log out of the primary account only (allows for testing that the account
   // tracker preserves knowledge of "beta@example.com").
   NotifyLogoutOfPrimaryAccountOnly();
   observer()->SortEventsByUser();
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, "alpha@example.com"),
-                              TrackingEvent(SIGN_OUT, "beta@example.com"),
-                              TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, alpha_account_id),
+                              TrackingEvent(SIGN_OUT, beta_account_id),
+                              TrackingEvent(SIGN_OUT, primary_account_id)));
 
   // No events fire at all while profile is signed out.
-  NotifyTokenRevoked("alpha@example.com");
-  NotifyTokenAvailable("gamma@example.com");
+  NotifyTokenRevoked(alpha_account_id);
+  std::string gamma_account_id =
+      AddAccountWithToken("gamma", "gamma@example.com");
   EXPECT_TRUE(observer()->CheckEvents());
 
   // Signing the profile in again will resume tracking all accounts.
-  NotifyLogin(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess("beta@example.com");
-  ReturnOAuthUrlFetchSuccess("gamma@example.com");
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
+  NotifyLogin(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(beta_account_id);
+  ReturnOAuthUrlFetchSuccess(gamma_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
   observer()->SortEventsByUser();
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, "beta@example.com"),
-                              TrackingEvent(SIGN_IN, "gamma@example.com"),
-                              TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_IN, beta_account_id),
+                              TrackingEvent(SIGN_IN, gamma_account_id),
+                              TrackingEvent(SIGN_IN, primary_account_id)));
 
   // Revoking the primary token does not affect other accounts.
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenRevoked(primary_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id)));
 
-  NotifyTokenAvailable(kPrimaryAccountKey);
+  NotifyTokenAvailable(primary_account_id);
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
 }
 #endif
 
 // Primary/non-primary interactions
 
 TEST_F(AccountTrackerTest, MultiNoEventsBeforeLogin) {
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  NotifyTokenAvailable("user@example.com");
-  NotifyTokenRevoked("user@example.com");
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenAvailable("dummy_account_id");
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  NotifyTokenRevoked(account_id);
+  NotifyTokenRevoked("dummy_account_id");
 
 // Logout is not possible on ChromeOS.
 #if !defined(OS_CHROMEOS)
@@ -679,42 +701,44 @@
 // This test exercises true login/logout, which are not possible on ChromeOS.
 #if !defined(OS_CHROMEOS)
 TEST_F(AccountTrackerTest, MultiLogoutRemovesAllAccounts) {
-  NotifyLogin(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchSuccess("user@example.com");
+  std::string primary_account_id =
+      NotifyLogin(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  ReturnOAuthUrlFetchSuccess(account_id);
   observer()->Clear();
 
   NotifyLogoutOfAllAccounts();
   observer()->SortEventsByUser();
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey),
-                              TrackingEvent(SIGN_OUT, "user@example.com")));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id),
+                              TrackingEvent(SIGN_OUT, account_id)));
 }
 #endif
 
 TEST_F(AccountTrackerTest, MultiRevokePrimaryDoesNotRemoveAllAccounts) {
-  SetActiveAccount(kPrimaryAccountKey);
-  NotifyTokenAvailable(kPrimaryAccountKey);
-  ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
-  NotifyTokenAvailable("user@example.com");
-  ReturnOAuthUrlFetchSuccess("user@example.com");
+  std::string primary_account_id =
+      SetActiveAccount(kPrimaryAccountGaiaId, kPrimaryAccountEmail);
+  NotifyTokenAvailable(primary_account_id);
+  ReturnOAuthUrlFetchSuccess(primary_account_id);
+  std::string account_id = AddAccountWithToken("user", "user@example.com");
+  ReturnOAuthUrlFetchSuccess(account_id);
   observer()->Clear();
 
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenRevoked(primary_account_id);
   observer()->SortEventsByUser();
   EXPECT_TRUE(
-      observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
+      observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id)));
 }
 
 TEST_F(AccountTrackerTest, GetAccountsPrimary) {
-  SetupPrimaryLogin();
+  std::string primary_account_id = SetupPrimaryLogin();
 
   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
   EXPECT_EQ(1ul, ids.size());
-  EXPECT_EQ(kPrimaryAccountKey, ids[0].account_key);
-  EXPECT_EQ(AccountKeyToObfuscatedId(kPrimaryAccountKey), ids[0].gaia);
+  EXPECT_EQ(primary_account_id, ids[0].account_key);
+  EXPECT_EQ(AccountKeyToObfuscatedId(primary_account_id), ids[0].gaia);
 }
 
 TEST_F(AccountTrackerTest, GetAccountsSignedOut) {
@@ -723,49 +747,52 @@
 }
 
 TEST_F(AccountTrackerTest, GetAccountsOnlyReturnAccountsWithTokens) {
-  SetupPrimaryLogin();
+  std::string primary_account_id = SetupPrimaryLogin();
 
-  NotifyTokenAvailable("alpha@example.com");
-  NotifyTokenAvailable("beta@example.com");
-  ReturnOAuthUrlFetchSuccess("beta@example.com");
+  std::string alpha_account_id =
+      AddAccountWithToken("alpha", "alpha@example.com");
+  std::string beta_account_id = AddAccountWithToken("beta", "beta@example.com");
+  ReturnOAuthUrlFetchSuccess(beta_account_id);
 
   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
   EXPECT_EQ(2ul, ids.size());
-  EXPECT_EQ(kPrimaryAccountKey, ids[0].account_key);
-  EXPECT_EQ(AccountKeyToObfuscatedId(kPrimaryAccountKey), ids[0].gaia);
-  EXPECT_EQ("beta@example.com", ids[1].account_key);
-  EXPECT_EQ(AccountKeyToObfuscatedId("beta@example.com"), ids[1].gaia);
+  EXPECT_EQ(primary_account_id, ids[0].account_key);
+  EXPECT_EQ(AccountKeyToObfuscatedId(primary_account_id), ids[0].gaia);
+  EXPECT_EQ(beta_account_id, ids[1].account_key);
+  EXPECT_EQ(AccountKeyToObfuscatedId(beta_account_id), ids[1].gaia);
 }
 
 TEST_F(AccountTrackerTest, GetAccountsSortOrder) {
-  SetupPrimaryLogin();
+  std::string primary_account_id = SetupPrimaryLogin();
 
-  NotifyTokenAvailable("zeta@example.com");
-  ReturnOAuthUrlFetchSuccess("zeta@example.com");
-  NotifyTokenAvailable("alpha@example.com");
-  ReturnOAuthUrlFetchSuccess("alpha@example.com");
+  std::string zeta_account_id = AddAccountWithToken("zeta", "zeta@example.com");
+  ReturnOAuthUrlFetchSuccess(zeta_account_id);
+  std::string alpha_account_id =
+      AddAccountWithToken("alpha", "alpha@example.com");
+  ReturnOAuthUrlFetchSuccess(alpha_account_id);
 
   // The primary account will be first in the vector. Remaining accounts
   // will be sorted by gaia ID.
   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
   EXPECT_EQ(3ul, ids.size());
-  EXPECT_EQ(kPrimaryAccountKey, ids[0].account_key);
-  EXPECT_EQ(AccountKeyToObfuscatedId(kPrimaryAccountKey), ids[0].gaia);
-  EXPECT_EQ("alpha@example.com", ids[1].account_key);
-  EXPECT_EQ(AccountKeyToObfuscatedId("alpha@example.com"), ids[1].gaia);
-  EXPECT_EQ("zeta@example.com", ids[2].account_key);
-  EXPECT_EQ(AccountKeyToObfuscatedId("zeta@example.com"), ids[2].gaia);
+  EXPECT_EQ(primary_account_id, ids[0].account_key);
+  EXPECT_EQ(AccountKeyToObfuscatedId(primary_account_id), ids[0].gaia);
+  EXPECT_EQ(alpha_account_id, ids[1].account_key);
+  EXPECT_EQ(AccountKeyToObfuscatedId(alpha_account_id), ids[1].gaia);
+  EXPECT_EQ(zeta_account_id, ids[2].account_key);
+  EXPECT_EQ(AccountKeyToObfuscatedId(zeta_account_id), ids[2].gaia);
 }
 
 TEST_F(AccountTrackerTest, GetAccountsReturnNothingWhenPrimarySignedOut) {
-  SetupPrimaryLogin();
+  std::string primary_account_id = SetupPrimaryLogin();
 
-  NotifyTokenAvailable("zeta@example.com");
-  ReturnOAuthUrlFetchSuccess("zeta@example.com");
-  NotifyTokenAvailable("alpha@example.com");
-  ReturnOAuthUrlFetchSuccess("alpha@example.com");
+  std::string zeta_account_id = AddAccountWithToken("zeta", "zeta@example.com");
+  ReturnOAuthUrlFetchSuccess(zeta_account_id);
+  std::string alpha_account_id =
+      AddAccountWithToken("alpha", "alpha@example.com");
+  ReturnOAuthUrlFetchSuccess(alpha_account_id);
 
-  NotifyTokenRevoked(kPrimaryAccountKey);
+  NotifyTokenRevoked(primary_account_id);
 
   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
   EXPECT_EQ(0ul, ids.size());
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index 57d03b35..73e9e52 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -533,7 +533,6 @@
   db_.set_page_size(2048);
   db_.set_cache_size(32);
   db_.set_exclusive_locking();
-  db_.set_restrict_to_user();
   db_.set_histogram_tag("Passwords");
 
   if (!db_.Open(db_path_)) {
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc
index 599c7eb88..bb9643b 100644
--- a/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -256,21 +256,19 @@
 }
 
 bool PasswordAutofillManager::MaybeShowPasswordSuggestions(
-    const gfx::RectF& bounds) {
+    const gfx::RectF& bounds,
+    base::i18n::TextDirection text_direction) {
   if (login_to_password_info_.empty())
     return false;
-  // TODO(crbug.com/865469): Get text direction from the renderer.
-  OnShowPasswordSuggestions(login_to_password_info_.begin()->first,
-                            base::i18n::IsRTL() ? base::i18n::RIGHT_TO_LEFT
-                                                : base::i18n::LEFT_TO_RIGHT,
-                            base::string16(),
-                            autofill::SHOW_ALL | autofill::IS_PASSWORD_FIELD,
-                            bounds);
+  OnShowPasswordSuggestions(
+      login_to_password_info_.begin()->first, text_direction, base::string16(),
+      autofill::SHOW_ALL | autofill::IS_PASSWORD_FIELD, bounds);
   return true;
 }
 
 bool PasswordAutofillManager::MaybeShowPasswordSuggestionsWithGeneration(
-    const gfx::RectF& bounds) {
+    const gfx::RectF& bounds,
+    base::i18n::TextDirection text_direction) {
   if (login_to_password_info_.empty())
     return false;
   std::vector<autofill::Suggestion> suggestions;
@@ -299,11 +297,8 @@
         metrics_util::SHOW_ALL_SAVED_PASSWORDS_CONTEXT_PASSWORD);
   }
 
-  autofill_client_->ShowAutofillPopup(
-      bounds,
-      base::i18n::IsRTL() ? base::i18n::RIGHT_TO_LEFT
-                          : base::i18n::LEFT_TO_RIGHT,
-      suggestions, false, weak_ptr_factory_.GetWeakPtr());
+  autofill_client_->ShowAutofillPopup(bounds, text_direction, suggestions,
+                                      false, weak_ptr_factory_.GetWeakPtr());
   return true;
 }
 
diff --git a/components/password_manager/core/browser/password_autofill_manager.h b/components/password_manager/core/browser/password_autofill_manager.h
index ec83952..0168e79 100644
--- a/components/password_manager/core/browser/password_autofill_manager.h
+++ b/components/password_manager/core/browser/password_autofill_manager.h
@@ -69,12 +69,15 @@
   // This is currently used for cases in which the automatic generation
   // option is offered through a different UI surface than the popup
   // (e.g. via the keyboard accessory on Android).
-  bool MaybeShowPasswordSuggestions(const gfx::RectF& bounds);
+  bool MaybeShowPasswordSuggestions(const gfx::RectF& bounds,
+                                    base::i18n::TextDirection text_direction);
 
   // If there are relevant credentials for the current frame, shows them with
   // an additional 'generation' option and returns true. Otherwise, does nothing
   // and returns false.
-  bool MaybeShowPasswordSuggestionsWithGeneration(const gfx::RectF& bounds);
+  bool MaybeShowPasswordSuggestionsWithGeneration(
+      const gfx::RectF& bounds,
+      base::i18n::TextDirection text_direction);
 
   // Called when main frame navigates. Not called for in-page navigations.
   void DidNavigateMainFrame();
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
index 73521362..e1a1003 100644
--- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -741,7 +741,7 @@
   gfx::RectF element_bounds;
   EXPECT_FALSE(
       password_autofill_manager_->MaybeShowPasswordSuggestionsWithGeneration(
-          element_bounds));
+          element_bounds, base::i18n::RIGHT_TO_LEFT));
 }
 
 TEST_F(PasswordAutofillManagerTest,
@@ -764,13 +764,13 @@
       l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_GENERATE_PASSWORD);
   EXPECT_CALL(*autofill_client,
               ShowAutofillPopup(
-                  element_bounds, _,
+                  element_bounds, base::i18n::RIGHT_TO_LEFT,
                   SuggestionVectorValuesAre(testing::ElementsAreArray(
                       GetSuggestionList({test_username_, generation_string}))),
                   false, _));
   EXPECT_TRUE(
       password_autofill_manager_->MaybeShowPasswordSuggestionsWithGeneration(
-          element_bounds));
+          element_bounds, base::i18n::RIGHT_TO_LEFT));
 
   // Click "Generate password".
   EXPECT_CALL(*client, GeneratePassword());
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc
index 8cbd84e3..eea70aeb 100644
--- a/components/signin/core/browser/gaia_cookie_manager_service.cc
+++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -18,6 +18,7 @@
 #include "base/values.h"
 #include "components/data_use_measurement/core/data_use_user_data.h"
 #include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/signin_cookie_change_subscription.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_constants.h"
@@ -350,10 +351,19 @@
 }
 
 void GaiaCookieManagerService::Init() {
-  cookie_change_subscription_ = signin_client_->AddCookieChangeCallback(
-      GaiaUrls::GetInstance()->google_url(), kGaiaCookieName,
-      base::BindRepeating(&GaiaCookieManagerService::OnCookieChange,
-                          base::Unretained(this)));
+  scoped_refptr<net::URLRequestContextGetter> context_getter =
+      signin_client_->GetURLRequestContext();
+
+  // NOTE: |context_getter| can be nullptr when TestSigninClient is used in
+  // testing contexts.
+  if (context_getter) {
+    cookie_change_subscription_ =
+        std::make_unique<SigninCookieChangeSubscription>(
+            context_getter, GaiaUrls::GetInstance()->google_url(),
+            kGaiaCookieName,
+            base::BindRepeating(&GaiaCookieManagerService::OnCookieChange,
+                                base::Unretained(this)));
+  }
 }
 
 void GaiaCookieManagerService::Shutdown() {
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h
index 218b1b1..a59992ab 100644
--- a/components/signin/core/browser/gaia_cookie_manager_service.h
+++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -25,6 +25,7 @@
 class GaiaCookieRequest;
 class GoogleServiceAuthError;
 class OAuth2TokenService;
+class SigninCookieChangeSubscription;
 
 namespace network {
 class SharedURLLoaderFactory;
@@ -309,8 +310,7 @@
   std::string access_token_;
 
   // Subscription to be called whenever the GAIA cookies change.
-  std::unique_ptr<SigninClient::CookieChangeSubscription>
-      cookie_change_subscription_;
+  std::unique_ptr<SigninCookieChangeSubscription> cookie_change_subscription_;
 
   // A worklist for this class. Stores any pending requests that couldn't be
   // executed right away, since this class only permits one request to be
diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h
index 44a648b2..d41ac33 100644
--- a/components/signin/core/browser/signin_client.h
+++ b/components/signin/core/browser/signin_client.h
@@ -42,12 +42,6 @@
 // embedder.
 class SigninClient : public KeyedService {
  public:
-  // The subcription for cookie changed notifications.
-  class CookieChangeSubscription {
-   public:
-    virtual ~CookieChangeSubscription() = default;
-  };
-
   ~SigninClient() override = default;
 
   // If |for_ephemeral| is true, special kind of device ID for ephemeral users
@@ -90,15 +84,6 @@
   // Signin component is being used.
   virtual std::string GetProductVersion() = 0;
 
-  // Adds a callback to be called each time a cookie for |url| with name |name|
-  // changes.
-  // Note that |callback| will always be called on the thread that
-  // |AddCookieChangeCallback| was called on.
-  virtual std::unique_ptr<CookieChangeSubscription> AddCookieChangeCallback(
-      const GURL& url,
-      const std::string& name,
-      net::CookieChangeCallback callback) = 0;
-
   // Called after Google signin has succeeded.
   virtual void OnSignedIn(const std::string& account_id,
                           const std::string& gaia_id,
diff --git a/components/signin/core/browser/signin_cookie_change_subscription.h b/components/signin/core/browser/signin_cookie_change_subscription.h
index 8b4ac37..b00248e 100644
--- a/components/signin/core/browser/signin_cookie_change_subscription.h
+++ b/components/signin/core/browser/signin_cookie_change_subscription.h
@@ -11,15 +11,14 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/task_runner.h"
 #include "base/threading/thread_checker.h"
-#include "components/signin/core/browser/signin_client.h"
 #include "net/cookies/cookie_change_dispatcher.h"
 #include "net/url_request/url_request_context_getter.h"
 
 // The subscription for cookie changes. This class lives on the main thread.
 class SigninCookieChangeSubscription
-    : public SigninClient::CookieChangeSubscription,
-      public base::SupportsWeakPtr<SigninCookieChangeSubscription> {
+    : public base::SupportsWeakPtr<SigninCookieChangeSubscription> {
  public:
   // Creates a cookie change subscription and registers for cookie changed
   // events.
@@ -28,7 +27,7 @@
       const GURL& url,
       const std::string& name,
       net::CookieChangeCallback callback);
-  ~SigninCookieChangeSubscription() override;
+  ~SigninCookieChangeSubscription();
 
  private:
   // Holder of a cookie store cookie changed subscription.
diff --git a/components/signin/core/browser/test_signin_client.cc b/components/signin/core/browser/test_signin_client.cc
index 76f6f6e..a80e2fc 100644
--- a/components/signin/core/browser/test_signin_client.cc
+++ b/components/signin/core/browser/test_signin_client.cc
@@ -79,13 +79,6 @@
   database_->Init();
 }
 
-std::unique_ptr<SigninClient::CookieChangeSubscription>
-TestSigninClient::AddCookieChangeCallback(const GURL& url,
-                                          const std::string& name,
-                                          net::CookieChangeCallback callback) {
-  return std::make_unique<SigninClient::CookieChangeSubscription>();
-}
-
 void TestSigninClient::SetNetworkCallsDelayed(bool value) {
   network_calls_delayed_ = value;
 
diff --git a/components/signin/core/browser/test_signin_client.h b/components/signin/core/browser/test_signin_client.h
index 8e487d6..2ccb9dd8 100644
--- a/components/signin/core/browser/test_signin_client.h
+++ b/components/signin/core/browser/test_signin_client.h
@@ -78,13 +78,6 @@
     return &test_url_loader_factory_;
   }
 
-  // Registers |callback| and returns the subscription.
-  // Note that |callback| will never be called.
-  std::unique_ptr<SigninClient::CookieChangeSubscription>
-  AddCookieChangeCallback(const GURL& url,
-                          const std::string& name,
-                          net::CookieChangeCallback callback) override;
-
   void set_are_signin_cookies_allowed(bool value) {
     are_signin_cookies_allowed_ = value;
   }
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index 43be67c..d7922988 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -138,6 +138,10 @@
 
   ~SyncService() override {}
 
+  //////////////////////////////////////////////////////////////////////////////
+  // BASIC STATE ACCESS
+  //////////////////////////////////////////////////////////////////////////////
+
   // Returns the set of reasons that are keeping Sync disabled, as a bitmask of
   // DisableReason enum entries.
   virtual int GetDisableReasons() const = 0;
@@ -154,113 +158,25 @@
   // syncer::GetUploadToGoogleState instead of this.
   virtual State GetState() const = 0;
 
-  // Whether the user has completed the initial Sync setup. This does not mean
-  // that sync is currently running (due to delayed startup, unrecoverable
-  // errors, or shutdown). If you want to know whether Sync is actually running,
-  // use GetState instead.
-  virtual bool IsFirstSetupComplete() const = 0;
-
-  // DEPRECATED! Use GetDisableReasons/HasDisableReason instead.
-  // Equivalent to "!HasDisableReason(DISABLE_REASON_PLATFORM_OVERRIDE) &&
-  // !HasDisableReason(DISABLE_REASON_ENTERPRISE_POLICY)".
-  bool IsSyncAllowed() const;
-
-  // DEPRECATED! Use GetState instead. Equivalent to
-  // "GetState() == State::CONFIGURING || GetState() == State::ACTIVE".
-  // To see which datatypes are actually syncing, see GetActiveDataTypes().
-  bool IsSyncActive() const;
-
   // Returns true if the local sync backend server has been enabled through a
   // command line flag or policy. In this case sync is considered active but any
   // implied consent for further related services e.g. Suggestions, Web History
   // etc. is considered not granted.
   virtual bool IsLocalSyncEnabled() const = 0;
 
-  // Triggers a GetUpdates call for the specified |types|, pulling any new data
-  // from the sync server.
-  virtual void TriggerRefresh(const ModelTypeSet& types) = 0;
+  // Information about the currently signed in user.
+  virtual AccountInfo GetAuthenticatedAccountInfo() const = 0;
 
-  // Get the set of current active data types (those chosen or configured by
-  // the user which have not also encountered a runtime error).
-  // Note that if the Sync engine is in the middle of a configuration, this
-  // will the the empty set. Once the configuration completes the set will
-  // be updated.
-  virtual ModelTypeSet GetActiveDataTypes() const = 0;
-
-  // Returns the SyncClient instance associated with this service.
-  virtual SyncClient* GetSyncClient() const = 0;
-
-  // Adds/removes an observer. SyncService does not take ownership of the
-  // observer.
-  virtual void AddObserver(SyncServiceObserver* observer) = 0;
-  virtual void RemoveObserver(SyncServiceObserver* observer) = 0;
-
-  // Returns true if |observer| has already been added as an observer.
-  virtual bool HasObserver(const SyncServiceObserver* observer) const = 0;
-
-  // ---------------------------------------------------------------------------
-  // TODO(sync): The methods below were pulled from ProfileSyncService, and
-  // should be evaluated to see if they should stay.
-
-  // Called when a datatype (SyncableService) has a need for sync to start
-  // ASAP, presumably because a local change event has occurred but we're
-  // still in deferred start mode, meaning the SyncableService hasn't been
-  // told to MergeDataAndStartSyncing yet.
-  virtual void OnDataTypeRequestsSyncStartup(ModelType type) = 0;
-
-  // DEPRECATED! Use GetDisableReasons/HasDisableReason instead.
-  // Equivalent to having no disable reasons, i.e.
-  // "GetDisableReasons() == DISABLE_REASON_NONE".
-  bool CanSyncStart() const;
-
-  // Stops sync at the user's request. |data_fate| controls whether the sync
-  // engine should clear its data directory when it shuts down. Generally
-  // KEEP_DATA is used when the user just stops sync, and CLEAR_DATA is used
-  // when they sign out of the profile entirely.
-  virtual void RequestStop(SyncStopDataFate data_fate) = 0;
-
-  // The user requests that sync start. This only actually starts sync if
-  // IsSyncAllowed is true and the user is signed in. Once sync starts,
-  // other things such as IsFirstSetupComplete being false can still prevent
-  // it from moving into the "active" state.
-  virtual void RequestStart() = 0;
-
-  // Returns the set of types which are preferred for enabling. This is a
-  // superset of the active types (see GetActiveDataTypes()).
-  virtual ModelTypeSet GetPreferredDataTypes() const = 0;
-
-  // Called when a user chooses which data types to sync. |sync_everything|
-  // represents whether they chose the "keep everything synced" option; if
-  // true, |chosen_types| will be ignored and all data types will be synced.
-  // |sync_everything| means "sync all current and future data types."
-  // |chosen_types| must be a subset of UserSelectableTypes().
-  virtual void OnUserChoseDatatypes(bool sync_everything,
-                                    ModelTypeSet chosen_types) = 0;
-
-  // Called whe Sync has been setup by the user and can be started.
-  virtual void SetFirstSetupComplete() = 0;
-
-  // Returns true if initial sync setup is in progress (does not return true
-  // if the user is customizing sync after already completing setup once).
-  // SyncService uses this to determine if it's OK to start syncing, or if the
-  // user is still setting up the initial sync configuration.
-  bool IsFirstSetupInProgress() const;
-
-  // Called by the UI to notify the SyncService that UI is visible so it will
-  // not start syncing. This tells sync whether it's safe to start downloading
-  // data types yet (we don't start syncing until after sync setup is complete).
-  // The UI calls this and holds onto the instance for as long as any part of
-  // the signin wizard is displayed (even just the login UI).
-  // When the last outstanding handle is deleted, this kicks off the sync engine
-  // to ensure that data download starts. In this case,
-  // |ReconfigureDatatypeManager| will get triggered.
-  virtual std::unique_ptr<SyncSetupInProgressHandle>
-  GetSetupInProgressHandle() = 0;
-
-  virtual bool IsSetupInProgress() const = 0;
-
+  // The last authentication error that was encountered by the SyncService. This
+  // error can be either from Chrome's identity system (e.g. while trying to get
+  // an access token), or from the Sync server. It gets cleared when the error
+  // is resolved.
   virtual const GoogleServiceAuthError& GetAuthError() const = 0;
 
+  //////////////////////////////////////////////////////////////////////////////
+  // DERIVED STATE ACCESS
+  //////////////////////////////////////////////////////////////////////////////
+
   // DEPRECATED! Use GetDisableReasons/HasDisableReason instead.
   // Equivalent to "HasDisableReason(DISABLE_REASON_UNRECOVERABLE_ERROR)".
   bool HasUnrecoverableError() const;
@@ -270,9 +186,127 @@
   // GetState() == State::CONFIGURING || GetState() == State::ACTIVE".
   bool IsEngineInitialized() const;
 
-  // Return the active OpenTabsUIDelegate. If open/proxy tabs is not enabled or
-  // not currently syncing, returns nullptr.
-  virtual sync_sessions::OpenTabsUIDelegate* GetOpenTabsUIDelegate() = 0;
+  // DEPRECATED! Use GetDisableReasons/HasDisableReason instead.
+  // Equivalent to "!HasDisableReason(DISABLE_REASON_PLATFORM_OVERRIDE) &&
+  // !HasDisableReason(DISABLE_REASON_ENTERPRISE_POLICY)".
+  bool IsSyncAllowed() const;
+
+  // DEPRECATED! Use GetDisableReasons/HasDisableReason instead.
+  // Equivalent to having no disable reasons, i.e.
+  // "GetDisableReasons() == DISABLE_REASON_NONE".
+  bool CanSyncStart() const;
+
+  // DEPRECATED! Use GetState instead. Equivalent to
+  // "GetState() == State::CONFIGURING || GetState() == State::ACTIVE".
+  // To see which datatypes are actually syncing, see GetActiveDataTypes().
+  bool IsSyncActive() const;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // INITIAL SETUP / CONSENT
+  //////////////////////////////////////////////////////////////////////////////
+
+  // Returns true if initial sync setup is in progress (does not return true
+  // if the user is customizing sync after already completing setup once).
+  // SyncService uses this to determine if it's OK to start syncing, or if the
+  // user is still setting up the initial sync configuration.
+  bool IsFirstSetupInProgress() const;
+
+  // Whether the user has completed the initial Sync setup. This does not mean
+  // that sync is currently running (due to delayed startup, unrecoverable
+  // errors, or shutdown). If you want to know whether Sync is actually running,
+  // use GetState instead.
+  virtual bool IsFirstSetupComplete() const = 0;
+
+  // Called when Sync has been setup by the user and can be started.
+  virtual void SetFirstSetupComplete() = 0;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // SETUP-IN-PROGRESS HANDLING
+  //////////////////////////////////////////////////////////////////////////////
+
+  // Called by the UI to notify the SyncService that UI is visible so it will
+  // not start syncing. This tells sync whether it's safe to start downloading
+  // data types yet (we don't start syncing until after sync setup is complete).
+  // The UI calls this and holds onto the instance for as long as any part of
+  // the signin wizard is displayed (even just the login UI).
+  // When the last outstanding handle is deleted, this kicks off the sync engine
+  // to ensure that data download starts.
+  virtual std::unique_ptr<SyncSetupInProgressHandle>
+  GetSetupInProgressHandle() = 0;
+
+  // Whether a Sync setup is currently in progress, i.e. a setup UI is being
+  // shown.
+  virtual bool IsSetupInProgress() const = 0;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // DATA TYPE STATE
+  //////////////////////////////////////////////////////////////////////////////
+
+  // Returns the set of types which are preferred for enabling. This is a
+  // superset of the active types (see GetActiveDataTypes()).
+  virtual ModelTypeSet GetPreferredDataTypes() const = 0;
+
+  // Get the set of current active data types (those chosen or configured by
+  // the user which have not also encountered a runtime error).
+  // Note that if the Sync engine is in the middle of a configuration, this
+  // will the the empty set. Once the configuration completes the set will
+  // be updated.
+  virtual ModelTypeSet GetActiveDataTypes() const = 0;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // ACTIONS / STATE CHANGE REQUESTS
+  //////////////////////////////////////////////////////////////////////////////
+
+  // The user requests that sync start. This only actually starts sync if
+  // IsSyncAllowed is true and the user is signed in. Once sync starts,
+  // other things such as IsFirstSetupComplete being false can still prevent
+  // it from moving into the "active" state.
+  virtual void RequestStart() = 0;
+
+  // Stops sync at the user's request. |data_fate| controls whether the sync
+  // engine should clear its data directory when it shuts down. Generally
+  // KEEP_DATA is used when the user just stops sync, and CLEAR_DATA is used
+  // when they sign out of the profile entirely.
+  virtual void RequestStop(SyncStopDataFate data_fate) = 0;
+
+  // Called when a datatype (SyncableService) has a need for sync to start
+  // ASAP, presumably because a local change event has occurred but we're
+  // still in deferred start mode, meaning the SyncableService hasn't been
+  // told to MergeDataAndStartSyncing yet.
+  virtual void OnDataTypeRequestsSyncStartup(ModelType type) = 0;
+
+  // Called when a user chooses which data types to sync. |sync_everything|
+  // represents whether they chose the "keep everything synced" option; if
+  // true, |chosen_types| will be ignored and all data types will be synced.
+  // |sync_everything| means "sync all current and future data types."
+  // |chosen_types| must be a subset of UserSelectableTypes().
+  virtual void OnUserChoseDatatypes(bool sync_everything,
+                                    ModelTypeSet chosen_types) = 0;
+
+  // Triggers a GetUpdates call for the specified |types|, pulling any new data
+  // from the sync server. Used by tests and debug UI (sync-internals).
+  virtual void TriggerRefresh(const ModelTypeSet& types) = 0;
+
+  // Attempts to re-enable a data type that is currently disabled due to a
+  // data type error or an unready error. Note, this does not change the
+  // preferred state of a datatype, and is not persisted across restarts.
+  virtual void ReenableDatatype(ModelType type) = 0;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // OBSERVERS
+  //////////////////////////////////////////////////////////////////////////////
+
+  // Adds/removes an observer. SyncService does not take ownership of the
+  // observer.
+  virtual void AddObserver(SyncServiceObserver* observer) = 0;
+  virtual void RemoveObserver(SyncServiceObserver* observer) = 0;
+
+  // Returns true if |observer| has already been added as an observer.
+  virtual bool HasObserver(const SyncServiceObserver* observer) const = 0;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // ENCRYPTION
+  //////////////////////////////////////////////////////////////////////////////
 
   // Returns true if OnPassphraseRequired has been called for decryption and
   // we have an encrypted data type enabled.
@@ -313,21 +347,33 @@
   // to ensure thread safety.
   virtual bool IsCryptographerReady(const BaseTransaction* trans) const = 0;
 
+  //////////////////////////////////////////////////////////////////////////////
+  // ACCESS TO INNER OBJECTS
+  //////////////////////////////////////////////////////////////////////////////
+
+  // TODO(crbug.com/865936): Move this down into ProfileSyncService.
+  virtual SyncClient* GetSyncClient() const = 0;
+
+  // Return the active OpenTabsUIDelegate. If open/proxy tabs is not enabled or
+  // not currently syncing, returns nullptr.
+  virtual sync_sessions::OpenTabsUIDelegate* GetOpenTabsUIDelegate() = 0;
+
   // TODO(akalin): This is called mostly by ModelAssociators and
   // tests.  Figure out how to pass the handle to the ModelAssociators
   // directly, figure out how to expose this to tests, and remove this
   // function.
   virtual UserShare* GetUserShare() const = 0;
 
-  // Returns DeviceInfo provider for the local device.
+  // TODO(mastiz): Get rid of this, e.g. by moving it to SyncClient.
   virtual const LocalDeviceInfoProvider* GetLocalDeviceInfoProvider() const = 0;
 
-  // Called to re-enable a type disabled by DisableDatatype(..). Note, this does
-  // not change the preferred state of a datatype, and is not persisted across
-  // restarts.
-  virtual void ReenableDatatype(ModelType type) = 0;
+  // TODO(crbug.com/865936): Move this down into ProfileSyncService.
+  virtual GlobalIdMapper* GetGlobalIdMapper() const = 0;
 
-  // Return sync token status.
+  //////////////////////////////////////////////////////////////////////////////
+  // DETAILED STATE FOR DEBUG UI
+  //////////////////////////////////////////////////////////////////////////////
+
   virtual SyncTokenStatus GetSyncTokenStatus() const = 0;
 
   // Initializes a struct of status indicators with data from the engine.
@@ -335,7 +381,6 @@
   // the struct will be filled with default data.
   virtual bool QueryDetailedSyncStatus(SyncStatus* result) const = 0;
 
-  // Returns the last synced time.
   virtual base::Time GetLastSyncedTime() const = 0;
 
   virtual SyncCycleSnapshot GetLastCycleSnapshot() const = 0;
@@ -377,11 +422,6 @@
       const base::Callback<void(std::unique_ptr<base::ListValue>)>&
           callback) = 0;
 
-  // Information about the currently signed in user.
-  virtual AccountInfo GetAuthenticatedAccountInfo() const = 0;
-
-  virtual GlobalIdMapper* GetGlobalIdMapper() const = 0;
-
  protected:
   SyncService() {}
 
diff --git a/components/vector_icons/help_outline.icon b/components/vector_icons/help_outline.icon
index a6148ffa..ed491c6 100644
--- a/components/vector_icons/help_outline.icon
+++ b/components/vector_icons/help_outline.icon
@@ -31,3 +31,33 @@
 R_CUBIC_TO, 0, -2.25f, 3, -2.5f, 3, -5,
 R_CUBIC_TO, 0, -2.21f, -1.79f, -4, -4, -4,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
+R_CUBIC_TO, 0, 4.42f, -3.58f, 8, -8, 8,
+R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
+R_CUBIC_TO, 0, -4.42f, 3.58f, -8, 8, -8,
+CLOSE,
+R_MOVE_TO, 0, 14,
+R_CUBIC_TO, 3.31f, 0, 6, -2.69f, 6, -6,
+R_CUBIC_TO, 0, -3.31f, -2.69f, -6, -6, -6,
+R_CUBIC_TO, -3.31f, 0, -6, 2.69f, -6, 6,
+R_CUBIC_TO, 0, 3.31f, 2.69f, 6, 6, 6,
+CLOSE,
+R_MOVE_TO, -0.74f, -1.4f,
+R_V_LINE_TO, -1.39f,
+R_H_LINE_TO, 1.5f,
+R_V_LINE_TO, 1.39f,
+H_LINE_TO, 9.26f,
+CLOSE,
+MOVE_TO, 10, 5.6f,
+R_CUBIC_TO, 1.66f, 0, 3, 1.25f, 3, 2.8f,
+R_CUBIC_TO, 0, 1.75f, -2.24f, 1.88f, -2.24f, 3.46f,
+H_LINE_TO, 9.26f,
+CUBIC_TO, 9.26f, 9.58f, 11.5f, 9.8f, 11.5f, 8.4f,
+R_CUBIC_TO, 0, -0.77f, -0.67f, -1.4f, -1.5f, -1.4f,
+R_CUBIC_TO, -0.83f, 0, -1.5f, 0.63f, -1.5f, 1.4f,
+H_LINE_TO, 7,
+R_CUBIC_TO, 0, -1.55f, 1.34f, -2.8f, 3, -2.8f,
+CLOSE
diff --git a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
index 84ec47a..ed5fb413 100644
--- a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -31,6 +31,7 @@
 #include "services/network/public/mojom/request_context_frame_type.mojom.h"
 #include "storage/browser/blob/blob_storage_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
 
 namespace content {
@@ -60,6 +61,11 @@
       : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
 
   void SetUp() override {
+    // ServiceWorkerContextRequestHandler is a non-S13nServiceWorker specific
+    // class and we don't use it when S13nServiceWorker is enabled.
+    scoped_feature_list_.InitAndDisableFeature(
+        blink::features::kServiceWorkerServicification);
+
     helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
     context()->storage()->LazyInitializeForTest(base::DoNothing());
     base::RunLoop().RunUntilIdle();
@@ -160,6 +166,9 @@
   }
 
  protected:
+  // |scoped_feature_list_| must be before |thread_bundle_|.
+  // See comments in ServiceWorkerProviderHostTest.
+  base::test::ScopedFeatureList scoped_feature_list_;
   TestBrowserThreadBundle browser_thread_bundle_;
   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
   scoped_refptr<ServiceWorkerRegistration> registration_;
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
index bbaeb41..a17855cd 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -321,6 +321,8 @@
 
   // Also prevent a registration from claiming this host while it's not
   // yet execution ready.
+  // TODO(falken): Make an RAII helper instead of all these explcit allow and
+  // disallow calls.
   provider_host_->SetAllowAssociation(false);
 
   stripped_url_ = net::SimplifyUrlForRequest(url);
@@ -339,11 +341,9 @@
   if (JobWasCanceled())
     return;
 
-  const bool need_to_update = !force_update_started_ && registration &&
-                              context_->force_update_on_page_load();
-
-  if (provider_host_ && !need_to_update)
+  if (provider_host_)
     provider_host_->SetAllowAssociation(true);
+
   if (status != blink::ServiceWorkerStatusCode::kOk) {
     url_job_->FallbackToNetwork();
     TRACE_EVENT_ASYNC_END1(
@@ -376,11 +376,10 @@
           registration->pattern(), provider_host_->topmost_frame_url(),
           resource_context_, provider_host_->web_contents_getter())) {
     url_job_->FallbackToNetwork();
-    TRACE_EVENT_ASYNC_END2(
+    TRACE_EVENT_ASYNC_END1(
         "ServiceWorker",
         "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
-        url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
-        "Info", "ServiceWorker is blocked");
+        url_job_.get(), "Info", "ServiceWorker is blocked");
     return;
   }
 
@@ -395,8 +394,11 @@
     return;
   }
 
+  const bool need_to_update = !force_update_started_ && registration &&
+                              context_->force_update_on_page_load();
   if (need_to_update) {
     force_update_started_ = true;
+    provider_host_->SetAllowAssociation(false);
     context_->UpdateServiceWorker(
         registration.get(), true /* force_bypass_cache */,
         true /* skip_script_comparison */,
@@ -413,43 +415,112 @@
 
   scoped_refptr<ServiceWorkerVersion> active_version =
       registration->active_version();
+  if (!active_version) {
+    // Although there is no active version, a registration exists, so associate
+    // it, so it can be used for .ready.
+    // TODO(falken): There's no need to associate the registration just for
+    // .ready. Change this to AddMatchingRegistration instead, and call it
+    // unconditionally if there is a |provider_host_|.
+    provider_host_->AssociateRegistration(registration.get(),
+                                          false /* notify_controllerchange */);
 
-  // Wait until it's activated before firing fetch events.
-  if (active_version.get() &&
-      active_version->status() == ServiceWorkerVersion::ACTIVATING) {
-    provider_host_->SetAllowAssociation(false);
-    active_version->RegisterStatusChangeCallback(base::BindOnce(
-        &self::OnVersionStatusChanged, weak_factory_.GetWeakPtr(), registration,
-        active_version));
-    TRACE_EVENT_ASYNC_END2(
+    url_job_->FallbackToNetwork();
+    TRACE_EVENT_ASYNC_END1(
         "ServiceWorker",
         "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
-        url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
-        "Info", "Wait until finished SW activation");
+        url_job_.get(), "Info",
+        "No active version, so falling back to network");
     return;
   }
 
-  // TODO(falken): Factor out the rest of this function and
-  // OnVersionStatusChanged into the same function.
+  // TODO(falken): Change these to DCHECK if it holds.
+  CHECK(active_version->status() == ServiceWorkerVersion::ACTIVATING ||
+        active_version->status() == ServiceWorkerVersion::ACTIVATED);
 
-  // A registration exists, so associate it. Note that the controller is only
-  // set if there's an active version. If there's no active version, we should
-  // still associate so the provider host can use .ready.
-  provider_host_->AssociateRegistration(registration.get(),
-                                        false /* notify_controllerchange */);
+  // Wait until it's activated before firing fetch events.
+  if (active_version->status() == ServiceWorkerVersion::ACTIVATING) {
+    provider_host_->SetAllowAssociation(false);
+    registration->active_version()->RegisterStatusChangeCallback(base::BindOnce(
+        &ServiceWorkerControlleeRequestHandler::
+            ContinueWithInScopeMainResourceRequest,
+        weak_factory_.GetWeakPtr(), registration, active_version));
+    TRACE_EVENT_ASYNC_END1(
+        "ServiceWorker",
+        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+        url_job_.get(), "Info", "Wait until finished SW activation");
+    return;
+  }
 
-  if (!active_version.get() ||
-      active_version->status() != ServiceWorkerVersion::ACTIVATED) {
+  ContinueWithInScopeMainResourceRequest(std::move(registration),
+                                         std::move(active_version));
+}
+
+void ServiceWorkerControlleeRequestHandler::
+    ContinueWithInScopeMainResourceRequest(
+        scoped_refptr<ServiceWorkerRegistration> registration,
+        scoped_refptr<ServiceWorkerVersion> active_version) {
+  if (provider_host_)
+    provider_host_->SetAllowAssociation(true);
+
+  // The job may have been canceled before this was invoked. In that
+  // case, |url_job_| can't be used, so return.
+  if (JobWasCanceled()) {
+    TRACE_EVENT_ASYNC_END1(
+        "ServiceWorker",
+        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+        url_job_.get(), "Info", "The job was canceled");
+    return;
+  }
+
+  if (!provider_host_) {
+    url_job_->FallbackToNetwork();
+    TRACE_EVENT_ASYNC_END1(
+        "ServiceWorker",
+        "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+        url_job_.get(), "Info",
+        "The provider host is gone, so falling back to network");
+    return;
+  }
+
+  if (active_version->status() != ServiceWorkerVersion::ACTIVATED) {
+    // TODO(falken): Clean this up and clarify in what cases we come here. I
+    // guess it's:
+    // - strange system error cases where promoting from ACTIVATING to ACTIVATED
+    //   failed (shouldn't happen)
+    // - something calling Doom(), etc, making the active_version REDUNDANT
+    // - a version called skipWaiting() during activation so the expected
+    //   version is no longer the active one (shouldn't happen: skipWaiting()
+    //   waits for the active version to finish activating).
+    // In most cases, it sounds like falling back to network would not be right,
+    // since it's still in-scope. We probably should do:
+    //   1) If the provider host has an active version that is ACTIVATED, just
+    //      use that, even if it wasn't the expected one.
+    //   2) If the provider host has an active version that is not ACTIVATED,
+    //      just fail the load. The correct thing is probably to re-try
+    //      activating that version, but there's a risk of an infinite loop of
+    //      retries.
+    //   3) If the provider host does not have an active version, just fail the
+    //      load.
     url_job_->FallbackToNetwork();
     TRACE_EVENT_ASYNC_END2(
         "ServiceWorker",
         "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
-        url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
-        "Info",
-        "ServiceWorkerVersion is not available, so falling back to network");
+        url_job_.get(), "Info",
+        "The expected active version is not ACTIVATED, so falling back to "
+        "network",
+        "Status",
+        ServiceWorkerVersion::VersionStatusToString(active_version->status()));
     return;
   }
 
+  provider_host_->AssociateRegistration(registration.get(),
+                                        false /* notify_controllerchange */);
+
+  // TODO(falken): Change these to DCHECK if it holds, or else figure out
+  // how this happens.
+  CHECK_EQ(active_version, registration->active_version());
+  CHECK_EQ(active_version, provider_host_->controller());
+
   DCHECK_NE(active_version->fetch_handler_existence(),
             ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
   ServiceWorkerMetrics::CountControlledPageLoad(
@@ -461,47 +532,14 @@
   }
   bool is_forwarded =
       MaybeForwardToServiceWorker(url_job_.get(), active_version.get());
-
-  TRACE_EVENT_ASYNC_END2(
+  TRACE_EVENT_ASYNC_END1(
       "ServiceWorker",
       "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
-      url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
-      "Info",
+      url_job_.get(), "Info",
       (is_forwarded) ? "Forwarded to the ServiceWorker"
                      : "Skipped the ServiceWorker which has no fetch handler");
 }
 
-void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
-    scoped_refptr<ServiceWorkerRegistration> registration,
-    scoped_refptr<ServiceWorkerVersion> version) {
-  // The job may have been canceled before this was invoked.
-  if (JobWasCanceled())
-    return;
-
-  if (provider_host_)
-    provider_host_->SetAllowAssociation(true);
-  if (version != registration->active_version() ||
-      version->status() != ServiceWorkerVersion::ACTIVATED ||
-      !provider_host_) {
-    url_job_->FallbackToNetwork();
-    return;
-  }
-
-  DCHECK_NE(version->fetch_handler_existence(),
-            ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
-  ServiceWorkerMetrics::CountControlledPageLoad(
-      version->site_for_uma(), stripped_url_, is_main_frame_load_);
-
-  provider_host_->AssociateRegistration(registration.get(),
-                                        false /* notify_controllerchange */);
-
-  if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
-      IsResourceTypeFrame(resource_type_)) {
-    provider_host_->AddServiceWorkerToUpdate(version);
-  }
-  MaybeForwardToServiceWorker(url_job_.get(), version.get());
-}
-
 void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
     const scoped_refptr<ServiceWorkerRegistration>& original_registration,
     blink::ServiceWorkerStatusCode status,
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.h b/content/browser/service_worker/service_worker_controllee_request_handler.h
index ed148be..ac25b8d 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.h
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -96,7 +96,7 @@
   void DidLookupRegistrationForMainResource(
       blink::ServiceWorkerStatusCode status,
       scoped_refptr<ServiceWorkerRegistration> registration);
-  void OnVersionStatusChanged(
+  void ContinueWithInScopeMainResourceRequest(
       scoped_refptr<ServiceWorkerRegistration> registration,
       scoped_refptr<ServiceWorkerVersion> version);
 
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index 5974fee4..c1500a2 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -139,6 +139,11 @@
 
   ServiceWorkerContextCore* context() const { return helper_->context(); }
 
+  void SetProviderHostIsSecure(ServiceWorkerProviderHost* host,
+                               bool is_secure) {
+    host->info_->is_parent_frame_secure = is_secure;
+  }
+
  protected:
   TestBrowserThreadBundle browser_thread_bundle_;
   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
@@ -197,6 +202,34 @@
   SetBrowserClientForTesting(old_browser_client);
 }
 
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, InsecureContext) {
+  // Store an activated worker.
+  version_->set_fetch_handler_existence(
+      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+  registration_->SetActiveVersion(version_);
+  context()->storage()->StoreRegistration(registration_.get(), version_.get(),
+                                          base::DoNothing());
+  base::RunLoop().RunUntilIdle();
+
+  SetProviderHostIsSecure(provider_host_.get(), false);
+
+  // Conduct a main resource load.
+  ServiceWorkerRequestTestResources test_resources(
+      this, GURL("https://host/scope/doc"), RESOURCE_TYPE_MAIN_FRAME);
+  ServiceWorkerURLRequestJob* sw_job = test_resources.MaybeCreateJob();
+
+  EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
+  EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+  EXPECT_FALSE(version_->HasControllee());
+  base::RunLoop().RunUntilIdle();
+
+  // Verify we did not use the worker.
+  EXPECT_TRUE(sw_job->ShouldFallbackToNetwork());
+  EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+  EXPECT_FALSE(version_->HasControllee());
+}
+
 TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
   // Store a registration that is installed but not activated yet.
   version_->set_fetch_handler_existence(
diff --git a/content/browser/service_worker/service_worker_object_host.cc b/content/browser/service_worker/service_worker_object_host.cc
index 0af7708f..49b03786 100644
--- a/content/browser/service_worker/service_worker_object_host.cc
+++ b/content/browser/service_worker/service_worker_object_host.cc
@@ -18,8 +18,6 @@
 
 namespace {
 
-const int kMaxDebugLogSize = 256;
-
 using StatusCallback = base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
 using SetExtendableMessageEventSourceCallback =
     base::OnceCallback<bool(mojom::ExtendableMessageEventPtr*)>;
@@ -171,39 +169,21 @@
     : context_(context),
       provider_host_(provider_host),
       provider_origin_(url::Origin::Create(provider_host->document_url())),
-      provider_type_(provider_host->provider_type()),
       version_(std::move(version)),
       weak_ptr_factory_(this) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(context_ && provider_host_ && version_);
   DCHECK(context_->GetLiveRegistration(version_->registration_id()));
   version_->AddObserver(this);
-  AddToDebugLog(base::StringPrintf("ObjCtor:prov=%p,type=%d,this=%p",
-                                   provider_host_, provider_type_, this));
   bindings_.set_connection_error_handler(base::BindRepeating(
       &ServiceWorkerObjectHost::OnConnectionError, base::Unretained(this)));
 }
 
 ServiceWorkerObjectHost::~ServiceWorkerObjectHost() {
-  // TODO(crbug.com/838410): These CHECKs are temporary debugging for the linked
-  // bug.
-  AddToDebugLog(base::StringPrintf("ObjDtor:prov=%p,type=%d,this=%p",
-                                   provider_host_, provider_type_, this));
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (in_dtor_) {
-    CrashOnDoubleDelete();
-    return;
-  }
-  in_dtor_ = true;
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   version_->RemoveObserver(this);
 }
 
-void ServiceWorkerObjectHost::CrashOnDoubleDelete() {
-  std::string log = ServiceWorkerObjectHost::GetDebugLogString();
-  DEBUG_ALIAS_FOR_CSTR(debug_log, log.c_str(), 2048);
-  CHECK(false);
-}
-
 void ServiceWorkerObjectHost::OnVersionStateChanged(
     ServiceWorkerVersion* version) {
   DCHECK(version);
@@ -313,34 +293,7 @@
   if (!bindings_.empty())
     return;
   // Will destroy |this|.
-  AddToDebugLog(base::StringPrintf("HostErr:this=%p", this));
   provider_host_->RemoveServiceWorkerObjectHost(version_->version_id());
 }
 
-// static
-ServiceWorkerObjectHost::DebugLog*
-ServiceWorkerObjectHost::GetDebugLogInstance() {
-  static base::NoDestructor<DebugLog> g_log;
-  return g_log.get();
-}
-
-// static
-void ServiceWorkerObjectHost::AddToDebugLog(const std::string& event) {
-  DebugLog* log = GetDebugLogInstance();
-  log->push_back(event);
-  if (log->size() > kMaxDebugLogSize)
-    log->pop_front();
-}
-
-// static
-std::string ServiceWorkerObjectHost::GetDebugLogString() {
-  DebugLog* log = GetDebugLogInstance();
-  std::string result;
-  // Traverse from the end so if the string gets truncated we still
-  // have the most recent events.
-  for (auto iter = log->rbegin(); iter != log->rend(); ++iter)
-    result += *iter + "\n";
-  return result;
-}
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_object_host.h b/content/browser/service_worker/service_worker_object_host.h
index 4d512c7..0c43f3a 100644
--- a/content/browser/service_worker/service_worker_object_host.h
+++ b/content/browser/service_worker/service_worker_object_host.h
@@ -7,11 +7,9 @@
 
 #include <memory>
 
-#include "base/containers/circular_deque.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/no_destructor.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_types.h"
@@ -48,8 +46,6 @@
                           scoped_refptr<ServiceWorkerVersion> version);
   ~ServiceWorkerObjectHost() override;
 
-  void CrashOnDoubleDelete();
-
   // ServiceWorkerVersion::Observer overrides.
   void OnVersionStateChanged(ServiceWorkerVersion* version) override;
 
@@ -86,12 +82,6 @@
 
   base::WeakPtr<ServiceWorkerObjectHost> AsWeakPtr();
 
-  // TODO(crbug.com/838410): Instrumentation for the linked bug.
-  using DebugLog = base::circular_deque<std::string>;
-  static DebugLog* GetDebugLogInstance();
-  static void AddToDebugLog(const std::string& event);
-  static std::string GetDebugLogString();
-
  private:
   friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
 
@@ -118,7 +108,6 @@
   // don't expect that context to change origins and still hold on to the
   // object.
   const url::Origin provider_origin_;
-  const blink::mojom::ServiceWorkerProviderType provider_type_;
   scoped_refptr<ServiceWorkerVersion> version_;
   // Typically both |bindings_| and |remote_objects_| contain only one Mojo
   // connection, corresponding to the content::WebServiceWorkerImpl in the
@@ -131,9 +120,6 @@
   mojo::AssociatedInterfacePtrSet<blink::mojom::ServiceWorkerObject>
       remote_objects_;
 
-  // TODO(crbug.com/838410): Temporary debugging for the linked bug.
-  bool in_dtor_ = false;
-
   base::WeakPtrFactory<ServiceWorkerObjectHost> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerObjectHost);
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 4f0dd99d..7064702 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -297,18 +297,7 @@
 }
 
 ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
-  // TODO(crbug.com/838410): The CHECKs are temporary debugging for the linked
-  // bug.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  CHECK(!in_dtor_);
-  in_dtor_ = true;
-
-  if (!service_worker_object_hosts_.empty()) {
-    // Just log when hosts isn't empty. It'd be too noisy to record all provider
-    // ctor/dtor otherwise.
-    ServiceWorkerObjectHost::AddToDebugLog(
-        base::StringPrintf("ProvDtor:prov=%p,type=%d", this, info_->type));
-  }
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (context_)
     context_->UnregisterProviderHostByClientID(client_uuid_);
@@ -319,16 +308,6 @@
   // TODO(falken): Use ScopedObserver instead of this explicit call.
   RemoveAllMatchingRegistrations();
 
-  // Explicitly destroy the ServiceWorkerObjectHosts and
-  // ServiceWorkerRegistrationObjectHosts owned by |this|. Otherwise, this
-  // destructor can trigger their Mojo connection error handlers, which would
-  // call back into halfway destroyed |this|. This is because they are
-  // associated with the ServiceWorker interface, which can be destroyed while
-  // in this destructor (|running_hosted_version_|'s |event_dispatcher_|). See
-  // https://crbug.com/854993.
-  service_worker_object_hosts_.clear();
-  registration_object_hosts_.clear();
-
   // This host may be destroyed before it received the anticipated
   // HintToUpdateServiceWorker IPC from the renderer. This can occur on
   // navigation failure or if the frame closed soon after navigation. The
@@ -583,8 +562,8 @@
 
 void ServiceWorkerProviderHost::RemoveServiceWorkerObjectHost(
     int64_t version_id) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  CHECK(base::ContainsKey(service_worker_object_hosts_, version_id));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(base::ContainsKey(service_worker_object_hosts_, version_id));
   service_worker_object_hosts_.erase(version_id);
 }
 
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 1223abf..dba100e9c 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -467,6 +467,8 @@
   friend class ServiceWorkerProviderHostTest;
   friend class ServiceWorkerWriteToCacheJobTest;
   friend class ServiceWorkerContextRequestHandlerTest;
+  friend class service_worker_controllee_request_handler_unittest::
+      ServiceWorkerControlleeRequestHandlerTest;
   friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest, Update_SameScript);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
@@ -691,9 +693,6 @@
   // redirects.
   bool is_execution_ready_ = false;
 
-  // TODO(crbug.com/838410): Temporary debugging for the linked bug.
-  bool in_dtor_ = false;
-
   // For service worker clients. The service workers in the chain of redirects
   // during the main resource request for this client. These workers should be
   // updated "soon". See AddServiceWorkerToUpdate() documentation.
diff --git a/content/browser/service_worker/service_worker_script_loader_factory.h b/content/browser/service_worker/service_worker_script_loader_factory.h
index efc08ff..2eb05ea 100644
--- a/content/browser/service_worker/service_worker_script_loader_factory.h
+++ b/content/browser/service_worker/service_worker_script_loader_factory.h
@@ -6,6 +6,7 @@
 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_LOADER_FACTORY_H_
 
 #include "base/macros.h"
+#include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
@@ -30,7 +31,7 @@
 //
 // This factory creates either a ServiceWorkerNewScriptLoader or a
 // ServiceWorkerInstalledScriptLoader to load a script.
-class ServiceWorkerScriptLoaderFactory
+class CONTENT_EXPORT ServiceWorkerScriptLoaderFactory
     : public network::mojom::URLLoaderFactory {
  public:
   // |loader_factory| is used to load scripts. Typically
diff --git a/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc b/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
new file mode 100644
index 0000000..f623354
--- /dev/null
+++ b/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
@@ -0,0 +1,180 @@
+// 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.
+
+#include "content/browser/service_worker/service_worker_script_loader_factory.h"
+
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace content {
+
+namespace {
+
+// A URLLoaderFactory that returns 200 OK with an empty javascript to any
+// request.
+// TODO(bashi): Avoid duplicated MockNetworkURLLoaderFactory. This is almost the
+// same as EmbeddedWorkerTestHelper::MockNetworkURLLoaderFactory.
+class MockNetworkURLLoaderFactory final
+    : public network::mojom::URLLoaderFactory {
+ public:
+  MockNetworkURLLoaderFactory() = default;
+
+  // network::mojom::URLLoaderFactory implementation.
+  void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
+                            int32_t routing_id,
+                            int32_t request_id,
+                            uint32_t options,
+                            const network::ResourceRequest& url_request,
+                            network::mojom::URLLoaderClientPtr client,
+                            const net::MutableNetworkTrafficAnnotationTag&
+                                traffic_annotation) override {
+    const std::string headers =
+        "HTTP/1.1 200 OK\n"
+        "Content-Type: application/javascript\n\n";
+    net::HttpResponseInfo info;
+    info.headers = new net::HttpResponseHeaders(
+        net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
+    network::ResourceResponseHead response;
+    response.headers = info.headers;
+    response.headers->GetMimeType(&response.mime_type);
+    client->OnReceiveResponse(response);
+
+    const std::string body = "/*this body came from the network*/";
+    uint32_t bytes_written = body.size();
+    mojo::DataPipe data_pipe;
+    data_pipe.producer_handle->WriteData(body.data(), &bytes_written,
+                                         MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
+    client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+
+    network::URLLoaderCompletionStatus status;
+    status.error_code = net::OK;
+    client->OnComplete(status);
+  }
+
+  void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+    bindings_.AddBinding(this, std::move(request));
+  }
+
+ private:
+  mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+  DISALLOW_COPY_AND_ASSIGN(MockNetworkURLLoaderFactory);
+};
+
+}  // namespace
+
+class ServiceWorkerScriptLoaderFactoryTest : public testing::Test {
+ public:
+  ServiceWorkerScriptLoaderFactoryTest()
+      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+  ~ServiceWorkerScriptLoaderFactoryTest() override = default;
+
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        blink::features::kServiceWorkerServicification);
+
+    helper_ = std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath());
+    ServiceWorkerContextCore* context = helper_->context();
+    context->storage()->LazyInitializeForTest(base::DoNothing());
+    base::RunLoop().RunUntilIdle();
+
+    scope_ = GURL("https://host/scope");
+
+    blink::mojom::ServiceWorkerRegistrationOptions options;
+    options.scope = scope_;
+    registration_ = base::MakeRefCounted<ServiceWorkerRegistration>(
+        options, 1L /* registration_id */, context->AsWeakPtr());
+    version_ = base::MakeRefCounted<ServiceWorkerVersion>(
+        registration_.get(), GURL("https://host/script.js"),
+        context->storage()->NewVersionId(), context->AsWeakPtr());
+
+    std::unique_ptr<ServiceWorkerProviderHost> provider_host =
+        CreateProviderHostForServiceWorkerContext(
+            helper_->mock_render_process_id(),
+            true /* is_parent_frame_secure */, version_.get(),
+            context->AsWeakPtr(), &remote_endpoint_);
+    provider_host_ = provider_host->AsWeakPtr();
+    context->AddProviderHost(std::move(provider_host));
+
+    network_loader_factory_ = std::make_unique<MockNetworkURLLoaderFactory>();
+    helper_->SetNetworkFactory(network_loader_factory_.get());
+
+    factory_ = std::make_unique<ServiceWorkerScriptLoaderFactory>(
+        helper_->context()->AsWeakPtr(), provider_host_,
+        helper_->url_loader_factory_getter()->GetNetworkFactory());
+  }
+
+ protected:
+  network::mojom::URLLoaderPtr CreateTestLoaderAndStart(
+      network::TestURLLoaderClient* client) {
+    network::mojom::URLLoaderPtr loader;
+    network::ResourceRequest resource_request;
+    resource_request.url = scope_;
+    resource_request.resource_type = RESOURCE_TYPE_SERVICE_WORKER;
+    factory_->CreateLoaderAndStart(
+        mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */,
+        network::mojom::kURLLoadOptionNone, resource_request,
+        client->CreateInterfacePtr(),
+        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+    return loader;
+  }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
+  TestBrowserThreadBundle browser_thread_bundle_;
+  std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+  GURL scope_;
+  scoped_refptr<ServiceWorkerRegistration> registration_;
+  scoped_refptr<ServiceWorkerVersion> version_;
+  base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+  ServiceWorkerRemoteProviderEndpoint remote_endpoint_;
+  std::unique_ptr<MockNetworkURLLoaderFactory> network_loader_factory_;
+  std::unique_ptr<ServiceWorkerScriptLoaderFactory> factory_;
+};
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, Success) {
+  network::TestURLLoaderClient client;
+  network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+  client.RunUntilComplete();
+  EXPECT_EQ(net::OK, client.completion_status().error_code);
+}
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, Redundant) {
+  version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
+
+  network::TestURLLoaderClient client;
+  network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+  client.RunUntilComplete();
+  EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+}
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, NoProviderHost) {
+  helper_->context()->RemoveProviderHost(helper_->mock_render_process_id(),
+                                         provider_host_->provider_id());
+
+  network::TestURLLoaderClient client;
+  network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+  client.RunUntilComplete();
+  EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+}
+
+TEST_F(ServiceWorkerScriptLoaderFactoryTest, ContextDestroyed) {
+  helper_->ShutdownContext();
+  base::RunLoop().RunUntilIdle();
+
+  network::TestURLLoaderClient client;
+  network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
+  client.RunUntilComplete();
+  EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+}
+
+}  // namespace content
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index ce237a44..a73fa4c9 100644
--- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -60,6 +61,7 @@
 #include "storage/browser/blob/blob_url_request_job_factory.h"
 #include "storage/common/blob_storage/blob_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
@@ -195,6 +197,10 @@
   ~ServiceWorkerURLRequestJobTest() override {}
 
   void SetUp() override {
+    // ServiceWorkerURLRequestJob is a non-S13nServiceWorker specific class
+    // and we don't use it when S13nServiceWorker is enabled.
+    scoped_feature_list_.InitAndDisableFeature(
+        blink::features::kServiceWorkerServicification);
     browser_context_.reset(new TestBrowserContext);
     InitializeResourceContext(browser_context_.get());
   }
@@ -406,6 +412,10 @@
   }
   // ---------------------------------------------------------------------------
 
+  // |scoped_feature_list_| must be before |thread_bundle_|.
+  // See comments in ServiceWorkerProviderHostTest.
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   TestBrowserThreadBundle thread_bundle_;
   base::SimpleTestTickClock tick_clock_;
 
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 2a3f066..4dbeba6 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -113,25 +113,6 @@
   *time = base::TimeTicks();
 }
 
-std::string VersionStatusToString(ServiceWorkerVersion::Status status) {
-  switch (status) {
-    case ServiceWorkerVersion::NEW:
-      return "new";
-    case ServiceWorkerVersion::INSTALLING:
-      return "installing";
-    case ServiceWorkerVersion::INSTALLED:
-      return "installed";
-    case ServiceWorkerVersion::ACTIVATING:
-      return "activating";
-    case ServiceWorkerVersion::ACTIVATED:
-      return "activated";
-    case ServiceWorkerVersion::REDUNDANT:
-      return "redundant";
-  }
-  NOTREACHED() << status;
-  return std::string();
-}
-
 const int kInvalidTraceId = -1;
 
 int NextTraceId() {
@@ -1347,6 +1328,7 @@
     provider_host_by_uuid.second->CountFeature(feature);
 }
 
+// static
 bool ServiceWorkerVersion::IsInstalled(ServiceWorkerVersion::Status status) {
   switch (status) {
     case ServiceWorkerVersion::NEW:
@@ -1362,6 +1344,27 @@
   return false;
 }
 
+// static
+std::string ServiceWorkerVersion::VersionStatusToString(
+    ServiceWorkerVersion::Status status) {
+  switch (status) {
+    case ServiceWorkerVersion::NEW:
+      return "new";
+    case ServiceWorkerVersion::INSTALLING:
+      return "installing";
+    case ServiceWorkerVersion::INSTALLED:
+      return "installed";
+    case ServiceWorkerVersion::ACTIVATING:
+      return "activating";
+    case ServiceWorkerVersion::ACTIVATED:
+      return "activated";
+    case ServiceWorkerVersion::REDUNDANT:
+      return "redundant";
+  }
+  NOTREACHED() << status;
+  return std::string();
+}
+
 void ServiceWorkerVersion::IncrementPendingUpdateHintCount() {
   DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
   pending_update_hint_count_++;
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index ded989a..24d60fb 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -484,6 +484,7 @@
   }
 
   static bool IsInstalled(ServiceWorkerVersion::Status status);
+  static std::string VersionStatusToString(ServiceWorkerVersion::Status status);
 
   // For scheduling Soft Update after main resource requests. We schedule
   // a Soft Update to happen "soon" after each main resource request, attempting
diff --git a/content/common/background_fetch/background_fetch_types.typemap b/content/common/background_fetch/background_fetch_types.typemap
index 57d741b2..491505e 100644
--- a/content/common/background_fetch/background_fetch_types.typemap
+++ b/content/common/background_fetch/background_fetch_types.typemap
@@ -15,5 +15,4 @@
   "blink.mojom.BackgroundFetchOptions=content::BackgroundFetchOptions",
   "blink.mojom.BackgroundFetchRegistration=content::BackgroundFetchRegistration",
   "content.mojom.BackgroundFetchSettledFetch=::content::BackgroundFetchSettledFetch",
-  "blink.mojom.IconDefinition=content::IconDefinition",
 ]
diff --git a/content/renderer/pepper/pepper_url_loader_host.cc b/content/renderer/pepper/pepper_url_loader_host.cc
index 681130e..b4a262c 100644
--- a/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/content/renderer/pepper/pepper_url_loader_host.cc
@@ -260,7 +260,9 @@
   DCHECK(web_request.GetSkipServiceWorker());
 
   WebAssociatedURLLoaderOptions options;
-  if (!has_universal_access_) {
+  if (has_universal_access_) {
+    options.grant_universal_access = true;
+  } else {
     // All other HTTP requests are untrusted.
     options.untrusted_http = true;
     if (filled_in_request_data.allow_cross_origin_requests) {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index e616760..145a8de 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1534,6 +1534,7 @@
     "../browser/service_worker/service_worker_read_from_cache_job_unittest.cc",
     "../browser/service_worker/service_worker_registration_unittest.cc",
     "../browser/service_worker/service_worker_request_handler_unittest.cc",
+    "../browser/service_worker/service_worker_script_loader_factory_unittest.cc",
     "../browser/service_worker/service_worker_storage_unittest.cc",
     "../browser/service_worker/service_worker_url_request_job_unittest.cc",
     "../browser/service_worker/service_worker_version_unittest.cc",
diff --git a/dbus/BUILD.gn b/dbus/BUILD.gn
index 042d8c0..f8f8ce3 100644
--- a/dbus/BUILD.gn
+++ b/dbus/BUILD.gn
@@ -64,8 +64,6 @@
     "mock_bus.h",
     "mock_exported_object.cc",
     "mock_exported_object.h",
-    "mock_object_manager.cc",
-    "mock_object_manager.h",
     "mock_object_proxy.cc",
     "mock_object_proxy.h",
   ]
diff --git a/dbus/bus.cc b/dbus/bus.cc
index 29043609..2f3db88 100644
--- a/dbus/bus.cc
+++ b/dbus/bus.cc
@@ -311,7 +311,7 @@
   }
 
   scoped_refptr<ObjectManager> object_manager =
-      new ObjectManager(this, service_name, object_path);
+      ObjectManager::Create(this, service_name, object_path);
   object_manager_table_[key] = object_manager;
 
   return object_manager.get();
diff --git a/dbus/mock_object_manager.cc b/dbus/mock_object_manager.cc
deleted file mode 100644
index 3f0c0a1..0000000
--- a/dbus/mock_object_manager.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2013 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 "dbus/mock_object_manager.h"
-
-namespace dbus {
-
-MockObjectManager::MockObjectManager(Bus* bus,
-                                     const std::string& service_name,
-                                     const ObjectPath& object_path)
-    : ObjectManager(bus, service_name, object_path) {
-}
-
-MockObjectManager::~MockObjectManager() = default;
-
-}  // namespace dbus
diff --git a/dbus/mock_object_manager.h b/dbus/mock_object_manager.h
deleted file mode 100644
index 6eb95de..0000000
--- a/dbus/mock_object_manager.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013 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 DBUS_MOCK_OBJECT_MANAGER_H_
-#define DBUS_MOCK_OBJECT_MANAGER_H_
-
-#include <string>
-
-#include "dbus/message.h"
-#include "dbus/object_manager.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace dbus {
-
-// Mock for ObjectManager.
-class MockObjectManager : public ObjectManager {
- public:
-  MockObjectManager(Bus* bus,
-                    const std::string& service_name,
-                    const ObjectPath& object_path);
-
-  MOCK_METHOD2(RegisterInterface, void(const std::string&,
-                                       Interface*));
-  MOCK_METHOD1(UnregisterInterface, void(const std::string&));
-  MOCK_METHOD0(GetObjects, std::vector<ObjectPath>());
-  MOCK_METHOD1(GetObjectsWithInterface,
-               std::vector<ObjectPath>(const std::string&));
-  MOCK_METHOD1(GetObjectProxy, ObjectProxy*(const ObjectPath&));
-  MOCK_METHOD2(GetProperties, PropertySet*(const ObjectPath&,
-                                           const std::string&));
-
- protected:
-  ~MockObjectManager() override;
-};
-
-}  // namespace dbus
-
-#endif  // DBUS_MOCK_OBJECT_MANAGER_H_
diff --git a/dbus/object_manager.cc b/dbus/object_manager.cc
index 90d7337..9bca1c0e 100644
--- a/dbus/object_manager.cc
+++ b/dbus/object_manager.cc
@@ -28,6 +28,25 @@
 
 ObjectManager::Object::~Object() = default;
 
+scoped_refptr<ObjectManager> ObjectManager::Create(
+    Bus* bus,
+    const std::string& service_name,
+    const ObjectPath& object_path) {
+  auto object_manager =
+      base::WrapRefCounted(new ObjectManager(bus, service_name, object_path));
+
+  // Set up a match rule and a filter function to handle PropertiesChanged
+  // signals from the service. This is important to avoid any race conditions
+  // that might cause us to miss PropertiesChanged signals once all objects are
+  // initialized via GetManagedObjects.
+  base::PostTaskAndReplyWithResult(
+      bus->GetDBusTaskRunner(), FROM_HERE,
+      base::BindOnce(&ObjectManager::SetupMatchRuleAndFilter, object_manager),
+      base::BindOnce(&ObjectManager::OnSetupMatchRuleAndFilterComplete,
+                     object_manager));
+  return object_manager;
+}
+
 ObjectManager::ObjectManager(Bus* bus,
                              const std::string& service_name,
                              const ObjectPath& object_path)
@@ -46,16 +65,6 @@
   object_proxy_->SetNameOwnerChangedCallback(
       base::Bind(&ObjectManager::NameOwnerChanged,
                  weak_ptr_factory_.GetWeakPtr()));
-
-  // Set up a match rule and a filter function to handle PropertiesChanged
-  // signals from the service. This is important to avoid any race conditions
-  // that might cause us to miss PropertiesChanged signals once all objects are
-  // initialized via GetManagedObjects.
-  base::PostTaskAndReplyWithResult(
-      bus_->GetDBusTaskRunner(),
-      FROM_HERE,
-      base::Bind(&ObjectManager::SetupMatchRuleAndFilter, this),
-      base::Bind(&ObjectManager::OnSetupMatchRuleAndFilterComplete, this));
 }
 
 ObjectManager::~ObjectManager() {
diff --git a/dbus/object_manager.h b/dbus/object_manager.h
index 035d569..05388de 100644
--- a/dbus/object_manager.h
+++ b/dbus/object_manager.h
@@ -136,9 +136,9 @@
 // ObjectManager implements both the D-Bus client components of the D-Bus
 // Object Manager interface, as internal methods, and a public API for
 // client classes to utilize.
-class CHROME_DBUS_EXPORT ObjectManager
+class CHROME_DBUS_EXPORT ObjectManager final
     : public base::RefCountedThreadSafe<ObjectManager> {
-public:
+ public:
   // ObjectManager::Interface must be implemented by any class wishing to have
   // its remote objects managed by an ObjectManager.
   class Interface {
@@ -184,43 +184,43 @@
   };
 
   // Client code should use Bus::GetObjectManager() instead of this constructor.
-  ObjectManager(Bus* bus,
-                const std::string& service_name,
-                const ObjectPath& object_path);
+  static scoped_refptr<ObjectManager> Create(Bus* bus,
+                                             const std::string& service_name,
+                                             const ObjectPath& object_path);
 
   // Register a client implementation class |interface| for the given D-Bus
   // interface named in |interface_name|. That object's CreateProperties()
   // method will be used to create instances of dbus::PropertySet* when
   // required.
-  virtual void RegisterInterface(const std::string& interface_name,
-                                 Interface* interface);
+  void RegisterInterface(const std::string& interface_name,
+                         Interface* interface);
 
   // Unregister the implementation class for the D-Bus interface named in
   // |interface_name|, objects and properties of this interface will be
   // ignored.
-  virtual void UnregisterInterface(const std::string& interface_name);
+  void UnregisterInterface(const std::string& interface_name);
 
   // Returns a list of object paths, in an undefined order, of objects known
   // to this manager.
-  virtual std::vector<ObjectPath> GetObjects();
+  std::vector<ObjectPath> GetObjects();
 
   // Returns the list of object paths, in an undefined order, of objects
   // implementing the interface named in |interface_name| known to this manager.
-  virtual std::vector<ObjectPath> GetObjectsWithInterface(
+  std::vector<ObjectPath> GetObjectsWithInterface(
       const std::string& interface_name);
 
   // Returns a ObjectProxy pointer for the given |object_path|. Unlike
   // the equivalent method on Bus this will return NULL if the object
   // manager has not been informed of that object's existence.
-  virtual ObjectProxy* GetObjectProxy(const ObjectPath& object_path);
+  ObjectProxy* GetObjectProxy(const ObjectPath& object_path);
 
   // Returns a PropertySet* pointer for the given |object_path| and
   // |interface_name|, or NULL if the object manager has not been informed of
   // that object's existence or the interface's properties. The caller should
   // cast the returned pointer to the appropriate type, e.g.:
   //   static_cast<Properties*>(GetProperties(object_path, my_interface));
-  virtual PropertySet* GetProperties(const ObjectPath& object_path,
-                                     const std::string& interface_name);
+  PropertySet* GetProperties(const ObjectPath& object_path,
+                             const std::string& interface_name);
 
   // Instructs the object manager to refresh its list of managed objects;
   // automatically called by the D-Bus thread manager, there should never be
@@ -233,12 +233,14 @@
   // BLOCKING CALL.
   void CleanUp();
 
- protected:
-  virtual ~ObjectManager();
-
  private:
   friend class base::RefCountedThreadSafe<ObjectManager>;
 
+  ObjectManager(Bus* bus,
+                const std::string& service_name,
+                const ObjectPath& object_path);
+  ~ObjectManager();
+
   // Called from the constructor to add a match rule for PropertiesChanged
   // signals on the D-Bus thread and set up a corresponding filter function.
   bool SetupMatchRuleAndFilter();
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index ec0e7bb..17927b8 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -398,6 +398,9 @@
     return;
   }
 
+  if (override_headers_)
+    current_response_.headers = override_headers_;
+
   std::string redirect_location;
   if (override_headers_ && override_headers_->IsRedirect(&redirect_location)) {
     // The response headers may have been overridden by an |onHeadersReceived|
@@ -416,8 +419,6 @@
     redirect_info.new_url = new_url;
     redirect_info.new_site_for_cookies = new_url;
 
-    current_response_.headers = override_headers_;
-
     // These will get re-bound when a new request is initiated after Restart()
     // below.
     proxied_client_binding_.Close();
diff --git a/gpu/command_buffer/service/service_transfer_cache.cc b/gpu/command_buffer/service/service_transfer_cache.cc
index 6b28020..017eff6 100644
--- a/gpu/command_buffer/service/service_transfer_cache.cc
+++ b/gpu/command_buffer/service/service_transfer_cache.cc
@@ -212,7 +212,6 @@
   }
 
   for (auto it = entries_.begin(); it != entries_.end(); it++) {
-    uint32_t entry_id = it->first.entry_id;
     auto entry_type = it->first.entry_type;
     const auto* entry = it->second.entry.get();
     const cc::ServiceImageTransferCacheEntry* image_entry = nullptr;
@@ -224,13 +223,15 @@
 
     if (image_entry && image_entry->fits_on_gpu()) {
       std::string dump_name = base::StringPrintf(
-          "gpu/transfer_cache/cache_0x%" PRIXPTR "/gpu/entry_%d",
-          reinterpret_cast<uintptr_t>(this), entry_id);
+          "gpu/transfer_cache/cache_0x%" PRIXPTR "/gpu/entry_0x%" PRIXPTR,
+          reinterpret_cast<uintptr_t>(this),
+          reinterpret_cast<uintptr_t>(entry));
       DumpMemoryForImageTransferCacheEntry(pmd, dump_name, image_entry);
     } else {
       std::string dump_name = base::StringPrintf(
-          "gpu/transfer_cache/cache_0x%" PRIXPTR "/cpu/entry_%d",
-          reinterpret_cast<uintptr_t>(this), entry_id);
+          "gpu/transfer_cache/cache_0x%" PRIXPTR "/cpu/entry_0x%" PRIXPTR,
+          reinterpret_cast<uintptr_t>(this),
+          reinterpret_cast<uintptr_t>(entry));
       MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
       dump->AddScalar(MemoryAllocatorDump::kNameSize,
                       MemoryAllocatorDump::kUnitsBytes, entry->CachedSize());
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
index 78c0f0b..b9a37a4 100644
--- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h
+++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -149,6 +149,7 @@
   IPC_STRUCT_TRAITS_MEMBER(context_supports_distance_field_text)
   IPC_STRUCT_TRAITS_MEMBER(glyph_cache_max_texture_bytes)
   IPC_STRUCT_TRAITS_MEMBER(chromium_nonblocking_readback)
+  IPC_STRUCT_TRAITS_MEMBER(mesa_framebuffer_flip_y)
 
   IPC_STRUCT_TRAITS_MEMBER(major_version)
   IPC_STRUCT_TRAITS_MEMBER(minor_version)
diff --git a/headless/lib/headless_web_contents_browsertest.cc b/headless/lib/headless_web_contents_browsertest.cc
index d4fe437f..f106d5b 100644
--- a/headless/lib/headless_web_contents_browsertest.cc
+++ b/headless/lib/headless_web_contents_browsertest.cc
@@ -313,17 +313,16 @@
     std::string pdf_data;
     EXPECT_TRUE(base::Base64Decode(base64, &pdf_data));
 
+    auto pdf_span = base::as_bytes(base::make_span(pdf_data));
     int num_pages;
-    EXPECT_TRUE(chrome_pdf::GetPDFDocInfo(pdf_data.data(), pdf_data.size(),
-                                          &num_pages, nullptr));
+    EXPECT_TRUE(chrome_pdf::GetPDFDocInfo(pdf_span, &num_pages, nullptr));
     EXPECT_EQ(std::ceil(kDocHeight / kPaperHeight), num_pages);
 
     for (int i = 0; i < num_pages; i++) {
       double width_in_points;
       double height_in_points;
       EXPECT_TRUE(chrome_pdf::GetPDFPageSizeByIndex(
-          pdf_data.data(), pdf_data.size(), i, &width_in_points,
-          &height_in_points));
+          pdf_span, i, &width_in_points, &height_in_points));
       EXPECT_EQ(static_cast<int>(width_in_points),
                 static_cast<int>(kPaperWidth * printing::kPointsPerInch));
       EXPECT_EQ(static_cast<int>(height_in_points),
@@ -336,10 +335,9 @@
       std::vector<uint8_t> page_bitmap_data(kColorChannels *
                                             settings.area.size().GetArea());
       EXPECT_TRUE(chrome_pdf::RenderPDFPageToBitmap(
-          pdf_data.data(), pdf_data.size(), i, page_bitmap_data.data(),
-          settings.area.size().width(), settings.area.size().height(),
-          settings.dpi.width(), settings.dpi.height(), settings.autorotate,
-          settings.use_color));
+          pdf_span, i, page_bitmap_data.data(), settings.area.size().width(),
+          settings.area.size().height(), settings.dpi.width(),
+          settings.dpi.height(), settings.autorotate, settings.use_color));
       EXPECT_EQ(0x56, page_bitmap_data[0]);  // B
       EXPECT_EQ(0x34, page_bitmap_data[1]);  // G
       EXPECT_EQ(0x12, page_bitmap_data[2]);  // R
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index d6fb0e2..b83c0c4f 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -825,6 +825,9 @@
       <message name="IDS_IOS_KEYBOARD_REOPEN_CLOSED_TAB" desc="Title of the keyboard shortcut to reopen a recently closed tab. [Length: 20 em] [iOS only]">
         Reopen Closed Tab
       </message>
+      <message name="IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_TEXT" desc="Text for the LongPress Toolbar Tip in-product help promotion, explaining that the user can long press on the toolbar's button to display more options. [iOS only]">
+        Press and hold for more tab options
+      </message>
       <message name="IDS_IOS_MANAGED_DISCONNECT_DIALOG_ACCEPT" desc="Label on the button to proceed with signout and clear all Chrome data.[Length: 30em].">
         Accept and sign out
       </message>
diff --git a/ios/chrome/browser/signin/ios_chrome_signin_client.h b/ios/chrome/browser/signin/ios_chrome_signin_client.h
index e2a54c9cb..8298add 100644
--- a/ios/chrome/browser/signin/ios_chrome_signin_client.h
+++ b/ios/chrome/browser/signin/ios_chrome_signin_client.h
@@ -61,10 +61,6 @@
       content_settings::Observer* observer) override;
   void RemoveContentSettingsObserver(
       content_settings::Observer* observer) override;
-  std::unique_ptr<CookieChangeSubscription> AddCookieChangeCallback(
-      const GURL& url,
-      const std::string& name,
-      net::CookieChangeCallback callback) override;
   void DelayNetworkCall(const base::Closure& callback) override;
 
   // SigninErrorController::Observer implementation.
diff --git a/ios/chrome/browser/signin/ios_chrome_signin_client.mm b/ios/chrome/browser/signin/ios_chrome_signin_client.mm
index e28c3a2..7cec29e 100644
--- a/ios/chrome/browser/signin/ios_chrome_signin_client.mm
+++ b/ios/chrome/browser/signin/ios_chrome_signin_client.mm
@@ -7,7 +7,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/metrics/metrics_service.h"
 #include "components/signin/core/browser/cookie_settings_util.h"
-#include "components/signin/core/browser/signin_cookie_change_subscription.h"
 #include "components/signin/ios/browser/account_consistency_service.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/browser_state_info_cache.h"
@@ -136,18 +135,6 @@
   host_content_settings_map_->RemoveObserver(observer);
 }
 
-std::unique_ptr<SigninClient::CookieChangeSubscription>
-IOSChromeSigninClient::AddCookieChangeCallback(
-    const GURL& url,
-    const std::string& name,
-    net::CookieChangeCallback callback) {
-  scoped_refptr<net::URLRequestContextGetter> context_getter =
-      GetURLRequestContext();
-  DCHECK(context_getter.get());
-  return std::make_unique<SigninCookieChangeSubscription>(
-      context_getter, url, name, std::move(callback));
-}
-
 void IOSChromeSigninClient::DelayNetworkCall(const base::Closure& callback) {
   network_callback_helper_->HandleCallback(callback);
 }
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 77d1f02..5faac3fd 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -5338,6 +5338,7 @@
     }
     if (completion)
       completion();
+    [self.bubblePresenter presentLongPressBubbleIfEligible];
 
     if (self.foregroundTabWasAddedCompletionBlock) {
       self.foregroundTabWasAddedCompletionBlock();
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.h b/ios/chrome/browser/ui/bubble/bubble_presenter.h
index f0a9482..e6655b1 100644
--- a/ios/chrome/browser/ui/bubble/bubble_presenter.h
+++ b/ios/chrome/browser/ui/bubble/bubble_presenter.h
@@ -40,6 +40,10 @@
 // bubble will not be shown.
 - (void)presentBubblesIfEligible;
 
+// Presents the in-product help for the LongPress help if the feature engagement
+// and the application states determine that it is possible to present it.
+- (void)presentLongPressBubbleIfEligible;
+
 // Dismisses all bubbles.
 - (void)dismissBubbles;
 
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
index cc4840b..680e39d 100644
--- a/ios/chrome/browser/ui/bubble/bubble_presenter.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
@@ -42,6 +42,12 @@
 // dismissed, it remains allocated so that |userEngaged| remains accessible.
 @property(nonatomic, strong)
     BubbleViewControllerPresenter* bottomToolbarTipBubblePresenter;
+// Used to display the long press on toolbar buttons tip in-product help
+// promotion bubble. |nil| if the tip bubble has not yet been presented. Once
+// the bubble is dismissed, it remains allocated so that |userEngaged| remains
+// accessible.
+@property(nonatomic, strong)
+    BubbleViewControllerPresenter* longPressToolbarTipBubblePresenter;
 // Used to display the new tab tip in-product help promotion bubble. |nil| if
 // the new tab tip bubble has not yet been presented. Once the bubble is
 // dismissed, it remains allocated so that |userEngaged| remains accessible.
@@ -59,6 +65,8 @@
 @implementation BubblePresenter
 
 @synthesize bottomToolbarTipBubblePresenter = _bottomToolbarTipBubblePresenter;
+@synthesize longPressToolbarTipBubblePresenter =
+    _longPressToolbarTipBubblePresenter;
 @synthesize tabTipBubblePresenter = _tabTipBubblePresenter;
 @synthesize incognitoTabTipBubblePresenter = _incognitoTabTipBubblePresenter;
 @synthesize browserState = _browserState;
@@ -109,6 +117,26 @@
       ->AddOnInitializedCallback(base::BindRepeating(onInitializedBlock));
 }
 
+- (void)presentLongPressBubbleIfEligible {
+  DCHECK(self.browserState);
+  // Waits to present the bubble until the feature engagement tracker database
+  // is fully initialized. This method requires that |self.browserState| is not
+  // NULL.
+  __weak BubblePresenter* weakSelf = self;
+  void (^onInitializedBlock)(bool) = ^(bool successfullyLoaded) {
+    if (!successfullyLoaded)
+      return;
+    [weakSelf presentLongPressBubble];
+  };
+
+  // Because the new tab tip occurs on startup, the feature engagement
+  // tracker's database is not guaranteed to be loaded by this time. For the
+  // bubble to appear properly, a callback is used to guarantee the event data
+  // is loaded before the check to see if the promotion should be displayed.
+  feature_engagement::TrackerFactory::GetForBrowserState(self.browserState)
+      ->AddOnInitializedCallback(base::BindRepeating(onInitializedBlock));
+}
+
 - (void)dismissBubbles {
   [self.tabTipBubblePresenter dismissAnimated:NO];
   [self.incognitoTabTipBubblePresenter dismissAnimated:NO];
@@ -143,6 +171,35 @@
     [self presentBottomToolbarTipBubble];
 }
 
+- (void)presentLongPressBubble {
+  if (self.longPressToolbarTipBubblePresenter.isUserEngaged)
+    return;
+
+  if (![self canPresentBubble])
+    return;
+
+  BubbleArrowDirection arrowDirection =
+      IsSplitToolbarMode() ? BubbleArrowDirectionDown : BubbleArrowDirectionUp;
+  NSString* text = l10n_util::GetNSStringWithFixup(
+      IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_TEXT);
+  CGPoint searchButtonAnchor =
+      [self anchorPointToGuide:kTabSwitcherGuide direction:arrowDirection];
+
+  // If the feature engagement tracker does not consider it valid to display
+  // the tip, then end early to prevent the potential reassignment of the
+  // existing |longPressToolbarTipBubblePresenter| to nil.
+  BubbleViewControllerPresenter* presenter = [self
+      presentBubbleForFeature:feature_engagement::kIPHLongPressToolbarTipFeature
+                    direction:arrowDirection
+                    alignment:BubbleAlignmentTrailing
+                         text:text
+                  anchorPoint:searchButtonAnchor];
+  if (!presenter)
+    return;
+
+  self.bottomToolbarTipBubblePresenter = presenter;
+}
+
 // Presents and returns a bubble view controller for the |feature| with an arrow
 // |direction|, an arrow |alignment| and a |text| on an |anchorPoint|.
 - (BubbleViewControllerPresenter*)
@@ -180,8 +237,8 @@
       [self anchorPointToGuide:kSearchButtonGuide direction:arrowDirection];
 
   // If the feature engagement tracker does not consider it valid to display
-  // the new tab tip, then end early to prevent the potential reassignment
-  // of the existing |bottomToolbarTipBubblePresenter| to nil.
+  // the tip, then end early to prevent the potential reassignment of the
+  // existing |bottomToolbarTipBubblePresenter| to nil.
   BubbleViewControllerPresenter* presenter = [self
       presentBubbleForFeature:feature_engagement::kIPHBottomToolbarTipFeature
                     direction:arrowDirection
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm
index 447abadc..627b9bde 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -995,6 +995,13 @@
   [self.localDispatcher displayPrivacySettings];
 }
 
+#pragma mark - Accessibility
+
+- (BOOL)accessibilityPerformEscape {
+  [self.localDispatcher dismissHistoryWithCompletion:nil];
+  return YES;
+}
+
 #pragma mark Setter & Getters
 
 - (UIBarButtonItem*)cancelButton {
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.mm b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.mm
index 4f5a96c..608b147 100644
--- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.mm
+++ b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.mm
@@ -85,35 +85,34 @@
     _deleteButton = [[LegacyReadingListToolbarButton alloc]
         initWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_DELETE_BUTTON)
          destructive:YES
-            position:Leading];
-    _deleteButton.accessibilityIdentifier = kReadingListToolbarDeleteButtonID;
+            position:Leading
+          identifier:kReadingListToolbarDeleteButtonID];
 
     _deleteAllButton = [[LegacyReadingListToolbarButton alloc]
         initWithText:l10n_util::GetNSString(
                          IDS_IOS_READING_LIST_DELETE_ALL_READ_BUTTON)
          destructive:YES
-            position:Leading];
-    _deleteAllButton.accessibilityIdentifier =
-        kReadingListToolbarDeleteAllReadButtonID;
+            position:Leading
+          identifier:kReadingListToolbarDeleteAllReadButtonID];
 
     _markButton = [[LegacyReadingListToolbarButton alloc]
         initWithText:l10n_util::GetNSString(
                          IDS_IOS_READING_LIST_MARK_ALL_BUTTON)
          destructive:NO
-            position:Centered];
-    _markButton.accessibilityIdentifier = kReadingListToolbarMarkButtonID;
+            position:Centered
+          identifier:kReadingListToolbarMarkButtonID];
 
     _cancelButton = [[LegacyReadingListToolbarButton alloc]
         initWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_CANCEL_BUTTON)
          destructive:NO
-            position:Trailing];
-    _cancelButton.accessibilityIdentifier = kReadingListToolbarCancelButtonID;
+            position:Trailing
+          identifier:kReadingListToolbarCancelButtonID];
 
     _editButton = [[LegacyReadingListToolbarButton alloc]
         initWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_EDIT_BUTTON)
          destructive:NO
-            position:Trailing];
-    _editButton.accessibilityIdentifier = kReadingListToolbarEditButtonID;
+            position:Trailing
+          identifier:kReadingListToolbarEditButtonID];
 
     [_editButton addTarget:nil
                     action:@selector(enterEditingModePressed)
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h
index 36e9422..e8e5f62 100644
--- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h
+++ b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h
@@ -16,7 +16,8 @@
 // Initializer.
 - (instancetype)initWithText:(NSString*)labelText
                  destructive:(BOOL)isDestructive
-                    position:(ButtonPositioning)position;
+                    position:(ButtonPositioning)position
+                  identifier:(NSString*)identifier;
 
 // Associates a target object and action method with the UIButton.
 - (void)addTarget:(id)target
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.mm b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.mm
index af2bf380b..c522cd6 100644
--- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.mm
+++ b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.mm
@@ -33,7 +33,8 @@
 
 - (instancetype)initWithText:(NSString*)labelText
                  destructive:(BOOL)isDestructive
-                    position:(ButtonPositioning)position {
+                    position:(ButtonPositioning)position
+                  identifier:(NSString*)identifier {
   self = [super init];
   if (!self) {
     return self;
@@ -43,6 +44,7 @@
                      destructive:isDestructive
                         position:position];
   _button.translatesAutoresizingMaskIntoConstraints = NO;
+  _button.accessibilityIdentifier = identifier;
   [self addSubview:_button];
 
   NSDictionary* views = @{@"button" : _button};
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
index 8a3e8ac..7acb6cb 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -868,4 +868,11 @@
                                        atPoint:location];
 }
 
+#pragma mark - Accessibility
+
+- (BOOL)accessibilityPerformEscape {
+  [self.delegate dismissReadingListListViewController:self];
+  return YES;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
index 0ffa923..e58794034 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -1128,6 +1128,13 @@
   [self.dispatcher showSignin:command baseViewController:self];
 }
 
+#pragma mark - Accessibility
+
+- (BOOL)accessibilityPerformEscape {
+  [self.presentationDelegate showActiveRegularTabFromRecentTabs];
+  return YES;
+}
+
 #pragma mark - Private Helpers
 
 - (void)updateSyncState {
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 4ebd16b..00468a61 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -141,6 +141,7 @@
     "//components/sync",
     "//components/translate/core/browser",
     "//components/translate/core/common",
+    "//components/unified_consent",
     "//components/url_formatter",
     "//components/version_info",
     "//ios/chrome/app/strings",
@@ -435,10 +436,13 @@
     "//base",
     "//base/test:test_support",
     "//components/signin/core/browser",
+    "//components/unified_consent",
     "//ios/chrome/app/strings:ios_chromium_strings_grit",
     "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/ui:ui_util",
     "//ios/chrome/browser/ui/authentication:eg_test_support",
+    "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ui/base",
   ]
diff --git a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
index 99c2bb1..f129259 100644
--- a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
@@ -127,6 +127,9 @@
 
 // Test that submitting a form ensures saving the data as an autofill profile.
 - (void)testAutofillProfileSaving {
+  // TODO(crbug.com/866730): Re-enable when fixed
+  EARL_GREY_TEST_DISABLED(@"Test broken.");
+
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
 
@@ -147,6 +150,9 @@
 // Test that editing country names is followed by validating the value and
 // replacing it with a canonical one.
 - (void)testAutofillProfileEditing {
+  // TODO(crbug.com/866730): Re-enable when fixed
+  EARL_GREY_TEST_DISABLED(@"Test broken.");
+
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
 
@@ -181,6 +187,9 @@
 
 // Test that the page for viewing autofill profile details is accessible.
 - (void)testAccessibilityOnAutofillProfileViewPage {
+  // TODO(crbug.com/866730): Re-enable when fixed
+  EARL_GREY_TEST_DISABLED(@"Test broken.");
+
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
   chrome_test_util::VerifyAccessibilityForCurrentScreen();
@@ -190,6 +199,9 @@
 
 // Test that the page for editing autofill profile details is accessible.
 - (void)testAccessibilityOnAutofillProfileEditPage {
+  // TODO(crbug.com/866730): Re-enable when fixed
+  EARL_GREY_TEST_DISABLED(@"Test broken.");
+
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
   // Switch on edit mode.
@@ -204,6 +216,9 @@
 // Checks that if the autofill profiles and credit cards list view is in edit
 // mode, the "autofill" and "wallet" switch items are disabled.
 - (void)testListViewEditMode {
+  // TODO(crbug.com/866730): Re-enable when fixed
+  EARL_GREY_TEST_DISABLED(@"Test broken.");
+
   [self loadAndSubmitTheForm];
 
   [ChromeEarlGreyUI openSettingsMenu];
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
index 3caceea9..c87770c 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/settings/google_services_settings_coordinator.h"
 
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_mediator.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller.h"
@@ -34,7 +35,8 @@
                    style:CollectionViewControllerStyleAppBar];
   controller.presentationDelegate = self;
   self.viewController = controller;
-  self.mediator = [[GoogleServicesSettingsMediator alloc] init];
+  self.mediator = [[GoogleServicesSettingsMediator alloc]
+      initWithPrefService:self.browserState->GetPrefs()];
   self.mediator.consumer = controller;
   self.mediator.authService =
       AuthenticationServiceFactory::GetForBrowserState(self.browserState);
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
index 8eb0368..f88e194 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
@@ -5,9 +5,15 @@
 #import <EarlGrey/EarlGrey.h>
 #import <XCTest/XCTest.h>
 
+#include "components/prefs/pref_service.h"
+#include "components/unified_consent/pref_names.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h"
+#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
 #include "ios/chrome/test/earl_grey/accessibility_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
@@ -19,20 +25,22 @@
 #endif
 
 using l10n_util::GetNSString;
+using chrome_test_util::GetOriginalBrowserState;
 using chrome_test_util::GoogleServicesSettingsButton;
 using chrome_test_util::SettingsMenuBackButton;
 using chrome_test_util::SettingsDoneButton;
+using unified_consent::prefs::kUnifiedConsentGiven;
 
 // Integration tests using the Google services settings screen.
 @interface GoogleServicesSettingsTestCase : ChromeTestCase
 
-@property(nonatomic, strong) id<GREYMatcher> scollViewMatcher;
+@property(nonatomic, strong) id<GREYMatcher> scrollViewMatcher;
 
 @end
 
 @implementation GoogleServicesSettingsTestCase
 
-@synthesize scollViewMatcher = _scollViewMatcher;
+@synthesize scrollViewMatcher = _scrollViewMatcher;
 
 // Opens the Google services settings view, and closes it.
 - (void)testOpenGoogleServicesSettings {
@@ -41,9 +49,7 @@
   [self openGoogleServicesSettings];
 
   // Assert title and accessibility.
-  [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(
-                                   @"google_services_settings_view_controller")]
+  [[EarlGrey selectElementWithMatcher:self.scrollViewMatcher]
       assertWithMatcher:grey_notNil()];
   chrome_test_util::VerifyAccessibilityForCurrentScreen();
 
@@ -54,18 +60,75 @@
       performAction:grey_tap()];
 }
 
-// Tests if the Google Services settings contains only the non personalized
-// options when the user is not logged in.
-- (void)testServicesWhileSignedOut {
-  // TODO(crbug.com/863860): re-enable when fixed.
-  if (!IsIPadIdiom())
-    EARL_GREY_TEST_DISABLED(@"Fails on iPhones.");
-
+// Tests the Google Services settings, when the user is not logged in.
+// The personalized section is expect to be collapsed and the non-personalized
+// section is expected to be expanded.
+- (void)testOpeningServicesWhileSignedOut {
   if (!IsUIRefreshPhase1Enabled())
     EARL_GREY_TEST_SKIPPED(@"This test is UIRefresh only.");
   [self openGoogleServicesSettings];
-  [self assertSyncPersonalizedServicesCollapsed:YES];
+  [self assertPersonalizedServicesCollapsed:YES];
   [self assertNonPersonalizedServicesCollapsed:NO];
+}
+
+// Tests the Google Services settings, when the user is logged in without user
+// consent.
+// The "Sync Everything" section is expected to be visible.
+// The personalized section and the non-personalized section are expected to be
+// expanded.
+- (void)testOpeningServicesWhileSignedIn {
+  if (!IsUIRefreshPhase1Enabled())
+    EARL_GREY_TEST_SKIPPED(@"This test is UIRefresh only.");
+  PrefService* prefService = GetOriginalBrowserState()->GetPrefs();
+  prefService->SetBoolean(kUnifiedConsentGiven, false);
+  [SigninEarlGreyUI signinWithIdentity:[SigninEarlGreyUtils fakeIdentity1]];
+  [self openGoogleServicesSettings];
+  [self assertSyncEverythingSection];
+  [self assertPersonalizedServicesCollapsed:NO];
+  [self assertNonPersonalizedServicesCollapsed:NO];
+}
+
+// Tests the Google Services settings, when the user is logged in with user
+// consent.
+// The "Sync Everything" section is expected to be visible.
+// The personalized section and the non-personalized section are expected to be
+// collapsed.
+- (void)testOpeningServicesWhileSignedInAndConsentGiven {
+  if (!IsUIRefreshPhase1Enabled())
+    EARL_GREY_TEST_SKIPPED(@"This test is UIRefresh only.");
+  PrefService* prefService = GetOriginalBrowserState()->GetPrefs();
+  prefService->SetBoolean(kUnifiedConsentGiven, true);
+  [SigninEarlGreyUI signinWithIdentity:[SigninEarlGreyUtils fakeIdentity1]];
+  [self openGoogleServicesSettings];
+  [self assertSyncEverythingSection];
+  [self assertPersonalizedServicesCollapsed:YES];
+  [self assertNonPersonalizedServicesCollapsed:YES];
+}
+
+// Tests to expand/collapse the personalized section.
+- (void)testTogglePersonalizedServices {
+  if (!IsUIRefreshPhase1Enabled())
+    EARL_GREY_TEST_SKIPPED(@"This test is UIRefresh only.");
+  [self openGoogleServicesSettings];
+  [self assertPersonalizedServicesCollapsed:YES];
+  [self togglePersonalizedServicesSection];
+  [self assertPersonalizedServicesCollapsed:NO];
+  [[EarlGrey selectElementWithMatcher:self.scrollViewMatcher]
+      performAction:grey_scrollToContentEdgeWithStartPoint(kGREYContentEdgeTop,
+                                                           0.1f, 0.1f)];
+  [self togglePersonalizedServicesSection];
+  [self assertPersonalizedServicesCollapsed:YES];
+}
+
+// Tests to expand/collapse the non-personalized section.
+- (void)testToggleNonPersonalizedServices {
+  if (!IsUIRefreshPhase1Enabled())
+    EARL_GREY_TEST_SKIPPED(@"This test is UIRefresh only.");
+  [self openGoogleServicesSettings];
+  [self assertNonPersonalizedServicesCollapsed:NO];
+  [[EarlGrey selectElementWithMatcher:self.scrollViewMatcher]
+      performAction:grey_scrollToContentEdgeWithStartPoint(kGREYContentEdgeTop,
+                                                           0.1f, 0.1f)];
   [self toggleNonPersonalizedServicesSection];
   [self assertNonPersonalizedServicesCollapsed:YES];
   [self toggleNonPersonalizedServicesSection];
@@ -77,12 +140,20 @@
 - (void)openGoogleServicesSettings {
   [ChromeEarlGreyUI openSettingsMenu];
   [ChromeEarlGreyUI tapSettingsMenuButton:GoogleServicesSettingsButton()];
-  self.scollViewMatcher =
+  self.scrollViewMatcher =
       grey_accessibilityID(@"google_services_settings_view_controller");
-  [[EarlGrey selectElementWithMatcher:self.scollViewMatcher]
+  [[EarlGrey selectElementWithMatcher:self.scrollViewMatcher]
       assertWithMatcher:grey_notNil()];
 }
 
+- (void)togglePersonalizedServicesSection {
+  [[EarlGrey
+      selectElementWithMatcher:
+          grey_accessibilityLabel(GetNSString(
+              IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_PERSONALIZATION_TEXT))]
+      performAction:grey_tap()];
+}
+
 - (void)toggleNonPersonalizedServicesSection {
   [[EarlGrey
       selectElementWithMatcher:
@@ -92,18 +163,21 @@
 }
 
 - (void)assertCellWithTitleID:(int)titleID detailTextID:(int)detailTextID {
-  [[[EarlGrey
-      selectElementWithMatcher:grey_accessibilityLabel(GetNSString(titleID))]
-         usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp)
-      onElementWithMatcher:self.scollViewMatcher]
-      assertWithMatcher:grey_notNil()];
+  NSString* accessibilityLabel = GetNSString(titleID);
   if (detailTextID) {
-    [[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
-                                             GetNSString(detailTextID))]
-           usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp)
-        onElementWithMatcher:self.scollViewMatcher]
-        assertWithMatcher:grey_notNil()];
+    accessibilityLabel =
+        [NSString stringWithFormat:@"%@, %@", accessibilityLabel,
+                                   GetNSString(detailTextID)];
   }
+  [[[EarlGrey
+      selectElementWithMatcher:grey_allOf(
+                                   grey_accessibilityLabel(accessibilityLabel),
+                                   grey_kindOfClass(
+                                       [UICollectionViewCell class]),
+                                   grey_sufficientlyVisible(), nil)]
+         usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp)
+      onElementWithMatcher:self.scrollViewMatcher]
+      assertWithMatcher:grey_notNil()];
 }
 
 - (void)assertSyncEverythingSection {
@@ -111,7 +185,7 @@
                  detailTextID:0];
 }
 
-- (void)assertSyncPersonalizedServicesCollapsed:(BOOL)collapsed {
+- (void)assertPersonalizedServicesCollapsed:(BOOL)collapsed {
   [self
       assertCellWithTitleID:
           IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_PERSONALIZATION_TEXT
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_mediator.h b/ios/chrome/browser/ui/settings/google_services_settings_mediator.h
index 6babd13..89e9f1a 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_mediator.h
+++ b/ios/chrome/browser/ui/settings/google_services_settings_mediator.h
@@ -13,11 +13,18 @@
 
 class AuthenticationService;
 @class GoogleServicesSettingsViewController;
+class PrefService;
 
 // Mediator for the Google services settings.
 @interface GoogleServicesSettingsMediator
     : NSObject<GoogleServicesSettingsViewControllerModelDelegate>
 
+// Designated initializer. |prefService| should not be null.
+- (instancetype)initWithPrefService:(PrefService*)prefService
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
 // View controller.
 @property(nonatomic, weak) id<GoogleServicesSettingsConsumer> consumer;
 // Browser state.
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm
index cf116f5..26484ee 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm
+++ b/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/settings/google_services_settings_mediator.h"
 
+#include "components/prefs/pref_service.h"
+#include "components/unified_consent/pref_names.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
@@ -20,6 +22,7 @@
 #endif
 
 using l10n_util::GetNSString;
+using unified_consent::prefs::kUnifiedConsentGiven;
 
 namespace {
 
@@ -67,6 +70,8 @@
 
 // Returns YES if the user is authenticated.
 @property(nonatomic, readonly) BOOL isAuthenticated;
+// Preference service.
+@property(nonatomic, readonly) PrefService* prefService;
 
 @end
 
@@ -74,9 +79,19 @@
 
 @synthesize consumer = _consumer;
 @synthesize authService = _authService;
+@synthesize prefService = _prefService;
 
 #pragma mark - Load model
 
+- (instancetype)initWithPrefService:(PrefService*)prefService {
+  self = [super init];
+  if (self) {
+    DCHECK(prefService);
+    _prefService = prefService;
+  }
+  return self;
+}
+
 // Loads SyncEverythingSectionIdentifier section.
 - (void)loadSyncEverythingSection {
   CollectionViewModel* model = self.consumer.collectionViewModel;
@@ -91,6 +106,7 @@
       [[SyncSwitchItem alloc] initWithType:SyncEverythingItemType];
   item.text = GetNSString(IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_EVERYTHING);
   item.enabled = YES;
+  item.on = [self isConsentGiven];
   return item;
 }
 
@@ -102,10 +118,11 @@
                  collapsedKey:kGoogleServicesSettingsPersonalizedSectionKey];
   SettingsCollapsibleItem* syncPersonalizationItem =
       [self syncPersonalizationItem];
-  syncPersonalizationItem.collapsed =
-      [model sectionIsCollapsed:PersonalizedSectionIdentifier];
   [model addItem:syncPersonalizationItem
       toSectionWithIdentifier:PersonalizedSectionIdentifier];
+  BOOL collapsed = self.isAuthenticated ? [self isConsentGiven] : YES;
+  syncPersonalizationItem.collapsed = collapsed;
+  [model setSection:PersonalizedSectionIdentifier collapsed:collapsed];
   [model addItem:[self syncBookmarksItem]
       toSectionWithIdentifier:PersonalizedSectionIdentifier];
   [model addItem:[self syncHistoryItem]
@@ -126,8 +143,6 @@
       toSectionWithIdentifier:PersonalizedSectionIdentifier];
   [model addItem:[self manageSyncedDataItem]
       toSectionWithIdentifier:PersonalizedSectionIdentifier];
-  [model setSection:PersonalizedSectionIdentifier
-          collapsed:!self.isAuthenticated];
 }
 
 // Creates SyncPersonalizationItemType item.
@@ -260,10 +275,11 @@
                  collapsedKey:kGoogleServicesSettingsNonPersonalizedSectionKey];
   SettingsCollapsibleItem* nonPersonalizedServicesItem =
       [self nonPersonalizedServicesItem];
-  nonPersonalizedServicesItem.collapsed =
-      [model sectionIsCollapsed:NonPersonalizedSectionIdentifier];
   [model addItem:nonPersonalizedServicesItem
       toSectionWithIdentifier:NonPersonalizedSectionIdentifier];
+  BOOL collapsed = self.isAuthenticated ? [self isConsentGiven] : NO;
+  nonPersonalizedServicesItem.collapsed = collapsed;
+  [model setSection:NonPersonalizedSectionIdentifier collapsed:collapsed];
   [model addItem:[self autocompleteSearchesAndURLsItem]
       toSectionWithIdentifier:NonPersonalizedSectionIdentifier];
   [model addItem:[self preloadPagesItem]
@@ -272,7 +288,6 @@
       toSectionWithIdentifier:NonPersonalizedSectionIdentifier];
   [model addItem:[self betterSearchAndBrowsingItemType]
       toSectionWithIdentifier:NonPersonalizedSectionIdentifier];
-  [model setSection:PersonalizedSectionIdentifier collapsed:YES];
 }
 
 // Creates NonPersonalizedServicesItemType item.
@@ -340,6 +355,10 @@
   return self.authService->IsAuthenticated();
 }
 
+- (BOOL)isConsentGiven {
+  return self.prefService->GetBoolean(kUnifiedConsentGiven);
+}
+
 #pragma mark - GoogleServicesSettingsViewControllerModelDelegate
 
 - (void)googleServicesSettingsViewControllerLoadModel:
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm
index cf73c92..2a80514 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_disclosure_header_footer_item.mm
@@ -110,6 +110,7 @@
     UIStackView* verticalStack = [[UIStackView alloc]
         initWithArrangedSubviews:@[ _titleLabel, _subtitleLabel ]];
     verticalStack.axis = UILayoutConstraintAxisVertical;
+    verticalStack.distribution = UIStackViewDistributionFillProportionally;
 
     // Disclosure ImageView. Initial pointing direction is to the right.
     _disclosureImageView = [[UIImageView alloc]
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.h b/ios/web_view/internal/signin/ios_web_view_signin_client.h
index de45064..37555cc 100644
--- a/ios/web_view/internal/signin/ios_web_view_signin_client.h
+++ b/ios/web_view/internal/signin/ios_web_view_signin_client.h
@@ -51,10 +51,6 @@
       content_settings::Observer* observer) override;
   void RemoveContentSettingsObserver(
       content_settings::Observer* observer) override;
-  std::unique_ptr<CookieChangeSubscription> AddCookieChangeCallback(
-      const GURL& url,
-      const std::string& name,
-      net::CookieChangeCallback callback) override;
   void DelayNetworkCall(const base::Closure& callback) override;
   std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
       GaiaAuthConsumer* consumer,
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.mm b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
index 58b86cd..7e6042e 100644
--- a/ios/web_view/internal/signin/ios_web_view_signin_client.mm
+++ b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
@@ -5,7 +5,6 @@
 #include "ios/web_view/internal/signin/ios_web_view_signin_client.h"
 
 #include "components/signin/core/browser/cookie_settings_util.h"
-#include "components/signin/core/browser/signin_cookie_change_subscription.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
@@ -98,18 +97,6 @@
   host_content_settings_map_->RemoveObserver(observer);
 }
 
-std::unique_ptr<SigninClient::CookieChangeSubscription>
-IOSWebViewSigninClient::AddCookieChangeCallback(
-    const GURL& url,
-    const std::string& name,
-    net::CookieChangeCallback callback) {
-  scoped_refptr<net::URLRequestContextGetter> context_getter =
-      GetURLRequestContext();
-  DCHECK(context_getter.get());
-  return std::make_unique<SigninCookieChangeSubscription>(
-      context_getter, url, name, std::move(callback));
-}
-
 void IOSWebViewSigninClient::DelayNetworkCall(const base::Closure& callback) {
   network_callback_helper_->HandleCallback(callback);
 }
diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc
index 589a1a0c..d3ecc1d 100644
--- a/ipc/ipc_sync_channel.cc
+++ b/ipc/ipc_sync_channel.cc
@@ -547,20 +547,6 @@
 
 // static
 std::unique_ptr<SyncChannel> SyncChannel::Create(
-    std::unique_ptr<ChannelFactory> factory,
-    Listener* listener,
-    const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
-    bool create_pipe_now,
-    base::WaitableEvent* shutdown_event) {
-  std::unique_ptr<SyncChannel> channel =
-      Create(listener, ipc_task_runner, listener_task_runner, shutdown_event);
-  channel->Init(std::move(factory), create_pipe_now);
-  return channel;
-}
-
-// static
-std::unique_ptr<SyncChannel> SyncChannel::Create(
     Listener* listener,
     const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
     const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
diff --git a/ipc/ipc_sync_channel.h b/ipc/ipc_sync_channel.h
index a54dbaa..1318fc3 100644
--- a/ipc/ipc_sync_channel.h
+++ b/ipc/ipc_sync_channel.h
@@ -33,7 +33,6 @@
 
 namespace IPC {
 
-class ChannelFactory;
 class SyncMessage;
 
 // This is similar to ChannelProxy, with the added feature of supporting sending
@@ -88,14 +87,6 @@
       bool create_pipe_now,
       base::WaitableEvent* shutdown_event);
 
-  static std::unique_ptr<SyncChannel> Create(
-      std::unique_ptr<ChannelFactory> factory,
-      Listener* listener,
-      const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
-      bool create_pipe_now,
-      base::WaitableEvent* shutdown_event);
-
   // Creates an uninitialized sync channel. Call ChannelProxy::Init to
   // initialize the channel. This two-step setup allows message filters to be
   // added before any messages are sent or received.
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn
index f9e2ccbb..37560240 100644
--- a/media/capture/BUILD.gn
+++ b/media/capture/BUILD.gn
@@ -270,6 +270,13 @@
       "//third_party/libsync",
     ]
   }
+
+  if (is_fuchsia) {
+    sources += [
+      "video/fuchsia/video_capture_device_factory_fuchsia.cc",
+      "video/fuchsia/video_capture_device_factory_fuchsia.h",
+    ]
+  }
 }
 
 source_set("test_support") {
diff --git a/media/capture/video/create_video_capture_device_factory.cc b/media/capture/video/create_video_capture_device_factory.cc
index 9ca6f8c3..9e4bcfc 100644
--- a/media/capture/video/create_video_capture_device_factory.cc
+++ b/media/capture/video/create_video_capture_device_factory.cc
@@ -22,6 +22,8 @@
 #include "media/capture/video/mac/video_capture_device_factory_mac.h"
 #elif defined(OS_ANDROID)
 #include "media/capture/video/android/video_capture_device_factory_android.h"
+#elif defined(OS_FUCHSIA)
+#include "media/capture/video/fuchsia/video_capture_device_factory_fuchsia.h"
 #endif
 
 namespace media {
@@ -54,6 +56,8 @@
   return std::make_unique<VideoCaptureDeviceFactoryMac>();
 #elif defined(OS_ANDROID)
   return std::make_unique<VideoCaptureDeviceFactoryAndroid>();
+#elif defined(OS_FUCHSIA)
+  return std::make_unique<VideoCaptureDeviceFactoryFuchsia>();
 #else
   NOTIMPLEMENTED();
   return nullptr;
diff --git a/media/capture/video/fuchsia/video_capture_device_factory_fuchsia.cc b/media/capture/video/fuchsia/video_capture_device_factory_fuchsia.cc
new file mode 100644
index 0000000..42c2e28
--- /dev/null
+++ b/media/capture/video/fuchsia/video_capture_device_factory_fuchsia.cc
@@ -0,0 +1,35 @@
+// 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.
+
+#include "media/capture/video/fuchsia/video_capture_device_factory_fuchsia.h"
+
+#include "base/logging.h"
+
+namespace media {
+
+VideoCaptureDeviceFactoryFuchsia::VideoCaptureDeviceFactoryFuchsia() = default;
+VideoCaptureDeviceFactoryFuchsia::~VideoCaptureDeviceFactoryFuchsia() = default;
+
+std::unique_ptr<VideoCaptureDevice>
+VideoCaptureDeviceFactoryFuchsia::CreateDevice(
+    const VideoCaptureDeviceDescriptor& device_descriptor) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+void VideoCaptureDeviceFactoryFuchsia::GetDeviceDescriptors(
+    VideoCaptureDeviceDescriptors* device_descriptors) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  device_descriptors->clear();
+}
+
+void VideoCaptureDeviceFactoryFuchsia::GetSupportedFormats(
+    const VideoCaptureDeviceDescriptor& device,
+    VideoCaptureFormats* capture_formats) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  capture_formats->clear();
+}
+
+}  // namespace media
diff --git a/media/capture/video/fuchsia/video_capture_device_factory_fuchsia.h b/media/capture/video/fuchsia/video_capture_device_factory_fuchsia.h
new file mode 100644
index 0000000..7a5a650
--- /dev/null
+++ b/media/capture/video/fuchsia/video_capture_device_factory_fuchsia.h
@@ -0,0 +1,31 @@
+// 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.
+
+#ifndef MEDIA_CAPTURE_VIDEO_FUCHSIA_VIDEO_CAPTURE_DEVICE_FACTORY_FUCHSIA_H_
+#define MEDIA_CAPTURE_VIDEO_FUCHSIA_VIDEO_CAPTURE_DEVICE_FACTORY_FUCHSIA_H_
+
+#include "media/capture/video/video_capture_device_factory.h"
+
+namespace media {
+
+class CAPTURE_EXPORT VideoCaptureDeviceFactoryFuchsia
+    : public VideoCaptureDeviceFactory {
+ public:
+  VideoCaptureDeviceFactoryFuchsia();
+  ~VideoCaptureDeviceFactoryFuchsia() override;
+
+  std::unique_ptr<VideoCaptureDevice> CreateDevice(
+      const VideoCaptureDeviceDescriptor& device_descriptor) override;
+  void GetDeviceDescriptors(
+      VideoCaptureDeviceDescriptors* device_descriptors) override;
+  void GetSupportedFormats(const VideoCaptureDeviceDescriptor& device,
+                           VideoCaptureFormats* supported_formats) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryFuchsia);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_CAPTURE_VIDEO_FUCHSIA_VIDEO_CAPTURE_DEVICE_FACTORY_FUCHSIA_H_
diff --git a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java
index e3be8b3d..f7d3f80 100644
--- a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java
+++ b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java
@@ -20,6 +20,7 @@
 import org.chromium.mojo.system.Pair;
 
 import java.io.Closeable;
+import java.util.concurrent.Executor;
 
 /**
  * Base class for mojo generated interfaces.
@@ -318,6 +319,67 @@
     }
 
     /**
+     * A {@link MessageReceiverWithResponder} implementation that forwards all calls to the thread
+     * the ThreadSafeForwarder was created.
+     */
+    class ThreadSafeForwarder implements MessageReceiverWithResponder {
+
+        /**
+         * The {@link MessageReceiverWithResponder} that will receive a serialized message for
+         * each method call.
+         */
+        private final MessageReceiverWithResponder mMessageReceiver;
+
+        /**
+         * The {@link Executor} to forward all tasks to.
+         */
+        private final Executor mExecutor;
+
+        /**
+         * Constructor.
+         *
+         * @param core the Core implementation used to create pipes and access the async waiter.
+         * @param messageReceiver the message receiver to send message to.
+         */
+        public ThreadSafeForwarder(Core core, MessageReceiverWithResponder messageReceiver) {
+            mMessageReceiver = messageReceiver;
+            mExecutor = ExecutorFactory.getExecutorForCurrentThread(core);
+        }
+
+        /**
+         * @see org.chromium.mojo.bindings.MessageReceiver#close()
+         */
+        @Override
+        public void close() {
+            mExecutor.execute(() -> {
+                mMessageReceiver.close();
+            });
+        }
+
+        /**
+         * @see org.chromium.mojo.bindings.MessageReceiver#accept()
+         */
+        @Override
+        public boolean accept(Message message) {
+            mExecutor.execute(() -> {
+                mMessageReceiver.accept(message);
+            });
+            return true;
+        }
+
+        /**
+         * @see org.chromium.mojo.bindings.MessageReceiverWithResponder#acceptWithResponder()
+         */
+        @Override
+        public boolean acceptWithResponder(Message message, MessageReceiver responder) {
+            mExecutor.execute(() -> {
+                mMessageReceiver.acceptWithResponder(message, responder);
+            });
+            return true;
+        }
+    }
+
+    /**
      * The |Manager| object enables building of proxies and stubs for a given interface.
      *
      * @param <I> the type of the interface the manager can handle.
@@ -386,6 +448,32 @@
         }
 
         /**
+         * Constructs a thread-safe Proxy forwarding the calls to the given message receiver.
+         * All calls can be performed from any thread and are posted to the {@link Executor} that
+         * is associated with the thread on which this method was called on.
+         *
+         * The original Proxy object is unbound.
+         */
+        public final P buildThreadSafeProxy(P proxy) {
+            HandlerImpl handlerImpl = (HandlerImpl) proxy.getProxyHandler();
+            Core core = handlerImpl.getCore();
+            int version = handlerImpl.getVersion();
+
+            Router router = new RouterImpl(handlerImpl.passHandle());
+            // Close the original proxy now that its handle has been passed.
+            proxy.close();
+
+            proxy = buildProxy(
+                core, new ThreadSafeForwarder(core, new AutoCloseableRouter(core, router)));
+            DelegatingConnectionErrorHandler handlers = new DelegatingConnectionErrorHandler();
+            handlers.addConnectionErrorHandler(proxy);
+            router.setErrorHandler(handlers);
+            router.start();
+            ((HandlerImpl) proxy.getProxyHandler()).setVersion(version);
+            return proxy;
+        }
+
+        /**
          * Binds the implementation to the given |router|.
          */
         final void bind(Core core, I impl, Router router) {
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 836f7cb8..380809e6 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -2424,6 +2424,7 @@
     "data/ssl/certificates/key_usage_rsa_no_extension.pem",
     "data/ssl/certificates/large_key.pem",
     "data/ssl/certificates/localhost_cert.pem",
+    "data/ssl/certificates/login.trustwave.com.pem",
     "data/ssl/certificates/mit.davidben.der",
     "data/ssl/certificates/multi-root-A-by-B.pem",
     "data/ssl/certificates/multi-root-B-by-C.pem",
@@ -2486,7 +2487,6 @@
     "data/ssl/certificates/subjectAltName_www_example_com.pem",
     "data/ssl/certificates/thawte.single.pem",
     "data/ssl/certificates/tls_feature_extension.pem",
-    "data/ssl/certificates/trustcenter.websecurity.symantec.com.pem",
     "data/ssl/certificates/unescaped.pem",
     "data/ssl/certificates/unittest.key.bin",
     "data/ssl/certificates/unittest.originbound.der",
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index d9d3aed..ecd0d81 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -341,16 +341,16 @@
 
   // TODO(eroman): Update this test to use a synthetic certificate, so the test
   // does not break in the future. The certificate chain in question expires on
-  // Dec 22 23:59:59 2018 GMT 2018, at which point this test will start failing.
+  // Jun 12 14:33:43 2020 GMT, at which point this test will start failing.
   if (base::Time::Now() >
-      base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1545523199)) {
+      base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1591972423)) {
     FAIL() << "This test uses a certificate chain which is now expired. Please "
               "disable and file a bug.";
     return;
   }
 
   scoped_refptr<X509Certificate> chain = CreateCertificateChainFromFile(
-      GetTestCertsDirectory(), "trustcenter.websecurity.symantec.com.pem",
+      GetTestCertsDirectory(), "login.trustwave.com.pem",
       X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
   ASSERT_TRUE(chain);
 
@@ -358,7 +358,7 @@
   //
   // This way CRLSet coverage will be sufficient for EV revocation checking,
   // so this test does not depend on online revocation checking.
-  ASSERT_EQ(1u, chain->intermediate_buffers().size());
+  ASSERT_GE(chain->intermediate_buffers().size(), 1u);
   base::StringPiece spki;
   ASSERT_TRUE(
       asn1::ExtractSPKIFromDERCert(x509_util::CryptoBufferAsStringPiece(
@@ -371,7 +371,7 @@
 
   CertVerifyResult verify_result;
   int flags = 0;
-  int error = Verify(chain.get(), "trustcenter.websecurity.symantec.com", flags,
+  int error = Verify(chain.get(), "login.trustwave.com", flags,
                      crl_set.get(), CertificateList(), &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index 85de448..ed5dbf47 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -10,7 +10,7 @@
 - google.single.der
 - google.single.pem
 - thawte.single.pem : Certificates for testing parsing of different formats.
-- trustcenter.websecurity.symantec.com.pem :
+- login.trustwave.com.pem :
      Certificate for testing EV with multiple OIDs. Regression test for crbug.com/705285
 
 - googlenew.chain.pem : The refreshed Google certificate
@@ -352,4 +352,4 @@
 - key_usage_p256_digitalsignature.pem
 - key_usage_p256_both.pem
      Self-signed P-256 certificates with various combinations of keyUsage
-     flags. Their private key is key_usage_p256.key.
\ No newline at end of file
+     flags. Their private key is key_usage_p256.key.
diff --git a/net/data/ssl/certificates/login.trustwave.com.pem b/net/data/ssl/certificates/login.trustwave.com.pem
new file mode 100644
index 0000000..e8dc28a
--- /dev/null
+++ b/net/data/ssl/certificates/login.trustwave.com.pem
@@ -0,0 +1,356 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            06:db:17:73:de:b5:08:bf:b6:86:a8:c5:ad:ce:d9:2b:0f:dc:9d
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = "Trustwave Extended Validation SHA256 CA, Level 1", emailAddress = ca@trustwave.com
+        Validity
+            Not Before: Jun 13 08:33:43 2018 GMT
+            Not After : Jun 12 14:33:43 2020 GMT
+        Subject: CN = login.trustwave.com, O = "Trustwave Holdings, Inc.", L = Chicago, ST = Illinois, C = US, serialNumber = 3939737, businessCategory = Private Organization, jurisdictionC = US, jurisdictionST = Delaware
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:dd:80:8b:d6:ac:0e:14:cd:fc:39:eb:17:8f:f5:
+                    9b:c8:0f:0f:03:dd:46:d8:72:a7:2f:bb:61:e4:0a:
+                    9f:db:1a:7f:94:7a:b5:5b:04:ac:92:5f:37:e8:58:
+                    54:08:5c:39:19:85:54:a9:d1:96:d2:f6:c9:67:e1:
+                    6d:c2:fb:40:c9:86:3c:b8:97:fe:83:8d:c4:35:2e:
+                    59:a8:22:d3:6e:01:a2:f5:26:17:4a:d4:4c:7a:61:
+                    5a:5e:8e:4d:db:bf:2d:4c:e8:98:8f:60:69:a4:e7:
+                    2d:fb:b1:83:b6:3d:a1:97:2f:c5:ce:f1:47:7f:7b:
+                    68:72:6e:1e:95:e1:2c:cd:9b:25:31:fa:9f:9a:0e:
+                    ba:f6:a8:d4:8c:40:9b:20:1b:ef:0e:f6:32:b1:c1:
+                    ef:15:ec:5a:42:c3:6a:2d:4e:30:e7:44:61:22:41:
+                    f9:77:5a:42:25:10:ed:36:60:c2:d5:67:f7:7f:c4:
+                    d7:54:5e:49:99:5d:45:a7:4c:c9:5d:a4:5d:75:70:
+                    b6:9e:a3:8a:d9:6a:4c:d5:dd:c6:dd:12:9b:a1:90:
+                    85:08:92:93:87:f9:e7:69:96:82:c6:e9:5c:06:15:
+                    42:48:54:6e:15:5c:5b:bc:30:d9:3f:7c:8e:52:30:
+                    76:5d:3b:1a:ba:39:a3:eb:8e:83:ab:43:e4:90:a7:
+                    6e:af
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: critical
+                Digital Signature, Key Encipherment
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, TLS Web Server Authentication
+            X509v3 Subject Key Identifier: 
+                75:E8:CF:E7:D7:4B:78:94:85:CD:C8:DF:52:03:2E:CD:FB:F9:FF:87
+            X509v3 Authority Key Identifier: 
+                keyid:E5:E4:24:59:15:32:27:C9:20:B3:42:02:6C:B0:EF:32:DE:9B:20:5A
+
+            X509v3 Certificate Policies: 
+                Policy: 2.23.140.1.1
+                Policy: 2.16.840.1.114404.1.1.2.4.1
+                  CPS: https://ssl.trustwave.com/CA
+
+            X509v3 Subject Alternative Name: 
+                DNS:login.trustwave.com, DNS:cdn-login.trustwave.com, DNS:ssl.trustwave.com, DNS:sitedata.securetrust.com, DNS:sealserver.trustwave.com, DNS:sitedata.xramp.com, DNS:seal.securetrust.com, DNS:sealserver.trustkeeper.net, DNS:seal.xramp.com, DNS:rogers.trustwave.com, DNS:optus.trustwave.com, DNS:tis.trustwave.com, DNS:globe.trustwave.com, DNS:inmarsat.trustwave.com
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.trustwave.com/EVCA2_L1.crl
+
+            Authority Information Access: 
+                OCSP - URI:http://ocsp.trustwave.com/
+                CA Issuers - URI:http://ssl.trustwave.com/issuers/EVCA2_L1.crt
+
+            CT Precertificate SCTs: 
+                Signed Certificate Timestamp:
+                    Version   : v1 (0x0)
+                    Log ID    : A4:B9:09:90:B4:18:58:14:87:BB:13:A2:CC:67:70:0A:
+                                3C:35:98:04:F9:1B:DF:B8:E3:77:CD:0E:C8:0D:DC:10
+                    Timestamp : Jun 13 14:33:44.010 2018 GMT
+                    Extensions: none
+                    Signature : ecdsa-with-SHA256
+                                30:46:02:21:00:97:A4:CA:04:0F:F8:5D:DB:8D:94:65:
+                                24:B6:4B:C4:14:31:0C:36:B3:E4:8D:3B:0A:C2:8E:C6:
+                                F4:B6:B8:80:08:02:21:00:D3:2F:6E:7A:35:1E:BB:7C:
+                                3B:CB:02:79:BE:BD:4B:3F:DD:58:6A:31:A7:35:52:19:
+                                3E:88:EE:15:80:5D:65:68
+                Signed Certificate Timestamp:
+                    Version   : v1 (0x0)
+                    Log ID    : EE:4B:BD:B7:75:CE:60:BA:E1:42:69:1F:AB:E1:9E:66:
+                                A3:0F:7E:5F:B0:72:D8:83:00:C4:7B:89:7A:A8:FD:CB
+                    Timestamp : Jun 13 14:33:44.829 2018 GMT
+                    Extensions: none
+                    Signature : ecdsa-with-SHA256
+                                30:44:02:20:3B:3F:8E:F8:1D:73:88:3E:DF:34:35:D6:
+                                DE:FF:9B:F0:BA:61:84:9A:CF:0C:6F:60:07:FD:4B:12:
+                                DD:26:2F:FD:02:20:5C:EA:8D:59:CE:65:9F:7E:5D:A2:
+                                AE:C5:2F:E2:36:7A:19:E4:9E:48:45:73:C5:A6:CA:49:
+                                FD:A4:BF:94:0F:45
+                Signed Certificate Timestamp:
+                    Version   : v1 (0x0)
+                    Log ID    : 56:14:06:9A:2F:D7:C2:EC:D3:F5:E1:BD:44:B2:3E:C7:
+                                46:76:B9:BC:99:11:5C:C0:EF:94:98:55:D6:89:D0:DD
+                    Timestamp : Jun 13 14:33:43.623 2018 GMT
+                    Extensions: none
+                    Signature : ecdsa-with-SHA256
+                                30:45:02:20:40:A4:5B:11:00:BC:B3:4B:DA:48:00:FF:
+                                49:1D:1A:9E:1D:54:9D:42:36:66:99:8C:BD:27:75:48:
+                                AF:B1:13:B9:02:21:00:F5:EE:79:36:96:16:59:55:4F:
+                                73:B1:C8:6E:B0:C6:29:E1:EB:03:7E:86:37:83:C5:68:
+                                42:C3:83:BA:30:DE:D0
+    Signature Algorithm: sha256WithRSAEncryption
+         4b:a9:32:a2:94:ef:5a:a7:67:44:03:53:32:56:36:0f:12:0b:
+         3b:7a:6d:66:2b:ee:47:a9:35:26:30:62:86:9b:7d:aa:38:83:
+         13:ff:d0:56:ce:84:71:f8:16:49:ef:cc:70:da:34:ee:79:0e:
+         2a:82:05:82:e8:f7:e7:d6:b4:ed:85:ac:e7:d2:c3:f8:8a:8f:
+         ee:af:e2:d0:ba:3a:a9:a3:f8:70:ba:46:f0:16:05:60:d1:26:
+         6a:e4:05:00:86:fe:44:8c:68:44:6b:ec:d4:5a:41:00:3a:b1:
+         66:42:29:b8:47:1f:84:1e:94:5e:a4:f9:16:52:af:9f:3a:77:
+         d9:20:7c:01:82:9d:d9:9c:6f:9c:db:9f:90:21:1b:0b:05:7e:
+         e0:1d:d0:2f:e1:18:5c:c3:7f:f8:84:f7:f5:90:ac:09:9b:06:
+         90:48:b9:a9:b0:bd:2e:63:67:bc:8f:62:2f:c7:e2:18:ba:c9:
+         8c:96:dc:98:8e:5c:60:66:5a:aa:ee:54:bd:ce:49:08:ca:09:
+         92:bb:0f:26:07:ba:8c:df:88:4f:28:ef:eb:32:99:d3:2d:a7:
+         e0:c4:d4:51:d5:c9:a9:db:bf:c3:f7:14:4b:62:13:69:09:e9:
+         13:49:82:20:b3:31:ae:83:a7:0d:2c:de:69:3b:e2:3b:f0:9d:
+         67:61:98:3f
+-----BEGIN CERTIFICATE-----
+MIIIWzCCB0OgAwIBAgITBtsXc961CL+2hqjFrc7ZKw/cnTANBgkqhkiG9w0BAQsF
+ADCBsTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQHEwdD
+aGljYWdvMSEwHwYDVQQKExhUcnVzdHdhdmUgSG9sZGluZ3MsIEluYy4xOTA3BgNV
+BAMTMFRydXN0d2F2ZSBFeHRlbmRlZCBWYWxpZGF0aW9uIFNIQTI1NiBDQSwgTGV2
+ZWwgMTEfMB0GCSqGSIb3DQEJARYQY2FAdHJ1c3R3YXZlLmNvbTAeFw0xODA2MTMw
+ODMzNDNaFw0yMDA2MTIxNDMzNDNaMIHUMRwwGgYDVQQDExNsb2dpbi50cnVzdHdh
+dmUuY29tMSEwHwYDVQQKExhUcnVzdHdhdmUgSG9sZGluZ3MsIEluYy4xEDAOBgNV
+BAcTB0NoaWNhZ28xETAPBgNVBAgTCElsbGlub2lzMQswCQYDVQQGEwJVUzEQMA4G
+A1UEBRMHMzkzOTczNzEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzAR
+BgsrBgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdgIvWrA4Uzfw56xeP9ZvIDw8D
+3UbYcqcvu2HkCp/bGn+UerVbBKySXzfoWFQIXDkZhVSp0ZbS9sln4W3C+0DJhjy4
+l/6DjcQ1LlmoItNuAaL1JhdK1Ex6YVpejk3bvy1M6JiPYGmk5y37sYO2PaGXL8XO
+8Ud/e2hybh6V4SzNmyUx+p+aDrr2qNSMQJsgG+8O9jKxwe8V7FpCw2otTjDnRGEi
+Qfl3WkIlEO02YMLVZ/d/xNdUXkmZXUWnTMldpF11cLaeo4rZakzV3cbdEpuhkIUI
+kpOH+edploLG6VwGFUJIVG4VXFu8MNk/fI5SMHZdOxq6OaPrjoOrQ+SQp26vAgMB
+AAGjggRFMIIEQTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE
+FjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwHQYDVR0OBBYEFHXoz+fXS3iUhc3I31ID
+Ls37+f+HMB8GA1UdIwQYMBaAFOXkJFkVMifJILNCAmyw7zLemyBaME4GA1UdIARH
+MEUwBwYFZ4EMAQEwOgYMYIZIAYb9ZAEBAgQBMCowKAYIKwYBBQUHAgEWHGh0dHBz
+Oi8vc3NsLnRydXN0d2F2ZS5jb20vQ0EwggFDBgNVHREEggE6MIIBNoITbG9naW4u
+dHJ1c3R3YXZlLmNvbYIXY2RuLWxvZ2luLnRydXN0d2F2ZS5jb22CEXNzbC50cnVz
+dHdhdmUuY29tghhzaXRlZGF0YS5zZWN1cmV0cnVzdC5jb22CGHNlYWxzZXJ2ZXIu
+dHJ1c3R3YXZlLmNvbYISc2l0ZWRhdGEueHJhbXAuY29tghRzZWFsLnNlY3VyZXRy
+dXN0LmNvbYIac2VhbHNlcnZlci50cnVzdGtlZXBlci5uZXSCDnNlYWwueHJhbXAu
+Y29tghRyb2dlcnMudHJ1c3R3YXZlLmNvbYITb3B0dXMudHJ1c3R3YXZlLmNvbYIR
+dGlzLnRydXN0d2F2ZS5jb22CE2dsb2JlLnRydXN0d2F2ZS5jb22CFmlubWFyc2F0
+LnRydXN0d2F2ZS5jb20wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC50cnVz
+dHdhdmUuY29tL0VWQ0EyX0wxLmNybDBxBggrBgEFBQcBAQRlMGMwJgYIKwYBBQUH
+MAGGGmh0dHA6Ly9vY3NwLnRydXN0d2F2ZS5jb20vMDkGCCsGAQUFBzAChi1odHRw
+Oi8vc3NsLnRydXN0d2F2ZS5jb20vaXNzdWVycy9FVkNBMl9MMS5jcnQwggF+Bgor
+BgEEAdZ5AgQCBIIBbgSCAWoBaAB3AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3
+zQ7IDdwQAAABY/mREUoAAAQDAEgwRgIhAJekygQP+F3bjZRlJLZLxBQxDDaz5I07
+CsKOxvS2uIAIAiEA0y9uejUeu3w7ywJ5vr1LP91YajGnNVIZPojuFYBdZWgAdQDu
+S723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAWP5kRR9AAAEAwBGMEQC
+IDs/jvgdc4g+3zQ11t7/m/C6YYSazwxvYAf9SxLdJi/9AiBc6o1ZzmWffl2irsUv
+4jZ6GeSeSEVzxabKSf2kv5QPRQB2AFYUBpov18Ls0/XhvUSyPsdGdrm8mRFcwO+U
+mFXWidDdAAABY/mRD8cAAAQDAEcwRQIgQKRbEQC8s0vaSAD/SR0anh1UnUI2ZpmM
+vSd1SK+xE7kCIQD17nk2lhZZVU9zschusMYp4esDfoY3g8VoQsODujDe0DANBgkq
+hkiG9w0BAQsFAAOCAQEAS6kyopTvWqdnRANTMlY2DxILO3ptZivuR6k1JjBihpt9
+qjiDE//QVs6EcfgWSe/McNo07nkOKoIFguj359a07YWs59LD+IqP7q/i0Lo6qaP4
+cLpG8BYFYNEmauQFAIb+RIxoRGvs1FpBADqxZkIpuEcfhB6UXqT5FlKvnzp32SB8
+AYKd2ZxvnNufkCEbCwV+4B3QL+EYXMN/+IT39ZCsCZsGkEi5qbC9LmNnvI9iL8fi
+GLrJjJbcmI5cYGZaqu5Uvc5JCMoJkrsPJge6jN+ITyjv6zKZ0y2n4MTUUdXJqdu/
+w/cUS2ITaQnpE0mCILMxroOnDSzeaTviO/CdZ2GYPw==
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            35:96:2f:30:5c:5a:0b:ec:40:0d:4e:98:77:52:8c:65
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = US, O = SecureTrust Corporation, CN = SecureTrust CA
+        Validity
+            Not Before: Sep  1 14:35:34 2016 GMT
+            Not After : Sep 29 14:35:34 2024 GMT
+        Subject: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = "Trustwave Extended Validation SHA256 CA, Level 1", emailAddress = ca@trustwave.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:ad:ef:66:1c:ba:a2:bf:af:3d:15:62:24:ec:f6:
+                    9e:40:bb:96:a2:cf:25:75:15:f8:ac:d2:c7:78:3e:
+                    ff:5f:b2:6b:4d:f6:97:b8:84:1a:2d:fa:d4:38:3b:
+                    72:45:a6:6c:d0:bb:49:b0:41:e0:a6:be:dd:52:89:
+                    c3:20:7e:bd:3e:30:4f:ac:78:3e:84:12:ee:ee:86:
+                    f8:b9:d1:31:dc:9d:37:35:04:9d:9d:1f:df:a8:f6:
+                    34:64:c1:f6:34:fe:de:f5:31:52:28:a7:2d:67:f4:
+                    a6:cc:0f:23:19:c9:55:99:d8:93:1a:0d:5b:4f:1e:
+                    b1:81:6b:8f:5a:af:4e:a6:b2:10:4a:09:0f:e4:d4:
+                    5e:d4:67:93:43:b5:3f:13:5c:f1:2e:a6:b0:e8:f7:
+                    90:5a:31:12:1c:f1:9e:8a:5c:b0:d2:3a:fa:a9:5c:
+                    87:33:96:9c:93:da:6c:eb:4b:0d:dc:22:8d:1a:eb:
+                    21:c9:a4:1e:df:0d:9b:63:14:49:f5:14:47:fe:c2:
+                    0b:08:09:a6:4d:b8:dc:fd:c5:eb:19:03:06:75:a6:
+                    2d:6a:21:a7:5d:b7:38:e6:bd:fd:72:a7:db:ca:76:
+                    7b:d6:13:cf:34:4b:45:6c:e7:6a:93:70:bb:23:cb:
+                    eb:84:81:e2:29:a0:2d:16:44:cc:45:25:a6:1c:79:
+                    38:1f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE, pathlen:0
+            X509v3 Subject Key Identifier: 
+                E5:E4:24:59:15:32:27:C9:20:B3:42:02:6C:B0:EF:32:DE:9B:20:5A
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.trustwave.com/STCA.crl
+
+            X509v3 Certificate Policies: 
+                Policy: X509v3 Any Policy
+                  CPS: https://ssl.trustwave.com/CA
+
+            Authority Information Access: 
+                OCSP - URI:http://ocsp.trustwave.com
+                CA Issuers - URI:http://ssl.trustwave.com/issuers/STCA.crt
+
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, TLS Web Server Authentication
+            X509v3 Authority Key Identifier: 
+                keyid:42:32:B6:16:FA:04:FD:FE:5D:4B:7A:C3:FD:F7:4C:40:1D:5A:43:AF
+
+            X509v3 Subject Alternative Name: 
+                email:ca@trustwave.com
+    Signature Algorithm: sha256WithRSAEncryption
+         65:0c:20:39:2b:be:53:09:d3:01:cb:b8:fd:e5:92:77:82:c0:
+         65:3a:99:9d:e0:d7:b8:f2:53:64:49:c2:14:62:9d:87:2d:ad:
+         aa:f2:1b:b2:61:db:40:d0:f7:fa:69:4c:7a:31:4c:80:03:c3:
+         62:43:b0:2e:41:ca:99:5a:6e:d7:90:9c:b8:21:ae:5d:7b:2b:
+         56:fa:3c:ef:ab:cd:60:3f:34:52:95:c2:8e:ae:f0:68:7b:2f:
+         3d:22:52:e8:ad:ed:90:43:e1:e2:9c:45:e7:71:45:97:0f:42:
+         59:c3:f4:a4:d1:22:cf:78:49:1a:68:a2:db:2e:0a:ff:d8:e5:
+         bf:b5:14:c3:d5:d4:aa:d8:b5:b7:28:f7:21:15:95:a3:44:58:
+         ba:66:88:4b:2a:bc:b8:f1:89:61:26:b7:bd:6b:cf:3f:b4:4b:
+         9f:4e:b4:0f:e2:86:76:c6:3f:d5:eb:9e:17:bb:c1:fd:72:6c:
+         23:4e:3b:98:19:40:c2:ab:fc:eb:33:7c:b6:7b:a1:52:80:08:
+         63:8f:2e:57:12:65:14:56:f7:c8:00:b3:31:3e:d5:9b:e5:1e:
+         47:63:6a:67:d3:4a:ce:32:32:f5:28:ad:89:fd:36:15:e7:8c:
+         05:a5:db:c3:6e:0f:d9:b7:14:f8:84:d8:ee:74:7b:31:03:9c:
+         74:e2:68:e4
+-----BEGIN CERTIFICATE-----
+MIIFCzCCA/OgAwIBAgIQNZYvMFxaC+xADU6Yd1KMZTANBgkqhkiG9w0BAQsFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTE2MDkwMTE0MzUzNFoXDTI0MDky
+OTE0MzUzNFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhJbGxpbm9pczEQMA4G
+A1UEBxMHQ2hpY2FnbzEhMB8GA1UEChMYVHJ1c3R3YXZlIEhvbGRpbmdzLCBJbmMu
+MTkwNwYDVQQDEzBUcnVzdHdhdmUgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTSEEyNTYg
+Q0EsIExldmVsIDExHzAdBgkqhkiG9w0BCQEWEGNhQHRydXN0d2F2ZS5jb20wggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt72YcuqK/rz0VYiTs9p5Au5ai
+zyV1Ffis0sd4Pv9fsmtN9pe4hBot+tQ4O3JFpmzQu0mwQeCmvt1SicMgfr0+ME+s
+eD6EEu7uhvi50THcnTc1BJ2dH9+o9jRkwfY0/t71MVIopy1n9KbMDyMZyVWZ2JMa
+DVtPHrGBa49ar06mshBKCQ/k1F7UZ5NDtT8TXPEuprDo95BaMRIc8Z6KXLDSOvqp
+XIczlpyT2mzrSw3cIo0a6yHJpB7fDZtjFEn1FEf+wgsICaZNuNz9xesZAwZ1pi1q
+Iaddtzjmvf1yp9vKdnvWE880S0Vs52qTcLsjy+uEgeIpoC0WRMxFJaYceTgfAgMB
+AAGjggGFMIIBgTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTl5CRZFTIn
+ySCzQgJssO8y3psgWjAOBgNVHQ8BAf8EBAMCAYYwMgYDVR0fBCswKTAnoCWgI4Yh
+aHR0cDovL2NybC50cnVzdHdhdmUuY29tL1NUQ0EuY3JsMD0GA1UdIAQ2MDQwMgYE
+VR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3NzbC50cnVzdHdhdmUuY29tL0NB
+MGwGCCsGAQUFBwEBBGAwXjAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudHJ1c3R3
+YXZlLmNvbTA1BggrBgEFBQcwAoYpaHR0cDovL3NzbC50cnVzdHdhdmUuY29tL2lz
+c3VlcnMvU1RDQS5jcnQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB8G
+A1UdIwQYMBaAFEIythb6BP3+XUt6w/33TEAdWkOvMBsGA1UdEQQUMBKBEGNhQHRy
+dXN0d2F2ZS5jb20wDQYJKoZIhvcNAQELBQADggEBAGUMIDkrvlMJ0wHLuP3lkneC
+wGU6mZ3g17jyU2RJwhRinYctraryG7Jh20DQ9/ppTHoxTIADw2JDsC5ByplabteQ
+nLghrl17K1b6PO+rzWA/NFKVwo6u8Gh7Lz0iUuit7ZBD4eKcRedxRZcPQlnD9KTR
+Is94SRpootsuCv/Y5b+1FMPV1KrYtbco9yEVlaNEWLpmiEsqvLjxiWEmt71rzz+0
+S59OtA/ihnbGP9Xrnhe7wf1ybCNOO5gZQMKr/OszfLZ7oVKACGOPLlcSZRRW98gA
+szE+1ZvlHkdjamfTSs4yMvUorYn9NhXnjAWl28NuD9m3FPiE2O50ezEDnHTiaOQ=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0c:f0:8e:5c:08:16:a5:ad:42:7f:f0:eb:27:18:59:d0
+    Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C = US, O = SecureTrust Corporation, CN = SecureTrust CA
+        Validity
+            Not Before: Nov  7 19:31:18 2006 GMT
+            Not After : Dec 31 19:40:55 2029 GMT
+        Subject: C = US, O = SecureTrust Corporation, CN = SecureTrust CA
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:ab:a4:81:e5:95:cd:f5:f6:14:8e:c2:4f:ca:d4:
+                    e2:78:95:58:9c:41:e1:0d:99:40:24:17:39:91:33:
+                    66:e9:be:e1:83:af:62:5c:89:d1:fc:24:5b:61:b3:
+                    e0:11:11:41:1c:1d:6e:f0:b8:bb:f8:de:a7:81:ba:
+                    a6:48:c6:9f:1d:bd:be:8e:a9:41:3e:b8:94:ed:29:
+                    1a:d4:8e:d2:03:1d:03:ef:6d:0d:67:1c:57:d7:06:
+                    ad:ca:c8:f5:fe:0e:af:66:25:48:04:96:0b:5d:a3:
+                    ba:16:c3:08:4f:d1:46:f8:14:5c:f2:c8:5e:01:99:
+                    6d:fd:88:cc:86:a8:c1:6f:31:42:6c:52:3e:68:cb:
+                    f3:19:34:df:bb:87:18:56:80:26:c4:d0:dc:c0:6f:
+                    df:de:a0:c2:91:16:a0:64:11:4b:44:bc:1e:f6:e7:
+                    fa:63:de:66:ac:76:a4:71:a3:ec:36:94:68:7a:77:
+                    a4:b1:e7:0e:2f:81:7a:e2:b5:72:86:ef:a2:6b:8b:
+                    f0:0f:db:d3:59:3f:ba:72:bc:44:24:9c:e3:73:b3:
+                    f7:af:57:2f:42:26:9d:a9:74:ba:00:52:f2:4b:cd:
+                    53:7c:47:0b:36:85:0e:66:a9:08:97:16:34:57:c1:
+                    66:f7:80:e3:ed:70:54:c7:93:e0:2e:28:15:59:87:
+                    ba:bb
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            1.3.6.1.4.1.311.20.2: 
+                ...C.A
+            X509v3 Key Usage: 
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                42:32:B6:16:FA:04:FD:FE:5D:4B:7A:C3:FD:F7:4C:40:1D:5A:43:AF
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.securetrust.com/STCA.crl
+
+            1.3.6.1.4.1.311.21.1: 
+                ...
+    Signature Algorithm: sha1WithRSAEncryption
+         30:ed:4f:4a:e1:58:3a:52:72:5b:b5:a6:a3:65:18:a6:bb:51:
+         3b:77:e9:9d:ea:d3:9f:5c:e0:45:65:7b:0d:ca:5b:e2:70:50:
+         b2:94:05:14:ae:49:c7:8d:41:07:12:73:94:7e:0c:23:21:fd:
+         bc:10:7f:60:10:5a:72:f5:98:0e:ac:ec:b9:7f:dd:7a:6f:5d:
+         d3:1c:f4:ff:88:05:69:42:a9:05:71:c8:b7:ac:26:e8:2e:b4:
+         8c:6a:ff:71:dc:b8:b1:df:99:bc:7c:21:54:2b:e4:58:a2:bb:
+         57:29:ae:9e:a9:a3:19:26:0f:99:2e:08:b0:ef:fd:69:cf:99:
+         1a:09:8d:e3:a7:9f:2b:c9:36:34:7b:24:b3:78:4c:95:17:a4:
+         06:26:1e:b6:64:52:36:5f:60:67:d9:9c:c5:05:74:0b:e7:67:
+         23:d2:08:fc:88:e9:ae:8b:7f:e1:30:f4:37:7e:fd:c6:32:da:
+         2d:9e:44:30:30:6c:ee:07:de:d2:34:fc:d2:ff:40:f6:4b:f4:
+         66:46:06:54:a6:f2:32:0a:63:26:30:6b:9b:d1:dc:8b:47:ba:
+         e1:b9:d5:62:d0:a2:a0:f4:67:05:78:29:63:1a:6f:04:d6:f8:
+         c6:4c:a3:9a:b1:37:b4:8d:e5:28:4b:1d:9e:2c:c2:b8:68:bc:
+         ed:02:ee:31
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/trustcenter.websecurity.symantec.com.pem b/net/data/ssl/certificates/trustcenter.websecurity.symantec.com.pem
deleted file mode 100644
index e3143a9..0000000
--- a/net/data/ssl/certificates/trustcenter.websecurity.symantec.com.pem
+++ /dev/null
@@ -1,225 +0,0 @@
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            63:2e:d9:c0:ee:ab:b8:f6:1b:1e:57:cb:6c:95:f5:2e
-    Signature Algorithm: sha256WithRSAEncryption
-        Issuer: C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 EV SSL CA - G3
-        Validity
-            Not Before: Dec 22 00:00:00 2016 GMT
-            Not After : Dec 22 23:59:59 2018 GMT
-        Subject: 1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/businessCategory=Private Organization/serialNumber=2158113, C=US/postalCode=94043, ST=California, L=Mountain View/street=350 Ellis Street, O=Symantec Corporation, OU=Infrastructure Operations, CN=trustcenter.websecurity.symantec.com
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-                Public-Key: (2048 bit)
-                Modulus:
-                    00:aa:a4:a8:81:35:74:69:14:e1:2c:cb:cd:16:91:
-                    35:ea:76:ac:81:7b:15:41:46:92:f2:21:87:86:23:
-                    9c:66:42:ee:67:4a:df:23:97:42:f1:d7:54:27:dd:
-                    7a:78:2f:58:6f:50:fb:d2:7e:14:42:98:a3:fd:8e:
-                    cb:d7:48:51:dd:51:27:8b:49:08:80:98:3e:a7:f7:
-                    92:b2:06:d3:5e:26:71:3e:65:2d:b2:6a:af:6c:21:
-                    80:37:6e:aa:22:ae:d2:74:3a:2b:34:ea:4d:5f:dc:
-                    bf:95:f4:86:ea:41:f3:11:c8:c2:3a:33:1e:4e:d2:
-                    8f:0b:1c:69:fa:18:7f:1f:b1:56:6f:6d:8b:c3:c8:
-                    31:30:8e:09:fd:f7:82:c8:d9:03:83:2f:51:69:3c:
-                    8f:ee:f2:a9:5e:b2:ac:10:26:f0:cb:ae:72:44:7d:
-                    11:65:b4:49:3f:4e:41:2d:33:ed:a4:19:b1:ad:14:
-                    63:34:01:f4:1d:11:83:9e:ef:e8:30:4b:f1:55:a2:
-                    a0:80:3d:ca:59:ca:7b:8f:75:85:a2:9d:01:56:0c:
-                    96:77:e2:12:ff:d9:b3:e5:48:d4:b0:a5:63:50:51:
-                    c3:8d:35:cb:87:16:09:5c:6e:0a:e3:82:da:b0:cd:
-                    a4:60:c0:af:69:13:a3:7d:d1:04:c3:8f:c5:30:b8:
-                    cc:ff
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Subject Alternative Name: 
-                DNS:trustcenter.websecurity.symantec.com
-            X509v3 Basic Constraints: 
-                CA:FALSE
-            X509v3 Key Usage: critical
-                Digital Signature, Key Encipherment
-            X509v3 Extended Key Usage: 
-                TLS Web Server Authentication, TLS Web Client Authentication
-            X509v3 Certificate Policies: 
-                Policy: 2.23.140.1.1
-                Policy: 2.16.840.1.113733.1.7.23.6
-                  CPS: https://d.symcb.com/cps
-                  User Notice:
-                    Explicit Text: https://d.symcb.com/rpa
-
-            X509v3 Authority Key Identifier: 
-                keyid:01:59:AB:E7:DD:3A:0B:59:A6:64:63:D6:CF:20:07:57:D5:91:E7:6A
-
-            X509v3 CRL Distribution Points: 
-
-                Full Name:
-                  URI:http://sr.symcb.com/sr.crl
-
-            Authority Information Access: 
-                OCSP - URI:http://sr.symcd.com
-                CA Issuers - URI:http://sr.symcb.com/sr.crt
-
-            1.3.6.1.4.1.11129.2.4.2: 
-    Signature Algorithm: sha256WithRSAEncryption
-         0c:e4:4b:4c:57:2e:a7:df:f2:7e:9e:8b:d9:c1:25:99:a8:12:
-         8e:cd:fe:2d:9d:1a:4c:00:00:bb:50:2c:8f:cd:87:8c:13:4b:
-         07:e2:5e:79:0d:b8:c1:eb:c0:ed:4d:6a:93:a5:db:c8:f3:4c:
-         52:12:e0:41:31:c7:1f:6f:aa:8b:94:55:62:46:4c:18:60:b5:
-         ec:bd:e3:87:80:60:dc:40:59:d2:1f:5b:b9:83:00:4a:70:9f:
-         0a:95:8c:8c:f2:2d:18:98:d3:15:cd:db:81:c0:dd:85:34:d5:
-         ce:1b:c1:14:0b:29:ca:2a:cb:81:7e:18:e9:da:8b:ae:1b:3b:
-         d9:db:60:40:52:7f:0b:e5:2b:e2:57:ce:cd:0e:28:96:de:5a:
-         48:a7:75:5a:20:6e:92:73:c9:d0:2a:84:db:24:dd:64:a5:90:
-         1c:3c:e8:68:3c:87:fc:1e:5d:7f:0b:97:1a:c6:52:79:82:8e:
-         f9:ce:02:d6:e1:50:b4:53:a0:33:f3:01:a0:3a:f4:06:5a:38:
-         b0:ad:19:f5:9a:32:0b:82:44:23:60:02:38:79:d1:fc:c6:e0:
-         77:8d:12:80:00:f9:78:4a:c3:7f:72:7a:ad:7c:05:7f:c8:e0:
-         13:3b:44:47:6d:f7:ee:58:0d:c6:ed:73:93:5e:99:28:9e:3e:
-         1f:60:b4:54
------BEGIN CERTIFICATE-----
-MIIHRTCCBi2gAwIBAgIQYy7ZwO6ruPYbHlfLbJX1LjANBgkqhkiG9w0BAQsFADB3
-MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd
-BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5bWFudGVj
-IENsYXNzIDMgRVYgU1NMIENBIC0gRzMwHhcNMTYxMjIyMDAwMDAwWhcNMTgxMjIy
-MjM1OTU5WjCCATgxEzARBgsrBgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIB
-AgwIRGVsYXdhcmUxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRAwDgYD
-VQQFEwcyMTU4MTEzMQswCQYDVQQGEwJVUzEOMAwGA1UEEQwFOTQwNDMxEzARBgNV
-BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxGTAXBgNVBAkM
-EDM1MCBFbGxpcyBTdHJlZXQxHTAbBgNVBAoMFFN5bWFudGVjIENvcnBvcmF0aW9u
-MSIwIAYDVQQLDBlJbmZyYXN0cnVjdHVyZSBPcGVyYXRpb25zMS0wKwYDVQQDDCR0
-cnVzdGNlbnRlci53ZWJzZWN1cml0eS5zeW1hbnRlYy5jb20wggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQCqpKiBNXRpFOEsy80WkTXqdqyBexVBRpLyIYeG
-I5xmQu5nSt8jl0Lx11Qn3Xp4L1hvUPvSfhRCmKP9jsvXSFHdUSeLSQiAmD6n95Ky
-BtNeJnE+ZS2yaq9sIYA3bqoirtJ0Ois06k1f3L+V9IbqQfMRyMI6Mx5O0o8LHGn6
-GH8fsVZvbYvDyDEwjgn994LI2QODL1FpPI/u8qlesqwQJvDLrnJEfRFltEk/TkEt
-M+2kGbGtFGM0AfQdEYOe7+gwS/FVoqCAPcpZynuPdYWinQFWDJZ34hL/2bPlSNSw
-pWNQUcONNcuHFglcbgrjgtqwzaRgwK9pE6N90QTDj8UwuMz/AgMBAAGjggMIMIID
-BDAvBgNVHREEKDAmgiR0cnVzdGNlbnRlci53ZWJzZWN1cml0eS5zeW1hbnRlYy5j
-b20wCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
-AwEGCCsGAQUFBwMCMG8GA1UdIARoMGYwBwYFZ4EMAQEwWwYLYIZIAYb4RQEHFwYw
-TDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUH
-AgIwGQwXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwHwYDVR0jBBgwFoAUAVmr5906
-C1mmZGPWzyAHV9WR52owKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3NyLnN5bWNi
-LmNvbS9zci5jcmwwVwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8v
-c3Iuc3ltY2QuY29tMCYGCCsGAQUFBzAChhpodHRwOi8vc3Iuc3ltY2IuY29tL3Ny
-LmNydDCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHYA3esdK3oNT6Ygi4GtgWhw
-fi6OnQHVXIiNPRHEzbbsvswAAAFZI/WvZwAABAMARzBFAiB2aElKdjf+/hhIZ5UU
-jLXLhb8t4O4SroL85Xy0e0L+tQIhAP81wCJr4JonZ+Vn0UPOEj+EqmmUFtYzI+hV
-cU6XVEjOAHYA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFZI/Wv
-uAAABAMARzBFAiA3camsaIGN2AHELeYmjcLeds/4N3/GV/VOvx78gLmqBgIhAO7e
-gwMKhlU2UOVZUH2ZEdH3BECDr+/PY1buXFzm9DJuAHUAvHjh38X2PGhGSTNNoQ+h
-Xwl5aSAJwIG08/aRfz7ZuKUAAAFZI/WwZQAABAMARjBEAiArg7uTYAvh3IBU4Qlz
-zOZxjY8JzjoxEUk20hkzsy54mAIgc2uRlElRnMfFeUoMSBGLKk9VPC0LZUpmSs4O
-xEiL22AwDQYJKoZIhvcNAQELBQADggEBAAzkS0xXLqff8n6ei9nBJZmoEo7N/i2d
-GkwAALtQLI/Nh4wTSwfiXnkNuMHrwO1NapOl28jzTFIS4EExxx9vqouUVWJGTBhg
-tey944eAYNxAWdIfW7mDAEpwnwqVjIzyLRiY0xXN24HA3YU01c4bwRQLKcoqy4F+
-GOnai64bO9nbYEBSfwvlK+JXzs0OKJbeWkindVogbpJzydAqhNsk3WSlkBw86Gg8
-h/weXX8LlxrGUnmCjvnOAtbhULRToDPzAaA69AZaOLCtGfWaMguCRCNgAjh50fzG
-4HeNEoAA+XhKw39yeq18BX/I4BM7REdt9+5YDcbtc5NemSiePh9gtFQ=
------END CERTIFICATE-----
-
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            7e:e1:4a:6f:6f:ef:f2:d3:7f:3f:ad:65:4d:3a:da:b4
-        Signature Algorithm: sha256WithRSAEncryption
-        Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G5
-        Validity
-            Not Before: Oct 31 00:00:00 2013 GMT
-            Not After : Oct 30 23:59:59 2023 GMT
-        Subject: C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 EV SSL CA - G3
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-            RSA Public Key: (2048 bit)
-                Modulus (2048 bit):
-                    00:d8:a1:65:74:23:e8:2b:64:e2:32:d7:33:37:3d:
-                    8e:f5:34:16:48:dd:4f:7f:87:1c:f8:44:23:13:8e:
-                    fb:11:d8:44:5a:18:71:8e:60:16:26:92:9b:fd:17:
-                    0b:e1:71:70:42:fe:bf:fa:1c:c0:aa:a3:a7:b5:71:
-                    e8:ff:18:83:f6:df:10:0a:13:62:c8:3d:9c:a7:de:
-                    2e:3f:0c:d9:1d:e7:2e:fb:2a:ce:c8:9a:7f:87:bf:
-                    d8:4c:04:15:32:c9:d1:cc:95:71:a0:4e:28:4f:84:
-                    d9:35:fb:e3:86:6f:94:53:e6:72:8a:63:67:2e:be:
-                    69:f6:f7:6e:8e:9c:60:04:eb:29:fa:c4:47:42:d2:
-                    78:98:e3:ec:0b:a5:92:dc:b7:9a:bd:80:64:2b:38:
-                    7c:38:09:5b:66:f6:2d:95:7a:86:b2:34:2e:85:9e:
-                    90:0e:5f:b7:5d:a4:51:72:46:70:13:bf:67:f2:b6:
-                    a7:4d:14:1e:6c:b9:53:ee:23:1a:4e:8d:48:55:43:
-                    41:b1:89:75:6a:40:28:c5:7d:dd:d2:6e:d2:02:19:
-                    2f:7b:24:94:4b:eb:f1:1a:a9:9b:e3:23:9a:ea:fa:
-                    33:ab:0a:2c:b7:f4:60:08:dd:9f:1c:cd:dd:2d:01:
-                    66:80:af:b3:2f:29:1d:23:b8:8a:e1:a1:70:07:0c:
-                    34:0f
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            Authority Information Access: 
-                OCSP - URI:http://s2.symcb.com
-
-            X509v3 Basic Constraints: critical
-                CA:TRUE, pathlen:0
-            X509v3 Certificate Policies: 
-                Policy: X509v3 Any Policy
-                  CPS: http://www.symauth.com/cps
-                  User Notice:
-                    Explicit Text: http://www.symauth.com/rpa
-
-            X509v3 CRL Distribution Points: 
-                URI:http://s1.symcb.com/pca3-g5.crl
-
-            X509v3 Key Usage: critical
-                Certificate Sign, CRL Sign
-            X509v3 Subject Alternative Name: 
-                DirName:/CN=SymantecPKI-1-533
-            X509v3 Subject Key Identifier: 
-                01:59:AB:E7:DD:3A:0B:59:A6:64:63:D6:CF:20:07:57:D5:91:E7:6A
-            X509v3 Authority Key Identifier: 
-                keyid:7F:D3:65:A7:C2:DD:EC:BB:F0:30:09:F3:43:39:FA:02:AF:33:31:33
-
-    Signature Algorithm: sha256WithRSAEncryption
-        42:01:55:7b:d0:16:1a:5d:58:e8:bb:9b:a8:4d:d7:f3:d7:eb:
-        13:94:86:d6:7f:21:0b:47:bc:57:9b:92:5d:4f:05:9f:38:a4:
-        10:7c:cf:83:be:06:43:46:8d:08:bc:6a:d7:10:a6:fa:ab:af:
-        2f:61:a8:63:f2:65:df:7f:4c:88:12:88:4f:b3:69:d9:ff:27:
-        c0:0a:97:91:8f:56:fb:89:c4:a8:bb:92:2d:1b:73:b0:c6:ab:
-        36:f4:96:6c:20:08:ef:0a:1e:66:24:45:4f:67:00:40:c8:07:
-        54:74:33:3b:a6:ad:bb:23:9f:66:ed:a2:44:70:34:fb:0e:ea:
-        01:fd:cf:78:74:df:a7:ad:55:b7:5f:4d:f6:d6:3f:e0:86:ce:
-        24:c7:42:a9:13:14:44:35:4b:b6:df:c9:60:ac:0c:7f:d9:93:
-        21:4b:ee:9c:e4:49:02:98:d3:60:7b:5c:bc:d5:30:2f:07:ce:
-        44:42:c4:0b:99:fe:e6:9f:fc:b0:78:86:51:6d:d1:2c:9d:c6:
-        96:fb:85:82:bb:04:2f:f7:62:80:ef:62:da:7f:f6:0e:ac:90:
-        b8:56:bd:79:3f:f2:80:6e:a3:d9:b9:0f:5d:3a:07:1d:91:93:
-        86:4b:29:4c:e1:dc:b5:e1:e0:33:9d:b3:cb:36:91:4b:fe:a1:
-        b4:ee:f0:f9
------BEGIN CERTIFICATE-----
-MIIFKzCCBBOgAwIBAgIQfuFKb2/v8tN/P61lTTratDANBgkqhkiG9w0BAQsFADCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
-ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB3MQsw
-CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
-BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5bWFudGVjIENs
-YXNzIDMgRVYgU1NMIENBIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQDYoWV0I+grZOIy1zM3PY71NBZI3U9/hxz4RCMTjvsR2ERaGHGOYBYmkpv9
-FwvhcXBC/r/6HMCqo6e1cej/GIP23xAKE2LIPZyn3i4/DNkd5y77Ks7Imn+Hv9hM
-BBUyydHMlXGgTihPhNk1++OGb5RT5nKKY2cuvmn2926OnGAE6yn6xEdC0niY4+wL
-pZLct5q9gGQrOHw4CVtm9i2VeoayNC6FnpAOX7ddpFFyRnATv2fytqdNFB5suVPu
-IxpOjUhVQ0GxiXVqQCjFfd3SbtICGS97JJRL6/EaqZvjI5rq+jOrCiy39GAI3Z8c
-zd0tAWaAr7MvKR0juIrhoXAHDDQPAgMBAAGjggFdMIIBWTAvBggrBgEFBQcBAQQj
-MCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wEgYDVR0TAQH/BAgw
-BgEB/wIBADBlBgNVHSAEXjBcMFoGBFUdIAAwUjAmBggrBgEFBQcCARYaaHR0cDov
-L3d3dy5zeW1hdXRoLmNvbS9jcHMwKAYIKwYBBQUHAgIwHBoaaHR0cDovL3d3dy5z
-eW1hdXRoLmNvbS9ycGEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3MxLnN5bWNi
-LmNvbS9wY2EzLWc1LmNybDAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwx
-GjAYBgNVBAMTEVN5bWFudGVjUEtJLTEtNTMzMB0GA1UdDgQWBBQBWavn3ToLWaZk
-Y9bPIAdX1ZHnajAfBgNVHSMEGDAWgBR/02Wnwt3su/AwCfNDOfoCrzMxMzANBgkq
-hkiG9w0BAQsFAAOCAQEAQgFVe9AWGl1Y6LubqE3X89frE5SG1n8hC0e8V5uSXU8F
-nzikEHzPg74GQ0aNCLxq1xCm+quvL2GoY/Jl339MiBKIT7Np2f8nwAqXkY9W+4nE
-qLuSLRtzsMarNvSWbCAI7woeZiRFT2cAQMgHVHQzO6atuyOfZu2iRHA0+w7qAf3P
-eHTfp61Vt19N9tY/4IbOJMdCqRMURDVLtt/JYKwMf9mTIUvunORJApjTYHtcvNUw
-LwfORELEC5n+5p/8sHiGUW3RLJ3GlvuFgrsEL/digO9i2n/2DqyQuFa9eT/ygG6j
-2bkPXToHHZGThkspTOHcteHgM52zyzaRS/6htO7w+Q==
------END CERTIFICATE-----
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc
index 901d01eb9..1cc80d6 100644
--- a/net/quic/chromium/quic_chromium_client_session.cc
+++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -1601,13 +1601,17 @@
 int QuicChromiumClientSession::HandleWriteError(
     int error_code,
     scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> packet) {
+  current_connection_migration_cause_ = ON_WRITE_ERROR;
+  LogHandshakeStatusOnConnectionMigrationSignal();
+
   base::UmaHistogramSparse("Net.QuicSession.WriteError", -error_code);
   if (IsCryptoHandshakeConfirmed()) {
     base::UmaHistogramSparse("Net.QuicSession.WriteError.HandshakeConfirmed",
                              -error_code);
   }
+
   if (error_code == ERR_MSG_TOO_BIG || stream_factory_ == nullptr ||
-      !migrate_session_on_network_change_v2_) {
+      !migrate_session_on_network_change_v2_ || !IsCryptoHandshakeConfirmed()) {
     return error_code;
   }
 
@@ -1655,7 +1659,7 @@
     // Close the connection if migration failed. Do not cause a
     // connection close packet to be sent since socket may be borked.
     connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
-                                  "Write and subsequent migration failed",
+                                  "Write error with nulled stream factory",
                                   quic::ConnectionCloseBehavior::SILENT_CLOSE);
     return;
   }
@@ -1666,13 +1670,11 @@
     // Close the connection if migration failed. Do not cause a
     // connection close packet to be sent since socket may be borked.
     connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
-                                  "Write and subsequent migration failed",
+                                  "Write error for non-migratable session",
                                   quic::ConnectionCloseBehavior::SILENT_CLOSE);
     return;
   }
 
-  LogHandshakeStatusOnConnectionMigrationSignal();
-
   NetworkChangeNotifier::NetworkHandle new_network =
       stream_factory_->FindAlternateNetwork(
           GetDefaultSocket()->GetBoundNetwork());
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index d0511b7..74af500 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -389,6 +389,9 @@
   const NetLogWithSource net_log_;
   int num_sent_client_hellos_;
   QuicChromiumClientSession* session_;
+  // If connection migraiton is supported, |network_| denotes the network on
+  // which |session_| is created.
+  NetworkChangeNotifier::NetworkHandle network_;
   CompletionOnceCallback host_resolution_callback_;
   CompletionOnceCallback callback_;
   AddressList address_list_;
@@ -422,6 +425,7 @@
                                  NetLogSourceType::QUIC_STREAM_FACTORY_JOB)),
       num_sent_client_hellos_(0),
       session_(nullptr),
+      network_(NetworkChangeNotifier::kInvalidNetworkHandle),
       weak_factory_(this) {
   net_log_.BeginEvent(
       NetLogEventType::QUIC_STREAM_FACTORY_JOB,
@@ -552,7 +556,7 @@
   int rv = factory_->CreateSession(
       key_, quic_version_, cert_verify_flags_, require_confirmation,
       address_list_, dns_resolution_start_time_, dns_resolution_end_time_,
-      net_log_, &session_);
+      net_log_, &session_, &network_);
   if (rv != OK) {
     DCHECK(rv != ERR_IO_PENDING);
     DCHECK(!session_);
@@ -1456,7 +1460,8 @@
     base::TimeTicks dns_resolution_start_time,
     base::TimeTicks dns_resolution_end_time,
     const NetLogWithSource& net_log,
-    QuicChromiumClientSession** session) {
+    QuicChromiumClientSession** session,
+    NetworkChangeNotifier::NetworkHandle* network) {
   TRACE_EVENT0(kNetTracingCategory, "QuicStreamFactory::CreateSession");
   IPEndPoint addr = *address_list.begin();
   const quic::QuicServerId& server_id = key.server_id();
@@ -1471,14 +1476,15 @@
     return rv;
 
   if (migrate_sessions_on_network_change_v2_) {
+    *network = socket->GetBoundNetwork();
     if (default_network_ == NetworkChangeNotifier::kInvalidNetworkHandle) {
       // QuicStreamFactory may miss the default network signal before its
       // creation, update |default_network_| when the first socket is bound
       // to the default network.
-      default_network_ = socket->GetBoundNetwork();
+      default_network_ = *network;
     } else {
       UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.DefaultNetworkMatch",
-                            default_network_ == socket->GetBoundNetwork());
+                            default_network_ == *network);
     }
   }
 
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index df3c14f..7fe42c6 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -418,7 +418,8 @@
                     base::TimeTicks dns_resolution_start_time,
                     base::TimeTicks dns_resolution_end_time,
                     const NetLogWithSource& net_log,
-                    QuicChromiumClientSession** session);
+                    QuicChromiumClientSession** session,
+                    NetworkChangeNotifier::NetworkHandle* network);
   void ActivateSession(const QuicSessionAliasKey& key,
                        QuicChromiumClientSession* session);
   void MarkAllActiveSessionsGoingAway();
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index 3668057..f550b40b 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -4375,6 +4375,72 @@
   EXPECT_TRUE(quic_data3.AllWriteDataConsumed());
 }
 
+// Test that connection will be closed with PACKET_WRITE_ERROR if a write error
+// is triggered before handshake is confirmed and connection migration is turned
+// on.
+TEST_P(QuicStreamFactoryTest, MigrationOnWriteErrorBeforeHandshakeConfirmed) {
+  InitializeConnectionMigrationV2Test(
+      {kDefaultNetworkForTests, kNewNetworkForTests});
+
+  // Use unmocked crypto stream to do crypto connect.
+  crypto_client_stream_factory_.set_handshake_mode(
+      quic::MockCryptoClientStream::USE_DEFAULT_CRYPTO_STREAM);
+
+  MockQuicData socket_data;
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  // Trigger PACKET_WRITE_ERROR when sending packets in crypto connect.
+  socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  // Create request, should fail after the write of the CHLO fails.
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_, version_, privacy_mode_,
+                            DEFAULT_PRIORITY, SocketTag(),
+                            /*cert_verify_flags=*/0, url_, net_log_,
+                            &net_error_details_, callback_.callback()));
+  EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult());
+  EXPECT_FALSE(HasActiveSession(host_port_pair_));
+  EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+
+  // Verify new requests can be sent normally.
+  crypto_client_stream_factory_.set_handshake_mode(
+      quic::MockCryptoClientStream::COLD_START);
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+  MockQuicData socket_data2;
+  socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data2.AddSocketDataToFactory(socket_factory_.get());
+
+  QuicStreamRequest request2(factory_.get());
+  EXPECT_EQ(ERR_IO_PENDING,
+            request2.Request(host_port_pair_, version_, privacy_mode_,
+                             DEFAULT_PRIORITY, SocketTag(),
+                             /*cert_verify_flags=*/0, url_, net_log_,
+                             &net_error_details_, callback_.callback()));
+  EXPECT_FALSE(HasActiveSession(host_port_pair_));
+  EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+  // Run the message loop to complete host resolution.
+  base::RunLoop().RunUntilIdle();
+
+  // Complete handshake. QuicStreamFactory::Job should complete and succeed.
+  crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
+      quic::QuicSession::HANDSHAKE_CONFIRMED);
+  EXPECT_THAT(callback_.WaitForResult(), IsOk());
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
+  EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+
+  // Create QuicHttpStream.
+  std::unique_ptr<HttpStream> stream = CreateStream(&request2);
+  EXPECT_TRUE(stream.get());
+  stream.reset();
+  EXPECT_TRUE(socket_data.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+  EXPECT_TRUE(socket_data2.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
+}
+
 void QuicStreamFactoryTestBase::TestMigrationOnWriteError(
     IoMode write_error_mode) {
   InitializeConnectionMigrationV2Test(
diff --git a/pdf/pdf.cc b/pdf/pdf.cc
index d824a06d..f32f8175 100644
--- a/pdf/pdf.cc
+++ b/pdf/pdf.cc
@@ -8,10 +8,6 @@
 
 #include <utility>
 
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
 #include "base/logging.h"
 #include "base/macros.h"
 #include "pdf/out_of_process_instance.h"
@@ -51,8 +47,7 @@
 }  // namespace
 
 #if defined(OS_WIN)
-bool RenderPDFPageToDC(const void* pdf_buffer,
-                       int buffer_size,
+bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer,
                        int page_number,
                        HDC dc,
                        int dpi_x,
@@ -77,8 +72,8 @@
       pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width, bounds_height),
       fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds,
       autorotate, use_color);
-  return engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size, page_number,
-                                           settings, dc);
+  return engine_exports->RenderPDFPageToDC(pdf_buffer, page_number, settings,
+                                           dc);
 }
 
 void SetPDFEnsureTypefaceCharactersAccessible(
@@ -95,8 +90,7 @@
 }
 #endif  // defined(OS_WIN)
 
-bool GetPDFDocInfo(const void* pdf_buffer,
-                   int buffer_size,
+bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
                    int* page_count,
                    double* max_page_width) {
   ScopedSdkInitializer scoped_sdk_initializer;
@@ -104,12 +98,10 @@
     return false;
 
   PDFEngineExports* engine_exports = PDFEngineExports::Get();
-  return engine_exports->GetPDFDocInfo(pdf_buffer, buffer_size, page_count,
-                                       max_page_width);
+  return engine_exports->GetPDFDocInfo(pdf_buffer, page_count, max_page_width);
 }
 
-bool GetPDFPageSizeByIndex(const void* pdf_buffer,
-                           int pdf_buffer_size,
+bool GetPDFPageSizeByIndex(base::span<const uint8_t> pdf_buffer,
                            int page_number,
                            double* width,
                            double* height) {
@@ -119,12 +111,11 @@
 
   chrome_pdf::PDFEngineExports* engine_exports =
       chrome_pdf::PDFEngineExports::Get();
-  return engine_exports->GetPDFPageSizeByIndex(pdf_buffer, pdf_buffer_size,
-                                               page_number, width, height);
+  return engine_exports->GetPDFPageSizeByIndex(pdf_buffer, page_number, width,
+                                               height);
 }
 
-bool RenderPDFPageToBitmap(const void* pdf_buffer,
-                           int pdf_buffer_size,
+bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
                            int page_number,
                            void* bitmap_buffer,
                            int bitmap_width,
@@ -141,8 +132,8 @@
   PDFEngineExports::RenderingSettings settings(
       dpi_x, dpi_y, pp::Rect(bitmap_width, bitmap_height), true, false, true,
       true, autorotate, use_color);
-  return engine_exports->RenderPDFPageToBitmap(
-      pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer);
+  return engine_exports->RenderPDFPageToBitmap(pdf_buffer, page_number,
+                                               settings, bitmap_buffer);
 }
 
 bool ConvertPdfPagesToNupPdf(
diff --git a/pdf/pdf.h b/pdf/pdf.h
index bc36bb51..40bb162 100644
--- a/pdf/pdf.h
+++ b/pdf/pdf.h
@@ -33,7 +33,6 @@
 
 // |pdf_buffer| is the buffer that contains the entire PDF document to be
 //     rendered.
-// |buffer_size| is the size of |pdf_buffer| in bytes.
 // |page_number| is the 0-based index of the page to be rendered.
 // |dc| is the device context to render into.
 // |dpi_x| and |dpi_y| is the resolution.
@@ -58,8 +57,7 @@
 //     the output bound.
 // |use_color| specifies color or grayscale.
 // Returns false if the document or the page number are not valid.
-bool RenderPDFPageToDC(const void* pdf_buffer,
-                       int buffer_size,
+bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer,
                        int page_number,
                        HDC dc,
                        int dpi_x,
@@ -85,22 +83,19 @@
 
 // |page_count| and |max_page_width| are optional and can be NULL.
 // Returns false if the document is not valid.
-bool GetPDFDocInfo(const void* pdf_buffer,
-                   int buffer_size,
+bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
                    int* page_count,
                    double* max_page_width);
 
 // Gets the dimensions of a specific page in a document.
 // |pdf_buffer| is the buffer that contains the entire PDF document to be
 //     rendered.
-// |pdf_buffer_size| is the size of |pdf_buffer| in bytes.
 // |page_number| is the page number that the function will get the dimensions
 //     of.
 // |width| is the output for the width of the page in points.
 // |height| is the output for the height of the page in points.
 // Returns false if the document or the page number are not valid.
-bool GetPDFPageSizeByIndex(const void* pdf_buffer,
-                           int pdf_buffer_size,
+bool GetPDFPageSizeByIndex(base::span<const uint8_t> pdf_buffer,
                            int page_number,
                            double* width,
                            double* height);
@@ -108,7 +103,6 @@
 // Renders PDF page into 4-byte per pixel BGRA color bitmap.
 // |pdf_buffer| is the buffer that contains the entire PDF document to be
 //     rendered.
-// |pdf_buffer_size| is the size of |pdf_buffer| in bytes.
 // |page_number| is the 0-based index of the page to be rendered.
 // |bitmap_buffer| is the output buffer for bitmap.
 // |bitmap_width| is the width of the output bitmap.
@@ -118,8 +112,7 @@
 //     the output bound.
 // |use_color| specifies color or grayscale.
 // Returns false if the document or the page number are not valid.
-bool RenderPDFPageToBitmap(const void* pdf_buffer,
-                           int pdf_buffer_size,
+bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
                            int page_number,
                            void* bitmap_buffer,
                            int bitmap_width,
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index 1e4dc14..ade944a0 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -7,12 +7,6 @@
 
 #include <stdint.h>
 
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
 #include <memory>
 #include <set>
 #include <string>
@@ -22,6 +16,7 @@
 #include "base/optional.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "ppapi/c/dev/pp_cursor_type_dev.h"
 #include "ppapi/c/dev/ppp_printing_dev.h"
 #include "ppapi/c/ppb_input_event.h"
@@ -35,6 +30,10 @@
 #include "ui/gfx/geometry/point_f.h"
 
 #if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#if defined(OS_WIN)
 typedef void (*PDFEnsureTypefaceCharactersAccessible)(const LOGFONT* font,
                                                       const wchar_t* text,
                                                       size_t text_length);
@@ -445,8 +444,7 @@
 
 #if defined(OS_WIN)
   // See the definition of RenderPDFPageToDC in pdf.cc for details.
-  virtual bool RenderPDFPageToDC(const void* pdf_buffer,
-                                 int buffer_size,
+  virtual bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer,
                                  int page_number,
                                  const RenderingSettings& settings,
                                  HDC dc) = 0;
@@ -459,8 +457,7 @@
 #endif  // defined(OS_WIN)
 
   // See the definition of RenderPDFPageToBitmap in pdf.cc for details.
-  virtual bool RenderPDFPageToBitmap(const void* pdf_buffer,
-                                     int pdf_buffer_size,
+  virtual bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
                                      int page_number,
                                      const RenderingSettings& settings,
                                      void* bitmap_buffer) = 0;
@@ -483,14 +480,12 @@
       void** dest_pdf_buffer,
       size_t* dest_pdf_buffer_size) = 0;
 
-  virtual bool GetPDFDocInfo(const void* pdf_buffer,
-                             int buffer_size,
+  virtual bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
                              int* page_count,
                              double* max_page_width) = 0;
 
   // See the definition of GetPDFPageSizeByIndex in pdf.cc for details.
-  virtual bool GetPDFPageSizeByIndex(const void* pdf_buffer,
-                                     int pdf_buffer_size,
+  virtual bool GetPDFPageSizeByIndex(base::span<const uint8_t> pdf_buffer,
                                      int page_number,
                                      double* width,
                                      double* height) = 0;
diff --git a/pdf/pdfium/pdfium_engine_exports.cc b/pdf/pdfium/pdfium_engine_exports.cc
index 2dcfc55..dad6a99 100644
--- a/pdf/pdfium/pdfium_engine_exports.cc
+++ b/pdf/pdfium/pdfium_engine_exports.cc
@@ -95,12 +95,10 @@
 }
 
 ScopedFPDFDocument LoadPdfData(base::span<const uint8_t> pdf_buffer) {
-  ScopedFPDFDocument doc;
-  if (base::IsValueInRangeForNumericType<int>(pdf_buffer.size())) {
-    doc.reset(
-        FPDF_LoadMemDocument(pdf_buffer.data(), pdf_buffer.size(), nullptr));
-  }
-  return doc;
+  if (!base::IsValueInRangeForNumericType<int>(pdf_buffer.size()))
+    return nullptr;
+  return ScopedFPDFDocument(
+      FPDF_LoadMemDocument(pdf_buffer.data(), pdf_buffer.size(), nullptr));
 }
 
 ScopedFPDFDocument CreatePdfDoc(
@@ -188,13 +186,12 @@
 PDFiumEngineExports::~PDFiumEngineExports() {}
 
 #if defined(OS_WIN)
-bool PDFiumEngineExports::RenderPDFPageToDC(const void* pdf_buffer,
-                                            int buffer_size,
-                                            int page_number,
-                                            const RenderingSettings& settings,
-                                            HDC dc) {
-  ScopedFPDFDocument doc(
-      FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr));
+bool PDFiumEngineExports::RenderPDFPageToDC(
+    base::span<const uint8_t> pdf_buffer,
+    int page_number,
+    const RenderingSettings& settings,
+    HDC dc) {
+  ScopedFPDFDocument doc = LoadPdfData(pdf_buffer);
   if (!doc)
     return false;
   ScopedFPDFPage page(FPDF_LoadPage(doc.get(), page_number));
@@ -276,13 +273,11 @@
 #endif  // defined(OS_WIN)
 
 bool PDFiumEngineExports::RenderPDFPageToBitmap(
-    const void* pdf_buffer,
-    int pdf_buffer_size,
+    base::span<const uint8_t> pdf_buffer,
     int page_number,
     const RenderingSettings& settings,
     void* bitmap_buffer) {
-  ScopedFPDFDocument doc(
-      FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr));
+  ScopedFPDFDocument doc = LoadPdfData(pdf_buffer);
   if (!doc)
     return false;
   ScopedFPDFPage page(FPDF_LoadPage(doc.get(), page_number));
@@ -342,12 +337,10 @@
                               dest_pdf_buffer_size);
 }
 
-bool PDFiumEngineExports::GetPDFDocInfo(const void* pdf_buffer,
-                                        int buffer_size,
+bool PDFiumEngineExports::GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
                                         int* page_count,
                                         double* max_page_width) {
-  ScopedFPDFDocument doc(
-      FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr));
+  ScopedFPDFDocument doc = LoadPdfData(pdf_buffer);
   if (!doc)
     return false;
 
@@ -373,13 +366,12 @@
   return true;
 }
 
-bool PDFiumEngineExports::GetPDFPageSizeByIndex(const void* pdf_buffer,
-                                                int pdf_buffer_size,
-                                                int page_number,
-                                                double* width,
-                                                double* height) {
-  ScopedFPDFDocument doc(
-      FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr));
+bool PDFiumEngineExports::GetPDFPageSizeByIndex(
+    base::span<const uint8_t> pdf_buffer,
+    int page_number,
+    double* width,
+    double* height) {
+  ScopedFPDFDocument doc = LoadPdfData(pdf_buffer);
   if (!doc)
     return false;
   return FPDF_GetPageSizeByIndex(doc.get(), page_number, width, height) != 0;
diff --git a/pdf/pdfium/pdfium_engine_exports.h b/pdf/pdfium/pdfium_engine_exports.h
index 3a23d85..4a2133c 100644
--- a/pdf/pdfium/pdfium_engine_exports.h
+++ b/pdf/pdfium/pdfium_engine_exports.h
@@ -21,8 +21,7 @@
 
 // PDFEngineExports:
 #if defined(OS_WIN)
-  bool RenderPDFPageToDC(const void* pdf_buffer,
-                         int buffer_size,
+  bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer,
                          int page_number,
                          const RenderingSettings& settings,
                          HDC dc) override;
@@ -32,8 +31,7 @@
   void SetPDFUseGDIPrinting(bool enable) override;
   void SetPDFUsePrintMode(int mode) override;
 #endif  // defined(OS_WIN)
-  bool RenderPDFPageToBitmap(const void* pdf_buffer,
-                             int pdf_buffer_size,
+  bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
                              int page_number,
                              const RenderingSettings& settings,
                              void* bitmap_buffer) override;
@@ -50,12 +48,10 @@
                                   size_t page_size_height,
                                   void** dest_pdf_buffer,
                                   size_t* dest_pdf_buffer_size) override;
-  bool GetPDFDocInfo(const void* pdf_buffer,
-                     int buffer_size,
+  bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
                      int* page_count,
                      double* max_page_width) override;
-  bool GetPDFPageSizeByIndex(const void* pdf_buffer,
-                             int pdf_buffer_size,
+  bool GetPDFPageSizeByIndex(base::span<const uint8_t> pdf_buffer,
                              int page_number,
                              double* width,
                              double* height) override;
diff --git a/pdf/pdfium/pdfium_engine_exports_unittest.cc b/pdf/pdfium/pdfium_engine_exports_unittest.cc
index 818dfc6c..76c7e62 100644
--- a/pdf/pdfium/pdfium_engine_exports_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_exports_unittest.cc
@@ -61,15 +61,12 @@
   std::string pdf_data;
   ASSERT_TRUE(base::ReadFileToString(pdf_path, &pdf_data));
 
-  EXPECT_FALSE(GetPDFDocInfo(nullptr, 0, nullptr, nullptr));
-
-  ASSERT_TRUE(
-      GetPDFDocInfo(pdf_data.data(), pdf_data.size(), nullptr, nullptr));
+  auto pdf_span = base::as_bytes(base::make_span(pdf_data));
+  ASSERT_TRUE(GetPDFDocInfo(pdf_span, nullptr, nullptr));
 
   int page_count;
   double max_page_width;
-  ASSERT_TRUE(GetPDFDocInfo(pdf_data.data(), pdf_data.size(), &page_count,
-                            &max_page_width));
+  ASSERT_TRUE(GetPDFDocInfo(pdf_span, &page_count, &max_page_width));
   EXPECT_EQ(2, page_count);
   EXPECT_DOUBLE_EQ(200.0, max_page_width);
 }
@@ -82,17 +79,16 @@
   std::string pdf_data;
   ASSERT_TRUE(base::ReadFileToString(pdf_path, &pdf_data));
 
-  EXPECT_FALSE(GetPDFPageSizeByIndex(nullptr, 0, 0, nullptr, nullptr));
+  auto pdf_span = base::as_bytes(base::make_span(pdf_data));
+  EXPECT_FALSE(GetPDFPageSizeByIndex(pdf_span, 0, nullptr, nullptr));
 
   int page_count;
-  ASSERT_TRUE(
-      GetPDFDocInfo(pdf_data.data(), pdf_data.size(), &page_count, nullptr));
+  ASSERT_TRUE(GetPDFDocInfo(pdf_span, &page_count, nullptr));
   ASSERT_EQ(2, page_count);
   for (int page_number = 0; page_number < page_count; ++page_number) {
     double width;
     double height;
-    ASSERT_TRUE(GetPDFPageSizeByIndex(pdf_data.data(), pdf_data.size(),
-                                      page_number, &width, &height));
+    ASSERT_TRUE(GetPDFPageSizeByIndex(pdf_span, page_number, &width, &height));
     EXPECT_DOUBLE_EQ(200.0, width);
     EXPECT_DOUBLE_EQ(200.0, height);
   }
@@ -118,15 +114,16 @@
       pdf_buffers, 2, 512, 792, &output_pdf_buffer, &output_pdf_buffer_size));
   ASSERT_GT(output_pdf_buffer_size, 0U);
   ASSERT_NE(output_pdf_buffer, nullptr);
+
+  base::span<const uint8_t> output_pdf_span = base::make_span(
+      reinterpret_cast<uint8_t*>(output_pdf_buffer), output_pdf_buffer_size);
   int page_count;
-  ASSERT_TRUE(GetPDFDocInfo(output_pdf_buffer, output_pdf_buffer_size,
-                            &page_count, nullptr));
+  ASSERT_TRUE(GetPDFDocInfo(output_pdf_span, &page_count, nullptr));
   ASSERT_EQ(1, page_count);
 
   double width;
   double height;
-  ASSERT_TRUE(GetPDFPageSizeByIndex(output_pdf_buffer, output_pdf_buffer_size,
-                                    0, &width, &height));
+  ASSERT_TRUE(GetPDFPageSizeByIndex(output_pdf_span, 0, &width, &height));
   EXPECT_DOUBLE_EQ(792.0, width);
   EXPECT_DOUBLE_EQ(512.0, height);
 
@@ -152,15 +149,17 @@
       pdf_buffer, 4, 512, 792, &output_pdf_buffer, &output_pdf_buffer_size));
   ASSERT_GT(output_pdf_buffer_size, 0U);
   ASSERT_NE(output_pdf_buffer, nullptr);
+
+  base::span<const uint8_t> output_pdf_span = base::make_span(
+      reinterpret_cast<uint8_t*>(output_pdf_buffer), output_pdf_buffer_size);
   int page_count;
-  ASSERT_TRUE(GetPDFDocInfo(output_pdf_buffer, output_pdf_buffer_size,
-                            &page_count, nullptr));
+  ASSERT_TRUE(GetPDFDocInfo(output_pdf_span, &page_count, nullptr));
   ASSERT_EQ(2, page_count);
   for (int page_number = 0; page_number < page_count; ++page_number) {
     double width;
     double height;
-    ASSERT_TRUE(GetPDFPageSizeByIndex(output_pdf_buffer, output_pdf_buffer_size,
-                                      page_number, &width, &height));
+    ASSERT_TRUE(
+        GetPDFPageSizeByIndex(output_pdf_span, page_number, &width, &height));
     EXPECT_DOUBLE_EQ(512.0, width);
     EXPECT_DOUBLE_EQ(792.0, height);
   }
diff --git a/services/audio/input_controller.cc b/services/audio/input_controller.cc
index 75d2b371..4dd7694 100644
--- a/services/audio/input_controller.cc
+++ b/services/audio/input_controller.cc
@@ -227,7 +227,7 @@
 
 void InputController::Record() {
   DCHECK_CALLED_ON_VALID_THREAD(owning_thread_);
-  SCOPED_UMA_HISTOGRAM_TIMER("Media.InputController.RecordTime");
+  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime");
 
   if (!stream_ || audio_callback_)
     return;
@@ -248,7 +248,7 @@
 
 void InputController::Close() {
   DCHECK_CALLED_ON_VALID_THREAD(owning_thread_);
-  SCOPED_UMA_HISTOGRAM_TIMER("Media.InputController.CloseTime");
+  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
 
   if (!stream_)
     return;
@@ -352,7 +352,7 @@
                                bool enable_agc) {
   DCHECK_CALLED_ON_VALID_THREAD(owning_thread_);
   DCHECK(!stream_);
-  SCOPED_UMA_HISTOGRAM_TIMER("Media.InputController.CreateTime");
+  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime");
   handler_->OnLog("AIC::DoCreate");
 
 #if defined(AUDIO_POWER_MONITORING)
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc
index bb96809a..629fd22 100644
--- a/services/network/cors/preflight_controller.cc
+++ b/services/network/cors/preflight_controller.cc
@@ -169,18 +169,12 @@
 base::Optional<CORSErrorStatus> CheckPreflightResult(
     PreflightResult* result,
     const ResourceRequest& original_request) {
-  base::Optional<mojom::CORSError> error =
+  base::Optional<CORSErrorStatus> status =
       result->EnsureAllowedCrossOriginMethod(original_request.method);
-  if (error)
-    return CORSErrorStatus(*error, original_request.method);
+  if (status)
+    return status;
 
-  std::string detected_error_header;
-  error = result->EnsureAllowedCrossOriginHeaders(original_request.headers,
-                                                  &detected_error_header);
-  if (error)
-    return CORSErrorStatus(*error, detected_error_header);
-
-  return base::nullopt;
+  return result->EnsureAllowedCrossOriginHeaders(original_request.headers);
 }
 
 // TODO(toyoshim): Remove this class once the Network Service is enabled.
diff --git a/services/network/public/cpp/cors/preflight_result.cc b/services/network/public/cpp/cors/preflight_result.cc
index 17f936a..3cf0f25 100644
--- a/services/network/public/cpp/cors/preflight_result.cc
+++ b/services/network/public/cpp/cors/preflight_result.cc
@@ -112,8 +112,7 @@
 
 PreflightResult::~PreflightResult() = default;
 
-base::Optional<mojom::CORSError>
-PreflightResult::EnsureAllowedCrossOriginMethod(
+base::Optional<CORSErrorStatus> PreflightResult::EnsureAllowedCrossOriginMethod(
     const std::string& method) const {
   // Request method is normalized to upper case, and comparison is performed in
   // case-sensitive way, that means access control header should provide an
@@ -127,13 +126,13 @@
   if (!credentials_ && methods_.find("*") != methods_.end())
     return base::nullopt;
 
-  return mojom::CORSError::kMethodDisallowedByPreflightResponse;
+  return CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                         method);
 }
 
-base::Optional<mojom::CORSError>
+base::Optional<CORSErrorStatus>
 PreflightResult::EnsureAllowedCrossOriginHeaders(
-    const net::HttpRequestHeaders& headers,
-    std::string* detected_header) const {
+    const net::HttpRequestHeaders& headers) const {
   if (!credentials_ && headers_.find("*") != headers_.end())
     return base::nullopt;
 
@@ -149,9 +148,8 @@
       // fine.
       if (IsForbiddenHeader(key))
         continue;
-      if (detected_header)
-        *detected_header = header.key;
-      return mojom::CORSError::kHeaderDisallowedByPreflightResponse;
+      return CORSErrorStatus(
+          mojom::CORSError::kHeaderDisallowedByPreflightResponse, header.key);
     }
   }
   return base::nullopt;
@@ -172,7 +170,7 @@
   if (EnsureAllowedCrossOriginMethod(method))
     return false;
 
-  if (EnsureAllowedCrossOriginHeaders(headers, nullptr))
+  if (EnsureAllowedCrossOriginHeaders(headers))
     return false;
 
   return true;
diff --git a/services/network/public/cpp/cors/preflight_result.h b/services/network/public/cpp/cors/preflight_result.h
index 4916ca2d..bd49e120 100644
--- a/services/network/public/cpp/cors/preflight_result.h
+++ b/services/network/public/cpp/cors/preflight_result.h
@@ -11,6 +11,7 @@
 #include "base/component_export.h"
 #include "base/containers/flat_set.h"
 #include "base/optional.h"
+#include "services/network/public/cpp/cors/cors_error_status.h"
 #include "services/network/public/mojom/cors.mojom-shared.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 
@@ -45,19 +46,17 @@
   ~PreflightResult();
 
   // Checks if the given |method| is allowed by the CORS-preflight response.
-  base::Optional<mojom::CORSError> EnsureAllowedCrossOriginMethod(
+  base::Optional<CORSErrorStatus> EnsureAllowedCrossOriginMethod(
       const std::string& method) const;
 
   // Checks if the given all |headers| are allowed by the CORS-preflight
-  // response. |detected_header| indicates the disallowed header name if the
-  // pointer is valid.
+  // response.
   // This does not reject when the headers contain forbidden headers
   // (https://fetch.spec.whatwg.org/#forbidden-header-name) because they may be
   // added by the user agent. They must be checked separately and rejected for
   // JavaScript-initiated requests.
-  base::Optional<mojom::CORSError> EnsureAllowedCrossOriginHeaders(
-      const net::HttpRequestHeaders& headers,
-      std::string* detected_header) const;
+  base::Optional<CORSErrorStatus> EnsureAllowedCrossOriginHeaders(
+      const net::HttpRequestHeaders& headers) const;
 
   // Checks if the given combination of |credentials_mode|, |method|, and
   // |headers| is allowed by the CORS-preflight response.
diff --git a/services/network/public/cpp/cors/preflight_result_unittest.cc b/services/network/public/cpp/cors/preflight_result_unittest.cc
index a0395df..2a83e34af 100644
--- a/services/network/public/cpp/cors/preflight_result_unittest.cc
+++ b/services/network/public/cpp/cors/preflight_result_unittest.cc
@@ -26,7 +26,7 @@
   const std::string request_headers;
   const mojom::FetchCredentialsMode request_credentials_mode;
 
-  const base::Optional<mojom::CORSError> expected_result;
+  const base::Optional<CORSErrorStatus> expected_result;
 };
 
 const TestCase method_cases[] = {
@@ -67,29 +67,36 @@
     // Not found in the preflight response and the safe lit.
     {"", "", mojom::FetchCredentialsMode::kOmit, "OPTIONS", "",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kMethodDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                     "OPTIONS")},
     {"", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kMethodDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                     "PUT")},
     {"", "", mojom::FetchCredentialsMode::kOmit, "DELETE", "",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kMethodDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                     "DELETE")},
     {"GET", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kMethodDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                     "PUT")},
     {"GET, POST, DELETE", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kMethodDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                     "PUT")},
 
     // Request method is normalized to upper-case, but allowed methods is not.
     // Comparison is in case-sensitive, that means allowed methods should be in
     // upper case.
     {"put", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kMethodDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                     "PUT")},
     {"put", "", mojom::FetchCredentialsMode::kOmit, "put", "",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kMethodDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
+                     "put")},
     {"PUT", "", mojom::FetchCredentialsMode::kOmit, "put", "",
      mojom::FetchCredentialsMode::kOmit, base::nullopt},
     // ... But, GET is always allowed by the safe list.
@@ -117,7 +124,8 @@
      mojom::FetchCredentialsMode::kOmit, base::nullopt},
     {"GET", "*", mojom::FetchCredentialsMode::kInclude, "GET", "xyzzy:t",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kHeaderDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
+                     "xyzzy")},
 
     // Forbidden headers can pass.
     {"GET", "", mojom::FetchCredentialsMode::kOmit, "GET",
@@ -126,13 +134,16 @@
     // Not found in the preflight response and the safe list.
     {"GET", "", mojom::FetchCredentialsMode::kOmit, "GET", "X-MY-HEADER:t",
      mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kHeaderDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
+                     "X-MY-HEADER")},
     {"GET", "X-SOME-OTHER-HEADER", mojom::FetchCredentialsMode::kOmit, "GET",
      "X-MY-HEADER:t", mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kHeaderDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
+                     "X-MY-HEADER")},
     {"GET", "X-MY-HEADER", mojom::FetchCredentialsMode::kOmit, "GET",
      "X-MY-HEADER:t\r\nY-MY-HEADER:t", mojom::FetchCredentialsMode::kOmit,
-     mojom::CORSError::kHeaderDisallowedByPreflightResponse},
+     CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
+                     "Y-MY-HEADER")},
 };
 
 TEST_F(PreflightResultTest, MaxAge) {
@@ -177,7 +188,7 @@
     net::HttpRequestHeaders headers;
     headers.AddHeadersFromString(test.request_headers);
     EXPECT_EQ(test.expected_result,
-              result->EnsureAllowedCrossOriginHeaders(headers, nullptr));
+              result->EnsureAllowedCrossOriginHeaders(headers));
   }
 }
 
diff --git a/services/video_capture/device_factory_provider_impl.cc b/services/video_capture/device_factory_provider_impl.cc
index 787d39b..a23ce63 100644
--- a/services/video_capture/device_factory_provider_impl.cc
+++ b/services/video_capture/device_factory_provider_impl.cc
@@ -113,6 +113,8 @@
   std::unique_ptr<media::VideoCaptureDeviceFactory> media_device_factory =
       media::CreateVideoCaptureDeviceFactory(
           base::ThreadTaskRunnerHandle::Get());
+  DCHECK(media_device_factory);
+
   auto video_capture_system = std::make_unique<media::VideoCaptureSystemImpl>(
       std::move(media_device_factory));
 
diff --git a/sql/connection.cc b/sql/connection.cc
index 6735720..b50f9f2 100644
--- a/sql/connection.cc
+++ b/sql/connection.cc
@@ -203,6 +203,21 @@
   current_expecter_cb_ = nullptr;
 }
 
+// static
+base::FilePath Connection::JournalPath(const base::FilePath& db_path) {
+  return base::FilePath(db_path.value() + FILE_PATH_LITERAL("-journal"));
+}
+
+// static
+base::FilePath Connection::WriteAheadLogPath(const base::FilePath& db_path) {
+  return base::FilePath(db_path.value() + FILE_PATH_LITERAL("-wal"));
+}
+
+// static
+base::FilePath Connection::SharedMemoryFilePath(const base::FilePath& db_path) {
+  return base::FilePath(db_path.value() + FILE_PATH_LITERAL("-shm"));
+}
+
 Connection::StatementRef::StatementRef(Connection* connection,
                                        sqlite3_stmt* stmt,
                                        bool was_valid)
@@ -245,7 +260,6 @@
       page_size_(0),
       cache_size_(0),
       exclusive_locking_(false),
-      restrict_to_user_(false),
       transaction_nesting_(0),
       needs_rollback_(false),
       in_memory_(false),
@@ -562,8 +576,7 @@
   // Put the collection of diagnostic data next to the databases.  In most
   // cases, this is the profile directory, but safe-browsing stores a Cookies
   // file in the directory above the profile directory.
-  base::FilePath breadcrumb_path(
-      db_path.DirName().Append(FILE_PATH_LITERAL("sqlite-diag")));
+  base::FilePath breadcrumb_path = db_path.DirName().AppendASCII("sqlite-diag");
 
   // Lock against multiple updates to the diagnostics file.  This code should
   // seldom be called in the first place, and when called it should seldom be
@@ -1137,8 +1150,8 @@
 bool Connection::Delete(const base::FilePath& path) {
   base::AssertBlockingAllowed();
 
-  base::FilePath journal_path(path.value() + FILE_PATH_LITERAL("-journal"));
-  base::FilePath wal_path(path.value() + FILE_PATH_LITERAL("-wal"));
+  base::FilePath journal_path = Connection::JournalPath(path);
+  base::FilePath wal_path = Connection::WriteAheadLogPath(path);
 
   std::string journal_str = AsUTF8ForSQL(journal_path);
   std::string wal_str = AsUTF8ForSQL(wal_path);
@@ -1162,16 +1175,13 @@
   vfs->xDelete(vfs, path_str.c_str(), 0);
 
   int journal_exists = 0;
-  vfs->xAccess(vfs, journal_str.c_str(), SQLITE_ACCESS_EXISTS,
-               &journal_exists);
+  vfs->xAccess(vfs, journal_str.c_str(), SQLITE_ACCESS_EXISTS, &journal_exists);
 
   int wal_exists = 0;
-  vfs->xAccess(vfs, wal_str.c_str(), SQLITE_ACCESS_EXISTS,
-               &wal_exists);
+  vfs->xAccess(vfs, wal_str.c_str(), SQLITE_ACCESS_EXISTS, &wal_exists);
 
   int path_exists = 0;
-  vfs->xAccess(vfs, path_str.c_str(), SQLITE_ACCESS_EXISTS,
-               &path_exists);
+  vfs->xAccess(vfs, path_str.c_str(), SQLITE_ACCESS_EXISTS, &path_exists);
 
   return !journal_exists && !wal_exists && !path_exists;
 }
@@ -1631,37 +1641,6 @@
     return false;
   }
 
-  // TODO(shess): OS_WIN support?
-#if defined(OS_POSIX)
-  if (restrict_to_user_) {
-    DCHECK_NE(file_name, std::string(":memory"));
-    base::FilePath file_path(file_name);
-    int mode = 0;
-    // TODO(shess): Arguably, failure to retrieve and change
-    // permissions should be fatal if the file exists.
-    if (base::GetPosixFilePermissions(file_path, &mode)) {
-      mode &= base::FILE_PERMISSION_USER_MASK;
-      base::SetPosixFilePermissions(file_path, mode);
-
-      // SQLite sets the permissions on these files from the main
-      // database on create.  Set them here in case they already exist
-      // at this point.  Failure to set these permissions should not
-      // be fatal unless the file doesn't exist.
-      base::FilePath journal_path(file_name + FILE_PATH_LITERAL("-journal"));
-      base::FilePath wal_path(file_name + FILE_PATH_LITERAL("-wal"));
-      base::SetPosixFilePermissions(journal_path, mode);
-      base::SetPosixFilePermissions(wal_path, mode);
-    }
-  }
-#endif  // defined(OS_POSIX)
-
-  // SQLite uses a lookaside buffer to improve performance of small mallocs.
-  // Chromium already depends on small mallocs being efficient, so we disable
-  // this to avoid the extra memory overhead.
-  // This must be called immediatly after opening the database before any SQL
-  // statements are run.
-  sqlite3_db_config(db_, SQLITE_DBCONFIG_LOOKASIDE, nullptr, 0, 0);
-
   // Enable extended result codes to provide more color on I/O errors.
   // Not having extended result codes is not a fatal problem, as
   // Chromium code does not attempt to handle I/O errors anyhow.  The
diff --git a/sql/connection.h b/sql/connection.h
index 055c290..8083cf6 100644
--- a/sql/connection.h
+++ b/sql/connection.h
@@ -108,12 +108,6 @@
   // This must be called before Open() to have an effect.
   void set_exclusive_locking() { exclusive_locking_ = true; }
 
-  // Call to cause Open() to restrict access permissions of the
-  // database file to only the owner.
-  //
-  // This is only supported on OS_POSIX and is a noop on other platforms.
-  void set_restrict_to_user() { restrict_to_user_ = true; }
-
   // Call to use alternative status-tracking for mmap.  Usually this is tracked
   // in the meta table, but some databases have no meta table.
   // TODO(shess): Maybe just have all databases use the alt option?
@@ -469,6 +463,39 @@
     clock_ = std::move(clock);
   }
 
+  // Computes the path of a database's rollback journal.
+  //
+  // The journal file is created at the beginning of the database's first
+  // transaction. The file may be removed and re-created between transactions,
+  // depending on whether the database is opened in exclusive mode, and on
+  // configuration options. The journal file does not exist when the database
+  // operates in WAL mode.
+  //
+  // This is intended for internal use and tests. To preserve our ability to
+  // iterate on our SQLite configuration, features must avoid relying on
+  // the existence of specific files.
+  static base::FilePath JournalPath(const base::FilePath& db_path);
+
+  // Computes the path of a database's write-ahead log (WAL).
+  //
+  // The WAL file exists while a database is opened in WAL mode.
+  //
+  // This is intended for internal use and tests. To preserve our ability to
+  // iterate on our SQLite configuration, features must avoid relying on
+  // the existence of specific files.
+  static base::FilePath WriteAheadLogPath(const base::FilePath& db_path);
+
+  // Computes the path of a database's shared memory (SHM) file.
+  //
+  // The SHM file is used to coordinate between multiple processes using the
+  // same database in WAL mode. Thus, this file only exists for databases using
+  // WAL and not opened in exclusive mode.
+  //
+  // This is intended for internal use and tests. To preserve our ability to
+  // iterate on our SQLite configuration, features must avoid relying on
+  // the existence of specific files.
+  static base::FilePath SharedMemoryFilePath(const base::FilePath& db_path);
+
  private:
   // For recovery module.
   friend class Recovery;
@@ -718,7 +745,6 @@
   int page_size_;
   int cache_size_;
   bool exclusive_locking_;
-  bool restrict_to_user_;
 
   // Holds references to all cached statements so they remain active.
   //
diff --git a/sql/connection_unittest.cc b/sql/connection_unittest.cc
index 2d32bfa..a09fe824 100644
--- a/sql/connection_unittest.cc
+++ b/sql/connection_unittest.cc
@@ -867,85 +867,74 @@
 }
 #endif  // defined(OS_ANDROID)
 
-TEST_F(SQLConnectionTest, Delete) {
+TEST_F(SQLConnectionTest, DeleteNonWal) {
   EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
   db().Close();
 
   // Should have both a main database file and a journal file because
   // of journal_mode TRUNCATE.
-  base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
+  base::FilePath journal_path = sql::Connection::JournalPath(db_path());
   ASSERT_TRUE(GetPathExists(db_path()));
-  ASSERT_TRUE(GetPathExists(journal));
+  ASSERT_TRUE(GetPathExists(journal_path));
 
   sql::Connection::Delete(db_path());
   EXPECT_FALSE(GetPathExists(db_path()));
-  EXPECT_FALSE(GetPathExists(journal));
+  EXPECT_FALSE(GetPathExists(journal_path));
 }
 
-// This test manually sets on disk permissions, these don't exist on Fuchsia.
-#if defined(OS_POSIX)
-// Test that set_restrict_to_user() trims database permissions so that
-// only the owner (and root) can read.
-TEST_F(SQLConnectionTest, UserPermission) {
-  // If the bots all had a restrictive umask setting such that
-  // databases are always created with only the owner able to read
-  // them, then the code could break without breaking the tests.
-  // Temporarily provide a more permissive umask.
+#if defined(OS_POSIX)  // This test operates on POSIX file permissions.
+TEST_F(SQLConnectionTest, PosixFilePermissions) {
   db().Close();
   sql::Connection::Delete(db_path());
   ASSERT_FALSE(GetPathExists(db_path()));
+
+  // If the bots all had a restrictive umask setting such that databases are
+  // always created with only the owner able to read them, then the code could
+  // break without breaking the tests. Temporarily provide a more permissive
+  // umask.
   ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
+
   ASSERT_TRUE(db().Open(db_path()));
 
-  // Cause the journal file to be created.  If the default
-  // journal_mode is changed back to DELETE, then parts of this test
-  // will need to be updated.
+  // Cause the journal file to be created. If the default journal_mode is
+  // changed back to DELETE, this test will need to be updated.
   EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
 
-  base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
   int mode;
-
-  // Given a permissive umask, the database is created with permissive
-  // read access for the database and journal.
   ASSERT_TRUE(GetPathExists(db_path()));
-  ASSERT_TRUE(GetPathExists(journal));
-  mode = base::FILE_PERMISSION_MASK;
   EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
-  ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
-  mode = base::FILE_PERMISSION_MASK;
-  EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
-  ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
+  ASSERT_EQ(mode, 0600);
 
-  // Re-open with restricted permissions and verify that the modes
-  // changed for both the main database and the journal.
-  db().Close();
-  db().set_restrict_to_user();
-  ASSERT_TRUE(db().Open(db_path()));
-  ASSERT_TRUE(GetPathExists(db_path()));
-  ASSERT_TRUE(GetPathExists(journal));
-  mode = base::FILE_PERMISSION_MASK;
-  EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
-  ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
-  mode = base::FILE_PERMISSION_MASK;
-  EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
-  ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
+  {
+    base::FilePath journal_path = sql::Connection::JournalPath(db_path());
+    DLOG(ERROR) << "journal_path: " << journal_path;
+    ASSERT_TRUE(GetPathExists(journal_path));
+    EXPECT_TRUE(base::GetPosixFilePermissions(journal_path, &mode));
+    ASSERT_EQ(mode, 0600);
+  }
 
-  // Delete and re-create the database, the restriction should still apply.
+  // Reopen the database and turn on WAL mode.
   db().Close();
   sql::Connection::Delete(db_path());
+  ASSERT_FALSE(GetPathExists(db_path()));
   ASSERT_TRUE(db().Open(db_path()));
-  ASSERT_TRUE(GetPathExists(db_path()));
-  ASSERT_FALSE(GetPathExists(journal));
-  mode = base::FILE_PERMISSION_MASK;
-  EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
-  ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
+  ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL"));
+  ASSERT_EQ("wal", ExecuteWithResult(&db(), "PRAGMA journal_mode"));
 
-  // Verify that journal creation inherits the restriction.
-  EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
-  ASSERT_TRUE(GetPathExists(journal));
-  mode = base::FILE_PERMISSION_MASK;
-  EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
-  ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
+  // The WAL file is created lazily on first change.
+  ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
+
+  {
+    base::FilePath wal_path = sql::Connection::WriteAheadLogPath(db_path());
+    ASSERT_TRUE(GetPathExists(wal_path));
+    EXPECT_TRUE(base::GetPosixFilePermissions(wal_path, &mode));
+    ASSERT_EQ(mode, 0600);
+
+    base::FilePath shm_path = sql::Connection::SharedMemoryFilePath(db_path());
+    ASSERT_TRUE(GetPathExists(shm_path));
+    EXPECT_TRUE(base::GetPosixFilePermissions(shm_path, &mode));
+    ASSERT_EQ(mode, 0600);
+  }
 }
 #endif  // defined(OS_POSIX)
 
@@ -1439,8 +1428,8 @@
 }
 
 TEST_F(SQLConnectionTest, RegisterIntentToUpload) {
-  base::FilePath breadcrumb_path(
-      db_path().DirName().Append(FILE_PATH_LITERAL("sqlite-diag")));
+  base::FilePath breadcrumb_path =
+      db_path().DirName().AppendASCII("sqlite-diag");
 
   // No stale diagnostic store.
   ASSERT_TRUE(!base::PathExists(breadcrumb_path));
diff --git a/sql/sqlite_features_unittest.cc b/sql/sqlite_features_unittest.cc
index 962b16b..64cc7e3f 100644
--- a/sql/sqlite_features_unittest.cc
+++ b/sql/sqlite_features_unittest.cc
@@ -321,7 +321,7 @@
   ASSERT_TRUE(db().Execute("CREATE TABLE t (id INTEGER PRIMARY KEY)"));
   db().Close();
 
-  base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
+  base::FilePath journal = sql::Connection::JournalPath(db_path());
   ASSERT_TRUE(GetPathExists(db_path()));
   ASSERT_TRUE(GetPathExists(journal));
 
@@ -450,7 +450,7 @@
 // additional work into Chromium shutdown.  Verify that SQLite supports a config
 // option to not checkpoint on close.
 TEST_F(SQLiteFeaturesTest, WALNoClose) {
-  base::FilePath wal_path(db_path().value() + FILE_PATH_LITERAL("-wal"));
+  base::FilePath wal_path = sql::Connection::WriteAheadLogPath(db_path());
 
   // Turn on WAL mode, then verify that the mode changed (WAL is supported).
   ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL"));
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 5a12e05..97e1f31 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -207,8 +207,6 @@
 # http://crbug.com/721414
 # TODO(rockot): add support for webRequest API.
 -ExtensionWebRequestApiTest.WebRequestBlocking
--ExtensionWebRequestApiTest.WebRequestDeclarative2
--ExtensionWebRequestApiTest.WebRequestDiceHeaderProtection
 -ExtensionWebRequestApiTest.WebRequestTypes
 # Needs synchronization to wait until after URLLoaderFactories are rebound.
 -DevToolsFrontendInWebRequestApiTest.HiddenRequests
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index f9cc1a4..8ecd550 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3222,7 +3222,10 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled"
+                    "name": "Enabled",
+                    "params": {
+                        "connection_options": "NSTP"
+                    }
                 }
             ]
         }
@@ -4058,6 +4061,21 @@
             ]
         }
     ],
+    "StopNonTimersInBackground": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Experiment",
+                    "enable_features": [
+                        "stop-non-timers-in-background"
+                    ]
+                }
+            ]
+        }
+    ],
     "SuperfishInterstitial": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 82326085..3fb4f9e 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -71,7 +71,6 @@
 crbug.com/591099 compositing/layer-creation/stacking-context-overlap-nested.html [ Failure ]
 crbug.com/591099 compositing/perpendicular-layer-sorting.html [ Failure ]
 crbug.com/591099 compositing/self-painting-layers.html [ Failure ]
-crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ]
 crbug.com/591099 compositing/squashing/squash-above-fixed-3.html [ Failure ]
 crbug.com/591099 compositing/squashing/squash-same-transform-ancestor.html [ Failure ]
 crbug.com/591099 compositing/squashing/squashing-inside-perspective.html [ Failure ]
@@ -352,7 +351,7 @@
 crbug.com/591099 external/wpt/editing/run/justifyleft.html [ Pass ]
 crbug.com/591099 external/wpt/editing/run/justifyright.html [ Pass ]
 crbug.com/591099 external/wpt/editing/run/misc.html [ Pass ]
-crbug.com/591099 external/wpt/editing/run/multitest.html [ Pass ]
+crbug.com/591099 external/wpt/editing/run/multitest.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/editing/run/strikethrough.html [ Pass ]
 crbug.com/591099 external/wpt/editing/run/subscript.html [ Pass ]
 crbug.com/591099 external/wpt/editing/run/unlink.html [ Pass ]
@@ -476,8 +475,6 @@
 crbug.com/591099 external/wpt/xhr/send-authentication-prompt-2-manual.htm [ Failure ]
 crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ]
 crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ]
-crbug.com/591099 fast/backgrounds/border-radius-split-background-image.html [ Failure ]
-crbug.com/591099 fast/backgrounds/border-radius-split-background.html [ Failure ]
 crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ]
 crbug.com/591099 fast/backgrounds/size/backgroundSize16.html [ Failure ]
 crbug.com/591099 fast/block/basic/quirk-percent-height-table-cell.html [ Failure ]
@@ -492,12 +489,8 @@
 crbug.com/591099 fast/borders/bidi-002.html [ Failure ]
 crbug.com/859497 fast/borders/bidi-009a.html [ Failure ]
 crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ]
-crbug.com/714962 fast/borders/border-image-outset-split-inline.html [ Failure ]
-crbug.com/714962 fast/borders/border-styles-split.html [ Failure ]
 crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/box-shadow/box-shadow.html [ Failure ]
-crbug.com/591099 fast/box-shadow/inset-subpixel.html [ Failure ]
-crbug.com/591099 fast/box-shadow/inset.html [ Failure ]
 crbug.com/591099 fast/box-sizing/replaced.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/first-letter-next-sibling-crash.html [ Crash ]
 crbug.com/591099 fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html [ Crash ]
@@ -511,7 +504,6 @@
 crbug.com/591099 fast/css-grid-layout/grid-self-baseline-vertical-lr-04.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/grid-self-baseline-vertical-lr-05.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/maximize-tracks-definite-indefinite-width.html [ Failure ]
-crbug.com/591099 fast/css-grid-layout/mozilla/grid-repeat-auto-fill-fit-004.html [ Failure Pass ]
 crbug.com/591099 fast/css-grid-layout/percent-padding-margin-resolution-grid-item.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/fixed-height-stf-img-block-child-percent-height.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/fixed-height-stf-img-inline-child-percent-height.html [ Failure ]
@@ -540,17 +532,14 @@
 crbug.com/591099 fast/events/background-tab-on-submit-synthesized-ctrl-click.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
-crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
+crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Pass ]
 crbug.com/591099 fast/forms/text-control-intrinsic-widths.html [ Timeout ]
 crbug.com/591099 fast/inline-block/vertical-align-top-and-bottom-2.html [ Failure ]
 crbug.com/591099 fast/inline/absolute-positioned-block-in-centred-block.html [ Failure ]
 crbug.com/714962 fast/inline/continuation-outlines-with-layers-2.html [ Failure ]
 crbug.com/591099 fast/inline/continuation-outlines-with-layers.html [ Failure ]
 crbug.com/591099 fast/inline/continuation-outlines.html [ Failure ]
-crbug.com/591099 fast/inline/inline-box-background-long-image.html [ Failure ]
-crbug.com/591099 fast/inline/inline-box-background-repeat-x.html [ Failure ]
 crbug.com/591099 fast/inline/inline-box-background-repeat-y.html [ Failure ]
-crbug.com/591099 fast/inline/inline-box-background.html [ Failure ]
 crbug.com/591099 fast/inline/inline-focus-ring-under-absolute-enclosing-relative-div.html [ Failure ]
 crbug.com/591099 fast/inline/inline-with-empty-inline-children.html [ Failure ]
 crbug.com/591099 fast/inline/nested-text-descendants.html [ Failure ]
@@ -576,7 +565,7 @@
 crbug.com/591099 fast/table/empty-table-percent-height.html [ Failure ]
 crbug.com/591099 fast/table/height-percent-test-vertical.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure ]
-crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure Pass ]
+crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-replaced-content-in-cell.html [ Failure ]
 crbug.com/858998 fast/table/table-continuation-outline-paint-crash.html [ Failure ]
 crbug.com/591099 fast/table/table-display-types-vertical.html [ Failure ]
@@ -594,13 +583,10 @@
 crbug.com/591099 fast/text/whitespace/018.html [ Failure ]
 crbug.com/591099 fast/writing-mode/auto-sizing-orthogonal-flows.html [ Failure ]
 crbug.com/714962 fast/writing-mode/background-vertical-lr.html [ Failure ]
-crbug.com/591099 fast/writing-mode/background-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/writing-mode/basic-vertical-line.html [ Failure ]
 crbug.com/591099 fast/writing-mode/border-image-vertical-lr.html [ Failure ]
-crbug.com/714962 fast/writing-mode/border-image-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/writing-mode/border-radius-clipping-vertical-lr.html [ Failure ]
 crbug.com/714962 fast/writing-mode/border-styles-vertical-lr.html [ Failure ]
-crbug.com/714962 fast/writing-mode/border-styles-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/writing-mode/fieldsets.html [ Failure ]
 crbug.com/714962 fast/writing-mode/flipped-blocks-hit-test-line-edges.html [ Failure ]
 crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ]
@@ -611,11 +597,8 @@
 crbug.com/855039 html/details_summary/details-writing-mode-align-left.html [ Failure ]
 crbug.com/855039 html/details_summary/details-writing-mode-align-right.html [ Failure ]
 crbug.com/855039 html/details_summary/details-writing-mode.html [ Failure ]
-crbug.com/591099 http/tests/csspaint/invalidation-background-image.html [ Timeout ]
-crbug.com/591099 http/tests/csspaint/invalidation-border-image.html [ Timeout ]
-crbug.com/591099 http/tests/csspaint/invalidation-content-image.html [ Timeout ]
 crbug.com/591099 http/tests/devtools/console-resource-errors.js [ Failure Pass ]
-crbug.com/591099 http/tests/devtools/console/console-search.js [ Pass Timeout ]
+crbug.com/591099 http/tests/devtools/console/console-search.js [ Timeout ]
 crbug.com/591099 http/tests/devtools/persistence/persistence-merge-editor-tabs.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js [ Failure ]
@@ -651,67 +634,37 @@
 crbug.com/591099 inspector-protocol/layers/get-layers.js [ Failure ]
 crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ]
 crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Failure Pass ]
+crbug.com/591099 media/video-layer-crash.html [ Failure ]
+crbug.com/591099 media/video-poster-scale.html [ Failure ]
+crbug.com/591099 media/video-zoom.html [ Failure ]
 crbug.com/591099 paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ]
 crbug.com/591099 paint/invalidation/background/background-misaligned.html [ Failure ]
-crbug.com/591099 paint/invalidation/background/backgroundSizeRepaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/block-layout-inline-children-replaced.html [ Failure ]
-crbug.com/591099 paint/invalidation/box/border-radius-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/box/border-repaint-glitch.html [ Failure ]
-crbug.com/591099 paint/invalidation/box/box-inline-resize.html [ Failure ]
-crbug.com/591099 paint/invalidation/box/box-shadow-dynamic.html [ Failure ]
-crbug.com/591099 paint/invalidation/bugzilla-3509.html [ Failure ]
-crbug.com/591099 paint/invalidation/bugzilla-5699.html [ Failure ]
-crbug.com/591099 paint/invalidation/bugzilla-6278.html [ Failure ]
-crbug.com/591099 paint/invalidation/bugzilla-6473.html [ Failure ]
-crbug.com/591099 paint/invalidation/bugzilla-7235.html [ Failure ]
-crbug.com/591099 paint/invalidation/clip/caret-ancestor-clip-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/control-clip.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/outline-clip-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/subpixel-offset-scaled-transform-composited.html [ Failure ]
-crbug.com/591099 paint/invalidation/css-grid-layout/grid-element-change-columns-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/css-grid-layout/grid-element-change-rows-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/css-grid-layout/grid-item-change-column-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/css-grid-layout/grid-item-z-index-change-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/details-open-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/align-content-change-keeping-geometry.html [ Failure ]
-crbug.com/714962 paint/invalidation/flexbox/align-content-change-no-flex.html [ Failure ]
-crbug.com/591099 paint/invalidation/flexbox/align-content-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/flexbox/align-content-distribution-change-grid.html [ Failure ]
-crbug.com/591099 paint/invalidation/flexbox/align-items-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/flexbox/align-self-change-grid.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/align-self-change-keeping-geometry-grid.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/align-self-change-keeping-geometry.html [ Failure ]
-crbug.com/714962 paint/invalidation/flexbox/align-self-change-no-flex.html [ Failure ]
-crbug.com/591099 paint/invalidation/flexbox/align-self-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/justify-content-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/flexbox/justify-content-distribution-change-grid.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/justify-items-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/justify-items-legacy-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/justify-self-change-keeping-geometry.html [ Failure ]
-crbug.com/591099 paint/invalidation/flexbox/justify-self-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/repaint-on-margin-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/scrollbars-changed.html [ Failure ]
-crbug.com/591099 paint/invalidation/float-move-during-layout.html [ Failure ]
 crbug.com/591099 paint/invalidation/float-new-in-block.html [ Failure ]
 crbug.com/591099 paint/invalidation/forms/slider-thumb-float.html [ Failure ]
-crbug.com/591099 paint/invalidation/iframe-display-block-to-display-none.html [ Failure ]
-crbug.com/591099 paint/invalidation/iframe-display-none-to-display-block.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-1.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-10.html [ Failure ]
-crbug.com/591099 paint/invalidation/line-flow-with-floats-2.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-3.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-4.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-5.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-6.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-7.html [ Failure ]
-crbug.com/591099 paint/invalidation/line-flow-with-floats-8.html [ Failure ]
 crbug.com/591099 paint/invalidation/line-flow-with-floats-9.html [ Failure ]
-crbug.com/591099 paint/invalidation/list-marker-2.html [ Failure ]
-crbug.com/591099 paint/invalidation/make-children-non-inline.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/column-rules-fixed-height.html [ Failure ]
 crbug.com/824918 paint/invalidation/multicol/multicol-repaint.html [ Failure ]
-crbug.com/824918 paint/invalidation/multicol/multicol-with-text.html [ Failure ]
 crbug.com/591099 paint/invalidation/offset-change-wrong-invalidation-with-float.html [ Failure ]
 crbug.com/591099 paint/invalidation/outline/focus-continuations.html [ Failure ]
 crbug.com/591099 paint/invalidation/outline/focus-enable-continuations.html [ Failure ]
@@ -727,60 +680,24 @@
 crbug.com/591099 paint/invalidation/overflow/inline-box-overflow-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/justify-items-overflow-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/justify-self-overflow-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/overflow/line-overflow.html [ Failure ]
-crbug.com/591099 paint/invalidation/overflow/repaint-resized-overflow.html [ Failure ]
-crbug.com/591099 paint/invalidation/paint-invalidation-with-reparent-across-frame-boundaries.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/absolute-margin-change-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/align-content-position-change-grid.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/containing-block-position-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/position/intermediate-layout-position.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/justify-content-position-change-grid.html [ Failure ]
 crbug.com/591099 paint/invalidation/position/justify-content-position-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/layout-state-relative.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/position-change-keeping-geometry.html [ Failure ]
-crbug.com/591099 paint/invalidation/position/positioned-list-offset-change-repaint.html [ Failure ]
 crbug.com/714962 paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/position/relayout-fixed-position-after-scale.html [ Failure ]
-crbug.com/591099 paint/invalidation/quotes.html [ Failure ]
-crbug.com/591099 paint/invalidation/remove-inline-after-layout.html [ Failure ]
 crbug.com/591099 paint/invalidation/resize-iframe-text.html [ Failure ]
 crbug.com/591099 paint/invalidation/scroll/fixed-child-of-transformed-move-after-scroll.html [ Failure ]
 crbug.com/591099 paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html [ Failure ]
-crbug.com/591099 paint/invalidation/scroll/resize-scrollable-div.html [ Failure ]
-crbug.com/591099 paint/invalidation/scroll/resize-scrollable-iframe.html [ Failure ]
-crbug.com/591099 paint/invalidation/scroll/scrolled-iframe-scrollbar-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/selection/selected-replaced.html [ Failure ]
 crbug.com/591099 paint/invalidation/selection/selection-rl.html [ Failure ]
-crbug.com/591099 paint/invalidation/stacked-diacritics.html [ Failure ]
 crbug.com/591099 paint/invalidation/stacking-context-lost.html [ Failure ]
-crbug.com/591099 paint/invalidation/svg/absolute-sized-content-with-resources.xhtml [ Failure ]
 crbug.com/591099 paint/invalidation/svg/animated-path-inside-transformed-html.xhtml [ Failure Pass ]
 crbug.com/591099 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-content-with-resources.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-content.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-deep-shadow-tree-content.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-image.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-inner-svg.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-shadow-tree-content.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-use-on-symbol.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol.xhtml [ Failure ]
 crbug.com/714962 paint/invalidation/svg/resize-svg-invalidate-children-fixed-size-relative-child.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/resize-svg-invalidate-children.html [ Failure ]
 crbug.com/728378 paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ]
-crbug.com/591099 paint/invalidation/svg/svg-image-change-content-size.xhtml [ Failure ]
-crbug.com/591099 paint/invalidation/table/replace-col.html [ Failure ]
-crbug.com/591099 paint/invalidation/table/resize-table-row-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/table/table-cell-move.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-extra-bottom-grow.html [ Failure ]
-crbug.com/591099 paint/invalidation/table/table-shrink-row-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-two-pass-layout-overpaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/text-append-dirty-lines.html [ Failure ]
-crbug.com/591099 paint/invalidation/text-match-document-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/transform/change-transform.html [ Failure ]
 crbug.com/591099 paint/invalidation/window-resize/window-resize-no-layout-change2.html [ Failure ]
 crbug.com/591099 paint/invalidation/window-resize/window-resize-percent-width-height.html [ Failure ]
 crbug.com/591099 paint/invalidation/window-resize/window-resize-viewport-percent.html [ Failure ]
@@ -794,13 +711,14 @@
 crbug.com/591099 storage/indexeddb/index-cursor.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/mozilla/indexes.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Timeout ]
-crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass Timeout ]
+crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ]
 crbug.com/591099 storage/indexeddb/objectstore-keycursor.html [ Pass Timeout ]
 crbug.com/591099 svg/custom/object-sizing-no-width-height.xhtml [ Failure ]
 crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Failure ]
 crbug.com/591099 svg/in-html/sizing/svg-inline.html [ Failure ]
 crbug.com/591099 svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure ]
 crbug.com/591099 svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Failure ]
+crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Failure ]
 crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ Failure ]
 crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size.xhtml [ Failure ]
 crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ Failure ]
@@ -821,8 +739,10 @@
 crbug.com/591099 virtual/android/ [ Skip ]
 crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
 crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ]
-crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure ]
+crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure Timeout ]
 crbug.com/591099 virtual/gpu-rasterization/images/feature-policy-max-downscaling-image.html [ Failure ]
+crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-image-over-color.html [ Pass Timeout ]
+crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Pass Timeout ]
 crbug.com/591099 virtual/layout_ng/ [ Skip ]
 crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ]
 crbug.com/591099 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass ]
@@ -834,6 +754,9 @@
 crbug.com/591099 virtual/new-remote-playback-pipeline/ [ Skip ]
 crbug.com/591099 virtual/outofblink-cors/ [ Skip ]
 crbug.com/591099 virtual/paint-timing/external/wpt/paint-timing/sibling-painting-first-image.html [ Failure ]
+crbug.com/591099 virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-scroll.html [ Failure ]
+crbug.com/591099 virtual/paint-touchaction-rects/fast/events/touch/touch-rect-assert-first-layer-special.html [ Failure ]
+crbug.com/591099 virtual/paint-touchaction-rects/fast/events/touch/touch-rect-crash-on-unpromote-layer.html [ Failure ]
 crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ]
 crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ]
 crbug.com/591099 virtual/scroll_customization/ [ Skip ]
@@ -847,3 +770,5 @@
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fullscreen/full-screen-with-flex-item.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/video-display-toggle.html [ Failure ]
+crbug.com/591099 virtual/video-surface-layer/media/video-layer-crash.html [ Failure ]
+crbug.com/591099 virtual/video-surface-layer/media/video-poster-scale.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
index e0ccde5..e643bfc 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -130,6 +130,8 @@
 Bug(none) compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Pass ]
 Bug(none) compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ]
 crbug.com/865039 compositing/masks/mask-with-added-filters.html [ Pass ]
+# Link highlights are no longer affected by ancestor effects.
+crbug.com/857501 compositing/gestures/gesture-tapHighlight-with-filter.html [ Pass ]
 
 # These animation/transition tests should pass.
 Bug(none) animations/ [ Pass ]
@@ -313,69 +315,6 @@
 Bug(none) compositing/overflow-trumps-transform-style.html [ Failure ]
 Bug(none) compositing/backface-visibility/backface-visibility-hierarchical-transform.html [ Failure ]
 Bug(none) compositing/geometry/clipping-foreground.html [ Failure Pass ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-iframe-composited.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-iframe-composited-scrolled.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-iframe-composited-scrolled-late-composite.html [ Crash Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-iframe-composited-scrolled-late-noncomposite.html [ Crash Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-iframe.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-iframe-scrolled.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div-composited.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scrolled.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div-layout-change-2.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div-layout-change.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div-scrolled.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div-scrolled-late-composite.html [ Crash Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-1-overflow-div-scrolled-late-noncomposite.html [ Crash Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-composited-inner.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-composited-outer.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-inner.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-inner-late-composite.html [ Crash Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer-late-composite.html [ Crash Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-composited-inner.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-composited-inner-scroll-inner.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-composited-inner-scroll-outer.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-composited-outer.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-composited-outer-scroll-inner.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-composited-outer-scroll-outer.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-scrolled-inner.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-2-overflow-div-scrolled-outer.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-adjustment-clipping.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-composited-img.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-imagemap.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-img-and-text-2.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-img-and-text.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-img.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-img-transformed.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-invisible-inline.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-invisible-inline-squashing.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-nested-cursor2.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-nested-cursor3.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-on-promoted-overflow-div-scrolled.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-pixel-rotated-div.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-pixel-rotated-link.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-pixel-transparent.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-shadow-tree.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-div-boxshadow-absolute.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-div-boxshadow-fixed.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-div-boxshadow-fixed-nested2.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-div-boxshadow-fixed-nested.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-div-boxshadow.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-div-boxshadow-static.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-margin.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-multi-line.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-nested.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-scaled-document.html [ Crash Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-scaledX.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-scaledY.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-simple-window-scroll.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-skew-matrix.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-with-box-shadow.html [ Failure ]
-Bug(none) compositing/gestures/gesture-tapHighlight-with-squashing.html [ Failure ]
 Bug(none) compositing/masks/mask-with-removed-filters.html [ Failure ]
 Bug(none) compositing/video/video-controls-layer-creation.html [ Failure Pass ]
 
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index bbc9e56..36f82ef 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -104,6 +104,8 @@
 crbug.com/472330 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Pass ]
 crbug.com/817175 compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Pass ]
 crbug.com/736052 compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ]
+# Link highlights are no longer affected by ancestor effects.
+crbug.com/857501 compositing/gestures/gesture-tapHighlight-with-filter.html [ Pass ]
 
 Bug(none) paint/invalidation/clip/clip-flex-text.html [ Pass Failure ]
 Bug(none) virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f55e4da..4c29df8 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -162,6 +162,10 @@
 crbug.com/857490 virtual/user-activation-v2/fast/events/touch/gesture/touch-gesture-fling-with-page-scale.html [ Skip ]
 crbug.com/857490 virtual/user-activation-v2/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Skip ]
 crbug.com/857490 virtual/user-activation-v2/fast/events/wheel/wheel-fling-cancel.html [ Skip ]
+crbug.com/857490 virtual/paint-touchaction-rects/fast/events/touch/gesture/gesture-scrollbar-fling.html [ Skip ]
+crbug.com/857490 virtual/paint-touchaction-rects/fast/events/touch/gesture/pad-gesture-cancel.html [ Skip ]
+crbug.com/857490 virtual/paint-touchaction-rects/fast/events/touch/gesture/pad-gesture-fling.html [ Skip ]
+crbug.com/857490 virtual/paint-touchaction-rects/fast/events/touch/gesture/touch-gesture-fling-with-page-scale.html [ Skip ]
 
 # Sheriff 2018/05/25
 crbug.com/846749 [ Mac ] virtual/stable/http/tests/navigation/navigation-interrupted-by-fragment.html  [ Pass Failure ]
@@ -854,6 +858,7 @@
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/newmulticol/list-item.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/newmulticol/orphans-and-widows-balance.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/newmulticol/table-cell.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/orphans-relayout.html [ Crash ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/out-of-flow/abspos-auto-position-on-line-at-boundary.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/out-of-flow/abspos-auto-position-on-line.html [ Failure ]
@@ -1750,6 +1755,7 @@
 
 crbug.com/522648 fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ]
 crbug.com/522648 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ]
+crbug.com/522648 virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-iframes.html [ Skip ]
 crbug.com/520170 fast/dom/timer-throttling-hidden-page.html [ Failure Pass ]
 crbug.com/652536 fast/events/mouse-cursor-change-after-image-load.html [ Failure Pass Crash ]
 crbug.com/652536 virtual/mouseevent_fractional/fast/events/mouse-cursor-change-after-image-load.html [ Failure Pass Crash ]
@@ -1818,6 +1824,10 @@
 crbug.com/567837 virtual/scalefactor200/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Skip ]
 crbug.com/567837 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Skip ]
 
+crbug.com/853912 virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ]
+crbug.com/853912 virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-squashing.html [ Failure ]
+crbug.com/853912 virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
+
 # TODO(ojan): These tests aren't flaky. See crbug.com/517144.
 # Release trybots run asserts, but the main waterfall ones don't. So, even
 # though this is a non-flaky assert failure, we need to mark it [ Pass Crash ].
@@ -2220,6 +2230,7 @@
 crbug.com/613672 [ Mac ] virtual/mouseevent_fractional/fast/events/touch/multi-touch-user-gesture.html [ Skip ]
 crbug.com/613672 [ Mac ] virtual/scroll_customization/fast/events/touch/multi-touch-user-gesture.html [ Skip ]
 crbug.com/613672 [ Mac ] virtual/user-activation-v2/fast/events/touch/multi-touch-user-gesture.html [ Skip ]
+crbug.com/613672 [ Mac ] virtual/paint-touchaction-rects/fast/events/touch/multi-touch-user-gesture.html [ Skip ]
 crbug.com/613672 [ Mac ] fast/events/pointerevents/multi-pointer-event-in-slop-region.html [ Skip ]
 crbug.com/613672 [ Mac ] virtual/mouseevent_fractional/fast/events/pointerevents/multi-pointer-event-in-slop-region.html [ Skip ]
 crbug.com/613672 [ Mac ] virtual/user-activation-v2/fast/events/pointerevents/multi-pointer-event-in-slop-region.html [ Skip ]
@@ -3464,6 +3475,9 @@
 crbug.com/636055 external/wpt/css/css-multicol/multicol-span-all-margin-nested-002.xht [ Failure ]
 crbug.com/792446 external/wpt/css/css-multicol/multicol-span-float-001.xht [ Failure ]
 
+# Skip a virtual test that wpt-importer is unable to update baseline for correctly.
+crbug.com/866802 virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window.html [ Skip ]
+
 # This test times out on debug builds, see https://crbug.com/755810
 crbug.com/626703 [ Debug ] external/wpt/html/semantics/tabular-data/processing-model-1/span-limits.html [ Skip ]
 
@@ -3751,6 +3765,10 @@
 
 crbug.com/765116 external/wpt/xhr/responsexml-document-properties.htm [ Failure ]
 
+# Link highlights currently paint under ancestor affects but this is being
+# changed with BlinkGenPropertyTrees. Until that launches, this test will fail.
+crbug.com/857501 compositing/gestures/gesture-tapHighlight-with-filter.html [ Failure ]
+
 # Sheriff failures 2017-02-03
 crbug.com/688515 fast/spatial-navigation/snav-div-overflow-scrol-hidden.html [ Pass Failure ]
 
@@ -4632,3 +4650,11 @@
 crbug.com/865432 [ Linux ] external/wpt/workers/modules/dedicated-worker-import-blob-url.any.worker.html [ Timeout Pass ]
 
 crbug.com/865755 [ Debug ] virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html [ Failure Pass ]
+
+crbug.com/866785 [ Mac ] fast/forms/select/select-initial-position.html [ Failure Pass ]
+crbug.com/866785 [ Mac ] fast/parser/001.html [ Failure Pass ]
+crbug.com/866785 [ Mac ] fast/table/backgr_border-table-quirks-collapsed-border.html [ Failure Pass ]
+crbug.com/866785 [ Mac ] fast/table/backgr_border-table-quirks.html [ Failure Pass ]
+crbug.com/866785 [ Mac ] svg/as-border-image/svg-as-border-image-2.html [ Failure Pass ]
+crbug.com/866785 [ Mac ] svg/as-border-image/svg-as-border-image.html [ Failure Pass ]
+crbug.com/866785 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/text-track-menu-pointer-selection.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index 448c494..8c4af7f 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -558,6 +558,11 @@
     "args": ["--enable-threaded-compositing"]
   },
   {
+    "prefix": "paint-touchaction-rects",
+    "base": "fast/events/touch",
+    "args": ["--enable-blink-features=PaintTouchActionRects"]
+  },
+  {
     "prefix": "cors-rfc1918",
     "base": "http/tests/security/cors-rfc1918",
     "args": ["--enable-blink-features=CorsRFC1918"]
diff --git a/third_party/WebKit/LayoutTests/compositing/gestures/gesture-tapHighlight-with-filter-expected.html b/third_party/WebKit/LayoutTests/compositing/gestures/gesture-tapHighlight-with-filter-expected.html
new file mode 100644
index 0000000..4ff99fe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/gestures/gesture-tapHighlight-with-filter-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="../../resources/js-test.js"></script>
+<link rel="stylesheet" type="text/css" href="resources/link-highlight-style.css">
+<body onload="runTest();">
+<div style="transform: translateZ(0); position: relative; left: 10; top: 40">
+<span class="fauxHighlight" href="" id="targetLink">Target Link.</span>
+</div>
+<div style="position: relative; left: 10; top: 70">
+This test is successful if "Target Link" above is covered in a fully-opaque green rectangle with square corners.
+</div>
+<script>
+function runTest() {
+    if (window.testRunner)
+        testRunner.dumpAsTextWithPixelResults();
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/compositing/gestures/gesture-tapHighlight-with-filter.html b/third_party/WebKit/LayoutTests/compositing/gestures/gesture-tapHighlight-with-filter.html
new file mode 100644
index 0000000..5cdef6807
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/gestures/gesture-tapHighlight-with-filter.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<script src="../../resources/js-test.js"></script>
+<script src="resources/link-highlight-helper.js"></script>
+<link rel="stylesheet" type="text/css" href="resources/link-highlight-style.css">
+<body onload="runTest();">
+<div style="transform: translateZ(0); position: relative; left: 10; top: 40; filter:opacity(10%);">
+<a class="opaqueHighlight" href="" id="targetLink">Target Link.</a>
+</div>
+<div style="position: relative; left: 10; top: 70">
+This test is successful if "Target Link" above is covered in a fully-opaque green rectangle with square corners.
+</div>
+<script>
+function runTest() {
+    useMockHighlight();
+
+    var clientRect = document.getElementById('targetLink').getBoundingClientRect();
+    x = (clientRect.left + clientRect.right) / 2;
+    y = (clientRect.top + clientRect.bottom) / 2;
+    if (window.testRunner) {
+        testRunner.dumpAsTextWithPixelResults();
+        testRunner.waitUntilDone();
+    }
+
+    if (window.eventSender) {
+        eventSender.gestureShowPress(x, y);
+        requestAnimationFrame(function() { testRunner.notifyDone(); });
+    } else {
+        debug("This test requires DumpRenderTree.");
+    }
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver-expected.txt
rename to third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.html
rename to third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-helper.js b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-helper.js
index bc6d3cd..597170f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-helper.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-helper.js
@@ -165,7 +165,11 @@
 function generateAnswer(offer) {
   const pc = new RTCPeerConnection();
   return pc.setRemoteDescription(offer)
-  .then(() => pc.createAnswer());
+  .then(() => pc.createAnswer())
+  .then((answer) => {
+    pc.close();
+    return answer;
+  });
 }
 
 // Run a test function that return a promise that should
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt
index d08930f5..d16692f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt
@@ -1,12 +1,12 @@
 This is a testharness.js-based test.
-FAIL Calling replaceTrack on closed connection should reject with InvalidStateError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack with track of different kind should reject with TypeError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack on stopped sender should reject with InvalidStateError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack on sender with null track and not set to session description should resolve with sender.track set to given track Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack on sender not set to session description should resolve with sender.track set to given track Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack(null) on sender not set to session description should resolve with sender.track set to null Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack(null) on sender set to session description should resolve with sender.track set to null Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack on sender with stopped track and and set to session description should resolve with sender.track set to given track Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL Calling replaceTrack on sender with similar track and and set to session description should resolve with sender.track set to new track Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
+FAIL Calling replaceTrack on closed connection should reject with InvalidStateError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack with track of different kind should reject with TypeError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack on stopped sender should reject with InvalidStateError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack on sender with null track and not set to session description should resolve with sender.track set to given track promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack on sender not set to session description should resolve with sender.track set to given track promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack(null) on sender not set to session description should resolve with sender.track set to null promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack(null) on sender set to session description should resolve with sender.track set to null promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack on sender with stopped track and and set to session description should resolve with sender.track set to given track promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
+FAIL Calling replaceTrack on sender with similar track and and set to session description should resolve with sender.track set to new track promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument."
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https.html
index f7f83f26..8227085 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https.html
@@ -3,16 +3,12 @@
 <title>RTCRtpSender.prototype.replaceTrack</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="RTCPeerConnection-helper.js"></script>
 <script>
   'use strict';
 
   // Test is based on the following editor draft:
   // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
 
-  // The following helper functions are called from RTCPeerConnection-helper.js:
-  // generateMediaStreamTrack
-
   /*
     5.2.  RTCRtpSender Interface
       interface RTCRtpSender {
@@ -31,10 +27,12 @@
       4.  If connection's [[isClosed]] slot is true, return a promise rejected
           with a newly created InvalidStateError and abort these steps.
    */
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track = generateMediaStreamTrack('audio');
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
 
     const transceiver = pc.addTransceiver('audio');
     const { sender } = transceiver;
@@ -50,10 +48,12 @@
           transceiver kind of transceiver, return a promise rejected with a
           newly created TypeError.
    */
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track = generateMediaStreamTrack('video');
+    const stream = await navigator.mediaDevices.getUserMedia({video: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
 
     const transceiver = pc.addTransceiver('audio');
     const { sender } = transceiver;
@@ -67,10 +67,12 @@
       5.  If transceiver.stopped is true, return a promise rejected with a newly
           created InvalidStateError.
    */
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track = generateMediaStreamTrack('audio');
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
 
     const transceiver = pc.addTransceiver('audio');
     const { sender } = transceiver;
@@ -86,10 +88,12 @@
           (section 3.4.1.), then set sender's track attribute to withTrack, and
           return a promise resolved with undefined.
    */
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track = generateMediaStreamTrack('audio');
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
 
     const transceiver = pc.addTransceiver('audio');
     const { sender } = transceiver;
@@ -101,11 +105,15 @@
     });
   }, 'Calling replaceTrack on sender with null track and not set to session description should resolve with sender.track set to given track');
 
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track1 = generateMediaStreamTrack('audio');
-    const track2 = generateMediaStreamTrack('audio');
+    const stream1 = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream1.getTracks().forEach(track => track.stop()));
+    const [track1] = stream1.getTracks();
+    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream2.getTracks().forEach(track => track.stop()));
+    const [track2] = stream2.getTracks();
 
     const transceiver = pc.addTransceiver(track1);
     const { sender } = transceiver;
@@ -118,10 +126,12 @@
     });
   }, 'Calling replaceTrack on sender not set to session description should resolve with sender.track set to given track');
 
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track = generateMediaStreamTrack('audio');
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
 
     const transceiver = pc.addTransceiver(track);
     const { sender } = transceiver;
@@ -145,10 +155,12 @@
           3.  Queue a task that runs the following steps:
               2.  Set sender's track attribute to withTrack.
    */
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track = generateMediaStreamTrack('audio');
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
 
     const transceiver = pc.addTransceiver(track);
     const { sender } = transceiver;
@@ -175,11 +187,15 @@
           3.  Queue a task that runs the following steps:
               2.  Set sender's track attribute to withTrack.
    */
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track1 = generateMediaStreamTrack('audio');
-    const track2 = generateMediaStreamTrack('audio');
+    const stream1 = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream1.getTracks().forEach(track => track.stop()));
+    const [track1] = stream1.getTracks();
+    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream2.getTracks().forEach(track => track.stop()));
+    const [track2] = stream1.getTracks();
 
     const transceiver = pc.addTransceiver(track1);
     const { sender } = transceiver;
@@ -207,11 +223,15 @@
           3.  Queue a task that runs the following steps:
               2.  Set sender's track attribute to withTrack.
    */
-  promise_test(t => {
+  promise_test(async t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
-    const track1 = generateMediaStreamTrack('audio');
-    const track2 = generateMediaStreamTrack('audio');
+    const stream1 = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream1.getTracks().forEach(track => track.stop()));
+    const [track1] = stream1.getTracks();
+    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream2.getTracks().forEach(track => track.stop()));
+    const [track2] = stream1.getTracks();
 
     const transceiver = pc.addTransceiver(track1);
     const { sender } = transceiver;
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/border-radius-split-background-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/border-radius-split-background-expected.txt
new file mode 100644
index 0000000..b8a8da4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/border-radius-split-background-expected.txt
@@ -0,0 +1,30 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 179x452 [border: (1px solid #000000)]
+        LayoutInline {SPAN} at (0,0) size 177x418 [bgcolor=#808080] [border: (2px solid #000000)]
+          LayoutText {#text} at (3,19) size 50x114
+            text run at (3,19) width 50: "  "
+          LayoutBR {BR} at (53,19) size 0x0
+          LayoutText {#text} at (1,169) size 125x114
+            text run at (1,169) width 125: "     "
+          LayoutBR {BR} at (126,169) size 0x0
+          LayoutText {#text} at (1,319) size 175x114
+            text run at (1,319) width 175: "       "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (179,394) size 4x19
+        text run at (179,394) width 4: " "
+      LayoutNGBlockFlow {DIV} at (183,230) size 452x179 [border: (1px solid #000000)]
+        LayoutInline {SPAN} at (0,0) size 418x177 [bgcolor=#808080] [border: (2px solid #000000)]
+          LayoutText {#text} at (319,3) size 114x50
+            text run at (319,3) width 50: "  "
+          LayoutBR {BR} at (319,53) size 0x0
+          LayoutText {#text} at (169,1) size 114x125
+            text run at (169,1) width 125: "     "
+          LayoutBR {BR} at (169,126) size 0x0
+          LayoutText {#text} at (19,1) size 114x175
+            text run at (19,1) width 175: "       "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/border-radius-split-background-image-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/border-radius-split-background-image-expected.txt
new file mode 100644
index 0000000..ba9281f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/border-radius-split-background-image-expected.txt
@@ -0,0 +1,30 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 179x452 [border: (1px solid #000000)]
+        LayoutInline {SPAN} at (0,0) size 177x418 [bgcolor=#C0C0C0] [border: (2px solid #000000)]
+          LayoutText {#text} at (3,19) size 50x114
+            text run at (3,19) width 50: "  "
+          LayoutBR {BR} at (53,19) size 0x0
+          LayoutText {#text} at (1,169) size 125x114
+            text run at (1,169) width 125: "     "
+          LayoutBR {BR} at (126,169) size 0x0
+          LayoutText {#text} at (1,319) size 175x114
+            text run at (1,319) width 175: "       "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (179,394) size 4x19
+        text run at (179,394) width 4: " "
+      LayoutNGBlockFlow {DIV} at (183,230) size 452x179 [border: (1px solid #000000)]
+        LayoutInline {SPAN} at (0,0) size 418x177 [bgcolor=#C0C0C0] [border: (2px solid #000000)]
+          LayoutText {#text} at (319,3) size 114x50
+            text run at (319,3) width 50: "  "
+          LayoutBR {BR} at (319,53) size 0x0
+          LayoutText {#text} at (169,1) size 114x125
+            text run at (169,1) width 125: "     "
+          LayoutBR {BR} at (169,126) size 0x0
+          LayoutText {#text} at (19,1) size 114x175
+            text run at (19,1) width 175: "       "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/block-layout-inline-children-replaced-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/block-layout-inline-children-replaced-expected.txt
new file mode 100644
index 0000000..049ca3ba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/block-layout-inline-children-replaced-expected.txt
@@ -0,0 +1,49 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow DIV id='target' class='target'",
+          "rect": [0, 116, 402, 152],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='target' class='target'",
+          "rect": [0, 116, 402, 152],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutImage IMG",
+          "rect": [151, 117, 100, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='target' class='target'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutImage IMG",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/box/box-inline-resize-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/box/box-inline-resize-expected.txt
new file mode 100644
index 0000000..7da9edd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/box/box-inline-resize-expected.txt
@@ -0,0 +1,73 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'Chromium'",
+          "rect": [40, 107, 113, 27],
+          "reason": "geometry"
+        },
+        {
+          "object": "InlineTextBox 'Chromium'",
+          "rect": [8, 107, 113, 27],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutImage IMG id='foo'",
+          "rect": [8, 88, 32, 32],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutDeprecatedFlexibleBox DIV id='about-container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutImage IMG id='foo'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow H2",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'Chromium'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-3509-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-3509-expected.txt
new file mode 100644
index 0000000..4424b74b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-3509-expected.txt
@@ -0,0 +1,58 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='im'",
+          "rect": [11, 131, 100, 100],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='im'",
+          "rect": [11, 131, 50, 100],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u00A0'",
+          "rect": [11, 131, 4, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u00A0'",
+          "rect": [11, 131, 4, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTable TABLE",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='im'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\u00A0'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-5699-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-5699-expected.txt
new file mode 100644
index 0000000..4ce0944
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-5699-expected.txt
@@ -0,0 +1,66 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'Hello'",
+          "rect": [8, 184, 35, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Hello'",
+          "rect": [8, 156, 35, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u00A0'",
+          "rect": [8, 150, 4, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u00A0'",
+          "rect": [8, 136, 4, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow P",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\u00A0'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Hello'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-6278-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-6278-expected.txt
new file mode 100644
index 0000000..9bfcd53
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-6278-expected.txt
@@ -0,0 +1,206 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+          "rect": [10, 138, 292, 160],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [10, 303, 292, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'fringilla orci nibh sed neque. Quisque eu nulla'",
+          "rect": [10, 178, 291, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'non nisi molestie accumsan. Etiam tellus urna,'",
+          "rect": [10, 198, 290, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Phasellus vehicula, sem at posuere vehicula,'",
+          "rect": [10, 238, 278, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'laoreet ac, laoreet non, suscipit sed, sapien.'",
+          "rect": [10, 218, 270, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'augue nibh molestie nisl, nec ullamcorper'",
+          "rect": [10, 258, 262, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'malesuada, est libero feugiat libero, vel'",
+          "rect": [10, 158, 246, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+          "rect": [10, 138, 242, 200],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [10, 343, 242, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGTableCell TD id='col1'",
+          "rect": [10, 353, 242, 40],
+          "reason": "incremental"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Curabitur pretium, quam quis semper'",
+          "rect": [10, 138, 235, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Curabitur pretium, quam quis semper'",
+          "rect": [10, 138, 235, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'nec ullamcorper lacus ante vulputate'",
+          "rect": [10, 298, 229, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'accumsan. Etiam tellus urna, laoreet'",
+          "rect": [10, 218, 227, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'ac, laoreet non, suscipit sed, sapien.'",
+          "rect": [10, 238, 224, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'malesuada, est libero feugiat libero,'",
+          "rect": [10, 158, 222, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'vehicula, augue nibh molestie nisl,'",
+          "rect": [10, 278, 217, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Phasellus vehicula, sem at posuere'",
+          "rect": [10, 258, 217, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Quisque eu nulla non nisi molestie'",
+          "rect": [10, 198, 217, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'vel fringilla orci nibh sed neque.'",
+          "rect": [10, 178, 203, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'lacus ante vulputate pede.'",
+          "rect": [10, 278, 162, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGTableCell TD id='col1'",
+          "rect": [252, 138, 50, 215],
+          "reason": "incremental"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'pede.'",
+          "rect": [10, 318, 34, 19],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTable TABLE",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGTableCell TD id='col1'",
+      "reason": "incremental"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Curabitur pretium, quam quis semper'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'malesuada, est libero feugiat libero,'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'vel fringilla orci nibh sed neque.'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Quisque eu nulla non nisi molestie'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'accumsan. Etiam tellus urna, laoreet'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'ac, laoreet non, suscipit sed, sapien.'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Phasellus vehicula, sem at posuere'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'vehicula, augue nibh molestie nisl,'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'nec ullamcorper lacus ante vulputate'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'pede.'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGTableCell TD id='target'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-6473-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-6473-expected.txt
new file mode 100644
index 0000000..2d18ac2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-6473-expected.txt
@@ -0,0 +1,48 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (relative positioned) P",
+          "rect": [8, 152, 784, 20],
+          "reason": "chunk disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow HTML",
+          "rect": [8, 136, 784, 20],
+          "reason": "chunk appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutNGBlockFlow DIV id='allcontent'",
+      "reason": "style change"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) P",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'SUCCESS'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-7235-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-7235-expected.txt
new file mode 100644
index 0000000..393b305
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/bugzilla-7235-expected.txt
@@ -0,0 +1,57 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='t'",
+          "rect": [8, 176, 100, 100],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u00A0'",
+          "rect": [8, 156, 4, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u00A0'",
+          "rect": [8, 156, 4, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutInline (relative positioned) SPAN id='p'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\u00A0'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow (positioned) DIV id='t'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt
new file mode 100644
index 0000000..6c611f7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/clip/caret-ancestor-clip-change-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTextControl INPUT id='target'",
+          "rect": [8, 58, 105, 62],
+          "reason": "incremental"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+          "rect": [8, 58, 105, 62],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutBlockFlow DIV",
+          "rect": [10, 58, 1, 57],
+          "reason": "incremental"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/details-open-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/details-open-repaint-expected.txt
new file mode 100644
index 0000000..28c308760
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/details-open-repaint-expected.txt
@@ -0,0 +1,56 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTextControl INPUT",
+          "rect": [8, 72, 181, 22],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutDetailsMarker DIV id='details-marker'",
+          "rect": [8, 56, 11, 11],
+          "reason": "full"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutDetailsMarker DIV id='details-marker'",
+      "reason": "full"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='details-content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutTextControl INPUT",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "appeared"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-content-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-content-change-expected.txt
new file mode 100644
index 0000000..8e2cdc1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-content-change-expected.txt
@@ -0,0 +1,53 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox DIV id='container'",
+          "rect": [0, 52, 200, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 202, 200, 150],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 52, 200, 150],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutFlexibleBox DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-content-distribution-change-grid-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-content-distribution-change-grid-expected.txt
new file mode 100644
index 0000000..633ca46a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-content-distribution-change-grid-expected.txt
@@ -0,0 +1,62 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutGrid DIV id='container'",
+          "rect": [0, 52, 200, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 252, 200, 100],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 152, 200, 100],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 52, 200, 100],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutGrid DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-items-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-items-change-expected.txt
new file mode 100644
index 0000000..e9ac63f2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-items-change-expected.txt
@@ -0,0 +1,53 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox DIV id='container'",
+          "rect": [0, 52, 200, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [100, 52, 100, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 52, 100, 300],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutFlexibleBox DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-self-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-self-change-expected.txt
new file mode 100644
index 0000000..cdc2e2e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-self-change-expected.txt
@@ -0,0 +1,53 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox DIV class='flex'",
+          "rect": [0, 52, 200, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [100, 52, 100, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 52, 100, 300],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutFlexibleBox DIV class='flex'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-self-change-grid-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-self-change-grid-expected.txt
new file mode 100644
index 0000000..5e36446
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/align-self-change-grid-expected.txt
@@ -0,0 +1,72 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutGrid DIV id='container'",
+          "rect": [0, 52, 200, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item1'",
+          "rect": [0, 52, 100, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item3'",
+          "rect": [100, 202, 100, 150],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item2'",
+          "rect": [100, 127, 100, 150],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item3'",
+          "rect": [100, 127, 100, 150],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item2'",
+          "rect": [100, 52, 100, 150],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutGrid DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item1'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item2'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item3'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/justify-content-distribution-change-grid-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/justify-content-distribution-change-grid-expected.txt
new file mode 100644
index 0000000..9dd34e6a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/justify-content-distribution-change-grid-expected.txt
@@ -0,0 +1,62 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutGrid DIV id='container'",
+          "rect": [0, 52, 300, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [200, 52, 100, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [100, 52, 100, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 52, 100, 200],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutGrid DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/justify-self-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/justify-self-change-expected.txt
new file mode 100644
index 0000000..12837d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/justify-self-change-expected.txt
@@ -0,0 +1,72 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutGrid DIV id='container'",
+          "rect": [0, 52, 200, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item1'",
+          "rect": [0, 52, 100, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item3'",
+          "rect": [150, 52, 50, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item2'",
+          "rect": [125, 52, 50, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item3'",
+          "rect": [125, 52, 50, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item2'",
+          "rect": [100, 52, 50, 300],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutGrid DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item1'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item2'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item3'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/repaint-expected.txt
index cbfbd40..d7e849c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/flexbox/repaint-expected.txt
@@ -172,34 +172,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
       "object": "LayoutFlexibleBox DIV id='flexbox'",
       "reason": "geometry"
     },
@@ -236,34 +208,6 @@
       "reason": "subtree"
     },
     {
-      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
       "object": "LayoutFlexibleBox DIV id='flexbox'",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/float-move-during-layout-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/float-move-during-layout-expected.txt
new file mode 100644
index 0000000..7c8fe9a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/float-move-during-layout-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (floating) DIV",
+          "rect": [8, 210, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutNGBlockFlow (floating) DIV",
+          "rect": [8, 110, 100, 100],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='s'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow (floating) DIV",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/list-marker-2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/list-marker-2-expected.txt
new file mode 100644
index 0000000..4a41914
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/list-marker-2-expected.txt
@@ -0,0 +1,57 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutImage IMG id='target'",
+          "rect": [48, 100, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u2022 '",
+          "rect": [30, 185, 7, 19],
+          "reason": "subtree"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u2022 '",
+          "rect": [30, 135, 7, 19],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGListItem LI",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGListMarker (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\u2022 '",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutImage IMG id='target'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/make-children-non-inline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/make-children-non-inline-expected.txt
new file mode 100644
index 0000000..4465d55
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/make-children-non-inline-expected.txt
@@ -0,0 +1,205 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'about all the stuff'",
+          "rect": [8, 264, 110, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'about all the stuff'",
+          "rect": [8, 164, 110, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'write a book'",
+          "rect": [8, 144, 79, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'write a book'",
+          "rect": [8, 144, 79, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'more words.'",
+          "rect": [8, 104, 79, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'more words.'",
+          "rect": [8, 104, 79, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'that comes'",
+          "rect": [8, 284, 67, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'that comes'",
+          "rect": [8, 184, 67, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'the break.'",
+          "rect": [8, 324, 62, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'the break.'",
+          "rect": [8, 224, 62, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'I could'",
+          "rect": [8, 124, 44, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'I could'",
+          "rect": [8, 124, 44, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'words,'",
+          "rect": [8, 84, 43, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'words,'",
+          "rect": [8, 84, 43, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Word,'",
+          "rect": [8, 64, 39, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Word,'",
+          "rect": [8, 64, 39, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'after'",
+          "rect": [8, 304, 29, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'after'",
+          "rect": [8, 204, 29, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV id='target'",
+          "rect": [8, 164, 10, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutNGBlockFlow DIV",
+      "reason": "style change"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Word,'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'words,'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'more words.'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'I could'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'write a book'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV id='target'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'about all the stuff'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'that comes'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'after'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\n'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'the break.'",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/multicol/multicol-with-text-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/multicol/multicol-with-text-expected.txt
new file mode 100644
index 0000000..50f00cbe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/multicol/multicol-with-text-expected.txt
@@ -0,0 +1,95 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [488, 8, 80, 20],
+          "reason": "chunk appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='mc'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "incremental"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutMultiColumnSet (anonymous)",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-expected.txt
index 32c2602..7590e4a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-expected.txt
@@ -310,32 +310,32 @@
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [67, 138, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [67, 132, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [65, 60, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [65, 54, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [65, 21, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [65, 15, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
@@ -350,32 +350,32 @@
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 504, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 498, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 465, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 459, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 426, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 420, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "LayoutBlockFlow (floating) DIV",
@@ -400,32 +400,32 @@
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 177, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 171, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 99, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [59, 93, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 543, 32, 20],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 537, 32, 20],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "InlineTextBox 'x'",
@@ -460,12 +460,12 @@
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [63, 23, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [63, 17, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
@@ -480,52 +480,52 @@
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 506, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 500, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 467, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 461, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 428, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 422, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 179, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 173, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 140, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [59, 134, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
@@ -550,22 +550,22 @@
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [57, 101, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [57, 95, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [57, 62, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [57, 56, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-right-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-right-expected.txt
index 01b6082b..79d1273 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-right-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/float-overflow-right-expected.txt
@@ -290,32 +290,32 @@
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 504, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 498, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 465, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 459, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 426, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 420, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "LayoutBlockFlow (floating) DIV",
@@ -340,52 +340,52 @@
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 177, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 171, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 99, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [701, 93, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [695, 60, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [695, 54, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [695, 21, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [695, 15, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [693, 138, 40, 10],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
           "rect": [693, 132, 40, 10],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV",
@@ -420,12 +420,12 @@
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 543, 32, 20],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 537, 32, 20],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "InlineTextBox 'x'",
@@ -450,22 +450,22 @@
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [727, 101, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [727, 95, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [727, 62, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [727, 56, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
@@ -500,62 +500,62 @@
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 506, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 500, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 467, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 461, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 428, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 422, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 179, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 173, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 140, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [725, 134, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [721, 23, 16, 16],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
           "rect": [721, 17, 16, 16],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'x'",
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/line-overflow-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/line-overflow-expected.txt
new file mode 100644
index 0000000..cdf3d1a7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overflow/line-overflow-expected.txt
@@ -0,0 +1,160 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'velit. Integer sollicitudin nisi ut'",
+          "rect": [8, 182, 195, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'adipiscing, enim in scelerisque'",
+          "rect": [8, 102, 192, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'adipiscing, enim in scelerisque'",
+          "rect": [8, 102, 192, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'sollicitudin nisi ut urna blandit'",
+          "rect": [8, 182, 191, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'at sagittis eros leo pulvinar'",
+          "rect": [8, 162, 168, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'lacus, at sagittis eros leo'",
+          "rect": [8, 142, 151, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'urna blandit convallis.'",
+          "rect": [8, 202, 139, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'pulvinar velit. Integer'",
+          "rect": [8, 162, 136, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Cras faucibus. Nunc'",
+          "rect": [8, 82, 129, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Cras faucibus. Nunc'",
+          "rect": [8, 82, 129, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'convallis, augue '",
+          "rect": [8, 122, 106, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'convallis, augue'",
+          "rect": [8, 122, 102, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment ' eleifend lacus,'",
+          "rect": [103, 142, 94, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'convallis.'",
+          "rect": [8, 202, 60, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment ' eleifend'",
+          "rect": [149, 122, 54, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutInline SPAN id='t'",
+          "rect": [114, 92, 35, 49],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'purus'",
+          "rect": [114, 122, 35, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'purus'",
+          "rect": [38, 142, 35, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Cras faucibus. Nunc'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'adipiscing, enim in scelerisque'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'convallis, augue '",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutInline SPAN id='t'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'purus'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment ' eleifend'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'lacus, at sagittis eros leo'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'pulvinar velit. Integer'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'sollicitudin nisi ut urna blandit'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'convallis.'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overhanging-float-detach-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overhanging-float-detach-repaint-expected.txt
index bcb6c53..a78c034 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overhanging-float-detach-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/overhanging-float-detach-repaint-expected.txt
@@ -24,36 +24,6 @@
         }
       ]
     }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment 'Bug 105861'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment ': REGRESSION (r132591): Underpainting @ uofmchildrenshospital.org'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment 'This test checks that overhanging floats are properly repainted when a renderer is detached.'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment '\n'",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment 'This test has PASSED if there is no RED below.'",
-      "reason": "subtree"
-    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/paint-invalidation-with-reparent-across-frame-boundaries-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/paint-invalidation-with-reparent-across-frame-boundaries-expected.txt
new file mode 100644
index 0000000..d9d3bac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/paint-invalidation-with-reparent-across-frame-boundaries-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow HTML",
+          "rect": [18, 18, 22, 19],
+          "reason": "chunk disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'abc'",
+          "rect": [8, 187, 22, 19],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='inner-target'",
+      "reason": "appeared"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'abc'",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/absolute-margin-change-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/absolute-margin-change-repaint-expected.txt
new file mode 100644
index 0000000..cb09a85
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/absolute-margin-change-repaint-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='test'",
+          "rect": [0, 60, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='test'",
+          "rect": [0, 40, 100, 100],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV id='container'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow (positioned) DIV id='test'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/align-content-position-change-grid-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/align-content-position-change-grid-expected.txt
new file mode 100644
index 0000000..ac12646
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/align-content-position-change-grid-expected.txt
@@ -0,0 +1,77 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutGrid DIV id='container'",
+          "rect": [0, 52, 200, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 302, 200, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 252, 200, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 202, 200, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 152, 200, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 102, 200, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 52, 200, 50],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutGrid DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/block-layout-inline-children-float-positioned-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/block-layout-inline-children-float-positioned-expected.txt
index c205da1..b54119e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/block-layout-inline-children-float-positioned-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/block-layout-inline-children-float-positioned-expected.txt
@@ -47,18 +47,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow P",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment 'This is a test for regression against '",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment 'https://bugs.webkit.org/show_bug.cgi?id=40142'",
-      "reason": "subtree"
-    },
-    {
       "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='target'",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/containing-block-position-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/containing-block-position-change-expected.txt
new file mode 100644
index 0000000..def7cd3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/containing-block-position-change-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV",
+          "rect": [158, 74, 50, 50],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV",
+          "rect": [100, 74, 50, 50],
+          "reason": "style change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV id='t'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutNGBlockFlow (positioned) DIV",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/justify-content-position-change-grid-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/justify-content-position-change-grid-expected.txt
new file mode 100644
index 0000000..3ddd864
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/justify-content-position-change-grid-expected.txt
@@ -0,0 +1,77 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutGrid DIV id='container'",
+          "rect": [0, 52, 300, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [250, 52, 50, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [200, 52, 50, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [150, 52, 50, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [100, 52, 50, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [50, 52, 50, 200],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV class='item'",
+          "rect": [0, 52, 50, 200],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutGrid DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV class='item'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/layout-state-relative-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/layout-state-relative-expected.txt
new file mode 100644
index 0000000..b86a37fe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/layout-state-relative-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'PASS'",
+          "rect": [8, 152, 38, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'FAIL'",
+          "rect": [8, 152, 35, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV id='target'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'PASS'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt
new file mode 100644
index 0000000..19d8579
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned-expected.txt
@@ -0,0 +1,56 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'x'",
+          "rect": [8, 220, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'x'",
+          "rect": [8, 200, 100, 100],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutInline (relative positioned) SPAN",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutInline (relative positioned) SPAN id='target'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'x'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/positioned-list-offset-change-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/positioned-list-offset-change-repaint-expected.txt
new file mode 100644
index 0000000..9f49ad7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/positioned-list-offset-change-repaint-expected.txt
@@ -0,0 +1,60 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutImage IMG",
+          "rect": [8, 64, 214, 232],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutImage IMG",
+          "rect": [8, 64, 114, 232],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV id='container'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (positioned) UL id='list'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGListItem (positioned) LI",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGListMarker (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '\u2022 '",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutImage IMG",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/quotes-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/quotes-expected.txt
new file mode 100644
index 0000000..9740861
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/quotes-expected.txt
@@ -0,0 +1,80 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'quote 2'",
+          "rect": [17, 28, 47, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'quote 2'",
+          "rect": [16, 28, 47, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u003E'",
+          "rect": [64, 28, 9, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '\u003C'",
+          "rect": [8, 28, 9, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '}'",
+          "rect": [63, 28, 8, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment '{'",
+          "rect": [8, 28, 8, 19],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutInline \u003Cpseudo:before\u003E",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '{'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'quote 2'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutInline \u003Cpseudo:after\u003E",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment '}'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/remove-inline-after-layout-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/remove-inline-after-layout-expected.txt
new file mode 100644
index 0000000..e3e7171
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/remove-inline-after-layout-expected.txt
@@ -0,0 +1,72 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'This span should disappear. '",
+          "rect": [112, 193, 178, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [290, 108, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [112, 108, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [8, 108, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "NGPhysicalTextFragment ' '",
+          "rect": [108, 193, 4, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment ' '",
+          "rect": [108, 193, 4, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment ' '",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/remove-inline-layer-after-layout-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/remove-inline-layer-after-layout-expected.txt
index ae3e564..1211a7b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/remove-inline-layer-after-layout-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/remove-inline-layer-after-layout-expected.txt
@@ -37,14 +37,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment 'Tests invalidation after layouting and then removing a layered span. The span should disappear without any residue.'",
-      "reason": "subtree"
-    },
-    {
       "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-descandant-on-ancestor-layer-move-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-descandant-on-ancestor-layer-move-expected.txt
index d4cfcc9..b0bb565 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-descandant-on-ancestor-layer-move-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-descandant-on-ancestor-layer-move-expected.txt
@@ -20,22 +20,22 @@
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV",
           "rect": [428, 38, 300, 20],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV",
           "rect": [28, 38, 300, 20],
-          "reason": "appeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'There should only be one copy of this text.'",
           "rect": [428, 38, 270, 19],
-          "reason": "disappeared"
+          "reason": "subtree"
         },
         {
           "object": "NGPhysicalTextFragment 'There should only be one copy of this text.'",
           "rect": [28, 38, 270, 19],
-          "reason": "appeared"
+          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/resize-scrollable-iframe-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/resize-scrollable-iframe-expected.txt
new file mode 100644
index 0000000..c13f542c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/resize-scrollable-iframe-expected.txt
@@ -0,0 +1,91 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutView #document",
+          "rect": [8, 108, 300, 300],
+          "reason": "subtree"
+        },
+        {
+          "object": "HorizontalScrollbar",
+          "rect": [8, 393, 285, 15],
+          "reason": "scroll control"
+        },
+        {
+          "object": "HorizontalScrollbar",
+          "rect": [8, 193, 85, 15],
+          "reason": "scroll control"
+        },
+        {
+          "object": "VerticalScrollbar",
+          "rect": [293, 108, 15, 285],
+          "reason": "scroll control"
+        },
+        {
+          "object": "VerticalScrollbar",
+          "rect": [93, 108, 15, 85],
+          "reason": "scroll control"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutIFrame IFRAME id='iframe'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "geometry"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "geometry"
+    },
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll control"
+    },
+    {
+      "object": "LayoutNGBlockFlow HTML",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow BODY",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
index d2fa22f..9812a57 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
@@ -18,16 +18,6 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "NGPhysicalTextFragment 'When you scroll down the red square should have no painting glitches.'",
-          "rect": [8, 16, 447, 19],
-          "reason": "appeared"
-        },
-        {
-          "object": "NGPhysicalTextFragment 'When you scroll down the red square should have no painting glitches.'",
-          "rect": [8, 16, 447, 19],
-          "reason": "disappeared"
-        },
-        {
           "object": "LayoutNGBlockFlow (relative positioned) DIV id='ul'",
           "rect": [677, 252, 100, 100],
           "reason": "paint property change"
@@ -55,14 +45,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow P",
-      "reason": "subtree"
-    },
-    {
-      "object": "NGPhysicalTextFragment 'When you scroll down the red square should have no painting glitches.'",
-      "reason": "subtree"
-    },
-    {
       "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (floating) DIV class='right'",
       "reason": "subtree"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
index d397e324..caf40f8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
@@ -17,12 +17,12 @@
       "reason": "style change"
     },
     {
-      "object": "LayoutNGBlockFlow DIV id='container'",
-      "reason": "incremental"
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='container'",
+      "reason": "subtree"
     },
     {
       "object": "LayoutNGBlockFlow (positioned) DIV id='overlay'",
-      "reason": "appeared"
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selected-replaced-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selected-replaced-expected.txt
new file mode 100644
index 0000000..f591d20b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selected-replaced-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutImage (relative positioned) IMG id='test' class='moved'",
+          "rect": [8, 132, 214, 232],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutImage (relative positioned) IMG id='test' class='moved'",
+          "rect": [8, 52, 214, 232],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutImage (relative positioned) IMG id='test' class='moved'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/stacked-diacritics-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/stacked-diacritics-expected.txt
new file mode 100644
index 0000000..7368eeb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/stacked-diacritics-expected.txt
@@ -0,0 +1,29 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment '\u1EA6\u1EA4\u1EAA\u1EA8\u1EB0'",
+          "rect": [19, 166, 130, 43],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/absolute-sized-content-with-resources-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/absolute-sized-content-with-resources-expected.txt
new file mode 100644
index 0000000..2c6f16a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/absolute-sized-content-with-resources-expected.txt
@@ -0,0 +1,72 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGRect rect",
+          "rect": [42, 119, 334, 268],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutSVGRect rect",
+          "rect": [42, 119, 334, 268],
+          "reason": "paint property change"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGRect rect",
+          "rect": [17, 219, 84, 68],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutSVGRect rect",
+          "rect": [17, 219, 84, 68],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRect rect",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-content-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-content-expected.txt
new file mode 100644
index 0000000..b7a8f34c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-content-expected.txt
@@ -0,0 +1,58 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGRect rect id='targetRect'",
+          "rect": [9, 73, 400, 400],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [109, 73, 300, 400],
+          "reason": "incremental"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 102, 402],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRect rect id='targetRect'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt
new file mode 100644
index 0000000..5b81a0d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-content-with-resources-expected.txt
@@ -0,0 +1,78 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGEllipse circle",
+          "rect": [47, 111, 324, 324],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [47, 392, 324, 43],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [47, 111, 324, 43],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [110, 154, 261, 238],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutSVGEllipse circle",
+          "rect": [8, 154, 170, 238],
+          "reason": "subtree"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [8, 154, 39, 238],
+          "reason": "incremental"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGEllipse circle",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-deep-shadow-tree-content-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-deep-shadow-tree-content-expected.txt
new file mode 100644
index 0000000..477ab886
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-deep-shadow-tree-content-expected.txt
@@ -0,0 +1,66 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g id='targetUse'",
+          "rect": [209, 273, 200, 200],
+          "reason": "paint property change"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGContainer g id='targetUse'",
+          "rect": [59, 273, 50, 200],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer use",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer g id='targetUse'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRect rect id='targetRect'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-image-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-image-expected.txt
new file mode 100644
index 0000000..85dd1a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-image-expected.txt
@@ -0,0 +1,58 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGImage image",
+          "rect": [9, 73, 400, 400],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [109, 73, 300, 400],
+          "reason": "incremental"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 102, 402],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGImage image",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-inner-svg-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-inner-svg-expected.txt
new file mode 100644
index 0000000..f036e14a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-inner-svg-expected.txt
@@ -0,0 +1,62 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg",
+          "rect": [27, 69, 364, 366],
+          "reason": "paint property change"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg",
+          "rect": [13, 207, 92, 92],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGViewportContainer svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt
new file mode 100644
index 0000000..72d3d42
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-shadow-tree-content-expected.txt
@@ -0,0 +1,84 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGContainer use",
+          "rect": [209, 273, 200, 200],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutSVGRect rect id='targetRect1'",
+          "rect": [9, 73, 200, 200],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutSVGRect rect id='targetRect1'",
+          "rect": [59, 73, 150, 200],
+          "reason": "incremental"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGContainer use",
+          "rect": [59, 273, 50, 200],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer use",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRect rect id='targetRect'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer use",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer g id='targetUse'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRect rect id='targetRect1'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol-expected.txt
new file mode 100644
index 0000000..4b4d6b78
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-shadow-tree-content-with-symbol-expected.txt
@@ -0,0 +1,70 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg id='targetSymbol'",
+          "rect": [9, 73, 400, 400],
+          "reason": "paint property change"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 72, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg id='targetSymbol'",
+          "rect": [9, 223, 100, 100],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer use",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGViewportContainer svg id='targetSymbol'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRect rect",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRect rect",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-use-on-symbol-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-use-on-symbol-expected.txt
new file mode 100644
index 0000000..b36c330d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-use-on-symbol-expected.txt
@@ -0,0 +1,66 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg id='gamesBorder'",
+          "rect": [45, 87, 328, 330],
+          "reason": "paint property change"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg id='gamesBorder'",
+          "rect": [18, 211, 82, 83],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer use",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGViewportContainer svg id='gamesBorder'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.txt
new file mode 100644
index 0000000..c12e665
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.txt
@@ -0,0 +1,66 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 402, 402],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg id='gamesBorder'",
+          "rect": [27, 69, 364, 366],
+          "reason": "paint property change"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 102, 402],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGViewportContainer svg id='gamesBorder'",
+          "rect": [13, 207, 92, 92],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGContainer use",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGViewportContainer svg id='gamesBorder'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/svg-image-change-content-size-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/svg-image-change-content-size-expected.txt
new file mode 100644
index 0000000..82b75e2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/svg/svg-image-change-content-size-expected.txt
@@ -0,0 +1,49 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 602, 422],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+          "rect": [8, 52, 422, 422],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutImage img",
+          "rect": [9, 53, 420, 420],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow div id='contentBox'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutImage img",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/resize-table-row-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/resize-table-row-repaint-expected.txt
new file mode 100644
index 0000000..a3037fe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/resize-table-row-repaint-expected.txt
@@ -0,0 +1,48 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'MIDDLE'",
+          "rect": [3, 192, 63, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'MIDDLE'",
+          "rect": [3, 142, 63, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTable TABLE",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'MIDDLE'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/table-cell-move-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/table-cell-move-expected.txt
new file mode 100644
index 0000000..490e90c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/table-cell-move-expected.txt
@@ -0,0 +1,61 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGTableCell TD",
+          "rect": [8, 326, 60, 60],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [8, 266, 60, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [8, 206, 60, 60],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTable TABLE",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGTableCell TD",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGTableCell TD",
+      "reason": "disappeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/table-shrink-row-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/table-shrink-row-repaint-expected.txt
new file mode 100644
index 0000000..d3fdfec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/table/table-shrink-row-repaint-expected.txt
@@ -0,0 +1,349 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 850],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGTableCell TD id='resizeMe'",
+          "rect": [8, 112, 769, 210],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 782, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 742, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 722, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 682, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 662, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 622, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 602, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 562, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 542, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 502, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 482, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 442, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 422, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 382, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 362, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 322, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 302, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 242, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 182, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 122, 769, 60],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+          "rect": [8, 802, 769, 48],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '10'",
+          "rect": [13, 822, 16, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '13'",
+          "rect": [13, 802, 16, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '12'",
+          "rect": [13, 742, 16, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '10'",
+          "rect": [13, 622, 16, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '11'",
+          "rect": [13, 682, 15, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '9'",
+          "rect": [13, 762, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '8'",
+          "rect": [13, 702, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '7'",
+          "rect": [13, 642, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '6'",
+          "rect": [13, 582, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '9'",
+          "rect": [13, 562, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '5'",
+          "rect": [13, 522, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '8'",
+          "rect": [13, 502, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '4'",
+          "rect": [13, 462, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '7'",
+          "rect": [13, 442, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '3'",
+          "rect": [13, 402, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '6'",
+          "rect": [13, 382, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '2'",
+          "rect": [13, 342, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '5'",
+          "rect": [13, 322, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '4'",
+          "rect": [13, 262, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '3'",
+          "rect": [13, 202, 8, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "NGPhysicalTextFragment '2'",
+          "rect": [13, 142, 8, 19],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "Scrolling Contents Layer",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutTable TABLE",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutNGTableCell TD id='resizeMe'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '2'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '3'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '4'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '5'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '6'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '7'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '8'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '9'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '10'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '11'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '12'",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
+      "reason": "geometry"
+    },
+    {
+      "object": "NGPhysicalTextFragment '13'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/text-append-dirty-lines-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/text-append-dirty-lines-expected.txt
new file mode 100644
index 0000000..6fb569d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/text-append-dirty-lines-expected.txt
@@ -0,0 +1,128 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'sagittis aliquam nunc. Nullam pharetra molestie eros. Donec tempus purus ut ligula. Phasellus non nisl. Etiam eu mauris.'",
+          "rect": [8, 144, 756, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'sagittis aliquam nunc. Nullam pharetra molestie eros. Donec tempus purus ut ligula. Phasellus non nisl. Etiam eu mauris.'",
+          "rect": [8, 144, 756, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'laoreet feugiat. Phasellus mollis pulvinar mi. Etiam ut neque sed eros egestas laoreet. Vestibulum ullamcorper, nulla non'",
+          "rect": [8, 84, 751, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'laoreet feugiat. Phasellus mollis pulvinar mi. Etiam ut neque sed eros egestas laoreet. Vestibulum ullamcorper, nulla non'",
+          "rect": [8, 84, 751, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'pellentesque cursus. Proin vitae nulla. Vivamus in ipsum. Etiam mi. Nam malesuada purus in sem. Sed eget elit vel erat'",
+          "rect": [8, 64, 749, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'pellentesque cursus. Proin vitae nulla. Vivamus in ipsum. Etiam mi. Nam malesuada purus in sem. Sed eget elit vel erat'",
+          "rect": [8, 64, 749, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse placerat. Morbi tristique. Mauris eu lacus sed felis'",
+          "rect": [8, 44, 744, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse placerat. Morbi tristique. Mauris eu lacus sed felis'",
+          "rect": [8, 44, 744, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'fermentum ut, tortor. Sed rhoncus. Quisque enim metus, luctus tincidunt, vestibulum eu, vestibulum eu, libero. Mauris'",
+          "rect": [8, 124, 740, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'fermentum ut, tortor. Sed rhoncus. Quisque enim metus, luctus tincidunt, vestibulum eu, vestibulum eu, libero. Mauris'",
+          "rect": [8, 124, 740, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'feugiat molestie, mi lorem bibendum leo, ac gravida orci nunc nec nulla. Nunc nunc lorem, rhoncus et, rutrum ac,'",
+          "rect": [8, 104, 713, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'feugiat molestie, mi lorem bibendum leo, ac gravida orci nunc nec nulla. Nunc nunc lorem, rhoncus et, rutrum ac,'",
+          "rect": [8, 104, 713, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Curabitur a velit.'",
+          "rect": [8, 164, 106, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Curabitur a velit'",
+          "rect": [8, 164, 103, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow P id='target'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse placerat. Morbi tristique. Mauris eu lacus sed felis'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'pellentesque cursus. Proin vitae nulla. Vivamus in ipsum. Etiam mi. Nam malesuada purus in sem. Sed eget elit vel erat'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'laoreet feugiat. Phasellus mollis pulvinar mi. Etiam ut neque sed eros egestas laoreet. Vestibulum ullamcorper, nulla non'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'feugiat molestie, mi lorem bibendum leo, ac gravida orci nunc nec nulla. Nunc nunc lorem, rhoncus et, rutrum ac,'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'fermentum ut, tortor. Sed rhoncus. Quisque enim metus, luctus tincidunt, vestibulum eu, vestibulum eu, libero. Mauris'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'sagittis aliquam nunc. Nullam pharetra molestie eros. Donec tempus purus ut ligula. Phasellus non nisl. Etiam eu mauris.'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'Curabitur a velit.'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/text-match-document-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/text-match-document-change-expected.txt
new file mode 100644
index 0000000..b705847
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/text-match-document-change-expected.txt
@@ -0,0 +1,58 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "NGPhysicalTextFragment 'To be changed: findme (Manual testing:'",
+          "rect": [18, 130, 251, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'Find-in-page 'findme', then click here)'",
+          "rect": [18, 150, 240, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalTextFragment 'After change'",
+          "rect": [18, 130, 82, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "VerticalScrollbar",
+          "rect": [295, 102, 15, 400],
+          "reason": "scroll control"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll control"
+    },
+    {
+      "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='to-be-changed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "NGPhysicalTextFragment 'After change'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test-expected.txt
index a445bfc..5967758 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test-expected.txt
@@ -215,6 +215,31 @@
 console-filter-test.js:43 Hello 1
 console-filter-test.js:44 Hello 2
 
+Running: checkStartEndLineRegex
+>console-filter-test.js:24 outerGroup
+  >console-filter-test.js:31 innerGroup
+console-filter-test.js:43 Hello 1
+console-filter-test.js:44 Hello 2
+
+Running: checkStartEndLineRegexForAnchor
+log-source.js:3 1topGroup
+log-source.js:3 3topGroup
+log-source.js:3 5topGroup
+log-source.js:3 7topGroup
+log-source.js:3 9topGroup
+>console-filter-test.js:24 outerGroup
+  log-source.js:3 11outerGroup
+  log-source.js:3 13outerGroup
+  log-source.js:3 15outerGroup
+  log-source.js:3 17outerGroup
+  log-source.js:3 19outerGroup
+  >console-filter-test.js:31 innerGroup
+    log-source.js:3 21innerGroup
+    log-source.js:3 23innerGroup
+    log-source.js:3 25innerGroup
+    log-source.js:3 27innerGroup
+    log-source.js:3 29innerGroup
+
 Running: checkResetFilter
 console-filter-test.js:14 0topGroup
 log-source.js:3 1topGroup
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test.js
index 98ba5910..bcc8dbd 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-filter-test.js
@@ -144,6 +144,20 @@
       dumpVisibleMessages();
       next();
     },
+    function checkStartEndLineRegex(next)
+    {
+      Console.ConsoleView.instance()._filter._textFilterUI.setValue("/^Hello\\s\\d$/");
+      Console.ConsoleView.instance()._filter._onFilterChanged();
+      dumpVisibleMessages();
+      next();
+    },
+    function checkStartEndLineRegexForAnchor(next)
+    {
+      Console.ConsoleView.instance()._filter._textFilterUI.setValue("/^log-source\\.js:\\d+$/");
+      Console.ConsoleView.instance()._filter._onFilterChanged();
+      dumpVisibleMessages();
+      next();
+    },
     function checkResetFilter(next) {
       Console.ConsoleView.instance()._filter.reset();
       dumpVisibleMessages();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-pins-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-pins-expected.txt
new file mode 100644
index 0000000..fc4320f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-pins-expected.txt
@@ -0,0 +1,36 @@
+Tests that console can pin expressions.
+
+
+Running: testBeforeAdding
+No pins
+
+Running: testAddingExpression
+Name: document.activeElement
+Value: div#div1
+
+Running: testPinUpdatesDynamically
+Focusing the div2 on target page.
+Name: document.activeElement
+Value: div#div2
+
+Running: testNoSideEffectsWhileEditing
+Focusing the first pin's editor.
+Setting text to: "window.flag = true".
+Name: window.flag = true
+Value: (...)
+window.flag is now: false
+
+Running: testRemoveSinglePin
+Name: document.activeElement
+Value: div#div2
+Name: "Second pin"
+Value: "Second pin"
+
+Removing second pin
+
+Name: document.activeElement
+Value: div#div2
+
+Running: testRemoveAllPins
+No pins
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-pins.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-pins.js
new file mode 100644
index 0000000..49b75d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-pins.js
@@ -0,0 +1,100 @@
+// 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.
+
+(async function() {
+  TestRunner.addResult(`Tests that console can pin expressions.\n`);
+
+  await TestRunner.loadModule('console_test_runner');
+  await TestRunner.showPanel('console');
+  await TestRunner.loadHTML(`
+    <div tabIndex="-1" id="div1">foo 1</div>
+    <div tabIndex="-1" id="div2">foo 2</div>
+    <script>
+      window.flag = false;
+    </script>
+  `);
+  await TestRunner.evaluateInPagePromise(`div1.focus()`);
+  const consoleView = Console.ConsoleView.instance();
+  const pinPane = consoleView._pinPane;
+
+  TestRunner.runTestSuite([
+    async function testBeforeAdding(next) {
+      await dumpPinPaneContents();
+      next();
+    },
+
+    async function testAddingExpression(next) {
+      pinPane.addPin(`document.activeElement`);
+      await waitForEditors();
+      await waitForPinUpdate();
+      await dumpPinPaneContents();
+      next();
+    },
+
+    async function testPinUpdatesDynamically(next) {
+      TestRunner.addResult(`Focusing the div2 on target page.`);
+      await TestRunner.evaluateInPagePromise(`div2.focus()`);
+      await waitForPinUpdate();
+      await dumpPinPaneContents();
+      next();
+    },
+
+    async function testNoSideEffectsWhileEditing(next) {
+      TestRunner.addResult(`Focusing the first pin's editor.`);
+      await pinAt(0).focus();
+
+      const sideEffectExpression = `window.flag = true`;
+      TestRunner.addResult(`Setting text to: "${sideEffectExpression}".`);
+      pinAt(0)._editor.setText(sideEffectExpression);
+
+      await waitForPinUpdate();
+      await dumpPinPaneContents();
+      const flagResult = await TestRunner.evaluateInPagePromise(`window.flag`);
+      TestRunner.addResult(`window.flag is now: ${flagResult}`);
+
+      pinAt(0)._editor.setText(`document.activeElement`);
+      next();
+    },
+
+    async function testRemoveSinglePin(next) {
+      pinPane.addPin(`"Second pin"`);
+      await waitForEditors();
+      await waitForPinUpdate();
+      await dumpPinPaneContents();
+
+      TestRunner.addResult(`\nRemoving second pin\n`);
+      pinPane._removePin(pinAt(1));
+      await dumpPinPaneContents();
+      next();
+    },
+
+    async function testRemoveAllPins(next) {
+      pinPane._removeAllPins();
+      await dumpPinPaneContents();
+      next();
+    }
+  ]);
+
+  async function dumpPinPaneContents() {
+    if (!pinPane._pins.size) {
+      TestRunner.addResult(`No pins`);
+      return;
+    }
+    for (const pin of pinPane._pins)
+      TestRunner.addResult(`Name: ${pin._editor.text()}\nValue: ${pin._pinPreview.deepTextContent()}`);
+  }
+
+  async function waitForEditors() {
+    for (const pin of pinPane._pins)
+      await pin._editorPromise;
+  }
+
+  async function waitForPinUpdate(index) {
+    await TestRunner.addSnifferPromise(pinPane, '_updatedForTest');
+  }
+
+  function pinAt(index) {
+    return Array.from(pinPane._pins)[index];
+  }
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/README.md b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/README.md
index bfaea47..6f71052 100644
--- a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/README.md
+++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/README.md
@@ -1,80 +1,12 @@
-The certificate message files (\*.msg) and the signed exchange files
-(\*.sxg) in this directory are generated using the following commands.
+To regenerate the key/certificate pair for the signed-exchanges in this
+directory, run `generate-test-certs.sh`.
 
-gen-certurl and gen-signedexchange are available in [webpackage repository][1].
-Revision cf19833 is used to generate these files.
+The signed exchange files in this directory are generated using
+`generate-test-sxgs.sh`. it requires command-line tools in the
+[webpackage repository][1]. To install them, run:
+```
+go get -u github.com/WICG/webpackage/go/signedexchange/cmd/...
+```
+The revision of the tools used to generate the test files is `cf19833`.
 
 [1]: https://github.com/WICG/webpackage
-
-```
-# Install gen-certurl command.
-go get github.com/WICG/webpackage/go/signedexchange/cmd/gen-certurl
-
-# Install gen-signedexchange command.
-go get github.com/WICG/webpackage/go/signedexchange/cmd/gen-signedexchange
-
-# Generate key/certificate pair for 127.0.0.1 signed-exchanges
-(
-  cd src/third_party/blink/tools/blinkpy/third_party/wpt/certs;
-  openssl ecparam -out 127.0.0.1.sxg.key -name prime256v1 -genkey;
-  openssl req -new -sha256 -key 127.0.0.1.sxg.key -out 127.0.0.1.sxg.csr \
-    --subj '/CN=127.0.0.1/O=Test/C=US' \
-    -config 127.0.0.1.sxg.cnf;
-  openssl x509 -req -days 3650 \
-    -in 127.0.0.1.sxg.csr -extfile 127.0.0.1.sxg.ext \
-    -CA cacert.pem -CAkey cakey.pem -passin pass:web-platform-tests \
-    -set_serial 3 -out 127.0.0.1.sxg.pem
-)
-
-# Make dummy OCSP data for cbor certificate chains.
-echo -n OCSP >/tmp/ocsp
-
-# Generate the certificate chain of "127.0.0.1.sxg.pem".
-gen-certurl  \
-  -pem ../../../../../../../blink/tools/blinkpy/third_party/wpt/certs/127.0.0.1.sxg.pem \
-  -ocsp /tmp/ocsp \
-  > 127.0.0.1.sxg.pem.cbor
-
-# Generate the signed exchange file.
-gen-signedexchange \
-  -uri https://127.0.0.1:8443/test.html \
-  -status 200 \
-  -content sxg-location.html \
-  -certificate ../../../../../../../blink/tools/blinkpy/third_party/wpt/certs/127.0.0.1.sxg.pem \
-  -certUrl https://127.0.0.1:8443/loading/sxg/resources/127.0.0.1.sxg.pem.cbor \
-  -validityUrl https://127.0.0.1:8443/loading/sxg/resources/resource.validity.msg \
-  -privateKey ../../../../../../../blink/tools/blinkpy/third_party/wpt/certs/127.0.0.1.sxg.key \
-  -date 2018-04-01T00:00:00Z \
-  -expire 168h \
-  -o sxg-location.sxg \
-  -miRecordSize 100
-
-# Generate the signed exchange file which certificate file is not available.
-gen-signedexchange \
-  -uri https://127.0.0.1:8443/not_found_cert.html \
-  -status 200 \
-  -content sxg-location.html \
-  -certificate ../../../../../../../blink/tools/blinkpy/third_party/wpt/certs/127.0.0.1.sxg.pem \
-  -certUrl https://127.0.0.1:8443/loading/sxg/resources/not_found_cert.pem.cbor \
-  -validityUrl https://127.0.0.1:8443/loading/sxg/resources/not_found_cert.validity.msg \
-  -privateKey ../../../../../../../blink/tools/blinkpy/third_party/wpt/certs/127.0.0.1.sxg.key \
-  -date 2018-04-01T00:00:00Z \
-  -expire 168h \
-  -o sxg-cert-not-found.sxg \
-  -miRecordSize 100
-
-# Generate the signed exchange file which validity URL is different origin from
-# request URL.
-gen-signedexchange \
-  -uri https://127.0.0.1:8443/test.html \
-  -status 200 \
-  -content sxg-location.html \
-  -certificate ../../../../../../../blink/tools/blinkpy/third_party/wpt/certs/127.0.0.1.sxg.pem \
-  -certUrl https://127.0.0.1:8443/loading/sxg/resources/127.0.0.1.sxg.pem.cbor \
-  -validityUrl https://www2.127.0.0.1/loading/sxg/resources/resource.validity.msg \
-  -privateKey ../../../../../../../blink/tools/blinkpy/third_party/wpt/certs/127.0.0.1.sxg.key \
-  -date 2018-04-01T00:00:00Z \
-  -expire 168h \
-  -o sxg-invalid-validity-url.sxg \
-  -miRecordSize 100
-```
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/generate-test-certs.sh b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/generate-test-certs.sh
new file mode 100755
index 0000000..a8e7d26
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/generate-test-certs.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# 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.
+
+set -e
+
+topdir=$(git rev-parse --show-toplevel)
+cd $topdir/third_party/blink/tools/blinkpy/third_party/wpt/certs
+
+openssl ecparam -out 127.0.0.1.sxg.key -name prime256v1 -genkey;
+openssl req -new -sha256 -key 127.0.0.1.sxg.key -out 127.0.0.1.sxg.csr \
+  --subj '/CN=127.0.0.1/O=Test/C=US' \
+  -config 127.0.0.1.sxg.cnf;
+openssl x509 -req -days 3650 \
+  -in 127.0.0.1.sxg.csr -extfile 127.0.0.1.sxg.ext \
+  -CA cacert.pem -CAkey cakey.pem -passin pass:web-platform-tests \
+  -set_serial 3 -out 127.0.0.1.sxg.pem
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/generate-test-sxgs.sh b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/generate-test-sxgs.sh
new file mode 100755
index 0000000..856cdc1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/generate-test-sxgs.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# 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.
+
+set -e
+
+for cmd in gen-signedexchange gen-certurl; do
+    if ! command -v $cmd > /dev/null 2>&1; then
+        echo "$cmd is not installed. Please run:"
+        echo "  go get -u github.com/WICG/webpackage/go/signedexchange/cmd/..."
+        exit 1
+    fi
+done
+
+certs_dir=../../../../../../../blink/tools/blinkpy/third_party/wpt/certs
+tmpdir=$(mktemp -d)
+
+# Make dummy OCSP data for cbor certificate chains.
+echo -n OCSP >$tmpdir/ocsp
+
+# Generate the certificate chain of "127.0.0.1.sxg.pem".
+gen-certurl  \
+  -pem $certs_dir/127.0.0.1.sxg.pem \
+  -ocsp $tmpdir/ocsp \
+  > 127.0.0.1.sxg.pem.cbor
+
+# Generate the signed exchange file.
+gen-signedexchange \
+  -uri https://127.0.0.1:8443/test.html \
+  -status 200 \
+  -content sxg-location.html \
+  -certificate $certs_dir/127.0.0.1.sxg.pem \
+  -certUrl https://127.0.0.1:8443/loading/sxg/resources/127.0.0.1.sxg.pem.cbor \
+  -validityUrl https://127.0.0.1:8443/loading/sxg/resources/resource.validity.msg \
+  -privateKey $certs_dir/127.0.0.1.sxg.key \
+  -date 2018-04-01T00:00:00Z \
+  -expire 168h \
+  -o sxg-location.sxg \
+  -miRecordSize 100
+
+# Generate the signed exchange file which certificate file is not available.
+gen-signedexchange \
+  -uri https://127.0.0.1:8443/not_found_cert.html \
+  -status 200 \
+  -content sxg-location.html \
+  -certificate $certs_dir/127.0.0.1.sxg.pem \
+  -certUrl https://127.0.0.1:8443/loading/sxg/resources/not_found_cert.pem.cbor \
+  -validityUrl https://127.0.0.1:8443/loading/sxg/resources/not_found_cert.validity.msg \
+  -privateKey $certs_dir/127.0.0.1.sxg.key \
+  -date 2018-04-01T00:00:00Z \
+  -expire 168h \
+  -o sxg-cert-not-found.sxg \
+  -miRecordSize 100
+
+# Generate the signed exchange file which validity URL is different origin from
+# request URL.
+gen-signedexchange \
+  -uri https://127.0.0.1:8443/test.html \
+  -status 200 \
+  -content sxg-location.html \
+  -certificate $certs_dir/127.0.0.1.sxg.pem \
+  -certUrl https://127.0.0.1:8443/loading/sxg/resources/127.0.0.1.sxg.pem.cbor \
+  -validityUrl https://www2.127.0.0.1/loading/sxg/resources/resource.validity.msg \
+  -privateKey $certs_dir/127.0.0.1.sxg.key \
+  -date 2018-04-01T00:00:00Z \
+  -expire 168h \
+  -o sxg-invalid-validity-url.sxg \
+  -miRecordSize 100
+
+rm -fr $tmpdir
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/xss-DENIED-xsl-document-redirect-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/xss-DENIED-xsl-document-redirect-expected.txt
index 2fba8e5f..1894702e8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/xss-DENIED-xsl-document-redirect-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/security/xss-DENIED-xsl-document-redirect-expected.txt
@@ -1 +1,3 @@
+CONSOLE ERROR: Unsafe attempt to load URL http://localhost:8000/security/resources/target.xml from frame with URL http://127.0.0.1:8000/security/xss-DENIED-xsl-document-redirect.xml. Domains, protocols and ports must match.
+
 This test includes content via a cross-origin document() command. It passes if the load fails and thus there is no text below this line.
diff --git a/third_party/WebKit/LayoutTests/http/tests/workers/worker-redirect-expected.txt b/third_party/WebKit/LayoutTests/http/tests/workers/worker-redirect-expected.txt
index cd233a3..3120832 100644
--- a/third_party/WebKit/LayoutTests/http/tests/workers/worker-redirect-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/workers/worker-redirect-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE ERROR: Unsafe attempt to load URL http://localhost:8000/workers/resources/worker-redirect-target.js from frame with URL http://127.0.0.1:8000/workers/worker-redirect.html. Domains, protocols and ports must match.
+
 Test that loading the worker's script does not allow a cross origin redirect (bug 26146)
 
 SUCCESS: threw exception (SecurityError: Failed to construct 'Worker': Script at 'http://localhost:8000/workers/resources/worker-target.js' cannot be accessed from origin 'http://127.0.0.1:8000'.) when attempting to cross origin while loading the worker script.
diff --git a/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/README.txt b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/README.txt
new file mode 100644
index 0000000..1bc6124
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/README.txt
@@ -0,0 +1,2 @@
+# This suite runs the tests in LayoutTests/fast/events/touch/ with --enable-blink-features=PaintTouchActionRects.
+# See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-global-expected.txt b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-global-expected.txt
new file mode 100644
index 0000000..99046ce
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-global-expected.txt
@@ -0,0 +1,12 @@
+This tests verifies the hit test regions given to the compositor in the simple case where touch handles cover (or nearly cover) the entire document. It can only be run in DumpRenderTree.
+
+document: #document scrolling (0, 0, 800, 600)
+document: #document scrolling (0, 600, 785, 1400)
+
+html: #document scrolling (0, 0, 785, 2000)
+
+body: #document scrolling (5, 16, 775, 1968)
+
+webPageOverlay: no rects
+
+
diff --git a/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-many-expected.txt b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-many-expected.txt
new file mode 100644
index 0000000..ac27131
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-many-expected.txt
@@ -0,0 +1,111 @@
+Tests that there is an upper limit on the number of hit rects generated per layer. http://crbug.com/299177.
+
+Test node has 99 children with 100 rects
+Test node has 100 children with 101 rects
+FAIL - got 101 rects, expected 1.
+Test node has 101 children with 102 rects
+FAIL - got 102 rects, expected 1.
+manychildren: DIV#layer (0, 0, 290, 12)
+manychildren: DIV#layer (301, 21, 7, 7)
+manychildren: DIV#layer (301, 33, 7, 7)
+manychildren: DIV#layer (301, 45, 7, 7)
+manychildren: DIV#layer (301, 57, 7, 7)
+manychildren: DIV#layer (301, 69, 7, 7)
+manychildren: DIV#layer (301, 81, 7, 7)
+manychildren: DIV#layer (301, 93, 7, 7)
+manychildren: DIV#layer (301, 105, 7, 7)
+manychildren: DIV#layer (301, 117, 7, 7)
+manychildren: DIV#layer (301, 129, 7, 7)
+manychildren: DIV#layer (301, 141, 7, 7)
+manychildren: DIV#layer (301, 153, 7, 7)
+manychildren: DIV#layer (301, 165, 7, 7)
+manychildren: DIV#layer (301, 177, 7, 7)
+manychildren: DIV#layer (301, 189, 7, 7)
+manychildren: DIV#layer (301, 201, 7, 7)
+manychildren: DIV#layer (301, 213, 7, 7)
+manychildren: DIV#layer (301, 225, 7, 7)
+manychildren: DIV#layer (301, 237, 7, 7)
+manychildren: DIV#layer (301, 249, 7, 7)
+manychildren: DIV#layer (301, 261, 7, 7)
+manychildren: DIV#layer (301, 273, 7, 7)
+manychildren: DIV#layer (301, 285, 7, 7)
+manychildren: DIV#layer (301, 297, 7, 7)
+manychildren: DIV#layer (301, 309, 7, 7)
+manychildren: DIV#layer (301, 321, 7, 7)
+manychildren: DIV#layer (301, 333, 7, 7)
+manychildren: DIV#layer (301, 345, 7, 7)
+manychildren: DIV#layer (301, 357, 7, 7)
+manychildren: DIV#layer (301, 369, 7, 7)
+manychildren: DIV#layer (301, 381, 7, 7)
+manychildren: DIV#layer (301, 393, 7, 7)
+manychildren: DIV#layer (301, 405, 7, 7)
+manychildren: DIV#layer (301, 417, 7, 7)
+manychildren: DIV#layer (301, 429, 7, 7)
+manychildren: DIV#layer (301, 441, 7, 7)
+manychildren: DIV#layer (301, 453, 7, 7)
+manychildren: DIV#layer (301, 465, 7, 7)
+manychildren: DIV#layer (301, 477, 7, 7)
+manychildren: DIV#layer (301, 489, 7, 7)
+manychildren: DIV#layer (301, 501, 7, 7)
+manychildren: DIV#layer (301, 513, 7, 7)
+manychildren: DIV#layer (301, 525, 7, 7)
+manychildren: DIV#layer (301, 537, 7, 7)
+manychildren: DIV#layer (301, 549, 7, 7)
+manychildren: DIV#layer (301, 561, 7, 7)
+manychildren: DIV#layer (301, 573, 7, 7)
+manychildren: DIV#layer (301, 585, 7, 7)
+manychildren: DIV#layer (301, 597, 7, 7)
+manychildren: DIV#layer (301, 609, 7, 7)
+manychildren: DIV#layer (301, 621, 7, 7)
+manychildren: DIV#layer (301, 633, 7, 7)
+manychildren: DIV#layer (301, 645, 7, 7)
+manychildren: DIV#layer (301, 657, 7, 7)
+manychildren: DIV#layer (301, 669, 7, 7)
+manychildren: DIV#layer (301, 681, 7, 7)
+manychildren: DIV#layer (301, 693, 7, 7)
+manychildren: DIV#layer (301, 705, 7, 7)
+manychildren: DIV#layer (301, 717, 7, 7)
+manychildren: DIV#layer (301, 729, 7, 7)
+manychildren: DIV#layer (301, 741, 7, 7)
+manychildren: DIV#layer (301, 753, 7, 7)
+manychildren: DIV#layer (301, 765, 7, 7)
+manychildren: DIV#layer (301, 777, 7, 7)
+manychildren: DIV#layer (301, 789, 7, 7)
+manychildren: DIV#layer (301, 801, 7, 7)
+manychildren: DIV#layer (301, 813, 7, 7)
+manychildren: DIV#layer (301, 825, 7, 7)
+manychildren: DIV#layer (301, 837, 7, 7)
+manychildren: DIV#layer (301, 849, 7, 7)
+manychildren: DIV#layer (301, 861, 7, 7)
+manychildren: DIV#layer (301, 873, 7, 7)
+manychildren: DIV#layer (301, 885, 7, 7)
+manychildren: DIV#layer (301, 897, 7, 7)
+manychildren: DIV#layer (301, 909, 7, 7)
+manychildren: DIV#layer (301, 921, 7, 7)
+manychildren: DIV#layer (301, 933, 7, 7)
+manychildren: DIV#layer (301, 945, 7, 7)
+manychildren: DIV#layer (301, 957, 7, 7)
+manychildren: DIV#layer (301, 969, 7, 7)
+manychildren: DIV#layer (301, 981, 7, 7)
+manychildren: DIV#layer (301, 993, 7, 7)
+manychildren: DIV#layer (301, 1005, 7, 7)
+manychildren: DIV#layer (301, 1017, 7, 7)
+manychildren: DIV#layer (301, 1029, 7, 7)
+manychildren: DIV#layer (301, 1041, 7, 7)
+manychildren: DIV#layer (301, 1053, 7, 7)
+manychildren: DIV#layer (301, 1065, 7, 7)
+manychildren: DIV#layer (301, 1077, 7, 7)
+manychildren: DIV#layer (301, 1089, 7, 7)
+manychildren: DIV#layer (301, 1101, 7, 7)
+manychildren: DIV#layer (301, 1113, 7, 7)
+manychildren: DIV#layer (301, 1125, 7, 7)
+manychildren: DIV#layer (301, 1137, 7, 7)
+manychildren: DIV#layer (301, 1149, 7, 7)
+manychildren: DIV#layer (301, 1161, 7, 7)
+manychildren: DIV#layer (301, 1173, 7, 7)
+manychildren: DIV#layer (301, 1185, 7, 7)
+manychildren: DIV#layer (301, 1197, 7, 7)
+manychildren: DIV#layer (301, 1209, 7, 7)
+manychildren: DIV#layer (301, 1221, 7, 7)
+
+
diff --git a/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt
new file mode 100644
index 0000000..4ee93d8d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt
@@ -0,0 +1,20 @@
+This test verifies the hit test regions given to the compositor specifically around composited overflow scroll elements.
+
+scrollContent: DIV#scroll1 scrolling (1, 14, 273, 12)
+
+scrollContent5: DIV#scroll5 scrolling (1, 14, 273, 12)
+
+scrollContent6: DIV#scroll6 scrolling[-1,-14] (0, 0, 273, 12)
+
+nestedContent: DIV#scroll2b scrolling (1, 31, 256, 12)
+
+overflowwithhandler: DIV#overflowwithhandler (0, 0, 273, 52)
+overflowwithhandler: DIV#overflowwithhandler scrolling (1, 1, 256, 116)
+
+overflowwithborder: DIV#overflowwithborder (0, 0, 290, 70)
+overflowwithborder: DIV#overflowwithborder scrolling (10, 10, 255, 116)
+
+withTransform: DIV#transformed (0, 0, 271, 12)
+withTransform: DIV#scroll3 scrolling (1, 14, 273, 14)
+
+
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver-expected.txt
rename to third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt
index 03841d9e..8b4a12b3 100644
--- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt
@@ -1,7 +1,7 @@
 This is a testharness.js-based test.
 PASS Calling replaceTrack on closed connection should reject with InvalidStateError
 FAIL Calling replaceTrack with track of different kind should reject with TypeError assert_throws: function "function() { throw e }" threw object "InvalidModificationError" ("InvalidModificationError") expected object "TypeError" ("TypeError")
-FAIL Calling replaceTrack on stopped sender should reject with InvalidStateError transceiver.stop is not a function
+FAIL Calling replaceTrack on stopped sender should reject with InvalidStateError promise_test: Unhandled rejection with value: object "TypeError: transceiver.stop is not a function"
 PASS Calling replaceTrack on sender with null track and not set to session description should resolve with sender.track set to given track
 PASS Calling replaceTrack on sender not set to session description should resolve with sender.track set to given track
 PASS Calling replaceTrack(null) on sender not set to session description should resolve with sender.track set to null
diff --git a/third_party/blink/public/web/web_associated_url_loader_options.h b/third_party/blink/public/web/web_associated_url_loader_options.h
index c4b30a4..120995c 100644
--- a/third_party/blink/public/web/web_associated_url_loader_options.h
+++ b/third_party/blink/public/web/web_associated_url_loader_options.h
@@ -36,21 +36,19 @@
 namespace blink {
 
 struct WebAssociatedURLLoaderOptions {
-  WebAssociatedURLLoaderOptions()
-      : untrusted_http(false),
-        expose_all_response_headers(false),
-        preflight_policy(
-            network::mojom::CORSPreflightPolicy::kConsiderPreflight) {}
-
   // Whether to validate the method and headers as if this was an
   // XMLHttpRequest.
-  bool untrusted_http;
+  bool untrusted_http = false;
 
   // If policy is to use access control, whether to expose non-whitelisted
   // response headers to the client.
-  bool expose_all_response_headers;
+  bool expose_all_response_headers = false;
 
-  network::mojom::CORSPreflightPolicy preflight_policy;
+  // When true, omit origin related checks. USE WITH CARE.
+  bool grant_universal_access = false;
+
+  network::mojom::CORSPreflightPolicy preflight_policy =
+      network::mojom::CORSPreflightPolicy::kConsiderPreflight;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 2ca28ce..b681f4f 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -1581,19 +1581,11 @@
 void Element::setAttribute(const QualifiedName& name,
                            const StringOrTrustedHTML& stringOrHTML,
                            ExceptionState& exception_state) {
-  DCHECK(stringOrHTML.IsString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-  if (stringOrHTML.IsString() && GetDocument().RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedHTML` assignment.");
-    return;
+  String valueString =
+      TrustedHTML::GetString(stringOrHTML, &GetDocument(), exception_state);
+  if (!exception_state.HadException()) {
+    setAttribute(name, AtomicString(valueString));
   }
-
-  String valueString = stringOrHTML.IsString()
-                           ? stringOrHTML.GetAsString()
-                           : stringOrHTML.GetAsTrustedHTML()->toString();
-
-  setAttribute(name, AtomicString(valueString));
 }
 
 void Element::setAttribute(const QualifiedName& name,
@@ -1617,19 +1609,11 @@
 void Element::setAttribute(const QualifiedName& name,
                            const USVStringOrTrustedURL& stringOrURL,
                            ExceptionState& exception_state) {
-  DCHECK(stringOrURL.IsUSVString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-  if (stringOrURL.IsUSVString() && GetDocument().RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedURL` assignment.");
-    return;
+  String url =
+      TrustedURL::GetString(stringOrURL, &GetDocument(), exception_state);
+  if (!exception_state.HadException()) {
+    setAttribute(name, AtomicString(url));
   }
-
-  String valueString = stringOrURL.IsUSVString()
-                           ? stringOrURL.GetAsUSVString()
-                           : stringOrURL.GetAsTrustedURL()->toString();
-
-  setAttribute(name, AtomicString(valueString));
 }
 
 ALWAYS_INLINE void Element::SetAttributeInternal(
@@ -3480,20 +3464,11 @@
 
 void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html,
                            ExceptionState& exception_state) {
-  DCHECK(string_or_html.IsString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
-  if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedHTML` assignment.");
-    return;
+  String html =
+      TrustedHTML::GetString(string_or_html, &GetDocument(), exception_state);
+  if (!exception_state.HadException()) {
+    SetInnerHTMLFromString(html, exception_state);
   }
-
-  String html = string_or_html.IsString()
-                    ? string_or_html.GetAsString()
-                    : string_or_html.GetAsTrustedHTML()->toString();
-
-  SetInnerHTMLFromString(html, exception_state);
 }
 
 void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html) {
@@ -3537,20 +3512,11 @@
 
 void Element::setOuterHTML(const StringOrTrustedHTML& string_or_html,
                            ExceptionState& exception_state) {
-  DCHECK(string_or_html.IsString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
-  if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedHTML` assignment.");
-    return;
+  String html =
+      TrustedHTML::GetString(string_or_html, &GetDocument(), exception_state);
+  if (!exception_state.HadException()) {
+    SetOuterHTMLFromString(html, exception_state);
   }
-
-  String html = string_or_html.IsString()
-                    ? string_or_html.GetAsString()
-                    : string_or_html.GetAsTrustedHTML()->toString();
-
-  SetOuterHTMLFromString(html, exception_state);
 }
 
 Node* Element::InsertAdjacent(const String& where,
@@ -3697,20 +3663,11 @@
 void Element::insertAdjacentHTML(const String& where,
                                  const StringOrTrustedHTML& string_or_html,
                                  ExceptionState& exception_state) {
-  DCHECK(string_or_html.IsString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
-  if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedHTML` assignment.");
-    return;
+  String markup =
+      TrustedHTML::GetString(string_or_html, &GetDocument(), exception_state);
+  if (!exception_state.HadException()) {
+    insertAdjacentHTML(where, markup, exception_state);
   }
-
-  String markup = string_or_html.IsString()
-                      ? string_or_html.GetAsString()
-                      : string_or_html.GetAsTrustedHTML()->toString();
-
-  insertAdjacentHTML(where, markup, exception_state);
 }
 
 void Element::setPointerCapture(int pointer_id,
diff --git a/third_party/blink/renderer/core/dom/processing_instruction.cc b/third_party/blink/renderer/core/dom/processing_instruction.cc
index de81f25..2886f7b9 100644
--- a/third_party/blink/renderer/core/dom/processing_instruction.cc
+++ b/third_party/blink/renderer/core/dom/processing_instruction.cc
@@ -157,6 +157,8 @@
   loading_ = true;
   if (is_xsl_) {
     DCHECK(RuntimeEnabledFeatures::XSLTEnabled());
+    params.MutableResourceRequest().SetFetchRequestMode(
+        network::mojom::FetchRequestMode::kSameOrigin);
     XSLStyleSheetResource::Fetch(params, GetDocument().Fetcher(), this);
   } else {
     params.SetCharset(charset.IsEmpty() ? GetDocument().Encoding()
diff --git a/third_party/blink/renderer/core/dom/range.cc b/third_party/blink/renderer/core/dom/range.cc
index 332ba07..982e6756 100644
--- a/third_party/blink/renderer/core/dom/range.cc
+++ b/third_party/blink/renderer/core/dom/range.cc
@@ -975,23 +975,16 @@
   // Algorithm:
   // http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface
 
-  DCHECK(string_or_html.IsString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
   DCHECK(!string_or_html.IsNull());
 
   Document& document = start_.Container().GetDocument();
 
-  if (string_or_html.IsString() && document.RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedHTML` assignment.");
-    return nullptr;
+  String markup =
+      TrustedHTML::GetString(string_or_html, &document, exception_state);
+  if (!exception_state.HadException()) {
+    return createContextualFragmentFromString(markup, exception_state);
   }
-
-  String markup = string_or_html.IsString()
-                      ? string_or_html.GetAsString()
-                      : string_or_html.GetAsTrustedHTML()->toString();
-
-  return createContextualFragmentFromString(markup, exception_state);
+  return nullptr;
 }
 
 DocumentFragment* Range::createContextualFragmentFromString(
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc
index dfc0422..f0bd3ec17 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -129,20 +129,11 @@
 
 void ShadowRoot::setInnerHTML(const StringOrTrustedHTML& stringOrHtml,
                               ExceptionState& exception_state) {
-  DCHECK(stringOrHtml.IsString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
-  if (stringOrHtml.IsString() && GetDocument().RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedHTML` assignment.");
-    return;
+  String html =
+      TrustedHTML::GetString(stringOrHtml, &GetDocument(), exception_state);
+  if (!exception_state.HadException()) {
+    SetInnerHTMLFromString(html, exception_state);
   }
-
-  String html = stringOrHtml.IsString()
-                    ? stringOrHtml.GetAsString()
-                    : stringOrHtml.GetAsTrustedHTML()->toString();
-
-  SetInnerHTMLFromString(html, exception_state);
 }
 
 void ShadowRoot::RecalcStyle(StyleRecalcChange change) {
diff --git a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc
index c74a597..383579e 100644
--- a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc
@@ -414,6 +414,16 @@
     ResourceLoaderOptions resource_loader_options;
     resource_loader_options.data_buffering_policy = kDoNotBufferData;
 
+    if (options_.grant_universal_access) {
+      const auto mode = new_request.GetFetchRequestMode();
+      DCHECK(mode == network::mojom::FetchRequestMode::kNoCORS ||
+             mode == network::mojom::FetchRequestMode::kNavigate);
+      scoped_refptr<SecurityOrigin> origin =
+          SecurityOrigin::CreateUniqueOpaque();
+      origin->GrantUniversalAccess();
+      resource_loader_options.security_origin = std::move(origin);
+    }
+
     const ResourceRequest& webcore_request = new_request.ToResourceRequest();
     WebURLRequest::RequestContext context = webcore_request.GetRequestContext();
     if (context == WebURLRequest::kRequestContextUnspecified) {
diff --git a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
index d58fe49..699f85f 100644
--- a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
+++ b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
@@ -686,5 +686,60 @@
   EXPECT_FALSE(actual_response_.HttpHeaderField(header_name_string).IsEmpty());
 }
 
+TEST_F(WebAssociatedURLLoaderTest, AccessCheckForLocalURL) {
+  KURL url = ToKURL("file://test.pdf");
+
+  WebURLRequest request(url);
+  request.SetRequestContext(WebURLRequest::kRequestContextPlugin);
+  request.SetFetchRequestMode(network::mojom::FetchRequestMode::kNoCORS);
+  request.SetFetchCredentialsMode(network::mojom::FetchCredentialsMode::kOmit);
+
+  expected_response_ = WebURLResponse();
+  expected_response_.SetMIMEType("text/plain");
+  expected_response_.SetHTTPStatusCode(200);
+  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
+      url, expected_response_, frame_file_path_);
+
+  WebAssociatedURLLoaderOptions options;
+  expected_loader_ = CreateAssociatedURLLoader(options);
+  EXPECT_TRUE(expected_loader_);
+  expected_loader_->LoadAsynchronously(request, this);
+  ServeRequests();
+
+  // The request failes due to a security check.
+  EXPECT_FALSE(did_receive_response_);
+  EXPECT_FALSE(did_receive_data_);
+  EXPECT_FALSE(did_finish_loading_);
+  EXPECT_TRUE(did_fail_);
+}
+
+TEST_F(WebAssociatedURLLoaderTest, BypassAccessCheckForLocalURL) {
+  KURL url = ToKURL("file://test.pdf");
+
+  WebURLRequest request(url);
+  request.SetRequestContext(WebURLRequest::kRequestContextPlugin);
+  request.SetFetchRequestMode(network::mojom::FetchRequestMode::kNoCORS);
+  request.SetFetchCredentialsMode(network::mojom::FetchCredentialsMode::kOmit);
+
+  expected_response_ = WebURLResponse();
+  expected_response_.SetMIMEType("text/plain");
+  expected_response_.SetHTTPStatusCode(200);
+  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
+      url, expected_response_, frame_file_path_);
+
+  WebAssociatedURLLoaderOptions options;
+  options.grant_universal_access = true;
+  expected_loader_ = CreateAssociatedURLLoader(options);
+  EXPECT_TRUE(expected_loader_);
+  expected_loader_->LoadAsynchronously(request, this);
+  ServeRequests();
+
+  // The security check is bypassed due to |grant_universal_access|.
+  EXPECT_TRUE(did_receive_response_);
+  EXPECT_TRUE(did_receive_data_);
+  EXPECT_TRUE(did_finish_loading_);
+  EXPECT_FALSE(did_fail_);
+}
+
 #undef MAYBE_UntrustedCheckHeaders
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 0b2dc78..9526bfa 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -10081,45 +10081,6 @@
   bool failed_;
 };
 
-// FIXME: This would be better as a unittest on DocumentThreadableLoader but it
-// requires spin-up of a frame. It may be possible to remove that requirement
-// and convert it to a unittest.
-TEST_F(WebFrameTest, LoaderOriginAccess) {
-  FrameTestHelpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad("about:blank");
-
-  SchemeRegistry::RegisterURLSchemeAsDisplayIsolated("chrome");
-
-  // Cross-origin request.
-  KURL resource_url("chrome://test.pdf");
-  ResourceRequest request(resource_url);
-  request.SetRequestContext(WebURLRequest::kRequestContextObject);
-  request.SetFetchCredentialsMode(network::mojom::FetchCredentialsMode::kOmit);
-  RegisterMockedChromeURLLoad("test.pdf");
-
-  LocalFrame* frame(
-      ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame()));
-
-  MockDocumentThreadableLoaderClient client;
-  ThreadableLoaderOptions options;
-
-  // First try to load the request with regular access. Should fail.
-  request.SetFetchRequestMode(network::mojom::FetchRequestMode::kCORS);
-  ResourceLoaderOptions resource_loader_options;
-  DocumentThreadableLoader::LoadResourceSynchronously(
-      *ThreadableLoadingContext::Create(*frame->GetDocument()), request, client,
-      options, resource_loader_options);
-  EXPECT_TRUE(client.Failed());
-
-  client.Reset();
-  // Try to load the request with cross origin access. Should succeed.
-  request.SetFetchRequestMode(network::mojom::FetchRequestMode::kNoCORS);
-  DocumentThreadableLoader::LoadResourceSynchronously(
-      *ThreadableLoadingContext::Create(*frame->GetDocument()), request, client,
-      options, resource_loader_options);
-  EXPECT_FALSE(client.Failed());
-}
-
 TEST_F(WebFrameTest, DetachRemoteFrame) {
   FrameTestHelpers::WebViewHelper helper;
   helper.InitializeRemote();
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 2acc592..291d4b7a 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1738,11 +1738,6 @@
   if (page_color_overlay_)
     page_color_overlay_->GetGraphicsLayer()->Paint(nullptr);
 
-  // TODO(chrishtr): link highlights don't currently paint themselves, it's
-  // still driven by cc.  Fix this.
-  // TODO(pdr): Move this to LocalFrameView::UpdateLifecyclePhasesInternal.
-  GetPage()->GetLinkHighlights().UpdateGeometry();
-
   if (LocalFrameView* view = MainFrameImpl()->GetFrameView()) {
     LocalFrame* frame = MainFrameImpl()->GetFrame();
     WebWidgetClient* client =
@@ -3121,12 +3116,6 @@
 
   // Give the visual viewport's scroll layer its initial size.
   GetPage()->GetVisualViewport().MainFrameDidChangeSize();
-
-  // Make sure link highlight from previous page is cleared.
-  // TODO(pdr): Move this to Page::DidCommitLoad.
-  GetPage()->GetLinkHighlights().ResetForPageNavigation();
-  if (!MainFrameImpl())
-    return;
 }
 
 void WebViewImpl::ResizeAfterLayout() {
diff --git a/third_party/blink/renderer/core/frame/link_highlights.cc b/third_party/blink/renderer/core/frame/link_highlights.cc
index 34f1ffce..1f1bc64 100644
--- a/third_party/blink/renderer/core/frame/link_highlights.cc
+++ b/third_party/blink/renderer/core/frame/link_highlights.cc
@@ -30,9 +30,13 @@
 }
 
 void LinkHighlights::RemoveAllHighlights() {
-  if (timeline_) {
-    for (auto& highlight : link_highlights_)
+  for (auto& highlight : link_highlights_) {
+    if (timeline_)
       timeline_->AnimationDestroyed(*highlight);
+    if (auto* node = highlight->GetNode()) {
+      if (auto* layout_object = node->GetLayoutObject())
+        layout_object->SetNeedsPaintPropertyUpdate();
+    }
   }
   link_highlights_.clear();
 }
@@ -64,6 +68,7 @@
     link_highlights_.push_back(LinkHighlightImpl::Create(node));
     if (timeline_)
       timeline_->AnimationAttached(*link_highlights_.back());
+    node->GetLayoutObject()->SetNeedsPaintPropertyUpdate();
   }
 }
 
@@ -105,4 +110,25 @@
   animation_host_ = nullptr;
 }
 
+bool LinkHighlights::NeedsHighlightEffectInternal(
+    const LayoutObject& object) const {
+  for (auto& highlight : link_highlights_) {
+    if (auto* node = highlight->GetNode()) {
+      if (node->GetLayoutObject() == &object)
+        return true;
+    }
+  }
+  return false;
+}
+
+CompositorElementId LinkHighlights::element_id(const LayoutObject& object) {
+  for (auto& highlight : link_highlights_) {
+    if (auto* node = highlight->GetNode()) {
+      if (node->GetLayoutObject() == &object)
+        return highlight->element_id();
+    }
+  }
+  return CompositorElementId();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/link_highlights.h b/third_party/blink/renderer/core/frame/link_highlights.h
index 2eb1e31..940eb54 100644
--- a/third_party/blink/renderer/core/frame/link_highlights.h
+++ b/third_party/blink/renderer/core/frame/link_highlights.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
@@ -18,6 +19,7 @@
 class CompositorAnimationTimeline;
 class WebLayerTreeView;
 class LocalFrame;
+class LayoutObject;
 
 class CORE_EXPORT LinkHighlights final
     : public GarbageCollectedFinalized<LinkHighlights> {
@@ -31,6 +33,7 @@
 
   void SetTapHighlights(HeapVector<Member<Node>>&);
 
+  // Updates geometry on all highlights. See: LinkHighlightImpl::UpdateGeometry.
   void UpdateGeometry();
 
   void StartHighlightAnimationIfNeeded();
@@ -38,11 +41,22 @@
   void LayerTreeViewInitialized(WebLayerTreeView&);
   void WillCloseLayerTreeView(WebLayerTreeView&);
 
+  bool IsEmpty() const { return link_highlights_.IsEmpty(); }
+
+  bool NeedsHighlightEffect(const LayoutObject& object) const {
+    if (link_highlights_.IsEmpty())
+      return false;
+    return NeedsHighlightEffectInternal(object);
+  }
+
+  CompositorElementId element_id(const LayoutObject& object);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, verifyWebViewImplIntegration);
   FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, resetDuringNodeRemoval);
   FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, resetLayerTreeView);
   FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, multipleHighlights);
+  FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, HighlightLayerEffectNode);
 
   explicit LinkHighlights(Page&);
 
@@ -55,6 +69,8 @@
     return *page_;
   }
 
+  bool NeedsHighlightEffectInternal(const LayoutObject& object) const;
+
   Member<Page> page_;
   Vector<std::unique_ptr<LinkHighlightImpl>> link_highlights_;
   std::unique_ptr<CompositorAnimationHost> animation_host_;
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 4b1dd4d6..b8c7fad 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1550,21 +1550,12 @@
                                 const AtomicString& target,
                                 const String& features,
                                 ExceptionState& exception_state) {
-  DCHECK(stringOrUrl.IsUSVString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
-  if (!stringOrUrl.IsTrustedURL() && document_->RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedURL` assignment.");
-    return nullptr;
+  String url = TrustedURL::GetString(stringOrUrl, document_, exception_state);
+  if (!exception_state.HadException()) {
+    return openFromString(executionContext, current_window, entered_window, url,
+                          target, features, exception_state);
   }
-
-  String url = stringOrUrl.IsUSVString()
-                   ? stringOrUrl.GetAsUSVString()
-                   : stringOrUrl.GetAsTrustedURL()->toString();
-
-  return openFromString(executionContext, current_window, entered_window, url,
-                        target, features, exception_state);
+  return nullptr;
 }
 
 DOMWindow* LocalDOMWindow::openFromString(ExecutionContext* executionContext,
@@ -1609,21 +1600,12 @@
                                 LocalDOMWindow* calling_window,
                                 LocalDOMWindow* entered_window,
                                 ExceptionState& exception_state) {
-  DCHECK(stringOrUrl.IsUSVString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
-  if (!stringOrUrl.IsTrustedURL() && document_->RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedURL` assignment.");
-    return nullptr;
+  String url = TrustedURL::GetString(stringOrUrl, document_, exception_state);
+  if (!exception_state.HadException()) {
+    return openFromString(url, frame_name, window_features_string,
+                          calling_window, entered_window, exception_state);
   }
-
-  String url = stringOrUrl.IsUSVString()
-                   ? stringOrUrl.GetAsUSVString()
-                   : stringOrUrl.GetAsTrustedURL()->toString();
-
-  return openFromString(url, frame_name, window_features_string, calling_window,
-                        entered_window, exception_state);
+  return nullptr;
 }
 
 DOMWindow* LocalDOMWindow::openFromString(const String& url_string,
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 1a661a7..709ce20 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -51,6 +51,7 @@
 #include "third_party/blink/renderer/core/frame/browser_controls.h"
 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
 #include "third_party/blink/renderer/core/frame/frame_view_auto_size_info.h"
+#include "third_party/blink/renderer/core/frame/link_highlights.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/location.h"
@@ -119,6 +120,7 @@
 #include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/graphics/link_highlight.h"
 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
 #include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -2685,6 +2687,36 @@
   CollectDrawableLayersForLayerListRecursively(context, layer->MaskLayer());
 }
 
+static void CollectLinkHighlightLayersForLayerListRecursively(
+    GraphicsContext& context,
+    const GraphicsLayer* layer) {
+  DCHECK(RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled());
+
+  if (!layer || layer->Client().ShouldThrottleRendering())
+    return;
+
+  for (auto* highlight : layer->GetLinkHighlights()) {
+    DCHECK(highlight->effect())
+        << "Highlight effect node should have been created in PrePaint.";
+    auto* highlight_layer = highlight->Layer();
+    auto property_tree_state = layer->GetPropertyTreeState();
+    property_tree_state.SetEffect(highlight->effect());
+    ScopedPaintChunkProperties scope(context.GetPaintController(),
+                                     property_tree_state, *highlight,
+                                     DisplayItem::kForeignLayerLinkHighlight);
+    auto position = highlight_layer->position();
+    auto size = highlight_layer->bounds();
+    RecordForeignLayer(context, *highlight,
+                       DisplayItem::kForeignLayerLinkHighlight, highlight_layer,
+                       layer->GetOffsetFromTransformNode() +
+                           FloatSize(position.x(), position.y()),
+                       IntSize(size.width(), size.height()));
+  }
+
+  for (const auto* child : layer->Children())
+    CollectLinkHighlightLayersForLayerListRecursively(context, child);
+}
+
 static void PaintGraphicsLayerRecursively(GraphicsLayer* layer) {
   layer->PaintRecursively();
 
@@ -2768,6 +2800,13 @@
     }
   }
 
+  // TODO(chrishtr): Link highlights don't currently paint themselves,
+  // it's still driven by cc. Fix this.
+  // This uses an invalidation approach based on graphics layer raster
+  // invalidation so it must be after paint. This adds/removes link highlight
+  // layers so it must be before |CollectDrawableLayersForLayerListRecursively|.
+  frame_->GetPage()->GetLinkHighlights().UpdateGeometry();
+
   if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
     // BlinkGenPropertyTrees just needs a transient PaintController to
     // collect the foreign layers which doesn't need caching. It also
@@ -2790,8 +2829,11 @@
     // With BlinkGenPropertyTrees, |PaintRootGraphicsLayer| is the ancestor of
     // all drawable layers (see: PaintLayerCompositor::PaintRootGraphicsLayer)
     // so we do not need to collect scrollbars separately.
-    CollectDrawableLayersForLayerListRecursively(
-        context, layout_view->Compositor()->PaintRootGraphicsLayer());
+    auto* root = layout_view->Compositor()->PaintRootGraphicsLayer();
+    CollectDrawableLayersForLayerListRecursively(context, root);
+    // Link highlights paint after all other layers.
+    if (!frame_->GetPage()->GetLinkHighlights().IsEmpty())
+      CollectLinkHighlightLayersForLayerListRecursively(context, root);
     paint_controller_->CommitNewDisplayItems();
   }
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index 9e54670..9c31537 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -618,7 +618,8 @@
                                          const WebScrollIntoViewParams&);
 
   PaintArtifactCompositor* GetPaintArtifactCompositorForTesting() {
-    DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+    DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
+           RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled());
     return paint_artifact_compositor_.get();
   }
 
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc
index 588a7d6..3e6d778 100644
--- a/third_party/blink/renderer/core/frame/location.cc
+++ b/third_party/blink/renderer/core/frame/location.cc
@@ -121,20 +121,11 @@
                        LocalDOMWindow* entered_window,
                        const USVStringOrTrustedURL& stringOrUrl,
                        ExceptionState& exception_state) {
-  DCHECK(stringOrUrl.IsUSVString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
-  if (stringOrUrl.IsUSVString() &&
-      current_window->document()->RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedURL` assignment.");
-    return;
+  String url = TrustedURL::GetString(stringOrUrl, current_window->document(),
+                                     exception_state);
+  if (!exception_state.HadException()) {
+    SetLocation(url, current_window, entered_window, &exception_state);
   }
-
-  String url = stringOrUrl.IsUSVString()
-                   ? stringOrUrl.GetAsUSVString()
-                   : stringOrUrl.GetAsTrustedURL()->toString();
-  SetLocation(url, current_window, entered_window, &exception_state);
 }
 
 void Location::setProtocol(LocalDOMWindow* current_window,
@@ -233,45 +224,23 @@
     return;
   }
 
-  DCHECK(stringOrUrl.IsUSVString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-  DCHECK(!stringOrUrl.IsNull());
-
-  if (stringOrUrl.IsUSVString() &&
-      current_window->document()->RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedURL` assignment.");
-    return;
+  String url = TrustedURL::GetString(stringOrUrl, current_window->document(),
+                                     exception_state);
+  if (!exception_state.HadException()) {
+    SetLocation(url, current_window, entered_window, &exception_state);
   }
-
-  String url = stringOrUrl.IsUSVString()
-                   ? stringOrUrl.GetAsUSVString()
-                   : stringOrUrl.GetAsTrustedURL()->toString();
-
-  SetLocation(url, current_window, entered_window, &exception_state);
 }
 
 void Location::replace(LocalDOMWindow* current_window,
                        LocalDOMWindow* entered_window,
                        const USVStringOrTrustedURL& stringOrUrl,
                        ExceptionState& exception_state) {
-  DCHECK(stringOrUrl.IsUSVString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-  DCHECK(!stringOrUrl.IsNull());
-
-  if (stringOrUrl.IsUSVString() &&
-      current_window->document()->RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedURL` assignment.");
-    return;
+  String url = TrustedURL::GetString(stringOrUrl, current_window->document(),
+                                     exception_state);
+  if (!exception_state.HadException()) {
+    SetLocation(url, current_window, entered_window, &exception_state,
+                SetLocationPolicy::kReplaceThisFrame);
   }
-
-  String url = stringOrUrl.IsUSVString()
-                   ? stringOrUrl.GetAsUSVString()
-                   : stringOrUrl.GetAsTrustedURL()->toString();
-
-  SetLocation(url, current_window, entered_window, &exception_state,
-              SetLocationPolicy::kReplaceThisFrame);
 }
 
 void Location::reload(LocalDOMWindow* current_window) {
diff --git a/third_party/blink/renderer/core/html/html_base_element.cc b/third_party/blink/renderer/core/html/html_base_element.cc
index ffc67f0..095fa51 100644
--- a/third_party/blink/renderer/core/html/html_base_element.cc
+++ b/third_party/blink/renderer/core/html/html_base_element.cc
@@ -96,21 +96,7 @@
 
 void HTMLBaseElement::setHref(const USVStringOrTrustedURL& stringOrUrl,
                               ExceptionState& exception_state) {
-  DCHECK(stringOrUrl.IsUSVString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-  DCHECK(!stringOrUrl.IsNull());
-
-  if (stringOrUrl.IsUSVString() && GetDocument().RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedURL` assignment.");
-    return;
-  }
-
-  AtomicString value(stringOrUrl.IsUSVString()
-                         ? stringOrUrl.GetAsUSVString()
-                         : stringOrUrl.GetAsTrustedURL()->toString());
-
-  setAttribute(hrefAttr, value);
+  setAttribute(hrefAttr, stringOrUrl, exception_state);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc
index b371979..03578c25 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -2537,6 +2537,9 @@
 void LayoutBlockFlow::SetPaintFragment(
     scoped_refptr<const NGPhysicalFragment>) {}
 
+void LayoutBlockFlow::UpdatePaintFragmentFromCachedLayoutResult(
+    scoped_refptr<const NGPhysicalFragment>) {}
+
 void LayoutBlockFlow::ComputeOverflow(LayoutUnit old_client_after_edge,
                                       bool recompute_floats) {
   LayoutBlock::ComputeOverflow(old_client_after_edge, recompute_floats);
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h
index 8003efb0b..5eb703ee 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.h
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -461,6 +461,8 @@
                                      scoped_refptr<NGLayoutResult>);
   virtual void WillCollectInlines() {}
   virtual void SetPaintFragment(scoped_refptr<const NGPhysicalFragment>);
+  virtual void UpdatePaintFragmentFromCachedLayoutResult(
+      scoped_refptr<const NGPhysicalFragment>);
   virtual void ClearPaintFragment() {}
   virtual const NGPhysicalBoxFragment* CurrentFragment() const {
     return nullptr;
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 04a2eaf..3c379f3a 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -73,7 +73,6 @@
 class LayoutView;
 class LocalFrameView;
 class NGPhysicalBoxFragment;
-class ObjectPaintProperties;
 class PaintLayer;
 class PseudoStyleRequest;
 
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
index 6351676..07ff5f4 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -264,6 +264,8 @@
 template <typename Base>
 void LayoutNGMixin<Base>::SetPaintFragment(
     scoped_refptr<const NGPhysicalFragment> fragment) {
+  DCHECK(fragment);
+
   paint_fragment_ = NGPaintFragment::Create(std::move(fragment));
 
   // When paint fragment is replaced, the subtree needs paint invalidation to
@@ -272,6 +274,17 @@
 }
 
 template <typename Base>
+void LayoutNGMixin<Base>::UpdatePaintFragmentFromCachedLayoutResult(
+    scoped_refptr<const NGPhysicalFragment> fragment) {
+  DCHECK(fragment);
+
+  if (!paint_fragment_)
+    return SetPaintFragment(fragment);
+
+  paint_fragment_->UpdatePhysicalFragmentFromCachedLayoutResult(fragment);
+}
+
+template <typename Base>
 void LayoutNGMixin<Base>::ClearPaintFragment() {
   paint_fragment_ = nullptr;
 }
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
index 4ffae30..9a4fcba 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
@@ -68,8 +68,10 @@
   NGPaintFragment* PaintFragment() const override {
     return paint_fragment_.get();
   }
-  void SetPaintFragment(scoped_refptr<const NGPhysicalFragment>) override;
-  void ClearPaintFragment() override;
+  void SetPaintFragment(scoped_refptr<const NGPhysicalFragment>) final;
+  void UpdatePaintFragmentFromCachedLayoutResult(
+      scoped_refptr<const NGPhysicalFragment>) final;
+  void ClearPaintFragment() final;
 
  protected:
   bool IsOfType(LayoutObject::LayoutObjectType) const override;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 412a763..994b8f3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -214,10 +214,10 @@
       // don't re-set the result here.
       ToLayoutBlockFlow(box_)->SetCachedLayoutResult(
           constraint_space, break_token, layout_result);
-      if (!constraint_space.IsIntermediateLayout()) {
-        block_flow->ClearPaintFragment();
-        if (first_child && first_child.IsInline())
-          block_flow->SetPaintFragment(layout_result->PhysicalFragment());
+      if (!constraint_space.IsIntermediateLayout() && first_child &&
+          first_child.IsInline()) {
+        block_flow->UpdatePaintFragmentFromCachedLayoutResult(
+            layout_result->PhysicalFragment());
       }
       return layout_result;
     }
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc
index c0fbdaf5..5caccb1 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -175,11 +175,10 @@
     const KURL& url,
     const ResourceLoaderOptions& options,
     SecurityViolationReportingPolicy reporting_policy,
-    FetchParameters::OriginRestriction origin_restriction,
     ResourceRequest::RedirectStatus redirect_status) const {
   base::Optional<ResourceRequestBlockedReason> blocked_reason =
       CanRequestInternal(type, resource_request, url, options, reporting_policy,
-                         origin_restriction, redirect_status);
+                         redirect_status);
   if (blocked_reason &&
       reporting_policy == SecurityViolationReportingPolicy::kReport) {
     DispatchDidBlockRequest(resource_request, options.initiator_info,
@@ -276,7 +275,6 @@
     const KURL& url,
     const ResourceLoaderOptions& options,
     SecurityViolationReportingPolicy reporting_policy,
-    FetchParameters::OriginRestriction origin_restriction,
     ResourceRequest::RedirectStatus redirect_status) const {
   if (IsDetached()) {
     if (!resource_request.GetKeepalive() ||
@@ -292,8 +290,7 @@
   if (!security_origin)
     security_origin = GetSecurityOrigin();
 
-  if (origin_restriction != FetchParameters::kNoOriginRestriction &&
-      security_origin && !security_origin->CanDisplay(url)) {
+  if (security_origin && !security_origin->CanDisplay(url)) {
     if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
       AddErrorConsoleMessage(
           "Not allowed to load local resource: " + url.GetString(), kJSSource);
@@ -303,40 +300,13 @@
     return ResourceRequestBlockedReason::kOther;
   }
 
-  // Some types of resources can be loaded only from the same origin. Other
-  // types of resources, like Images, Scripts, and CSS, can be loaded from
-  // any URL.
-  switch (type) {
-    case Resource::kMainResource:
-    case Resource::kImage:
-    case Resource::kCSSStyleSheet:
-    case Resource::kScript:
-    case Resource::kFont:
-    case Resource::kRaw:
-    case Resource::kLinkPrefetch:
-    case Resource::kTextTrack:
-    case Resource::kImportResource:
-    case Resource::kAudio:
-    case Resource::kVideo:
-    case Resource::kManifest:
-    case Resource::kMock:
-      // By default these types of resources can be loaded from any origin.
-      // FIXME: Are we sure about Resource::kFont?
-      if (origin_restriction == FetchParameters::kRestrictToSameOrigin &&
-          !security_origin->CanRequest(url)) {
-        PrintAccessDeniedMessage(url);
-        return ResourceRequestBlockedReason::kOrigin;
-      }
-      break;
-    case Resource::kXSLStyleSheet:
-      DCHECK(RuntimeEnabledFeatures::XSLTEnabled());
-      FALLTHROUGH;
-    case Resource::kSVGDocument:
-      if (!security_origin->CanRequest(url)) {
-        PrintAccessDeniedMessage(url);
-        return ResourceRequestBlockedReason::kOrigin;
-      }
-      break;
+  if (resource_request.GetFetchRequestMode() ==
+      network::mojom::FetchRequestMode::kSameOrigin) {
+    DCHECK(security_origin);
+    if (!security_origin->CanRequest(url)) {
+      PrintAccessDeniedMessage(url);
+      return ResourceRequestBlockedReason::kOrigin;
+    }
   }
 
   // User Agent CSS stylesheets should only support loading images and should be
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h
index 6edc1fa2a..758fe92 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -38,7 +38,6 @@
       const KURL&,
       const ResourceLoaderOptions&,
       SecurityViolationReportingPolicy,
-      FetchParameters::OriginRestriction,
       ResourceRequest::RedirectStatus) const override;
   base::Optional<ResourceRequestBlockedReason> CheckCSPForRequest(
       WebURLRequest::RequestContext,
@@ -107,7 +106,6 @@
       const KURL&,
       const ResourceLoaderOptions&,
       SecurityViolationReportingPolicy,
-      FetchParameters::OriginRestriction,
       ResourceRequest::RedirectStatus) const;
 
   base::Optional<ResourceRequestBlockedReason> CheckCSPForRequestInternal(
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
index 4ae640c..082fdfb 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
@@ -310,7 +310,6 @@
             fetch_context_->CanRequest(
                 Resource::kScript, resource_request, url, options,
                 SecurityViolationReportingPolicy::kReport,
-                FetchParameters::kUseDefaultOriginRestrictionForType,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
   EXPECT_EQ(1u, policy->violation_reports_sent_.size());
 }
@@ -348,28 +347,24 @@
             fetch_context_->CanRequest(
                 Resource::kRaw, request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kNoRedirect));
 
   EXPECT_EQ(base::nullopt,
             fetch_context_->CanRequest(
                 Resource::kRaw, keepalive_request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kNoRedirect));
 
   EXPECT_EQ(base::nullopt,
             fetch_context_->CanRequest(
                 Resource::kRaw, request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 
   EXPECT_EQ(base::nullopt,
             fetch_context_->CanRequest(
                 Resource::kRaw, keepalive_request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 
   fetch_context_->SetIsDetached(true);
@@ -378,28 +373,24 @@
             fetch_context_->CanRequest(
                 Resource::kRaw, request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kNoRedirect));
 
   EXPECT_EQ(ResourceRequestBlockedReason::kOther,
             fetch_context_->CanRequest(
                 Resource::kRaw, keepalive_request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kNoRedirect));
 
   EXPECT_EQ(ResourceRequestBlockedReason::kOther,
             fetch_context_->CanRequest(
                 Resource::kRaw, request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 
   EXPECT_EQ(base::nullopt,
             fetch_context_->CanRequest(
                 Resource::kRaw, keepalive_request, url, ResourceLoaderOptions(),
                 SecurityViolationReportingPolicy::kSuppressReporting,
-                FetchParameters::kNoOriginRestriction,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 }
 
@@ -416,21 +407,18 @@
             fetch_context_->CanRequest(
                 Resource::kScript, resource_request, test_url, options,
                 SecurityViolationReportingPolicy::kReport,
-                FetchParameters::kUseDefaultOriginRestrictionForType,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 
   EXPECT_EQ(ResourceRequestBlockedReason::kOther,
             fetch_context_->CanRequest(
                 Resource::kImage, resource_request, test_url, options,
                 SecurityViolationReportingPolicy::kReport,
-                FetchParameters::kUseDefaultOriginRestrictionForType,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 
   EXPECT_EQ(base::nullopt,
             fetch_context_->CanRequest(
                 Resource::kImage, resource_request, data_url, options,
                 SecurityViolationReportingPolicy::kReport,
-                FetchParameters::kUseDefaultOriginRestrictionForType,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 }
 
@@ -452,7 +440,6 @@
             fetch_context_->CanRequest(
                 Resource::kImage, resource_request, data_url, options,
                 SecurityViolationReportingPolicy::kReport,
-                FetchParameters::kUseDefaultOriginRestrictionForType,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 }
 
diff --git a/third_party/blink/renderer/core/loader/document_threadable_loader.cc b/third_party/blink/renderer/core/loader/document_threadable_loader.cc
index 17862fe2..27721b93 100644
--- a/third_party/blink/renderer/core/loader/document_threadable_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_threadable_loader.cc
@@ -1207,10 +1207,6 @@
   }
 
   FetchParameters new_params(request, resource_loader_options);
-  if (request.GetFetchRequestMode() ==
-      network::mojom::FetchRequestMode::kNoCORS) {
-    new_params.SetOriginRestriction(FetchParameters::kNoOriginRestriction);
-  }
   DCHECK(!GetResource());
 
   checker_.WillAddClient();
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index ac8766cd6..d5ea7f6f 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -1528,7 +1528,6 @@
     const KURL& url,
     const ResourceLoaderOptions& options,
     SecurityViolationReportingPolicy reporting_policy,
-    FetchParameters::OriginRestriction origin_restriction,
     ResourceRequest::RedirectStatus redirect_status) const {
   if (document_ && document_->IsFreezingInProgress() &&
       !resource_request.GetKeepalive()) {
@@ -1538,8 +1537,7 @@
     return ResourceRequestBlockedReason::kOther;
   }
   return BaseFetchContext::CanRequest(type, resource_request, url, options,
-                                      reporting_policy, origin_restriction,
-                                      redirect_status);
+                                      reporting_policy, redirect_status);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
index c48424b..a3bbbf7 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -88,7 +88,6 @@
       const KURL& url,
       const ResourceLoaderOptions& options,
       SecurityViolationReportingPolicy reporting_policy,
-      FetchParameters::OriginRestriction origin_restriction,
       ResourceRequest::RedirectStatus redirect_status) const override;
   mojom::FetchCacheMode ResourceRequestCachePolicy(
       const ResourceRequest&,
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index ef4702c..29e6eff 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -269,8 +269,7 @@
     ResourceLoaderOptions options;
     return fetch_context->CanRequest(
         Resource::kImage, resource_request, input_url, options,
-        reporting_policy, FetchParameters::kUseDefaultOriginRestrictionForType,
-        ResourceRequest::RedirectStatus::kNoRedirect);
+        reporting_policy, ResourceRequest::RedirectStatus::kNoRedirect);
   }
 
   int filtered_load_callback_counter_;
diff --git a/third_party/blink/renderer/core/loader/resource/document_resource.cc b/third_party/blink/renderer/core/loader/resource/document_resource.cc
index 8ca4629e..2503a8c 100644
--- a/third_party/blink/renderer/core/loader/resource/document_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/document_resource.cc
@@ -38,6 +38,8 @@
                                                      ResourceClient* client) {
   DCHECK_EQ(params.GetResourceRequest().GetFrameType(),
             network::mojom::RequestContextFrameType::kNone);
+  DCHECK_EQ(params.GetResourceRequest().GetFetchRequestMode(),
+            network::mojom::FetchRequestMode::kSameOrigin);
   params.SetRequestContext(WebURLRequest::kRequestContextImage);
   return ToDocumentResource(
       fetcher->RequestResource(params, SVGDocumentResourceFactory(), client));
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
index 0f42c3e7..f88a1ce 100644
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -698,6 +698,7 @@
     GetVisualViewport().SetScrollOffset(ScrollOffset(), kProgrammaticScroll);
     hosts_using_features_.UpdateMeasurementsAndClear();
   }
+  GetLinkHighlights().ResetForPageNavigation();
 }
 
 void Page::AcceptLanguagesChanged() {
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn
index cc09a870..f4738106 100644
--- a/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -112,6 +112,8 @@
     "html_canvas_painter.h",
     "image_painter.cc",
     "image_painter.h",
+    "inline_box_painter_base.cc",
+    "inline_box_painter_base.h",
     "inline_flow_box_painter.cc",
     "inline_flow_box_painter.h",
     "inline_painter.cc",
@@ -136,6 +138,8 @@
     "ng/ng_box_fragment_painter.h",
     "ng/ng_fragment_painter.cc",
     "ng/ng_fragment_painter.h",
+    "ng/ng_inline_box_fragment_painter.cc",
+    "ng/ng_inline_box_fragment_painter.h",
     "ng/ng_paint_fragment.cc",
     "ng/ng_paint_fragment.h",
     "ng/ng_paint_fragment_traversal.cc",
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
index d4a5d96..a2d0f67f 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
@@ -637,7 +637,8 @@
 
   // Layer assignment is needed for allocating or removing composited
   // layers related to this PaintLayer; hence the below conditions.
-  if (reasons_to_composite || layer->GetCompositingState() != kNotComposited)
+  if (reasons_to_composite || layer->GetCompositingState() != kNotComposited ||
+      layer->LostGroupedMapping())
     layer->SetNeedsCompositingLayerAssignment();
 
   // At this point we have finished collecting all reasons to composite this
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
index 8ad4a737..db17154 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
 
 namespace blink {
 
@@ -129,4 +130,50 @@
             target->GetCompositingReasons());
 }
 
+// This test sets up a situation where a squashed PaintLayer loses its
+// backing, but does not change visual rect. Therefore the compositing system
+// must invalidate it because of change of backing.
+TEST_F(CompositingRequirementsUpdaterTest,
+       NeedsLayerAssignmentAfterSquashingRemoval) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      * {
+        margin: 0
+      }
+      #target {
+        width: 100px; height: 100px; backface-visibility: hidden
+      }
+      div {
+        width: 100px; height: 100px;
+        position: absolute;
+        background: lightblue;
+        top: 0px;
+      }
+    </style>
+    <div id=target></div>
+    <div id=squashed></div>
+  )HTML");
+
+  PaintLayer* squashed =
+      ToLayoutBoxModelObject(GetLayoutObjectByElementId("squashed"))->Layer();
+  EXPECT_EQ(kPaintsIntoGroupedBacking, squashed->GetCompositingState());
+
+  GetDocument().View()->SetTracksPaintInvalidations(true);
+
+  GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+                                                       "display: none");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  EXPECT_EQ(kNotComposited, squashed->GetCompositingState());
+  auto* tracking = GetDocument()
+                       .View()
+                       ->GetLayoutView()
+                       ->Layer()
+                       ->GraphicsLayerBacking()
+                       ->GetRasterInvalidationTracking();
+  EXPECT_TRUE(tracking->HasInvalidations());
+
+  EXPECT_EQ(IntRect(0, 0, 100, 100), tracking->Invalidations()[0].rect);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/find_properties_needing_update.h b/third_party/blink/renderer/core/paint/find_properties_needing_update.h
index f27d8d9..22a99601 100644
--- a/third_party/blink/renderer/core/paint/find_properties_needing_update.h
+++ b/third_party/blink/renderer/core/paint/find_properties_needing_update.h
@@ -117,6 +117,9 @@
                                 object_properties->Mask());
       DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->ClipPath(),
                                 object_properties->ClipPath());
+      DCHECK_OBJECT_PROPERTY_EQ(object_,
+                                original_properties_->LinkHighlightEffect(),
+                                object_properties->LinkHighlightEffect());
       DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->ClipPathClip(),
                                 object_properties->ClipPathClip());
       DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->MaskClip(),
diff --git a/third_party/blink/renderer/core/paint/inline_box_painter_base.cc b/third_party/blink/renderer/core/paint/inline_box_painter_base.cc
new file mode 100644
index 0000000..6bb6132
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/inline_box_painter_base.cc
@@ -0,0 +1,122 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
+
+#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
+#include "third_party/blink/renderer/core/paint/box_painter_base.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+
+namespace blink {
+
+void InlineBoxPainterBase::PaintBoxDecorationBackground(
+    BoxPainterBase& box_painter,
+    const PaintInfo& paint_info,
+    const LayoutPoint& paint_offset,
+    LayoutRect adjusted_frame_rect,
+    BackgroundImageGeometry geometry,
+    bool include_logical_left_edge,
+    bool include_logical_right_edge) {
+  // Shadow comes first and is behind the background and border.
+  PaintNormalBoxShadow(paint_info, line_style_, adjusted_frame_rect);
+
+  Color background_color =
+      line_style_.VisitedDependentColor(GetCSSPropertyBackgroundColor());
+  PaintFillLayers(box_painter, paint_info, background_color,
+                  line_style_.BackgroundLayers(), adjusted_frame_rect,
+                  geometry);
+
+  PaintInsetBoxShadow(paint_info, line_style_, adjusted_frame_rect);
+
+  IntRect adjusted_clip_rect;
+  BorderPaintingType border_painting_type =
+      GetBorderPaintType(adjusted_frame_rect, adjusted_clip_rect);
+  switch (border_painting_type) {
+    case kDontPaintBorders:
+      break;
+    case kPaintBordersWithoutClip:
+      BoxPainterBase::PaintBorder(
+          image_observer_, *document_, node_, paint_info, adjusted_frame_rect,
+          line_style_, kBackgroundBleedNone, include_logical_left_edge,
+          include_logical_right_edge);
+      break;
+    case kPaintBordersWithClip:
+      // FIXME: What the heck do we do with RTL here? The math we're using is
+      // obviously not right, but it isn't even clear how this should work at
+      // all.
+      LayoutRect image_strip_paint_rect =
+          PaintRectForImageStrip(adjusted_frame_rect, TextDirection::kLtr);
+      GraphicsContextStateSaver state_saver(paint_info.context);
+      paint_info.context.Clip(adjusted_clip_rect);
+      BoxPainterBase::PaintBorder(image_observer_, *document_, node_,
+                                  paint_info, image_strip_paint_rect,
+                                  line_style_);
+      break;
+  }
+}
+
+void InlineBoxPainterBase::PaintFillLayers(BoxPainterBase& box_painter,
+                                           const PaintInfo& info,
+                                           const Color& c,
+                                           const FillLayer& layer,
+                                           const LayoutRect& rect,
+                                           BackgroundImageGeometry& geometry,
+                                           SkBlendMode op) {
+  // FIXME: This should be a for loop or similar. It's a little non-trivial to
+  // do so, however, since the layers need to be painted in reverse order.
+  if (layer.Next())
+    PaintFillLayers(box_painter, info, c, *layer.Next(), rect, geometry, op);
+  PaintFillLayer(box_painter, info, c, layer, rect, geometry, op);
+}
+
+void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
+                                          const PaintInfo& paint_info,
+                                          const Color& c,
+                                          const FillLayer& fill_layer,
+                                          const LayoutRect& paint_rect,
+                                          BackgroundImageGeometry& geometry,
+                                          SkBlendMode op) {
+  StyleImage* img = fill_layer.GetImage();
+  bool has_fill_image = img && img->CanRender();
+
+  if (!object_has_multiple_boxes_ ||
+      (!has_fill_image && !style_.HasBorderRadius())) {
+    box_painter.PaintFillLayer(paint_info, c, fill_layer, paint_rect,
+                               kBackgroundBleedNone, geometry, op, false);
+    return;
+  }
+
+  // Handle fill images that clone or spans multiple lines.
+  bool multi_line = object_has_multiple_boxes_ &&
+                    style_.BoxDecorationBreak() != EBoxDecorationBreak::kClone;
+  LayoutRect rect = multi_line
+                        ? PaintRectForImageStrip(paint_rect, style_.Direction())
+                        : paint_rect;
+  GraphicsContextStateSaver state_saver(paint_info.context);
+  paint_info.context.Clip(PixelSnappedIntRect(paint_rect));
+  box_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
+                             kBackgroundBleedNone, geometry, op, multi_line,
+                             paint_rect.Size());
+}
+
+void InlineBoxPainterBase::PaintNormalBoxShadow(const PaintInfo& info,
+                                                const ComputedStyle& s,
+                                                const LayoutRect& paint_rect) {
+  BoxPainterBase::PaintNormalBoxShadow(
+      info, paint_rect, s, include_logical_left_edge_for_box_shadow_,
+      include_logical_right_edge_for_box_shadow_);
+}
+
+void InlineBoxPainterBase::PaintInsetBoxShadow(const PaintInfo& info,
+                                               const ComputedStyle& s,
+                                               const LayoutRect& paint_rect) {
+  BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
+      info, paint_rect, s, include_logical_left_edge_for_box_shadow_,
+      include_logical_right_edge_for_box_shadow_);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/inline_box_painter_base.h b/third_party/blink/renderer/core/paint/inline_box_painter_base.h
new file mode 100644
index 0000000..11725e5
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/inline_box_painter_base.h
@@ -0,0 +1,100 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_BOX_PAINTER_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_BOX_PAINTER_BASE_H_
+
+#include "third_party/blink/renderer/core/paint/box_painter_base.h"
+#include "third_party/blink/renderer/core/style/shadow_data.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class Color;
+class FillLayer;
+class IntRect;
+class LayoutPoint;
+class LayoutRect;
+struct PaintInfo;
+class ComputedStyle;
+
+// Common base class for InlineFlowBoxPainter and NGInlineBoxFragmentPainter.
+// Implements layout agnostic inline box painting behavior.
+class InlineBoxPainterBase {
+  STACK_ALLOCATED();
+
+ public:
+  InlineBoxPainterBase(const ImageResourceObserver& image_observer,
+                       const Document* document,
+                       Node* node,
+                       const ComputedStyle& style,
+                       const ComputedStyle& line_style)
+      : image_observer_(image_observer),
+        document_(document),
+        node_(node),
+        style_(style),
+        line_style_(line_style) {}
+
+  void PaintBoxDecorationBackground(BoxPainterBase&,
+                                    const PaintInfo&,
+                                    const LayoutPoint& paint_offset,
+                                    LayoutRect adjusted_frame_rect,
+                                    BackgroundImageGeometry,
+                                    bool include_logical_left_edge,
+                                    bool include_logical_right_edge);
+
+ protected:
+  void PaintFillLayers(BoxPainterBase&,
+                       const PaintInfo&,
+                       const Color&,
+                       const FillLayer&,
+                       const LayoutRect&,
+                       BackgroundImageGeometry& geometry,
+                       SkBlendMode op = SkBlendMode::kSrcOver);
+  void PaintFillLayer(BoxPainterBase&,
+                      const PaintInfo&,
+                      const Color&,
+                      const FillLayer&,
+                      const LayoutRect&,
+                      BackgroundImageGeometry& geometry,
+                      SkBlendMode op);
+  void PaintNormalBoxShadow(const PaintInfo&,
+                            const ComputedStyle&,
+                            const LayoutRect& paint_rect);
+  void PaintInsetBoxShadow(const PaintInfo&,
+                           const ComputedStyle&,
+                           const LayoutRect& paint_rect);
+
+  virtual LayoutRect PaintRectForImageStrip(const LayoutRect&,
+                                            TextDirection direction) const = 0;
+
+  enum BorderPaintingType {
+    kDontPaintBorders,
+    kPaintBordersWithoutClip,
+    kPaintBordersWithClip
+  };
+  virtual BorderPaintingType GetBorderPaintType(
+      const LayoutRect& adjusted_frame_rect,
+      IntRect& adjusted_clip_rect) const = 0;
+
+  const ImageResourceObserver& image_observer_;
+  Member<const Document> document_;
+  Member<Node> node_;
+
+  // Style for the corresponding node.
+  const ComputedStyle& style_;
+
+  // Style taking ::first-line into account.
+  const ComputedStyle& line_style_;
+
+  bool object_has_multiple_boxes_;
+  bool include_logical_left_edge_for_box_shadow_;
+  bool include_logical_right_edge_for_box_shadow_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_BOX_PAINTER_BASE_H_
diff --git a/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc b/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
index 004830e..da881ea 100644
--- a/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
+++ b/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/paint/inline_flow_box_painter.h"
 
 #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h"
+#include "third_party/blink/renderer/core/layout/line/inline_flow_box.h"
 #include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
 #include "third_party/blink/renderer/core/paint/background_image_geometry.h"
 #include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
@@ -16,6 +17,43 @@
 
 namespace blink {
 
+namespace {
+
+inline Node* GetNode(const LayoutObject* box_model) {
+  Node* node = nullptr;
+  for (const LayoutObject* obj = box_model; obj && !node; obj = obj->Parent())
+    node = obj->GeneratingNode();
+  return node;
+}
+
+inline const LayoutBoxModelObject* GetBoxModelObject(
+    const InlineFlowBox& flow_box) {
+  return ToLayoutBoxModelObject(
+      LineLayoutAPIShim::LayoutObjectFrom(flow_box.BoxModelObject()));
+}
+
+}  // anonymous namespace
+
+InlineFlowBoxPainter::InlineFlowBoxPainter(const InlineFlowBox& flow_box)
+    : InlineBoxPainterBase(
+          *GetBoxModelObject(flow_box),
+          &GetBoxModelObject(flow_box)->GetDocument(),
+          GetNode(GetBoxModelObject(flow_box)),
+          flow_box.GetLineLayoutItem().StyleRef(),
+          flow_box.GetLineLayoutItem().StyleRef(flow_box.IsFirstLineStyle())),
+      inline_flow_box_(flow_box) {
+  object_has_multiple_boxes_ = inline_flow_box_.PrevForSameLayoutObject() ||
+                               inline_flow_box_.NextForSameLayoutObject();
+  bool force_include_logical_edges =
+      (!inline_flow_box_.PrevForSameLayoutObject() &&
+       !inline_flow_box_.NextForSameLayoutObject()) ||
+      !inline_flow_box_.Parent();
+  include_logical_left_edge_for_box_shadow_ =
+      force_include_logical_edges || inline_flow_box_.IncludeLogicalLeftEdge();
+  include_logical_right_edge_for_box_shadow_ =
+      force_include_logical_edges || inline_flow_box_.IncludeLogicalRightEdge();
+}
+
 void InlineFlowBoxPainter::Paint(const PaintInfo& paint_info,
                                  const LayoutPoint& paint_offset,
                                  const LayoutUnit line_top,
@@ -38,7 +76,7 @@
 
   if (paint_info.phase == PaintPhase::kForeground) {
     // Paint our background, border and box-shadow.
-    PaintBoxDecorationBackground(paint_info, paint_offset);
+    PaintBackgroundBorderShadow(paint_info, paint_offset);
   }
 
   // Paint our children.
@@ -51,96 +89,6 @@
   }
 }
 
-void InlineFlowBoxPainter::PaintFillLayers(const PaintInfo& paint_info,
-                                           const Color& c,
-                                           const FillLayer& fill_layer,
-                                           const LayoutRect& rect,
-                                           SkBlendMode op) {
-  // FIXME: This should be a for loop or similar. It's a little non-trivial to
-  // do so, however, since the layers need to be painted in reverse order.
-  if (fill_layer.Next())
-    PaintFillLayers(paint_info, c, *fill_layer.Next(), rect, op);
-  PaintFillLayer(paint_info, c, fill_layer, rect, op);
-}
-
-void InlineFlowBoxPainter::PaintFillLayer(const PaintInfo& paint_info,
-                                          const Color& c,
-                                          const FillLayer& fill_layer,
-                                          const LayoutRect& rect,
-                                          SkBlendMode op) {
-  LayoutBoxModelObject* box_model = ToLayoutBoxModelObject(
-      LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.BoxModelObject()));
-  BackgroundImageGeometry geometry(*box_model);
-  StyleImage* img = fill_layer.GetImage();
-  bool has_fill_image = img && img->CanRender();
-  BoxModelObjectPainter box_model_painter(*box_model, &inline_flow_box_);
-  if ((!has_fill_image &&
-       !inline_flow_box_.GetLineLayoutItem().Style()->HasBorderRadius()) ||
-      (!inline_flow_box_.PrevForSameLayoutObject() &&
-       !inline_flow_box_.NextForSameLayoutObject()) ||
-      !inline_flow_box_.Parent()) {
-    bool object_has_multiple_boxes = false;
-    box_model_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
-                                     kBackgroundBleedNone, geometry, op,
-                                     object_has_multiple_boxes);
-  } else if (inline_flow_box_.GetLineLayoutItem()
-                 .Style()
-                 ->BoxDecorationBreak() == EBoxDecorationBreak::kClone) {
-    GraphicsContextStateSaver state_saver(paint_info.context);
-    paint_info.context.Clip(PixelSnappedIntRect(rect));
-    bool object_has_multiple_boxes = false;
-    box_model_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
-                                     kBackgroundBleedNone, geometry, op,
-                                     object_has_multiple_boxes);
-  } else {
-    // We have a fill image that spans multiple lines.
-    // FIXME: frameSize ought to be the same as rect.size().
-    LayoutSize frame_size(inline_flow_box_.Width(), inline_flow_box_.Height());
-    LayoutRect image_strip_paint_rect = PaintRectForImageStrip(
-        rect.Location(), frame_size,
-        inline_flow_box_.GetLineLayoutItem().Style()->Direction());
-    GraphicsContextStateSaver state_saver(paint_info.context);
-    // TODO(chrishtr): this should likely be pixel-snapped.
-    paint_info.context.Clip(PixelSnappedIntRect(rect));
-    bool object_has_multiple_boxes = true;
-    box_model_painter.PaintFillLayer(
-        paint_info, c, fill_layer, image_strip_paint_rect, kBackgroundBleedNone,
-        geometry, op, object_has_multiple_boxes, rect.Size());
-  }
-}
-
-inline bool InlineFlowBoxPainter::ShouldForceIncludeLogicalEdges() const {
-  return (!inline_flow_box_.PrevForSameLayoutObject() &&
-          !inline_flow_box_.NextForSameLayoutObject()) ||
-         !inline_flow_box_.Parent();
-}
-
-inline bool InlineFlowBoxPainter::IncludeLogicalLeftEdgeForBoxShadow() const {
-  return ShouldForceIncludeLogicalEdges() ||
-         inline_flow_box_.IncludeLogicalLeftEdge();
-}
-
-inline bool InlineFlowBoxPainter::IncludeLogicalRightEdgeForBoxShadow() const {
-  return ShouldForceIncludeLogicalEdges() ||
-         inline_flow_box_.IncludeLogicalRightEdge();
-}
-
-void InlineFlowBoxPainter::PaintNormalBoxShadow(const PaintInfo& info,
-                                                const ComputedStyle& s,
-                                                const LayoutRect& paint_rect) {
-  BoxPainterBase::PaintNormalBoxShadow(info, paint_rect, s,
-                                       IncludeLogicalLeftEdgeForBoxShadow(),
-                                       IncludeLogicalRightEdgeForBoxShadow());
-}
-
-void InlineFlowBoxPainter::PaintInsetBoxShadow(const PaintInfo& info,
-                                               const ComputedStyle& s,
-                                               const LayoutRect& paint_rect) {
-  BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
-      info, paint_rect, s, IncludeLogicalLeftEdgeForBoxShadow(),
-      IncludeLogicalRightEdgeForBoxShadow());
-}
-
 static LayoutRect ClipRectForNinePieceImageStrip(const InlineFlowBox& box,
                                                  const NinePieceImage& image,
                                                  const LayoutRect& paint_rect) {
@@ -170,8 +118,7 @@
 }
 
 LayoutRect InlineFlowBoxPainter::PaintRectForImageStrip(
-    const LayoutPoint& paint_offset,
-    const LayoutSize& frame_size,
+    const LayoutRect& paint_rect,
     TextDirection direction) const {
   // We have a fill/border/mask image that spans multiple lines.
   // We need to adjust the offset by the width of all previous lines.
@@ -200,20 +147,20 @@
       total_logical_width += curr->LogicalWidth();
   }
   LayoutUnit strip_x =
-      paint_offset.X() -
+      paint_rect.X() -
       (inline_flow_box_.IsHorizontal() ? logical_offset_on_line : LayoutUnit());
   LayoutUnit strip_y =
-      paint_offset.Y() -
+      paint_rect.Y() -
       (inline_flow_box_.IsHorizontal() ? LayoutUnit() : logical_offset_on_line);
   LayoutUnit strip_width = inline_flow_box_.IsHorizontal() ? total_logical_width
-                                                           : frame_size.Width();
+                                                           : paint_rect.Width();
   LayoutUnit strip_height = inline_flow_box_.IsHorizontal()
-                                ? frame_size.Height()
+                                ? paint_rect.Height()
                                 : total_logical_width;
   return LayoutRect(strip_x, strip_y, strip_width, strip_height);
 }
 
-InlineFlowBoxPainter::BorderPaintingType
+InlineBoxPainterBase::BorderPaintingType
 InlineFlowBoxPainter::GetBorderPaintType(const LayoutRect& adjusted_frame_rect,
                                          IntRect& adjusted_clip_rect) const {
   adjusted_clip_rect = PixelSnappedIntRect(adjusted_frame_rect);
@@ -242,14 +189,7 @@
   return kDontPaintBorders;
 }
 
-static inline Node* GetNode(const LayoutObject* box_model) {
-  Node* node = nullptr;
-  for (const LayoutObject* obj = box_model; obj && !node; obj = obj->Parent())
-    node = obj->GeneratingNode();
-  return node;
-}
-
-void InlineFlowBoxPainter::PaintBoxDecorationBackground(
+void InlineFlowBoxPainter::PaintBackgroundBorderShadow(
     const PaintInfo& paint_info,
     const LayoutPoint& paint_offset) {
   DCHECK(paint_info.phase == PaintPhase::kForeground);
@@ -265,17 +205,13 @@
   // boxes for a line may actually have to paint a background.
   LayoutObject* inline_flow_box_layout_object =
       LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.GetLineLayoutItem());
-  const ComputedStyle* style_to_use =
-      inline_flow_box_.GetLineLayoutItem().Style(
-          inline_flow_box_.IsFirstLineStyle());
   bool should_paint_box_decoration_background;
   if (inline_flow_box_.Parent())
     should_paint_box_decoration_background =
         inline_flow_box_layout_object->HasBoxDecorationBackground();
   else
     should_paint_box_decoration_background =
-        inline_flow_box_.IsFirstLineStyle() &&
-        style_to_use != inline_flow_box_.GetLineLayoutItem().Style();
+        inline_flow_box_.IsFirstLineStyle() && line_style_ != style_;
 
   if (!should_paint_box_decoration_background)
     return;
@@ -290,49 +226,14 @@
 
   LayoutRect paint_rect = AdjustedPaintRect(paint_offset);
 
-  IntRect adjusted_clip_rect;
-  BorderPaintingType border_painting_type =
-      GetBorderPaintType(paint_rect, adjusted_clip_rect);
-
-  // Shadow comes first and is behind the background and border.
-  PaintNormalBoxShadow(paint_info, *style_to_use, paint_rect);
-
-  Color background_color = inline_flow_box_layout_object->ResolveColor(
-      *style_to_use, GetCSSPropertyBackgroundColor());
-  PaintFillLayers(paint_info, background_color,
-                  style_to_use->BackgroundLayers(), paint_rect);
-  PaintInsetBoxShadow(paint_info, *style_to_use, paint_rect);
-
-  const LayoutObject* box_model = ToLayoutBoxModelObject(
+  const auto& box_model = *ToLayoutBoxModelObject(
       LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.BoxModelObject()));
-
-  switch (border_painting_type) {
-    case kDontPaintBorders:
-      break;
-    case kPaintBordersWithoutClip:
-      BoxPainterBase::PaintBorder(*box_model, box_model->GetDocument(),
-                                  GetNode(box_model), paint_info, paint_rect,
-                                  inline_flow_box_.GetLineLayoutItem().StyleRef(
-                                      inline_flow_box_.IsFirstLineStyle()),
-                                  kBackgroundBleedNone,
-                                  inline_flow_box_.IncludeLogicalLeftEdge(),
-                                  inline_flow_box_.IncludeLogicalRightEdge());
-      break;
-    case kPaintBordersWithClip:
-      // FIXME: What the heck do we do with RTL here? The math we're using is
-      // obviously not right, but it isn't even clear how this should work at
-      // all.
-      LayoutRect image_strip_paint_rect = PaintRectForImageStrip(
-          paint_rect.Location(), paint_rect.Size(), TextDirection::kLtr);
-      GraphicsContextStateSaver state_saver(paint_info.context);
-      paint_info.context.Clip(adjusted_clip_rect);
-      BoxPainterBase::PaintBorder(*box_model, box_model->GetDocument(),
-                                  GetNode(box_model), paint_info,
-                                  image_strip_paint_rect,
-                                  inline_flow_box_.GetLineLayoutItem().StyleRef(
-                                      inline_flow_box_.IsFirstLineStyle()));
-      break;
-  }
+  BackgroundImageGeometry geometry(box_model);
+  BoxModelObjectPainter box_painter(box_model, &inline_flow_box_);
+  PaintBoxDecorationBackground(box_painter, paint_info, paint_offset,
+                               paint_rect, geometry,
+                               inline_flow_box_.IncludeLogicalLeftEdge(),
+                               inline_flow_box_.IncludeLogicalRightEdge());
 }
 
 void InlineFlowBoxPainter::PaintMask(const PaintInfo& paint_info,
@@ -358,8 +259,10 @@
   const auto* mask_box_image = mask_nine_piece_image.GetImage();
 
   // Figure out if we need to push a transparency layer to render our mask.
-  PaintFillLayers(paint_info, Color::kTransparent,
-                  box_model.StyleRef().MaskLayers(), paint_rect);
+  BackgroundImageGeometry geometry(box_model);
+  BoxModelObjectPainter box_painter(box_model, &inline_flow_box_);
+  PaintFillLayers(box_painter, paint_info, Color::kTransparent,
+                  box_model.StyleRef().MaskLayers(), paint_rect, geometry);
 
   bool has_box_image = mask_box_image && mask_box_image->CanRender();
   if (!has_box_image || !mask_box_image->IsLoaded()) {
@@ -380,7 +283,8 @@
     // FIXME: What the heck do we do with RTL here? The math we're using is
     // obviously not right, but it isn't even clear how this should work at all.
     LayoutRect image_strip_paint_rect = PaintRectForImageStrip(
-        paint_rect.Location(), paint_rect.Size(), TextDirection::kLtr);
+        LayoutRect(paint_rect.Location(), paint_rect.Size()),
+        TextDirection::kLtr);
     FloatRect clip_rect(ClipRectForNinePieceImageStrip(
         inline_flow_box_, mask_nine_piece_image, paint_rect));
     GraphicsContextStateSaver state_saver(paint_info.context);
diff --git a/third_party/blink/renderer/core/paint/inline_flow_box_painter.h b/third_party/blink/renderer/core/paint/inline_flow_box_painter.h
index f3a6ccd111..f303dc8 100644
--- a/third_party/blink/renderer/core/paint/inline_flow_box_painter.h
+++ b/third_party/blink/renderer/core/paint/inline_flow_box_painter.h
@@ -5,6 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_FLOW_BOX_PAINTER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_FLOW_BOX_PAINTER_H_
 
+#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
+#include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
 #include "third_party/blink/renderer/core/style/shadow_data.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_types.h"
 #include "third_party/blink/renderer/platform/text/text_direction.h"
@@ -12,23 +14,19 @@
 
 namespace blink {
 
-class Color;
-class FillLayer;
 class InlineFlowBox;
 class IntRect;
 class LayoutPoint;
 class LayoutRect;
-class LayoutSize;
 class LayoutUnit;
 struct PaintInfo;
-class ComputedStyle;
 
-class InlineFlowBoxPainter {
+class InlineFlowBoxPainter : public InlineBoxPainterBase {
   STACK_ALLOCATED();
 
  public:
-  InlineFlowBoxPainter(const InlineFlowBox& inline_flow_box)
-      : inline_flow_box_(inline_flow_box) {}
+  InlineFlowBoxPainter(const InlineFlowBox&);
+
   void Paint(const PaintInfo&,
              const LayoutPoint& paint_offset,
              const LayoutUnit line_top,
@@ -36,40 +34,18 @@
 
   LayoutRect FrameRectClampedToLineTopAndBottomIfNeeded() const;
 
- private:
-  void PaintBoxDecorationBackground(const PaintInfo&,
-                                    const LayoutPoint& paint_offset);
-  void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
-  void PaintFillLayers(const PaintInfo&,
-                       const Color&,
-                       const FillLayer&,
-                       const LayoutRect&,
-                       SkBlendMode op = SkBlendMode::kSrcOver);
-  void PaintFillLayer(const PaintInfo&,
-                      const Color&,
-                      const FillLayer&,
-                      const LayoutRect&,
-                      SkBlendMode op);
-  inline bool ShouldForceIncludeLogicalEdges() const;
-  inline bool IncludeLogicalLeftEdgeForBoxShadow() const;
-  inline bool IncludeLogicalRightEdgeForBoxShadow() const;
-  void PaintNormalBoxShadow(const PaintInfo&,
-                            const ComputedStyle&,
-                            const LayoutRect& paint_rect);
-  void PaintInsetBoxShadow(const PaintInfo&,
-                           const ComputedStyle&,
-                           const LayoutRect& paint_rect);
-  LayoutRect PaintRectForImageStrip(const LayoutPoint& paint_offset,
-                                    const LayoutSize& frame_size,
-                                    TextDirection) const;
+ protected:
+  LayoutRect PaintRectForImageStrip(const LayoutRect&,
+                                    TextDirection) const override;
 
-  enum BorderPaintingType {
-    kDontPaintBorders,
-    kPaintBordersWithoutClip,
-    kPaintBordersWithClip
-  };
-  BorderPaintingType GetBorderPaintType(const LayoutRect& adjusted_frame_rect,
-                                        IntRect& adjusted_clip_rect) const;
+ private:
+  void PaintBackgroundBorderShadow(const PaintInfo&,
+                                   const LayoutPoint& paint_offset);
+  void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
+
+  BorderPaintingType GetBorderPaintType(
+      const LayoutRect& adjusted_frame_rect,
+      IntRect& adjusted_clip_rect) const override;
 
   LayoutRect AdjustedPaintRect(const LayoutPoint& paint_offset) const;
 
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index 683971b..e5e55976a 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -88,12 +88,10 @@
   DCHECK(compositor_animation_);
   compositor_animation_->SetAnimationDelegate(this);
 
-  CompositorElementId element_id =
-      CompositorElementIdFromUniqueObjectId(unique_id_);
-  compositor_animation_->AttachElement(element_id);
+  compositor_animation_->AttachElement(element_id());
   content_layer_->SetIsDrawable(true);
   content_layer_->SetOpacity(1);
-  content_layer_->SetElementId(element_id);
+  content_layer_->SetElementId(element_id());
   geometry_needs_update_ = true;
 }
 
@@ -108,6 +106,11 @@
 }
 
 void LinkHighlightImpl::ReleaseResources() {
+  if (!node_)
+    return;
+
+  if (auto* layout_object = node_->GetLayoutObject())
+    layout_object->SetNeedsPaintPropertyUpdate();
   node_.Clear();
 }
 
@@ -395,4 +398,20 @@
   return compositor_animation_.get();
 }
 
+CompositorElementId LinkHighlightImpl::element_id() {
+  return CompositorElementIdFromUniqueObjectId(unique_id_);
+}
+
+const EffectPaintPropertyNode* LinkHighlightImpl::effect() {
+  if (!node_)
+    return nullptr;
+
+  if (auto* layout_object = node_->GetLayoutObject()) {
+    if (auto* properties = layout_object->FirstFragment().PaintProperties())
+      return properties->LinkHighlightEffect();
+  }
+
+  return nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.h b/third_party/blink/renderer/core/paint/link_highlight_impl.h
index 2158cf7..0ead7e9 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.h
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.h
@@ -60,6 +60,11 @@
   ~LinkHighlightImpl() override;
 
   void StartHighlightAnimationIfNeeded();
+
+  // Recalculates |path_| based on |node_|'s geometry and updates the link
+  // highlight layer. To avoid re-computing |path_|, a dirty bit is used
+  // (see |geometry_needs_update_| and |Invalidate()|) which is based on raster
+  // invalidation of the owning graphics layer.
   void UpdateGeometry();
 
   // cc::ContentLayerClient implementation.
@@ -86,6 +91,12 @@
     return current_graphics_layer_;
   }
 
+  Node* GetNode() const { return node_; }
+
+  CompositorElementId element_id();
+
+  const EffectPaintPropertyNode* effect() override;
+
  private:
   LinkHighlightImpl(Node*);
 
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
index 1739a05..88bb5c8 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -27,6 +27,7 @@
 
 #include <memory>
 
+#include "cc/trees/layer_tree_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_float_point.h"
@@ -49,37 +50,72 @@
 #include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 
 namespace blink {
 
-namespace {
+class LinkHighlightImplTest : public testing::Test,
+                              public testing::WithParamInterface<bool>,
+                              private ScopedBlinkGenPropertyTreesForTest {
+ public:
+  LinkHighlightImplTest() : ScopedBlinkGenPropertyTreesForTest(GetParam()) {}
 
-GestureEventWithHitTestResults GetTargetedEvent(WebViewImpl* web_view_impl,
-                                                WebGestureEvent& touch_event) {
-  WebGestureEvent scaled_event = TransformWebGestureEvent(
-      web_view_impl->MainFrameImpl()->GetFrameView(), touch_event);
-  return web_view_impl->GetPage()
-      ->DeprecatedLocalMainFrame()
-      ->GetEventHandler()
-      .TargetGestureEvent(scaled_event, true);
-}
+ protected:
+  GestureEventWithHitTestResults GetTargetedEvent(
+      WebGestureEvent& touch_event) {
+    WebGestureEvent scaled_event = TransformWebGestureEvent(
+        web_view_helper_.GetWebView()->MainFrameImpl()->GetFrameView(),
+        touch_event);
+    return web_view_helper_.GetWebView()
+        ->GetPage()
+        ->DeprecatedLocalMainFrame()
+        ->GetEventHandler()
+        .TargetGestureEvent(scaled_event, true);
+  }
 
-std::string LinkRegisterMockedURLLoad() {
-  WebURL url = URLTestHelpers::RegisterMockedURLLoadFromBase(
-      WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(),
-      WebString::FromUTF8("test_touch_link_highlight.html"));
-  return url.GetString().Utf8();
-}
+  void SetUp() override {
+    WebURL url = URLTestHelpers::RegisterMockedURLLoadFromBase(
+        WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(),
+        WebString::FromUTF8("test_touch_link_highlight.html"));
+    web_view_helper_.InitializeAndLoad(url.GetString().Utf8());
+  }
 
-}  // namespace
+  void TearDown() override {
+    Platform::Current()
+        ->GetURLLoaderMockFactory()
+        ->UnregisterAllURLsAndClearMemoryCache();
 
-TEST(LinkHighlightImplTest, verifyWebViewImplIntegration) {
-  const std::string url = LinkRegisterMockedURLLoad();
-  FrameTestHelpers::WebViewHelper web_view_helper;
-  WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(url);
+    // Ensure we fully clean up while scoped settings are enabled. Without this,
+    // garbage collection would occur after ScopedBlinkGenPropertyTreesForTest
+    // is out of scope, so the settings would not apply in some destructors.
+    web_view_helper_.Reset();
+    ThreadState::Current()->CollectAllGarbage();
+  }
+
+  size_t ContentLayerCount() {
+    // paint_artifact_compositor()->EnableExtraDataForTesting() should be called
+    // before using this function.
+    DCHECK(paint_artifact_compositor()->GetExtraDataForTesting());
+    return paint_artifact_compositor()
+        ->GetExtraDataForTesting()
+        ->content_layers.size();
+  }
+
+  PaintArtifactCompositor* paint_artifact_compositor() {
+    auto* local_frame_view = web_view_helper_.LocalMainFrame()->GetFrameView();
+    return local_frame_view->GetPaintArtifactCompositorForTesting();
+  }
+
+  FrameTestHelpers::WebViewHelper web_view_helper_;
+};
+
+INSTANTIATE_TEST_CASE_P(All, LinkHighlightImplTest, testing::Bool());
+
+TEST_P(LinkHighlightImplTest, verifyWebViewImplIntegration) {
+  WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
   int page_width = 640;
   int page_height = 480;
   web_view_impl->Resize(WebSize(page_width, page_height));
@@ -94,17 +130,14 @@
   // .html file.
   touch_event.SetPositionInWidget(WebFloatPoint(20, 20));
 
-  ASSERT_TRUE(
-      web_view_impl->BestTapNode(GetTargetedEvent(web_view_impl, touch_event)));
+  ASSERT_TRUE(web_view_impl->BestTapNode(GetTargetedEvent(touch_event)));
 
   touch_event.SetPositionInWidget(WebFloatPoint(20, 40));
-  EXPECT_FALSE(
-      web_view_impl->BestTapNode(GetTargetedEvent(web_view_impl, touch_event)));
+  EXPECT_FALSE(web_view_impl->BestTapNode(GetTargetedEvent(touch_event)));
 
   touch_event.SetPositionInWidget(WebFloatPoint(20, 20));
   // Shouldn't crash.
-  web_view_impl->EnableTapHighlightAtPoint(
-      GetTargetedEvent(web_view_impl, touch_event));
+  web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
 
   const auto& highlights =
       web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
@@ -113,8 +146,7 @@
 
   // Find a target inside a scrollable div
   touch_event.SetPositionInWidget(WebFloatPoint(20, 100));
-  web_view_impl->EnableTapHighlightAtPoint(
-      GetTargetedEvent(web_view_impl, touch_event));
+  web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
   ASSERT_TRUE(highlights.at(0));
 
   // Enesure the timeline was added to a host.
@@ -126,24 +158,16 @@
   // Don't highlight if no "hand cursor"
   touch_event.SetPositionInWidget(
       WebFloatPoint(20, 220));  // An A-link with cross-hair cursor.
-  web_view_impl->EnableTapHighlightAtPoint(
-      GetTargetedEvent(web_view_impl, touch_event));
+  web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
   ASSERT_EQ(0U, highlights.size());
 
   touch_event.SetPositionInWidget(WebFloatPoint(20, 260));  // A text input box.
-  web_view_impl->EnableTapHighlightAtPoint(
-      GetTargetedEvent(web_view_impl, touch_event));
+  web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
   ASSERT_EQ(0U, highlights.size());
-
-  Platform::Current()
-      ->GetURLLoaderMockFactory()
-      ->UnregisterAllURLsAndClearMemoryCache();
 }
 
-TEST(LinkHighlightImplTest, resetDuringNodeRemoval) {
-  const std::string url = LinkRegisterMockedURLLoad();
-  FrameTestHelpers::WebViewHelper web_view_helper;
-  WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(url);
+TEST_P(LinkHighlightImplTest, resetDuringNodeRemoval) {
+  WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
 
   int page_width = 640;
   int page_height = 480;
@@ -156,8 +180,7 @@
                               kWebGestureDeviceTouchscreen);
   touch_event.SetPositionInWidget(WebFloatPoint(20, 20));
 
-  GestureEventWithHitTestResults targeted_event =
-      GetTargetedEvent(web_view_impl, touch_event);
+  GestureEventWithHitTestResults targeted_event = GetTargetedEvent(touch_event);
   Node* touch_node = web_view_impl->BestTapNode(targeted_event);
   ASSERT_TRUE(touch_node);
 
@@ -168,22 +191,16 @@
   GraphicsLayer* highlight_layer =
       highlights.link_highlights_.at(0)->CurrentGraphicsLayerForTesting();
   ASSERT_TRUE(highlight_layer);
-  EXPECT_TRUE(highlight_layer->GetLinkHighlight(0));
+  EXPECT_TRUE(highlight_layer->GetLinkHighlights().at(0));
 
   touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
   web_view_impl->UpdateAllLifecyclePhases();
-  EXPECT_EQ(0U, highlight_layer->NumLinkHighlights());
-
-  Platform::Current()
-      ->GetURLLoaderMockFactory()
-      ->UnregisterAllURLsAndClearMemoryCache();
+  EXPECT_EQ(0U, highlight_layer->GetLinkHighlights().size());
 }
 
 // A lifetime test: delete LayerTreeView while running LinkHighlights.
-TEST(LinkHighlightImplTest, resetLayerTreeView) {
-  const std::string url = LinkRegisterMockedURLLoad();
-  FrameTestHelpers::WebViewHelper web_view_helper;
-  WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(url);
+TEST_P(LinkHighlightImplTest, resetLayerTreeView) {
+  WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
 
   int page_width = 640;
   int page_height = 480;
@@ -196,8 +213,7 @@
                               kWebGestureDeviceTouchscreen);
   touch_event.SetPositionInWidget(WebFloatPoint(20, 20));
 
-  GestureEventWithHitTestResults targeted_event =
-      GetTargetedEvent(web_view_impl, touch_event);
+  GestureEventWithHitTestResults targeted_event = GetTargetedEvent(touch_event);
   Node* touch_node = web_view_impl->BestTapNode(targeted_event);
   ASSERT_TRUE(touch_node);
 
@@ -209,17 +225,11 @@
   GraphicsLayer* highlight_layer =
       highlights.at(0)->CurrentGraphicsLayerForTesting();
   ASSERT_TRUE(highlight_layer);
-  EXPECT_TRUE(highlight_layer->GetLinkHighlight(0));
-
-  Platform::Current()
-      ->GetURLLoaderMockFactory()
-      ->UnregisterAllURLsAndClearMemoryCache();
+  EXPECT_TRUE(highlight_layer->GetLinkHighlights().at(0));
 }
 
-TEST(LinkHighlightImplTest, multipleHighlights) {
-  const std::string url = LinkRegisterMockedURLLoad();
-  FrameTestHelpers::WebViewHelper web_view_helper;
-  WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(url);
+TEST_P(LinkHighlightImplTest, multipleHighlights) {
+  WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
 
   int page_width = 640;
   int page_height = 480;
@@ -244,10 +254,56 @@
   const auto& highlights =
       web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
   EXPECT_EQ(2U, highlights.size());
+}
 
-  Platform::Current()
-      ->GetURLLoaderMockFactory()
-      ->UnregisterAllURLsAndClearMemoryCache();
+TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) {
+  // This is testing the blink->cc layer integration.
+  if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
+    return;
+
+  int page_width = 640;
+  int page_height = 480;
+  WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
+  web_view_impl->Resize(WebSize(page_width, page_height));
+
+  paint_artifact_compositor()->EnableExtraDataForTesting();
+  web_view_impl->UpdateAllLifecyclePhases();
+  size_t layer_count_before_highlight = ContentLayerCount();
+
+  WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
+                              WebInputEvent::kNoModifiers,
+                              WebInputEvent::GetStaticTimeStampForTests(),
+                              kWebGestureDeviceTouchscreen);
+  touch_event.SetPositionInWidget(WebFloatPoint(20, 20));
+
+  GestureEventWithHitTestResults targeted_event = GetTargetedEvent(touch_event);
+  Node* touch_node = web_view_impl->BestTapNode(targeted_event);
+  ASSERT_TRUE(touch_node);
+
+  web_view_impl->EnableTapHighlightAtPoint(targeted_event);
+  // The highlight should create one additional layer.
+  EXPECT_EQ(layer_count_before_highlight + 1, ContentLayerCount());
+
+  const auto& highlights = web_view_impl->GetPage()->GetLinkHighlights();
+  auto* highlight = highlights.link_highlights_.at(0).get();
+  ASSERT_TRUE(highlight);
+
+  // Check that the link highlight cc layer has a cc effect property tree node.
+  auto* layer = highlight->Layer();
+  auto effect_tree_index = layer->effect_tree_index();
+  auto* property_trees = layer->layer_tree_host()->property_trees();
+  EXPECT_EQ(
+      effect_tree_index,
+      property_trees->element_id_to_effect_node_index[layer->element_id()]);
+  // The link highlight cc effect node should correspond to the blink effect
+  // node.
+  EXPECT_EQ(highlight->effect()->GetCompositorElementId(), layer->element_id());
+  EXPECT_TRUE(highlight->effect()->RequiresCompositingForAnimation());
+
+  touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
+  web_view_impl->UpdateAllLifecyclePhases();
+  // Removing the highlight layer should drop the cc layer count by one.
+  EXPECT_EQ(layer_count_before_highlight, ContentLayerCount());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 67dc662..1ba89d1 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -23,6 +23,7 @@
 #include "third_party/blink/renderer/core/paint/list_marker_painter.h"
 #include "third_party/blink/renderer/core/paint/ng/ng_box_clipper.h"
 #include "third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h"
 #include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
 #include "third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h"
 #include "third_party/blink/renderer/core/paint/object_painter.h"
@@ -176,17 +177,6 @@
   PaintOverflowControlsIfNeeded(info, paint_offset);
 }
 
-void NGBoxFragmentPainter::PaintInlineBox(const PaintInfo& paint_info,
-                                          const LayoutPoint& paint_offset) {
-  const LayoutPoint adjusted_paint_offset =
-      paint_offset + box_fragment_.Offset().ToLayoutPoint();
-  if (paint_info.phase == PaintPhase::kForeground &&
-      box_fragment_.Style().Visibility() == EVisibility::kVisible)
-    PaintBoxDecorationBackground(paint_info, adjusted_paint_offset);
-
-  PaintObject(paint_info, adjusted_paint_offset, true);
-}
-
 void NGBoxFragmentPainter::PaintObject(
     const PaintInfo& paint_info,
     const LayoutPoint& paint_offset,
@@ -335,7 +325,7 @@
   } else if (fragment.Type() == NGPhysicalFragment::kFragmentBox) {
     if (child.HasSelfPaintingLayer())
       return;
-    NGBoxFragmentPainter(child).PaintInlineBox(descendants_info, paint_offset);
+    NGInlineBoxFragmentPainter(child).Paint(descendants_info, paint_offset);
   } else {
     NOTREACHED();
   }
@@ -440,7 +430,6 @@
     NGPhysicalSize size = box_fragment_.Size();
     paint_rect = LayoutRect(LayoutPoint(), LayoutSize(size.width, size.height));
   }
-
   paint_rect.MoveBy(paint_offset);
 
   bool painting_overflow_contents =
@@ -776,15 +765,21 @@
                                              bool object_has_multiple_boxes) {
   PaintInfo paint_info(context, mask_rect, PaintPhase::kTextClip,
                        kGlobalPaintNormalPhase, 0);
-  const LayoutSize local_offset = box_fragment_.Offset().ToLayoutSize();
-  if (PhysicalFragment().IsBlockFlow()) {
-    // TODO(layout-dev): Add support for box-decoration-break: slice
-    // See BoxModelObjectPainter::LogicalOffsetOnLine
-    // if (box_fragment_.Style().BoxDecorationBreak() ==
-    //    EBoxDecorationBreak::kSlice) {
-    //  local_offset -= LogicalOffsetOnLine(*flow_box_);
-    //}
-    PaintBlockFlowContents(paint_info, paint_offset - local_offset);
+  LayoutSize local_offset = box_fragment_.Offset().ToLayoutSize();
+  if (object_has_multiple_boxes) {
+    NGInlineBoxFragmentPainter inline_box_painter(box_fragment_);
+    if (box_fragment_.Style().BoxDecorationBreak() ==
+        EBoxDecorationBreak::kSlice) {
+      LayoutUnit offset_on_line;
+      LayoutUnit total_width;
+      inline_box_painter.ComputeFragmentOffsetOnLine(
+          box_fragment_.Style().Direction(), &offset_on_line, &total_width);
+      LayoutSize line_offset(offset_on_line, LayoutUnit());
+      local_offset -= box_fragment_.Style().IsHorizontalWritingMode()
+                          ? line_offset
+                          : line_offset.TransposedSize();
+    }
+    inline_box_painter.Paint(paint_info, paint_offset - local_offset);
   } else {
     PaintObject(paint_info, paint_offset - local_offset);
   }
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index fcd0338..73fd17b 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -34,7 +34,9 @@
   NGBoxFragmentPainter(const NGPaintFragment&);
 
   void Paint(const PaintInfo&);
-  void PaintInlineBox(const PaintInfo&, const LayoutPoint& paint_offset);
+  void PaintObject(const PaintInfo&,
+                   const LayoutPoint&,
+                   bool suppress_box_decoration_background = false);
 
   // Hit tests this box fragment.
   // @param physical_offset Physical offset of this box fragment in paint layer.
@@ -82,9 +84,6 @@
       const LayoutPoint& paint_offset);
   void PaintInlineChildBoxUsingLegacyFallback(const NGPhysicalFragment&,
                                               const PaintInfo&);
-  void PaintObject(const PaintInfo&,
-                   const LayoutPoint&,
-                   bool suppress_box_decoration_background = false);
   void PaintBlockFlowContents(const PaintInfo&,
                               const LayoutPoint& paint_offset);
   void PaintInlineChild(const NGPaintFragment&,
diff --git a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
new file mode 100644
index 0000000..f26ccfa
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
@@ -0,0 +1,219 @@
+// 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.
+
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h"
+
+#include "third_party/blink/renderer/core/layout/background_bleed_avoidance.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
+#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_phase.h"
+#include "third_party/blink/renderer/core/style/nine_piece_image.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+
+namespace blink {
+
+NGInlineBoxFragmentPainter::NGInlineBoxFragmentPainter(
+    const NGPaintFragment& inline_box_fragment)
+    : InlineBoxPainterBase(
+          inline_box_fragment,
+          &inline_box_fragment.GetLayoutObject()->GetDocument(),
+          inline_box_fragment.GetLayoutObject()->GeneratingNode(),
+          inline_box_fragment.Style(),
+          // TODO(layout-dev): Should be first-line style.
+          inline_box_fragment.Style()),
+      inline_box_fragment_(inline_box_fragment),
+      border_edges_(NGBorderEdges::FromPhysical(
+          inline_box_fragment.PhysicalFragment().BorderEdges(),
+          inline_box_fragment.Style().GetWritingMode())) {
+  NGPaintFragment::FragmentRange fragments =
+      inline_box_fragment.InlineFragmentsFor(
+          inline_box_fragment.GetLayoutObject());
+  NGPaintFragment::FragmentRange::iterator iter = fragments.begin();
+  object_has_multiple_boxes_ = ++iter != fragments.end();
+  include_logical_left_edge_for_box_shadow_ =
+      !object_has_multiple_boxes_ || border_edges_.line_left;
+  include_logical_right_edge_for_box_shadow_ =
+      !object_has_multiple_boxes_ || border_edges_.line_right;
+}
+
+void NGInlineBoxFragmentPainter::Paint(const PaintInfo& paint_info,
+                                       const LayoutPoint& paint_offset) {
+  const LayoutPoint adjusted_paint_offset =
+      paint_offset + inline_box_fragment_.Offset().ToLayoutPoint();
+  if (paint_info.phase == PaintPhase::kForeground)
+    PaintBackgroundBorderShadow(paint_info, adjusted_paint_offset);
+
+  NGBoxFragmentPainter box_painter(inline_box_fragment_);
+  box_painter.PaintObject(paint_info, adjusted_paint_offset, true);
+}
+
+void NGInlineBoxFragmentPainter::PaintBackgroundBorderShadow(
+    const PaintInfo& paint_info,
+    const LayoutPoint& paint_offset) {
+  DCHECK(paint_info.phase == PaintPhase::kForeground);
+  if (inline_box_fragment_.Style().Visibility() != EVisibility::kVisible)
+    return;
+
+  // You can use p::first-line to specify a background. If so, the root line
+  // boxes for a line may actually have to paint a background.
+  bool should_paint_box_decoration_background;
+  if (inline_box_fragment_.Parent()) {
+    should_paint_box_decoration_background =
+        inline_box_fragment_.Style().HasBoxDecorationBackground();
+  } else {
+    // TODO(kojii): Get from fragment once available.
+    bool is_first_line = false;
+    should_paint_box_decoration_background =
+        is_first_line && line_style_ != style_;
+  }
+
+  if (!should_paint_box_decoration_background)
+    return;
+
+  if (DrawingRecorder::UseCachedDrawingIfPossible(
+          paint_info.context, inline_box_fragment_,
+          DisplayItem::kBoxDecorationBackground))
+    return;
+
+  DrawingRecorder recorder(paint_info.context, inline_box_fragment_,
+                           DisplayItem::kBoxDecorationBackground);
+
+  LayoutRect frame_rect =
+      inline_box_fragment_.PhysicalFragment().LocalRect().ToLayoutRect();
+  LayoutPoint adjusted_paint_offset = paint_offset;
+
+  LayoutRect adjusted_frame_rect =
+      LayoutRect(adjusted_paint_offset, frame_rect.Size());
+
+  // TODO(eae): Switch to LayoutNG version of BackgroundImageGeometry.
+  BackgroundImageGeometry geometry(*static_cast<const LayoutBoxModelObject*>(
+      inline_box_fragment_.GetLayoutObject()));
+  NGBoxFragmentPainter box_painter(inline_box_fragment_);
+  PaintBoxDecorationBackground(
+      box_painter, paint_info, paint_offset, adjusted_frame_rect, geometry,
+      border_edges_.line_left, border_edges_.line_right);
+}
+
+void NGInlineBoxFragmentPainter::ComputeFragmentOffsetOnLine(
+    TextDirection direction,
+    LayoutUnit* offset_on_line,
+    LayoutUnit* total_width) const {
+  WritingMode writing_mode = inline_box_fragment_.Style().GetWritingMode();
+  DCHECK(object_has_multiple_boxes_);
+  NGPaintFragment::FragmentRange fragments =
+      inline_box_fragment_.InlineFragmentsFor(
+          inline_box_fragment_.GetLayoutObject());
+
+  LayoutUnit before;
+  LayoutUnit after;
+  bool before_self = true;
+  for (auto iter = fragments.begin(); iter != fragments.end(); ++iter) {
+    if (*iter == &inline_box_fragment_) {
+      before_self = false;
+      continue;
+    }
+    if (before_self)
+      before += NGFragment(writing_mode, iter->PhysicalFragment()).InlineSize();
+    else
+      after += NGFragment(writing_mode, iter->PhysicalFragment()).InlineSize();
+  }
+
+  NGFragment logical_fragment(writing_mode,
+                              inline_box_fragment_.PhysicalFragment());
+  *total_width = before + after + logical_fragment.InlineSize();
+
+  // We're iterating over the fragments in physical order before so we need to
+  // swap before and after for RTL.
+  *offset_on_line = direction == TextDirection::kLtr ? before : after;
+}
+
+LayoutRect NGInlineBoxFragmentPainter::PaintRectForImageStrip(
+    const LayoutRect& paint_rect,
+    TextDirection direction) const {
+  // We have a fill/border/mask image that spans multiple lines.
+  // We need to adjust the offset by the width of all previous lines.
+  // Think of background painting on inlines as though you had one long line, a
+  // single continuous strip. Even though that strip has been broken up across
+  // multiple lines, you still paint it as though you had one single line. This
+  // means each line has to pick up the background where the previous line left
+  // off.
+  DCHECK(object_has_multiple_boxes_);
+  LayoutUnit offset_on_line;
+  LayoutUnit total_width;
+  ComputeFragmentOffsetOnLine(direction, &offset_on_line, &total_width);
+
+  if (inline_box_fragment_.Style().IsHorizontalWritingMode()) {
+    return LayoutRect(paint_rect.X() - offset_on_line, paint_rect.Y(),
+                      total_width, paint_rect.Height());
+  }
+  return LayoutRect(paint_rect.X(), paint_rect.Y() - offset_on_line,
+                    paint_rect.Width(), total_width);
+}
+
+static LayoutRect NGClipRectForNinePieceImageStrip(
+    const ComputedStyle& style,
+    const NGBorderEdges& border_edges,
+    const NinePieceImage& image,
+    const LayoutRect& paint_rect) {
+  LayoutRect clip_rect(paint_rect);
+  LayoutRectOutsets outsets = style.ImageOutsets(image);
+  if (style.IsHorizontalWritingMode()) {
+    clip_rect.SetY(paint_rect.Y() - outsets.Top());
+    clip_rect.SetHeight(paint_rect.Height() + outsets.Top() + outsets.Bottom());
+    if (border_edges.line_left) {
+      clip_rect.SetX(paint_rect.X() - outsets.Left());
+      clip_rect.SetWidth(paint_rect.Width() + outsets.Left());
+    }
+    if (border_edges.line_right)
+      clip_rect.SetWidth(clip_rect.Width() + outsets.Right());
+  } else {
+    clip_rect.SetX(paint_rect.X() - outsets.Left());
+    clip_rect.SetWidth(paint_rect.Width() + outsets.Left() + outsets.Right());
+    if (border_edges.line_left) {
+      clip_rect.SetY(paint_rect.Y() - outsets.Top());
+      clip_rect.SetHeight(paint_rect.Height() + outsets.Top());
+    }
+    if (border_edges.line_right)
+      clip_rect.SetHeight(clip_rect.Height() + outsets.Bottom());
+  }
+  return clip_rect;
+}
+
+InlineBoxPainterBase::BorderPaintingType
+NGInlineBoxFragmentPainter::GetBorderPaintType(
+    const LayoutRect& adjusted_frame_rect,
+    IntRect& adjusted_clip_rect) const {
+  adjusted_clip_rect = PixelSnappedIntRect(adjusted_frame_rect);
+  if (inline_box_fragment_.Parent() &&
+      inline_box_fragment_.Style().HasBorderDecoration()) {
+    const NinePieceImage& border_image =
+        inline_box_fragment_.Style().BorderImage();
+    StyleImage* border_image_source = border_image.GetImage();
+    bool has_border_image =
+        border_image_source && border_image_source->CanRender();
+    if (has_border_image && !border_image_source->IsLoaded())
+      return kDontPaintBorders;
+
+    // The simple case is where we either have no border image or we are the
+    // only box for this object.  In those cases only a single call to draw is
+    // required.
+    if (!has_border_image || !object_has_multiple_boxes_)
+      return kPaintBordersWithoutClip;
+
+    // We have a border image that spans multiple lines.
+    adjusted_clip_rect = PixelSnappedIntRect(NGClipRectForNinePieceImageStrip(
+        inline_box_fragment_.Style(), border_edges_, border_image,
+        adjusted_frame_rect));
+    return kPaintBordersWithClip;
+  }
+  return kDontPaintBorders;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
new file mode 100644
index 0000000..1baa3b5
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
@@ -0,0 +1,52 @@
+// 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.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_
+
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h"
+#include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/skia/include/core/SkBlendMode.h"
+
+namespace blink {
+
+class LayoutRect;
+class NGPaintFragment;
+struct PaintInfo;
+
+// Painter for LayoutNG inline box fragments. Delegates to NGBoxFragmentPainter
+// for all box painting logic that isn't specific to inline boxes.
+class NGInlineBoxFragmentPainter : public InlineBoxPainterBase {
+  STACK_ALLOCATED();
+
+ public:
+  NGInlineBoxFragmentPainter(const NGPaintFragment&);
+
+  void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+  void ComputeFragmentOffsetOnLine(TextDirection,
+                                   LayoutUnit* offset_on_line,
+                                   LayoutUnit* total_width) const;
+
+ protected:
+  LayoutRect PaintRectForImageStrip(const LayoutRect&,
+                                    TextDirection direction) const override;
+
+  BorderPaintingType GetBorderPaintType(
+      const LayoutRect& adjusted_frame_rect,
+      IntRect& adjusted_clip_rect) const override;
+
+ private:
+  void PaintBackgroundBorderShadow(const PaintInfo&,
+                                   const LayoutPoint& paint_offset);
+
+  const NGPaintFragment& inline_box_fragment_;
+  NGBorderEdges border_edges_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index 25d6ac1..3426189e 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
 #include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h"
 
 namespace blink {
 
@@ -163,6 +164,8 @@
 
 std::unique_ptr<NGPaintFragment> NGPaintFragment::Create(
     scoped_refptr<const NGPhysicalFragment> fragment) {
+  DCHECK(fragment);
+
   std::unique_ptr<NGPaintFragment> paint_fragment =
       std::make_unique<NGPaintFragment>(std::move(fragment), nullptr);
 
@@ -174,6 +177,25 @@
   return paint_fragment;
 }
 
+void NGPaintFragment::UpdatePhysicalFragmentFromCachedLayoutResult(
+    scoped_refptr<const NGPhysicalFragment> fragment) {
+  DCHECK(fragment);
+
+#if DCHECK_IS_ON()
+  // When updating to a cached layout result, only offset can change. Check
+  // children do not change.
+  const NGPhysicalContainerFragment& container_fragment =
+      ToNGPhysicalContainerFragment(*fragment);
+  DCHECK_EQ(Children().size(), container_fragment.Children().size());
+  for (unsigned i = 0; i < container_fragment.Children().size(); i++) {
+    DCHECK_EQ(Children()[i]->physical_fragment_.get(),
+              container_fragment.Children()[i].get());
+  }
+#endif
+
+  physical_fragment_ = fragment;
+}
+
 bool NGPaintFragment::IsDescendantOfNotSelf(
     const NGPaintFragment& ancestor) const {
   for (const NGPaintFragment* fragment = Parent(); fragment;
@@ -345,7 +367,7 @@
   DCHECK(layout_object);
   for (const auto& child : Children()) {
     if (child->GetLayoutObject() == layout_object) {
-      NGBoxFragmentPainter(*child).PaintInlineBox(
+      NGInlineBoxFragmentPainter(*child).Paint(
           paint_info, paint_offset + offset.ToLayoutPoint() /*, paint_offset*/);
       continue;
     }
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
index 370ad8c..68d62c6 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -46,6 +46,9 @@
     return *physical_fragment_;
   }
 
+  void UpdatePhysicalFragmentFromCachedLayoutResult(
+      scoped_refptr<const NGPhysicalFragment>);
+
   // The parent NGPaintFragment. This is nullptr for a root; i.e., when parent
   // is not for NGPaint. In the first phase, this means that this is a root of
   // an inline formatting context.
diff --git a/third_party/blink/renderer/core/paint/object_paint_properties.h b/third_party/blink/renderer/core/paint/object_paint_properties.h
index 736b174..aba1997 100644
--- a/third_party/blink/renderer/core/paint/object_paint_properties.h
+++ b/third_party/blink/renderer/core/paint/object_paint_properties.h
@@ -76,9 +76,9 @@
   // The hierarchy of the effect subtree created by a LayoutObject is as
   // follows:
   // [ effect ]
-  // |   Isolated group to apply various CSS effects, including opacity,
-  // |   mix-blend-mode, and for isolation if a mask needs to be applied or
-  // |   backdrop-dependent children are present.
+  // |     Isolated group to apply various CSS effects, including opacity,
+  // |     mix-blend-mode, and for isolation if a mask needs to be applied or
+  // |     backdrop-dependent children are present.
   // +-[ filter ]
   // |     Isolated group for CSS filter.
   // +-[ vertical/horizontal scrollbar effect ]
@@ -88,9 +88,12 @@
   // |     Isolated group for painting the CSS mask. This node will have
   // |     SkBlendMode::kDstIn and shall paint last, i.e. after masked contents.
   // +-[ clip path ]
-  //       Isolated group for painting the CSS clip-path. This node will have
-  //       SkBlendMode::kDstIn and shall paint last, i.e. after clipped
-  //       contents.
+  // |     Isolated group for painting the CSS clip-path. This node will have
+  // |     SkBlendMode::kDstIn and shall paint last, i.e. after clipped
+  // |     contents.
+  // +-[ link highlight effect ]
+  //       The link highlight effect is only used for link highlight animations
+  //       and should never have descendants.
   const EffectPaintPropertyNode* Effect() const { return effect_.get(); }
   const EffectPaintPropertyNode* Filter() const { return filter_.get(); }
   const EffectPaintPropertyNode* VerticalScrollbarEffect() const {
@@ -101,6 +104,9 @@
   }
   const EffectPaintPropertyNode* Mask() const { return mask_.get(); }
   const EffectPaintPropertyNode* ClipPath() const { return clip_path_.get(); }
+  const EffectPaintPropertyNode* LinkHighlightEffect() const {
+    return link_highlight_effect_.get();
+  }
 
   // The hierarchy of the clip subtree created by a LayoutObject is as follows:
   // [ fragment clip ]
@@ -174,6 +180,7 @@
   }
   bool ClearMask() { return Clear(mask_); }
   bool ClearClipPath() { return Clear(clip_path_); }
+  bool ClearLinkHighlightEffect() { return Clear(link_highlight_effect_); }
   bool ClearFragmentClip() { return Clear(fragment_clip_); }
   bool ClearClipPathClip() { return Clear(clip_path_clip_); }
   bool ClearMaskClip() { return Clear(mask_clip_); }
@@ -260,6 +267,11 @@
                               EffectPaintPropertyNode::State&& state) {
     return Update(clip_path_, parent, std::move(state));
   }
+  UpdateResult UpdateLinkHighlightEffect(
+      const EffectPaintPropertyNode& parent,
+      EffectPaintPropertyNode::State&& state) {
+    return Update(link_highlight_effect_, parent, std::move(state));
+  }
   UpdateResult UpdateFragmentClip(const ClipPaintPropertyNode& parent,
                                   ClipPaintPropertyNode::State&& state) {
     return Update(fragment_clip_, parent, std::move(state));
@@ -318,6 +330,8 @@
       cloned->mask_ = mask_->Clone();
     if (clip_path_)
       cloned->clip_path_ = clip_path_->Clone();
+    if (link_highlight_effect_)
+      cloned->link_highlight_effect_ = link_highlight_effect_->Clone();
     if (fragment_clip_)
       cloned->fragment_clip_ = fragment_clip_->Clone();
     if (clip_path_clip_)
@@ -389,6 +403,7 @@
   scoped_refptr<EffectPaintPropertyNode> horizontal_scrollbar_effect_;
   scoped_refptr<EffectPaintPropertyNode> mask_;
   scoped_refptr<EffectPaintPropertyNode> clip_path_;
+  scoped_refptr<EffectPaintPropertyNode> link_highlight_effect_;
   scoped_refptr<ClipPaintPropertyNode> fragment_clip_;
   scoped_refptr<ClipPaintPropertyNode> clip_path_clip_;
   scoped_refptr<ClipPaintPropertyNode> mask_clip_;
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 00d6c247..0cab1ff2 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include "third_party/blink/renderer/core/animation/scroll_timeline.h"
 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
+#include "third_party/blink/renderer/core/frame/link_highlights.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
@@ -134,6 +135,7 @@
   ALWAYS_INLINE void UpdateTransform();
   ALWAYS_INLINE void UpdateTransformForNonRootSVG();
   ALWAYS_INLINE void UpdateEffect();
+  ALWAYS_INLINE void UpdateLinkHighlightEffect();
   ALWAYS_INLINE void UpdateFilter();
   ALWAYS_INLINE void UpdateFragmentClip();
   ALWAYS_INLINE void UpdateCssClip();
@@ -693,6 +695,39 @@
   }
 }
 
+static bool NeedsLinkHighlightEffect(const LayoutObject& object) {
+  auto* page = object.GetFrame()->GetPage();
+  return page->GetLinkHighlights().NeedsHighlightEffect(object);
+}
+
+void FragmentPaintPropertyTreeBuilder::UpdateLinkHighlightEffect() {
+  if (NeedsPaintPropertyUpdate()) {
+    if (NeedsLinkHighlightEffect(object_)) {
+      // While the link highlight uses the current transform space for
+      // positioning, it's parent effect is the root so that it is not affected
+      // by enclosing filters.
+      const auto& parent = EffectPaintPropertyNode::Root();
+      EffectPaintPropertyNode::State link_highlight_state;
+      link_highlight_state.local_transform_space = context_.current.transform;
+      link_highlight_state.compositor_element_id =
+          object_.GetFrame()->GetPage()->GetLinkHighlights().element_id(
+              object_);
+      link_highlight_state.direct_compositing_reasons =
+          CompositingReason::kActiveOpacityAnimation;
+      // Unlike other property nodes, link highlight effect nodes are guaranteed
+      // to be leaf nodes and do not require subtree invalidation, so we do not
+      // call |OnUpdate| here.
+      properties_->UpdateLinkHighlightEffect(parent,
+                                             std::move(link_highlight_state));
+    } else {
+      // Unlike other property nodes, link highlight effect nodes are guaranteed
+      // to be leaf nodes and do not require subtree invalidation, so we do not
+      // call |OnClear| here.
+      properties_->ClearLinkHighlightEffect();
+    }
+  }
+}
+
 static bool NeedsFilter(const LayoutObject& object) {
   // TODO(trchen): SVG caches filters in SVGResources. Implement it.
   if (object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() &&
@@ -1763,6 +1798,7 @@
     UpdateTransform();
     UpdateClipPathClip(false);
     UpdateEffect();
+    UpdateLinkHighlightEffect();
     UpdateClipPathClip(true);  // Special pass for SPv1 composited clip-path.
     UpdateCssClip();
     UpdateFilter();
@@ -2407,10 +2443,11 @@
   bool needs_paint_properties =
       object_.StyleRef().ClipPath() || NeedsPaintOffsetTranslation(object_) ||
       NeedsTransform(object_) || NeedsClipPathClip(object_) ||
-      NeedsEffect(object_) || NeedsTransformForNonRootSVG(object_) ||
-      NeedsFilter(object_) || NeedsCssClip(object_) ||
-      NeedsInnerBorderRadiusClip(object_) || NeedsOverflowClip(object_) ||
-      NeedsPerspective(object_) || NeedsSVGLocalToBorderBoxTransform(object_) ||
+      NeedsEffect(object_) || NeedsLinkHighlightEffect(object_) ||
+      NeedsTransformForNonRootSVG(object_) || NeedsFilter(object_) ||
+      NeedsCssClip(object_) || NeedsInnerBorderRadiusClip(object_) ||
+      NeedsOverflowClip(object_) || NeedsPerspective(object_) ||
+      NeedsSVGLocalToBorderBoxTransform(object_) ||
       NeedsScrollOrScrollTranslation(object_);
   // Need of fragmentation clip will be determined in CreateFragmentContexts().
 
diff --git a/third_party/blink/renderer/core/svg/svg_resource.cc b/third_party/blink/renderer/core/svg/svg_resource.cc
index 4fe24df9..7e63350 100644
--- a/third_party/blink/renderer/core/svg/svg_resource.cc
+++ b/third_party/blink/renderer/core/svg/svg_resource.cc
@@ -128,6 +128,8 @@
   ResourceLoaderOptions options;
   options.initiator_info.name = FetchInitiatorTypeNames::css;
   FetchParameters params(ResourceRequest(url_), options);
+  params.MutableResourceRequest().SetFetchRequestMode(
+      network::mojom::FetchRequestMode::kSameOrigin);
   resource_document_ =
       DocumentResource::FetchSVGDocument(params, document.Fetcher(), this);
   target_ = ResolveTarget();
diff --git a/third_party/blink/renderer/core/svg/svg_use_element.cc b/third_party/blink/renderer/core/svg/svg_use_element.cc
index 06df52944..3f07e9b8 100644
--- a/third_party/blink/renderer/core/svg/svg_use_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_use_element.cc
@@ -212,6 +212,8 @@
   ResourceLoaderOptions options;
   options.initiator_info.name = localName();
   FetchParameters params(ResourceRequest(element_url_), options);
+  params.MutableResourceRequest().SetFetchRequestMode(
+      network::mojom::FetchRequestMode::kSameOrigin);
   DocumentResource::FetchSVGDocument(params, GetDocument().Fetcher(), this);
 }
 
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_html.cc b/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
index 2b1cf3fa06..54b6f1a6 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
@@ -4,7 +4,10 @@
 
 #include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
+#include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -30,6 +33,25 @@
   return TrustedHTML::Create(html);
 }
 
+String TrustedHTML::GetString(StringOrTrustedHTML stringOrHTML,
+                              const Document* doc,
+                              ExceptionState& exception_state) {
+  DCHECK(stringOrHTML.IsString() ||
+         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+  DCHECK(!stringOrHTML.IsNull());
+
+  if (!stringOrHTML.IsTrustedHTML() && doc && doc->RequireTrustedTypes()) {
+    exception_state.ThrowTypeError(
+        "This document requires `TrustedHTML` assignment.");
+    return g_empty_string;
+  }
+
+  String markup = stringOrHTML.IsString()
+                      ? stringOrHTML.GetAsString()
+                      : stringOrHTML.GetAsTrustedHTML()->toString();
+  return markup;
+}
+
 String TrustedHTML::toString() const {
   return html_;
 }
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_html.h b/third_party/blink/renderer/core/trustedtypes/trusted_html.h
index f9cf7a8b2..423b8c0 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_html.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_html.h
@@ -12,7 +12,10 @@
 
 namespace blink {
 
+class Document;
+class ExceptionState;
 class ScriptState;
+class StringOrTrustedHTML;
 
 class CORE_EXPORT TrustedHTML final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
@@ -26,6 +29,7 @@
   String toString() const;
   static TrustedHTML* escape(ScriptState*, const String& html);
   static TrustedHTML* unsafelyCreate(ScriptState*, const String& html);
+  static String GetString(StringOrTrustedHTML, const Document*, ExceptionState&);
 
  private:
   TrustedHTML(const String& html);
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_url.cc b/third_party/blink/renderer/core/trustedtypes/trusted_url.cc
index aca934a..38e6d981 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_url.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_url.cc
@@ -4,8 +4,11 @@
 
 #include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
+#include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -26,6 +29,25 @@
       ExecutionContext::From(script_state)->CompleteURL(url));
 }
 
+String TrustedURL::GetString(USVStringOrTrustedURL stringOrURL,
+                             const Document* doc,
+                             ExceptionState& exception_state) {
+  DCHECK(stringOrURL.IsUSVString() ||
+         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+  DCHECK(!stringOrURL.IsNull());
+
+  if (!stringOrURL.IsTrustedURL() && doc && doc->RequireTrustedTypes()) {
+    exception_state.ThrowTypeError(
+        "This document requires `TrustedURL` assignment.");
+    return g_empty_string;
+  }
+
+  String markup = stringOrURL.IsUSVString()
+                      ? stringOrURL.GetAsUSVString()
+                      : stringOrURL.GetAsTrustedURL()->toString();
+  return markup;
+}
+
 String TrustedURL::toString() const {
   return url_.GetString();
 }
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_url.h b/third_party/blink/renderer/core/trustedtypes/trusted_url.h
index 09fcec5..6e33c23 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_url.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_url.h
@@ -13,7 +13,10 @@
 
 namespace blink {
 
+class Document;
+class ExceptionState;
 class ScriptState;
+class USVStringOrTrustedURL;
 
 class CORE_EXPORT TrustedURL final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
@@ -25,6 +28,9 @@
   String toString() const;
   static TrustedURL* create(ScriptState*, const String& url);
   static TrustedURL* unsafelyCreate(ScriptState*, const String& url);
+  static String GetString(USVStringOrTrustedURL,
+                          const Document*,
+                          ExceptionState&);
 
  private:
   TrustedURL(const KURL&);
diff --git a/third_party/blink/renderer/core/xml/dom_parser.cc b/third_party/blink/renderer/core/xml/dom_parser.cc
index b322ad3a..5b9e53b 100644
--- a/third_party/blink/renderer/core/xml/dom_parser.cc
+++ b/third_party/blink/renderer/core/xml/dom_parser.cc
@@ -32,21 +32,12 @@
 Document* DOMParser::parseFromString(const StringOrTrustedHTML& stringOrHTML,
                                      const String& type,
                                      ExceptionState& exception_state) {
-  DCHECK(stringOrHTML.IsString() ||
-         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-  DCHECK(!stringOrHTML.IsNull());
-  if (context_document_ && stringOrHTML.IsString() &&
-      context_document_->RequireTrustedTypes()) {
-    exception_state.ThrowTypeError(
-        "This document requires `TrustedHTML` assignment.");
-    return nullptr;
+  String value =
+      TrustedHTML::GetString(stringOrHTML, context_document_, exception_state);
+  if (!exception_state.HadException()) {
+    return parseFromStringInternal(value, type);
   }
-
-  String valueString = stringOrHTML.IsString()
-                           ? stringOrHTML.GetAsString()
-                           : stringOrHTML.GetAsTrustedHTML()->toString();
-
-  return parseFromStringInternal(valueString, type);
+  return nullptr;
 }
 
 Document* DOMParser::parseFromStringInternal(const String& str,
diff --git a/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc b/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc
index bf18794d..59349d6 100644
--- a/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc
+++ b/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc
@@ -227,7 +227,8 @@
   fetch_options.initiator_info.name = FetchInitiatorTypeNames::xml;
   FetchParameters params(
       ResourceRequest(OwnerDocument()->CompleteURL(url_string)), fetch_options);
-  params.SetOriginRestriction(FetchParameters::kRestrictToSameOrigin);
+  params.MutableResourceRequest().SetFetchRequestMode(
+      network::mojom::FetchRequestMode::kSameOrigin);
   XSLStyleSheetResource* resource = XSLStyleSheetResource::FetchSynchronously(
       params, OwnerDocument()->Fetcher());
   if (!resource->Sheet())
diff --git a/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc b/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
index bb879481..1a08620 100644
--- a/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
+++ b/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
@@ -109,7 +109,6 @@
       ResourceLoaderOptions fetch_options;
       fetch_options.initiator_info.name = FetchInitiatorTypeNames::xml;
       FetchParameters params(ResourceRequest(url), fetch_options);
-      params.SetOriginRestriction(FetchParameters::kRestrictToSameOrigin);
       params.MutableResourceRequest().SetFetchRequestMode(
           network::mojom::FetchRequestMode::kSameOrigin);
       Resource* resource =
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js b/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
index c806078..b85a119 100644
--- a/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
+++ b/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-Console.ConsolePinPane = class extends UI.VBox {
+Console.ConsolePinPane = class extends UI.ThrottledWidget {
   constructor() {
-    super(true);
+    super(true, 250);
     this.registerRequiredCSS('console/consolePinPane.css');
+    this.registerRequiredCSS('object_ui/objectValue.css');
     this.contentElement.classList.add('console-pins', 'monospace');
     this.contentElement.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), false);
 
@@ -25,6 +26,7 @@
         const targetPin = targetPinElement[Console.ConsolePin._PinSymbol];
         contextMenu.editSection().appendItem(ls`Edit pin`, targetPin.focus.bind(targetPin));
         contextMenu.editSection().appendItem(ls`Remove pin`, this._removePin.bind(this, targetPin));
+        targetPin.appendToContextMenu(contextMenu);
       }
     }
     contextMenu.editSection().appendItem(ls`Remove all pins`, this._removeAllPins.bind(this));
@@ -52,6 +54,22 @@
     this.contentElement.appendChild(pin.element());
     this._pins.add(pin);
     pin.focus();
+    this.update();
+  }
+
+  /**
+   * @override
+   */
+  doUpdate() {
+    if (!this._pins.size)
+      return Promise.resolve();
+    if (this.isShowing())
+      this.update();
+    const updatePromises = Array.from(this._pins, pin => pin.updatePreview());
+    return Promise.all(updatePromises).then(this._updatedForTest.bind(this));
+  }
+
+  _updatedForTest() {
   }
 };
 
@@ -68,13 +86,16 @@
     <div class='console-pin'>
       ${deletePinIcon}
       <div class='console-pin-name' $='name'></div>
-      <div class='console-pin-preview'>${ls`not available`}</div>
+      <div class='console-pin-preview' $='preview'>${ls`not available`}</div>
     </div>`;
     this._pinElement = fragment.element();
+    this._pinPreview = fragment.$('preview');
     const nameElement = fragment.$('name');
     nameElement.title = expression;
     this._pinElement[Console.ConsolePin._PinSymbol] = this;
 
+    /** @type {?SDK.RemoteObject} */
+    this._resultObject = null;
     /** @type {?UI.TextEditor} */
     this._editor = null;
 
@@ -86,6 +107,7 @@
         autoHeight: true,
         placeholder: ls`Expression`
       });
+      this._editor.configureAutocomplete(ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(this._editor));
       this._editor.widget().show(nameElement);
       this._editor.widget().element.classList.add('console-pin-editor');
       this._editor.widget().element.tabIndex = -1;
@@ -109,6 +131,35 @@
     this._editor.widget().focus();
     this._editor.setSelection(TextUtils.TextRange.createFromLocation(Infinity, Infinity));
   }
+
+  /**
+   * @param {!UI.ContextMenu} contextMenu
+   */
+  appendToContextMenu(contextMenu) {
+    if (this._resultObject)
+      contextMenu.appendApplicableItems(this._resultObject);
+  }
+
+  /**
+   * @return {!Promise}
+   */
+  async updatePreview() {
+    if (!this._editor)
+      return;
+    const text = this._editor.textWithCurrentSuggestion().trim();
+    const isEditing = this._pinElement.hasFocus();
+    const timeout = isEditing ? 250 : undefined;
+    const {preview, result} = await ObjectUI.JavaScriptREPL.evaluateAndBuildPreview(text, isEditing, timeout);
+    this._resultObject = result ? (result.object || null) : null;
+    const previewText = preview.deepTextContent();
+    if (!previewText || previewText !== this._pinPreview.deepTextContent()) {
+      this._pinPreview.removeChildren();
+      if (result && SDK.RuntimeModel.isSideEffectFailure(result))
+        this._pinPreview.appendChild(createTextNode(`(...)`));
+      else
+        this._pinPreview.appendChild(previewText ? preview : createTextNode(ls`not available`));
+    }
+  }
 };
 
 Console.ConsolePin._PinSymbol = Symbol('pinSymbol');
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
index 1334e88..d31ce21 100644
--- a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
+++ b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
@@ -56,7 +56,7 @@
       this._editor.addEventListener(UI.TextEditor.Events.SuggestionChanged, this._onTextChanged, this);
       if (pinsEnabled) {
         const pinButton = this.element.createChild('span', 'command-pin-button');
-        pinButton.title = ls`Pin expression`;
+        pinButton.title = ls`Pin expression and continuously evaluate`;
         pinButton.addEventListener('click', () => {
           this.dispatchEventToListeners(Console.ConsolePrompt.Events.ExpressionPinned, this.text());
         });
@@ -232,23 +232,15 @@
     if (!str.length)
       return;
 
-    const currentExecutionContext = UI.context.flavor(SDK.ExecutionContext);
-    if (!this._isCaretAtEndOfPrompt() || !currentExecutionContext) {
-      this._appendCommand(str, true);
+    if (!this._isCaretAtEndOfPrompt()) {
+      await this._appendCommand(str, true);
       return;
     }
-    const result = await currentExecutionContext.runtimeModel.compileScript(str, '', false, currentExecutionContext.id);
-    if (str !== this.text())
-      return;
-    const exceptionDetails = result.exceptionDetails;
-    if (exceptionDetails &&
-        (exceptionDetails.exception.description.startsWith('SyntaxError: Unexpected end of input') ||
-         exceptionDetails.exception.description.startsWith('SyntaxError: Unterminated template literal'))) {
+
+    if (await ObjectUI.JavaScriptAutocomplete.isExpressionComplete(str))
+      await this._appendCommand(str, true);
+    else
       this._editor.newlineAndIndent();
-      this._enterProcessedForTest();
-      return;
-    }
-    await this._appendCommand(str, true);
     this._enterProcessedForTest();
   }
 
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js b/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
index fdc9790..ebf57f65 100644
--- a/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
+++ b/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
@@ -125,9 +125,9 @@
    */
   _buildTableMessage() {
     const formattedMessage = createElementWithClass('span', 'source-code');
-    const anchorElement = this._buildMessageAnchor();
-    if (anchorElement)
-      formattedMessage.appendChild(anchorElement);
+    this._anchorElement = this._buildMessageAnchor();
+    if (this._anchorElement)
+      formattedMessage.appendChild(this._anchorElement);
     const badgeElement = this._buildMessageBadge();
     if (badgeElement)
       formattedMessage.appendChild(badgeElement);
@@ -279,9 +279,9 @@
     messageElement.classList.add('console-message-text');
 
     const formattedMessage = createElementWithClass('span', 'source-code');
-    const anchorElement = this._buildMessageAnchor();
-    if (anchorElement)
-      formattedMessage.appendChild(anchorElement);
+    this._anchorElement = this._buildMessageAnchor();
+    if (this._anchorElement)
+      formattedMessage.appendChild(this._anchorElement);
     const badgeElement = this._buildMessageBadge();
     if (badgeElement)
       formattedMessage.appendChild(badgeElement);
@@ -921,8 +921,10 @@
    */
   matchesFilterRegex(regexObject) {
     regexObject.lastIndex = 0;
-    const text = this.contentElement().deepTextContent();
-    return regexObject.test(text);
+    const contentElement = this.contentElement();
+    const anchorText = this._anchorElement ? this._anchorElement.deepTextContent() : '';
+    return (anchorText && regexObject.test(anchorText.trim())) ||
+        regexObject.test(contentElement.deepTextContent().slice(anchorText.length));
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/main/Main.js b/third_party/blink/renderer/devtools/front_end/main/Main.js
index c275c35..c5dcc842 100644
--- a/third_party/blink/renderer/devtools/front_end/main/Main.js
+++ b/third_party/blink/renderer/devtools/front_end/main/Main.js
@@ -143,6 +143,8 @@
         Runtime.experiments.enableForTest('networkSearch');
       if (testPath.indexOf('console/viewport-testing/') !== -1)
         Runtime.experiments.enableForTest('consoleBelowPrompt');
+      if (testPath.indexOf('console/') !== -1)
+        Runtime.experiments.enableForTest('pinnedExpressions');
     }
 
     Runtime.experiments.setDefaultExperiments(
diff --git a/third_party/blink/renderer/devtools/front_end/network/networkConfigView.css b/third_party/blink/renderer/devtools/front_end/network/networkConfigView.css
index 5c9f81f3..6c5ede0d 100644
--- a/third_party/blink/renderer/devtools/front_end/network/networkConfigView.css
+++ b/third_party/blink/renderer/devtools/front_end/network/networkConfigView.css
@@ -64,7 +64,6 @@
 .network-config-ua input:not(.dt-radio-button) {
     display: block;
     width: calc(100% - 20px);
-    max-width: 250px;
 }
 
 .network-config-ua input[readonly] {
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js b/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
index cddc8a8..7ecf7bab 100644
--- a/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
+++ b/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
@@ -596,6 +596,23 @@
       return -1;
     return String.naturalOrderComparator(a, b);
   }
+
+  /**
+   * @param {string} expression
+   * @return {!Promise<boolean>}
+   */
+  static async isExpressionComplete(expression) {
+    const currentExecutionContext = UI.context.flavor(SDK.ExecutionContext);
+    if (!currentExecutionContext)
+      return true;
+    const result =
+        await currentExecutionContext.runtimeModel.compileScript(expression, '', false, currentExecutionContext.id);
+    if (!result.exceptionDetails)
+      return true;
+    const description = result.exceptionDetails.exception.description;
+    return !description.startsWith('SyntaxError: Unexpected end of input') &&
+        !description.startsWith('SyntaxError: Unterminated template literal');
+  }
 };
 
 /** @typedef {{title:(string|undefined), items:Array<string>}} */
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js b/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
index 8cb0c686..a23acce 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
@@ -54,6 +54,16 @@
   }
 
   /**
+   * @param {!SDK.RuntimeModel.EvaluationResult} response
+   */
+  static isSideEffectFailure(response) {
+    const exceptionDetails = !response[Protocol.Error] && response.exceptionDetails;
+    return !!(
+        exceptionDetails && exceptionDetails.exception &&
+        exceptionDetails.exception.description.startsWith('EvalError: Possible side-effect in debug-evaluate'));
+  }
+
+  /**
    * @return {!SDK.DebuggerModel}
    */
   debuggerModel() {
@@ -469,12 +479,8 @@
     const response = await this._agent.invoke_evaluate(
         {expression: SDK.RuntimeModel._sideEffectTestExpression, contextId: testContext.id, throwOnSideEffect: true});
 
-    const exceptionDetails = !response[Protocol.Error] && response.exceptionDetails;
-    const supports =
-        !!(exceptionDetails && exceptionDetails.exception &&
-           exceptionDetails.exception.description.startsWith('EvalError: Possible side-effect in debug-evaluate'));
-    this._hasSideEffectSupport = supports;
-    return supports;
+    this._hasSideEffectSupport = SDK.RuntimeModel.isSideEffectFailure(response);
+    return this._hasSideEffectSupport;
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js b/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
index 2e097049..7065379 100644
--- a/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
+++ b/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
@@ -40,10 +40,6 @@
     this._uiSourceCode = uiSourceCode;
     this._transformer = transformer;
 
-    /** @type {?Element} */
-    this._conditionEditorElement = null;
-    /** @type {?Element} */
-    this._conditionElement = null;
     /** @type {?Workspace.UILocation} */
     this._executionLocation = null;
     this._controlDown = false;
@@ -646,39 +642,7 @@
    * @param {?Bindings.BreakpointManager.Breakpoint} breakpoint
    * @param {?{lineNumber: number, columnNumber: number}} location
    */
-  _editBreakpointCondition(editorLineNumber, breakpoint, location) {
-    this._conditionElement = this._createConditionElement(editorLineNumber);
-    this._textEditor.addDecoration(this._conditionElement, editorLineNumber);
-
-    /**
-     * @this {Sources.DebuggerPlugin}
-     */
-    function finishEditing(committed, element, newText) {
-      this._textEditor.removeDecoration(/** @type {!Element} */ (this._conditionElement), editorLineNumber);
-      this._conditionEditorElement = null;
-      this._conditionElement = null;
-      if (!committed)
-        return;
-
-      if (breakpoint)
-        breakpoint.setCondition(newText);
-      else if (location)
-        this._setBreakpoint(location.lineNumber, location.columnNumber, newText, true);
-      else
-        this._createNewBreakpoint(editorLineNumber, newText, true);
-    }
-
-    const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));
-    UI.InplaceEditor.startEditing(/** @type {!Element} */ (this._conditionEditorElement), config);
-    this._conditionEditorElement.value = breakpoint ? breakpoint.condition() : '';
-    this._conditionEditorElement.select();
-  }
-
-  /**
-   * @param {number} editorLineNumber
-   * @return {!Element}
-   */
-  _createConditionElement(editorLineNumber) {
+  async _editBreakpointCondition(editorLineNumber, breakpoint, location) {
     const conditionElement = createElementWithClass('div', 'source-frame-breakpoint-condition');
 
     const labelElement = conditionElement.createChild('label', 'source-frame-breakpoint-message');
@@ -686,12 +650,58 @@
     labelElement.createTextChild(
         Common.UIString('The breakpoint on line %d will stop only if this expression is true:', editorLineNumber + 1));
 
-    const editorElement = UI.createInput('monospace', 'text');
-    conditionElement.appendChild(editorElement);
-    editorElement.id = 'source-frame-breakpoint-condition';
-    this._conditionEditorElement = editorElement;
 
-    return conditionElement;
+    this._textEditor.addDecoration(conditionElement, editorLineNumber);
+
+    /** @type {!UI.TextEditorFactory} */
+    const factory = await self.runtime.extension(UI.TextEditorFactory).instance();
+    const editor =
+        factory.createEditor({lineNumbers: false, lineWrapping: true, mimeType: 'javascript', autoHeight: true});
+    editor.widget().show(conditionElement);
+    if (breakpoint)
+      editor.setText(breakpoint.condition());
+    editor.setSelection(editor.fullRange());
+    editor.configureAutocomplete(ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(editor));
+    editor.widget().element.addEventListener('keydown', async event => {
+      if (isEnterKey(event) && !event.shiftKey) {
+        event.consume(true);
+        if (event.ctrlKey)
+
+          event.consume(true);
+        const expression = editor.text();
+        if (event.ctrlKey || await ObjectUI.JavaScriptAutocomplete.isExpressionComplete(expression))
+          finishEditing.call(this, true);
+        else
+          editor.newlineAndIndent();
+      }
+      if (isEscKey(event))
+        finishEditing.call(this, false);
+    }, true);
+    editor.widget().focus();
+    editor.widget().element.id = 'source-frame-breakpoint-condition';
+    editor.widget().element.addEventListener('blur', event => {
+      finishEditing.call(this, true);
+    }, true);
+    let finished = false;
+    /**
+     * @this {Sources.DebuggerPlugin}
+     */
+    function finishEditing(committed) {
+      if (finished)
+        return;
+      finished = true;
+      editor.widget().detach();
+      this._textEditor.removeDecoration(/** @type {!Element} */ (conditionElement), editorLineNumber);
+      if (!committed)
+        return;
+
+      if (breakpoint)
+        breakpoint.setCondition(editor.text().trim());
+      else if (location)
+        this._setBreakpoint(location.lineNumber, location.columnNumber, editor.text().trim(), true);
+      else
+        this._createNewBreakpoint(editorLineNumber, editor.text().trim(), true);
+    }
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/sources/sourcesView.css b/third_party/blink/renderer/devtools/front_end/sources/sourcesView.css
index 6b27b3e..42b8ab2 100644
--- a/third_party/blink/renderer/devtools/front_end/sources/sourcesView.css
+++ b/third_party/blink/renderer/devtools/front_end/sources/sourcesView.css
@@ -85,6 +85,7 @@
     width: 100%;
     box-shadow: none !important;
     outline: none !important;
+    background: white;
 }
 
 @-webkit-keyframes source-frame-value-update-highlight-animation {
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
index 2b6ef3b..6010077 100644
--- a/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
+++ b/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -74,7 +74,7 @@
       'Delete': 'delCharAfter',
       'Backspace': 'delCharBefore',
       'Tab': 'defaultTab',
-      'Shift-Tab': 'indentLess',
+      'Shift-Tab': 'indentLessOrPass',
       'Enter': 'newlineAndIndent',
       'Ctrl-Space': 'autocomplete',
       'Esc': 'dismiss',
@@ -1326,6 +1326,20 @@
 
 /**
  * @param {!CodeMirror} codeMirror
+ * @return {!Object|undefined}
+ */
+CodeMirror.commands.indentLessOrPass = function(codeMirror) {
+  const selections = codeMirror.listSelections();
+  if (selections.length === 1) {
+    const range = TextEditor.CodeMirrorUtils.toRange(selections[0].anchor, selections[0].head);
+    if (range.isEmpty() && !/^\s/.test(codeMirror.getLine(range.startLine)))
+      return CodeMirror.Pass;
+  }
+  codeMirror.execCommand('indentLess');
+};
+
+/**
+ * @param {!CodeMirror} codeMirror
  */
 CodeMirror.commands.gotoMatchingBracket = function(codeMirror) {
   const updatedSelections = [];
@@ -1371,6 +1385,7 @@
 };
 
 /**
+ * @param {!CodeMirror} codemirror
  * @return {!Object|undefined}
  */
 CodeMirror.commands.dismiss = function(codemirror) {
@@ -1389,6 +1404,7 @@
 };
 
 /**
+ * @param {!CodeMirror} codemirror
  * @return {!Object|undefined}
  */
 CodeMirror.commands.goSmartPageUp = function(codemirror) {
@@ -1398,6 +1414,7 @@
 };
 
 /**
+ * @param {!CodeMirror} codemirror
  * @return {!Object|undefined}
  */
 CodeMirror.commands.goSmartPageDown = function(codemirror) {
diff --git a/third_party/blink/renderer/modules/websockets/BUILD.gn b/third_party/blink/renderer/modules/websockets/BUILD.gn
index cc34a49d..b7a03c2 100644
--- a/third_party/blink/renderer/modules/websockets/BUILD.gn
+++ b/third_party/blink/renderer/modules/websockets/BUILD.gn
@@ -15,7 +15,6 @@
     "web_pepper_socket_channel_client_proxy.h",
     "web_pepper_socket_impl.cc",
     "web_pepper_socket_impl.h",
-    "websocket_channel.cc",
     "websocket_channel.h",
     "websocket_channel_client.h",
     "websocket_channel_impl.cc",
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.h b/third_party/blink/renderer/modules/websockets/dom_websocket.h
index 8a29012..48810310 100644
--- a/third_party/blink/renderer/modules/websockets/dom_websocket.h
+++ b/third_party/blink/renderer/modules/websockets/dom_websocket.h
@@ -43,6 +43,7 @@
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/modules/websockets/websocket_channel.h"
 #include "third_party/blink/renderer/modules/websockets/websocket_channel_client.h"
+#include "third_party/blink/renderer/modules/websockets/websocket_channel_impl.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/timer.h"
@@ -208,10 +209,10 @@
   enum BinaryType { kBinaryTypeBlob, kBinaryTypeArrayBuffer };
 
   // This function is virtual for unittests.
-  // FIXME: Move WebSocketChannel::create here.
   virtual WebSocketChannel* CreateChannel(ExecutionContext* context,
                                           WebSocketChannelClient* client) {
-    return WebSocketChannel::Create(context, client);
+    return WebSocketChannelImpl::Create(context, client,
+                                        SourceLocation::Capture(context));
   }
 
   // Adds a console message with JSMessageSource and ErrorMessageLevel.
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel.cc b/third_party/blink/renderer/modules/websockets/websocket_channel.cc
deleted file mode 100644
index 6dfdbb54b..0000000
--- a/third_party/blink/renderer/modules/websockets/websocket_channel.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2009, 2012 Google Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/websockets/websocket_channel.h"
-
-#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/websockets/websocket_channel_client.h"
-#include "third_party/blink/renderer/modules/websockets/websocket_channel_impl.h"
-
-namespace blink {
-
-WebSocketChannel* WebSocketChannel::Create(ExecutionContext* context,
-                                           WebSocketChannelClient* client) {
-  DCHECK(context);
-  DCHECK(client);
-  return WebSocketChannelImpl::Create(context, client,
-                                      SourceLocation::Capture(context));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel.h b/third_party/blink/renderer/modules/websockets/websocket_channel.h
index 70672cc..aa300aa4 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel.h
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel.h
@@ -44,13 +44,11 @@
 class BlobDataHandle;
 class DOMArrayBuffer;
 class KURL;
-class WebSocketChannelClient;
 
 class MODULES_EXPORT WebSocketChannel
     : public GarbageCollectedFinalized<WebSocketChannel> {
  public:
   WebSocketChannel() = default;
-  static WebSocketChannel* Create(ExecutionContext*, WebSocketChannelClient*);
 
   enum CloseEventCode {
     kCloseEventCodeNotSpecified = -1,
@@ -77,15 +75,13 @@
                     unsigned byte_offset,
                     unsigned byte_length) = 0;
   virtual void Send(scoped_refptr<BlobDataHandle>) = 0;
-
-  // For WorkerWebSocketChannel.
   virtual void SendTextAsCharVector(std::unique_ptr<Vector<char>>) = 0;
   virtual void SendBinaryAsCharVector(std::unique_ptr<Vector<char>>) = 0;
 
-  // Do not call |send| after calling this method.
+  // Do not call |Send| after calling this method.
   virtual void Close(int code, const String& reason) = 0;
 
-  // Log the reason text and close the connection. Will call didClose().
+  // Log the reason text and close the connection. Will call DidClose().
   // The MessageLevel parameter will be used for the level of the message
   // shown at the devtools console.
   // SourceLocation parameter may be shown with the reason text
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
index 5d4767e..d2d23606 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
@@ -55,12 +55,12 @@
 
 namespace blink {
 
+class WebSocketChannelClient;
 class WebSocketHandshakeThrottle;
 
 // This is an implementation of WebSocketChannel. This is created on the main
 // thread for Document, or on the worker thread for WorkerGlobalScope. All
 // functions must be called on the execution context's thread.
-// TODO(nhiroki): Merge this class into WebSocketChannel.
 class MODULES_EXPORT WebSocketChannelImpl final
     : public WebSocketChannel,
       public WebSocketHandleClient,
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 7658bd05..6d6cbae 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -180,7 +180,9 @@
       sampler_color_space_(color_params.GetSamplerGfxColorSpace()),
       use_half_float_storage_(color_params.PixelFormat() ==
                               kF16CanvasPixelFormat),
-      chromium_image_usage_(chromium_image_usage) {
+      chromium_image_usage_(chromium_image_usage),
+      opengl_flip_y_extension_(
+          ContextProvider()->GetCapabilities().mesa_framebuffer_flip_y) {
   // Used by browser tests to detect the use of a DrawingBuffer.
   TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation",
                        TRACE_EVENT_SCOPE_GLOBAL);
@@ -804,10 +806,15 @@
   state_restorer_->SetFramebufferBindingDirty();
   gl_->GenFramebuffers(1, &fbo_);
   gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+  if (opengl_flip_y_extension_)
+    gl_->FramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
+
   if (WantExplicitResolve()) {
     gl_->GenFramebuffers(1, &multisample_fbo_);
     gl_->BindFramebuffer(GL_FRAMEBUFFER, multisample_fbo_);
     gl_->GenRenderbuffers(1, &multisample_renderbuffer_);
+    if (opengl_flip_y_extension_)
+      gl_->FramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
   }
   if (!ResizeFramebufferInternal(size)) {
     DLOG(ERROR) << "Initialization failed to allocate backbuffer.";
@@ -926,6 +933,9 @@
                                   premultiplied_alpha_false_texture_);
     layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality);
 
+    if (opengl_flip_y_extension_)
+      layer_->SetFlipped(false);
+
     GraphicsLayer::RegisterContentsLayer(layer_.get());
   }
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
index f65927d..1170261 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -591,6 +591,8 @@
   ChromiumImageUsage chromium_image_usage_;
   bool ShouldUseChromiumImage();
 
+  bool opengl_flip_y_extension_;
+
   // A release callback that is run when the previouis image passed to
   // OffscreenCanvas::Commit() is no longer needed.
   std::unique_ptr<viz::SingleReleaseCallback> previous_image_release_callback_;
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h
index f675e99..7917887 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -245,9 +245,9 @@
 
   void AddLinkHighlight(LinkHighlight*);
   void RemoveLinkHighlight(LinkHighlight*);
-  // Exposed for tests
-  unsigned NumLinkHighlights() { return link_highlights_.size(); }
-  LinkHighlight* GetLinkHighlight(int i) { return link_highlights_[i]; }
+  const Vector<LinkHighlight*>& GetLinkHighlights() const {
+    return link_highlights_;
+  }
 
   int GetRenderingContext3D() const { return rendering_context3d_; }
 
diff --git a/third_party/blink/renderer/platform/graphics/link_highlight.h b/third_party/blink/renderer/platform/graphics/link_highlight.h
index b352afe5..4044ad95 100644
--- a/third_party/blink/renderer/platform/graphics/link_highlight.h
+++ b/third_party/blink/renderer/platform/graphics/link_highlight.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_LINK_HIGHLIGHT_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_LINK_HIGHLIGHT_H_
 
+#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 
 namespace cc {
@@ -13,14 +14,21 @@
 
 namespace blink {
 
-class PLATFORM_EXPORT LinkHighlight {
+class EffectPaintPropertyNode;
+
+class PLATFORM_EXPORT LinkHighlight : public DisplayItemClient {
  public:
+  ~LinkHighlight() override {}
+
   virtual void Invalidate() = 0;
   virtual void ClearCurrentGraphicsLayer() = 0;
   virtual cc::Layer* Layer() = 0;
 
- protected:
-  virtual ~LinkHighlight() = default;
+  virtual const EffectPaintPropertyNode* effect() = 0;
+
+  // DisplayItemClient methods
+  String DebugName() const final { return "LinkHighlight"; }
+  LayoutRect VisualRect() const final { return LayoutRect(); }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
index 307b7b6d..5f5984a 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -128,6 +128,7 @@
     DEBUG_STRING_CASE(ForeignLayerVideo);
     DEBUG_STRING_CASE(ForeignLayerWrapper);
     DEBUG_STRING_CASE(ForeignLayerContentsWrapper);
+    DEBUG_STRING_CASE(ForeignLayerLinkHighlight);
     DEFAULT_CASE;
   }
 }
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.h b/third_party/blink/renderer/platform/graphics/paint/display_item.h
index be66524..9965d5f 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -116,7 +116,8 @@
     kForeignLayerVideo,
     kForeignLayerWrapper,
     kForeignLayerContentsWrapper,
-    kForeignLayerLast = kForeignLayerContentsWrapper,
+    kForeignLayerLinkHighlight,
+    kForeignLayerLast = kForeignLayerLinkHighlight,
 
     kClipPaintPhaseFirst,
     kClipPaintPhaseLast = kClipPaintPhaseFirst + kPaintPhaseMax,
diff --git a/third_party/blink/renderer/platform/heap/heap_compact.cc b/third_party/blink/renderer/platform/heap/heap_compact.cc
index 4594fbfd..f9309e1 100644
--- a/third_party/blink/renderer/platform/heap/heap_compact.cc
+++ b/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -13,7 +13,6 @@
 #include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/time.h"
 
 namespace blink {
@@ -357,7 +356,7 @@
   if (!do_compact_)
     return;
 
-  Fixups().Add(slot);
+  traced_slots_.insert(slot);
 }
 
 void HeapCompact::RegisterMovingObjectCallback(MovableReference reference,
@@ -422,6 +421,13 @@
 void HeapCompact::StartThreadCompaction() {
   if (!do_compact_)
     return;
+
+  DCHECK(fixups_);
+  // The mapping between the slots and the backing stores are created
+  for (auto** slot : traced_slots_) {
+    fixups_->Add(slot);
+  }
+  traced_slots_.clear();
 }
 
 void HeapCompact::FinishThreadCompaction() {
diff --git a/third_party/blink/renderer/platform/heap/heap_compact.h b/third_party/blink/renderer/platform/heap/heap_compact.h
index dc32e77b..b11f12e0 100644
--- a/third_party/blink/renderer/platform/heap/heap_compact.h
+++ b/third_party/blink/renderer/platform/heap/heap_compact.h
@@ -10,6 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "third_party/blink/renderer/platform/heap/blink_gc.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
 
 #include <bitset>
@@ -164,6 +165,11 @@
   // the range of BlinkGC::ArenaIndices.
   unsigned compactable_arenas_;
 
+  // The set is to remember slots traced during the incremental and atomic
+  // marking phases. The mapping between the slots and the backing stores are
+  // created at the atomic pause phase.
+  HashSet<MovableReference*> traced_slots_;
+
   static bool force_compaction_gc_;
 };
 
diff --git a/third_party/blink/renderer/platform/loader/cors/cors.cc b/third_party/blink/renderer/platform/loader/cors/cors.cc
index 07a5246..38ad08b 100644
--- a/third_party/blink/renderer/platform/loader/cors/cors.cc
+++ b/third_party/blink/renderer/platform/loader/cors/cors.cc
@@ -146,6 +146,7 @@
   DCHECK(error_description);
 
   base::Optional<network::mojom::CORSError> error;
+  base::Optional<network::CORSErrorStatus> status;
 
   std::unique_ptr<network::cors::PreflightResult> result =
       network::cors::PreflightResult::Create(
@@ -164,23 +165,22 @@
     return false;
   }
 
-  error = result->EnsureAllowedCrossOriginMethod(
+  status = result->EnsureAllowedCrossOriginMethod(
       std::string(request_method.Ascii().data()));
-  if (error) {
+  if (status) {
     *error_description = CORS::GetErrorString(
-        CORS::ErrorParameter::CreateForPreflightResponseCheck(*error,
-                                                              request_method));
+        CORS::ErrorParameter::CreateForPreflightResponseCheck(
+            status->cors_error, request_method));
     return false;
   }
 
-  std::string detected_error_header;
-  error = result->EnsureAllowedCrossOriginHeaders(
-      *CreateNetHttpRequestHeaders(request_header_map), &detected_error_header);
-  if (error) {
+  status = result->EnsureAllowedCrossOriginHeaders(
+      *CreateNetHttpRequestHeaders(request_header_map));
+  if (status) {
     *error_description = CORS::GetErrorString(
         CORS::ErrorParameter::CreateForPreflightResponseCheck(
-            *error, String(detected_error_header.data(),
-                           detected_error_header.length())));
+            status->cors_error, String(status->failed_parameter.data(),
+                                       status->failed_parameter.length())));
     return false;
   }
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index 1b713826..69128b6 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -184,7 +184,6 @@
       const KURL&,
       const ResourceLoaderOptions&,
       SecurityViolationReportingPolicy,
-      FetchParameters::OriginRestriction,
       ResourceRequest::RedirectStatus) const {
     return ResourceRequestBlockedReason::kOther;
   }
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
index 970713f..49c1954 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -38,7 +38,6 @@
       decoder_options_(TextResourceDecoderOptions::kPlainTextContent),
       speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
       defer_(kNoDefer),
-      origin_restriction_(kUseDefaultOriginRestrictionForType),
       placeholder_image_request_type_(kDisallowPlaceholder) {}
 
 FetchParameters::FetchParameters(
@@ -48,7 +47,6 @@
       options_(data->options),
       speculative_preload_type_(data->speculative_preload_type),
       defer_(data->defer),
-      origin_restriction_(data->origin_restriction),
       resource_width_(data->resource_width),
       client_hint_preferences_(data->client_hint_preferences),
       placeholder_image_request_type_(data->placeholder_image_request_type) {}
@@ -60,7 +58,6 @@
       options_(options),
       speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
       defer_(kNoDefer),
-      origin_restriction_(kUseDefaultOriginRestrictionForType),
       placeholder_image_request_type_(kDisallowPlaceholder) {}
 
 FetchParameters::~FetchParameters() = default;
@@ -158,7 +155,6 @@
   data->options = CrossThreadResourceLoaderOptionsData(options_);
   data->speculative_preload_type = speculative_preload_type_;
   data->defer = defer_;
-  data->origin_restriction = origin_restriction_;
   data->resource_width = resource_width_;
   data->client_hint_preferences = client_hint_preferences_;
   data->placeholder_image_request_type = placeholder_image_request_type_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index 5e41c90..336a502 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -61,11 +61,6 @@
     kInDocument,  // The request was discovered in the main document
     kInserted     // The request was discovered in a document.write()
   };
-  enum OriginRestriction {
-    kUseDefaultOriginRestrictionForType,
-    kRestrictToSameOrigin,
-    kNoOriginRestriction
-  };
   enum PlaceholderImageRequestType {
     kDisallowPlaceholder = 0,  // The requested image must not be a placeholder.
     kAllowPlaceholder,         // The image is allowed to be a placeholder.
@@ -156,10 +151,6 @@
   // credentials mode.
   void SetCrossOriginAccessControl(const SecurityOrigin*,
                                    network::mojom::FetchCredentialsMode);
-  OriginRestriction GetOriginRestriction() const { return origin_restriction_; }
-  void SetOriginRestriction(OriginRestriction restriction) {
-    origin_restriction_ = restriction;
-  }
   const IntegrityMetadataSet IntegrityMetadata() const {
     return options_.integrity_metadata;
   }
@@ -207,7 +198,6 @@
   ResourceLoaderOptions options_;
   SpeculativePreloadType speculative_preload_type_;
   DeferOption defer_;
-  OriginRestriction origin_restriction_;
   ResourceWidth resource_width_;
   ClientHintsPreferences client_hint_preferences_;
   PlaceholderImageRequestType placeholder_image_request_type_;
@@ -236,7 +226,6 @@
   CrossThreadResourceLoaderOptionsData options;
   FetchParameters::SpeculativePreloadType speculative_preload_type;
   FetchParameters::DeferOption defer;
-  FetchParameters::OriginRestriction origin_restriction;
   FetchParameters::ResourceWidth resource_width;
   ClientHintsPreferences client_hint_preferences;
   FetchParameters::PlaceholderImageRequestType placeholder_image_request_type;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index dd3ff0f..a3a04d9 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -713,7 +713,7 @@
   KURL url = MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url());
   base::Optional<ResourceRequestBlockedReason> blocked_reason =
       Context().CanRequest(resource_type, resource_request, url, options,
-                           reporting_policy, params.GetOriginRestriction(),
+                           reporting_policy,
                            resource_request.GetRedirectStatus());
 
   if (Context().IsAdResource(url, resource_type,
@@ -1760,7 +1760,6 @@
   Context().CanRequest(resource->GetType(), resource->LastResourceRequest(),
                        resource->LastResourceRequest().Url(), params.Options(),
                        SecurityViolationReportingPolicy::kReport,
-                       params.GetOriginRestriction(),
                        resource->LastResourceRequest().GetRedirectStatus());
   RequestLoadStarted(resource->Identifier(), resource, params, kUse);
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index 40c3acbf..8911e7f7 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -305,7 +305,6 @@
     base::Optional<ResourceRequestBlockedReason> blocked_reason =
         Context().CanRequest(
             resource_type, *new_request, new_url, options, reporting_policy,
-            FetchParameters::kUseDefaultOriginRestrictionForType,
             ResourceRequest::RedirectStatus::kFollowedRedirect);
 
     if (Context().IsAdResource(new_url, resource_type,
@@ -601,7 +600,6 @@
           Context().CanRequest(
               resource_type, initial_request, original_url, options,
               SecurityViolationReportingPolicy::kReport,
-              FetchParameters::kUseDefaultOriginRestrictionForType,
               ResourceRequest::RedirectStatus::kFollowedRedirect);
       if (blocked_reason) {
         HandleError(ResourceError::CancelledDueToAccessCheckError(
diff --git a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
index a2e6067e..925d16a 100644
--- a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -74,7 +74,6 @@
       const KURL&,
       const ResourceLoaderOptions&,
       SecurityViolationReportingPolicy,
-      FetchParameters::OriginRestriction,
       ResourceRequest::RedirectStatus redirect_status) const override {
     return base::nullopt;
   }
diff --git a/third_party/libjingle_xmpp/xmpp/saslmechanism.cc b/third_party/libjingle_xmpp/xmpp/saslmechanism.cc
index e9348c92..1e91e35 100644
--- a/third_party/libjingle_xmpp/xmpp/saslmechanism.cc
+++ b/third_party/libjingle_xmpp/xmpp/saslmechanism.cc
@@ -11,7 +11,7 @@
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 #include "third_party/libjingle_xmpp/xmpp/constants.h"
 #include "third_party/libjingle_xmpp/xmpp/saslmechanism.h"
-#include "third_party/webrtc/rtc_base/base64.h"
+#include "third_party/webrtc/rtc_base/third_party/base64/base64.h"
 
 using rtc::Base64;
 
diff --git a/third_party/libjingle_xmpp/xmpp/xmpplogintask.cc b/third_party/libjingle_xmpp/xmpp/xmpplogintask.cc
index ff0ff96..9f8021a 100644
--- a/third_party/libjingle_xmpp/xmpp/xmpplogintask.cc
+++ b/third_party/libjingle_xmpp/xmpp/xmpplogintask.cc
@@ -18,7 +18,7 @@
 #include "third_party/libjingle_xmpp/xmpp/jid.h"
 #include "third_party/libjingle_xmpp/xmpp/saslmechanism.h"
 #include "third_party/libjingle_xmpp/xmpp/xmppengineimpl.h"
-#include "third_party/webrtc/rtc_base/base64.h"
+#include "third_party/webrtc/rtc_base/third_party/base64/base64.h"
 
 using rtc::ConstantLabel;
 
diff --git a/third_party/sqlite/BUILD.gn b/third_party/sqlite/BUILD.gn
index 8b9d383..6de49a44 100644
--- a/third_party/sqlite/BUILD.gn
+++ b/third_party/sqlite/BUILD.gn
@@ -23,10 +23,20 @@
     # New unicode61 tokenizer with built-in tables.
     "SQLITE_DISABLE_FTS3_UNICODE",
 
-    # Chromium currently does not enable fts4, disable extra code.
+    # Chrome does not enable fts4, disable extra code.
     "SQLITE_DISABLE_FTS4_DEFERRED",
     "SQLITE_ENABLE_ICU",
+
+    # Enables memory tracking needed to release unused memory.
+    #
+    # Needed for sqlite3_release_memory() and its variants to work. Without this
+    # option, the interfaces exist, but the methods are no-ops.
     "SQLITE_ENABLE_MEMORY_MANAGEMENT",
+
+    # Defaults the secure_delete pragma to 1.
+    #
+    # This causes SQLite to overwrite all deleted information with zeroes,
+    # trading additional I/O for better privacy guarantees.
     "SQLITE_SECURE_DELETE",
 
     # Custom flag to tweak pcache pools.
@@ -34,13 +44,13 @@
     "SQLITE_SEPARATE_CACHE_POOLS",
 
     # TODO(pwnall): SQLite adds mutexes to protect structures which cross
-    # threads. In theory Chromium should be able to turn this to "2" which
+    # threads. In theory Chrome should be able to turn this to "2" which
     # should give a slight speed boost. "2" is safe as long as a single
     # connection is not used by more than one thread at a time.
     "SQLITE_THREADSAFE=1",
 
     # SQLite can spawn threads to sort in parallel if configured
-    # appropriately.  Chromium doesn't configure SQLite for that, and would
+    # appropriately.  Chrome doesn't configure SQLite for that, and would
     # prefer to control distribution to worker threads.
     "SQLITE_MAX_WORKER_THREADS=0",
 
@@ -56,6 +66,17 @@
     # TODO(pwnall): Upstream the ability to use this define.
     "SQLITE_MMAP_READ_ONLY=1",
 
+    # The default POSIX permissions for a newly created SQLite database.
+    #
+    # If unspecified, this defaults to 0644. All the data stored by Chrome is
+    # private, so our databases use stricter settings.
+    "SQLITE_DEFAULT_FILE_PERMISSIONS=0600",
+
+    # SQLite uses a lookaside buffer to improve performance of small mallocs.
+    # Chrome already depends on small mallocs being efficient, so we disable
+    # this to avoid the extra memory overhead.
+    "SQLITE_DEFAULT_LOOKASIDE=0,0",
+
     # Needed by the SQL MemoryDumpProvider.
     #
     # Setting this to 1 is needed to collect the information reported by
@@ -64,7 +85,7 @@
     "SQLITE_DEFAULT_MEMSTATUS=1",
 
     # By default SQLite pre-allocates 100 pages of pcache data, which will not
-    # be released until the handle is closed.  This is contrary to Chromium's
+    # be released until the handle is closed.  This is contrary to Chrome's
     # memory-usage goals.
     "SQLITE_DEFAULT_PCACHE_INITSZ=0",
 
@@ -78,19 +99,23 @@
     #   src/tool/mkkeywordhash.c
 
     # The flags below are recommended in the SQLite documentation, and disable
-    # features Chromium doesn't use.
+    # features Chrome doesn't use.
     "SQLITE_LIKE_DOESNT_MATCH_BLOBS",
     "SQLITE_OMIT_DEPRECATED",
     "SQLITE_OMIT_PROGRESS_CALLBACK",
     "SQLITE_OMIT_SHARED_CACHE",
     "SQLITE_USE_ALLOCA",
 
-    # Chromium initializes SQLite manually in //sql/connection.cc.
+    # Chrome initializes SQLite manually in //sql/connection.cc.
     "SQLITE_OMIT_AUTOINIT",
 
-    # Chromium calls sqlite3_reset() correctly to reset prepared statements.
+    # Chrome calls sqlite3_reset() correctly to reset prepared statements.
     "SQLITE_OMIT_AUTORESET",
 
+    # Chromium does not use sqlite3_{get,free}_table().
+    # Chrome doesn't use sqlite3_compileoption_{used,get}().
+    "SQLITE_OMIT_COMPILEOPTION_DIAGS",
+
     # Chrome doesn't ship the SQLite shell, so command auto-completion is not
     # needed. Chrome developers who build the SQLite shell living at
     # //third_party/sqlite:sqlite_shell for diagnostic purposes will have to
@@ -100,20 +125,20 @@
     # Chrome does not use sqlite3_column_decltype().
     "SQLITE_OMIT_DECLTYPE",
 
-    # Chromium does not use sqlite3_{get,free}_table().
+    # Chrome does not use sqlite3_{get,free}_table().
     "SQLITE_OMIT_GET_TABLE",
 
-    # Chromium does not use sqlite3_{enable_}load_extension().
+    # Chrome does not use sqlite3_{enable_}load_extension().
     # Asides from giving us fairly minor code savings, this option disables code
     # that breaks our method for renaming SQLite's exported symbols. Last,
     # there's a tiny security benefit to knowing that WebSQL can't possibly
     # reach extension loading code.
     "SQLITE_OMIT_LOAD_EXTENSION",
 
-    # Chromium doesn't use TCL variables.
+    # Chrome doesn't use TCL variables.
     "SQLITE_OMIT_TCL_VARIABLE",
 
-    # Chromium doesn't use sqlite3_{profile,trace}().
+    # Chrome doesn't use sqlite3_{profile,trace}().
     "SQLITE_OMIT_TRACE",
 
     # Uses isnan() in the C99 standard library.
@@ -136,7 +161,7 @@
   }
 
   if (using_sanitizer) {
-    # Limit max length of data blobs and queries for fuzzing builds by 128 MB.
+    # Limit max length of data blobs and queries to 128 MB for fuzzing builds.
     defines += [
       "SQLITE_MAX_LENGTH=128000000",
       "SQLITE_MAX_SQL_LENGTH=128000000",
@@ -165,7 +190,7 @@
   cflags = []
   if (is_clang) {
     # sqlite contains a few functions that are unused, at least on
-    # Windows with Chromium's sqlite patches applied
+    # Windows with Chrome's sqlite patches applied
     # (interiorCursorEOF fts3EvalDeferredPhrase
     # fts3EvalSelectDeferred sqlite3Fts3InitHashTable
     # sqlite3Fts3InitTok).
@@ -205,22 +230,21 @@
   ]
 
   sources = [
-    "amalgamation/config.h",
-    "amalgamation/sqlite3.c",
     "amalgamation/sqlite3.h",
+    "sqlite3_shim.c",
     "src/src/recover.c",
     "src/src/recover_varint.c",
   ]
 
-  cflags = []
-  defines = [
-    # The generated sqlite3.c does not include sqlite3.h, so we cannot easily
-    # inject the renaming macros in amalgamation/export_renames.h. However,
-    # if the macro below is defined, sqlite3.c will #include "config.h", which
-    # can be used to inject the macros.
-    "_HAVE_SQLITE_CONFIG_H",
+  inputs = [
+    # This file is #included into sqlite3_shim.c, which injects Chrome-specific
+    # definitions into the SQLite amalgamation code.
+    "amalgamation/sqlite3.c",
   ]
 
+  cflags = []
+  defines = []
+
   if (is_component_build) {
     if (is_win) {
       defines += [ "SQLITE_API=__declspec(dllexport)" ]
diff --git a/third_party/sqlite/amalgamation/config.h b/third_party/sqlite/sqlite3_shim.c
similarity index 86%
rename from third_party/sqlite/amalgamation/config.h
rename to third_party/sqlite/sqlite3_shim.c
index 652a13e..2c03175 100644
--- a/third_party/sqlite/amalgamation/config.h
+++ b/third_party/sqlite/sqlite3_shim.c
@@ -2,10 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_SQLITE_AMALGAMATION_CONFIG_H_
-#define THIRD_PARTY_SQLITE_AMALGAMATION_CONFIG_H_
-
-// This file is included by sqlite3.c fairly early.
+// This is a shim that injects Chrome-specific defitions into sqlite3.c
+// BUILD.gn uses this instead of building the sqlite3 amalgamation directly.
 
 // We prefix chrome_ to SQLite's exported symbols, so that we don't clash with
 // other SQLite libraries loaded by the system libraries. This only matters when
@@ -38,4 +36,4 @@
 
 #endif  // defined(__linux__)
 
-#endif  // THIRD_PARTY_SQLITE_AMALGAMATION_CONFIG_H_
+#include "third_party/sqlite/amalgamation/sqlite3.c"
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 7561508..e5d3cefc4 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -19733,6 +19733,7 @@
       label="For DownloadPageScreenshot feature."/>
   <suffix name="HomePageButton" label="For HomePageButton feature."/>
   <suffix name="IncognitoWindow" label="For IncognitoWindow feature."/>
+  <suffix name="LongPressToolbarTip" label="For LongPressToolbar feature."/>
   <suffix name="MediaDownload" label="For MediaDownload feature."/>
   <suffix name="NewIncognitoTabTip" label="For NewIncognitoTabTip feature."/>
   <suffix name="NewTab" label="For NewTab feature."/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e1270fd..b1d326c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -119119,6 +119119,8 @@
       label="In product help to access download settings from download home."/>
   <suffix name="IPH_HomePageButton" label="In product help home page button."/>
   <suffix name="IPH_IncognitoWindow" label="In product help incognito window."/>
+  <suffix name="IPH_LongPressToolbarTip"
+      label="In product help LongPress toolbar."/>
   <suffix name="IPH_MediaDownload" label="In product help media download."/>
   <suffix name="IPH_NewIncognitoTabTip"
       label="In product help new incognito tab tip."/>
diff --git a/tools/perf/page_sets/data/rendering_mobile.json b/tools/perf/page_sets/data/rendering_mobile.json
index c83c3a8..10e8661 100644
--- a/tools/perf/page_sets/data/rendering_mobile.json
+++ b/tools/perf/page_sets/data/rendering_mobile.json
@@ -927,18 +927,30 @@
 	"microsoft_performance": {
             "DEFAULT": "tough_animation_cases_000.wprgo"
         },
-	"nytimes_scroll": {
-            "DEFAULT": "simple_mobile_sites_002.wprgo"
-        },
         "ebay_scroll": {
             "DEFAULT": "simple_mobile_sites_002.wprgo"
         },
+        "ebay_scroll_2018": {
+            "DEFAULT": "simple_mobile_sites_003.wprgo"
+        },
+        "flickr_scroll": {
+            "DEFAULT": "simple_mobile_sites_002.wprgo"
+        },
+        "flickr_scroll_2018": {
+            "DEFAULT": "simple_mobile_sites_003.wprgo"
+        },
         "nyc_gov_scroll": {
             "DEFAULT": "simple_mobile_sites_002.wprgo"
         },
-        "flickr_scroll": {
+        "nyc_gov_scroll_2018": {
+            "DEFAULT": "simple_mobile_sites_003.wprgo"
+        },
+        "nytimes_scroll": {
             "DEFAULT": "simple_mobile_sites_002.wprgo"
-	},
+        },
+        "nytimes_scroll_2018": {
+            "DEFAULT": "simple_mobile_sites_003.wprgo"
+        },
 	"aquarium_20k": {
             "DEFAULT": "tough_webgl_cases_006.wprgo"
         },
diff --git a/tools/perf/page_sets/data/simple_mobile_sites_003.wprgo.sha1 b/tools/perf/page_sets/data/simple_mobile_sites_003.wprgo.sha1
new file mode 100644
index 0000000..76f1e19
--- /dev/null
+++ b/tools/perf/page_sets/data/simple_mobile_sites_003.wprgo.sha1
@@ -0,0 +1 @@
+065b9689c56910180fe8518346451562b8fc6dda
\ No newline at end of file
diff --git a/tools/perf/page_sets/rendering/simple_mobile_sites.py b/tools/perf/page_sets/rendering/simple_mobile_sites.py
index ab4e31e2..89091ca5 100644
--- a/tools/perf/page_sets/rendering/simple_mobile_sites.py
+++ b/tools/perf/page_sets/rendering/simple_mobile_sites.py
@@ -41,16 +41,40 @@
   URL = 'http://www.ebay.co.uk/'
 
 
+class SimpleEbay2018Page(SimplePage):
+  BASE_NAME = 'ebay_scroll'
+  YEAR = '2018'
+  URL = 'http://www.ebay.co.uk/'
+
+
 class SimpleFlickrPage(SimplePage):
   BASE_NAME = 'flickr_scroll'
   URL = 'https://www.flickr.com/'
 
 
+class SimpleFlickr2018Page(SimplePage):
+  BASE_NAME = 'flickr_scroll'
+  YEAR = '2018'
+  URL = 'https://www.flickr.com/photos/flickr/albums/72157639858715274'
+
+
 class SimpleNYCGovPage(SimplePage):
   BASE_NAME = 'nyc_gov_scroll'
   URL = 'http://www.nyc.gov'
 
 
+class SimpleNYCGov2018Page(SimplePage):
+  BASE_NAME = 'nyc_gov_scroll'
+  YEAR = '2018'
+  URL = 'http://www.nyc.gov'
+
+
 class SimpleNYTimesPage(SimplePage):
   BASE_NAME = 'nytimes_scroll'
   URL = 'http://m.nytimes.com/'
+
+
+class SimpleNYTimes2018Page(SimplePage):
+  BASE_NAME = 'nytimes_scroll'
+  YEAR = '2018'
+  URL = 'http://m.nytimes.com/'
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
index 1c1752bb..606f4d1 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -612,13 +612,12 @@
  */
 SubDirectoryItem.prototype.updateSharedStatusIcon = function() {
   var icon = this.querySelector('.icon');
-  // TODO(crbug.com/857343): Evaluate if this can be fully removed.
-  // This line invalidates the metadata model cache and was causing some
-  // directories to not display modificationTime which comes from metadata
-  // because it invalidated before displaying it.
-  // this.parentTree_.metadataModel.notifyEntriesChanged([this.dirEntry_]);
-  this.parentTree_.metadataModel.get([this.dirEntry_], ['shared']).then(
-      function(metadata) {
+  this.parentTree_.metadataModel.notifyEntriesChanged([this.dirEntry_]);
+  this.parentTree_.metadataModel
+      .get(
+          [this.dirEntry_],
+          constants.LIST_CONTAINER_METADATA_PREFETCH_PROPERTY_NAMES)
+      .then(function(metadata) {
         icon.classList.toggle('shared', !!(metadata[0] && metadata[0].shared));
       });
 };
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 8530283..beae9238 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -724,7 +724,7 @@
     "//ui/resources:ui_test_pak",
   ]
 
-  if (!is_android && !is_ios) {
+  if (!is_ios) {
     sources += [ "render_text_unittest.cc" ]
     deps += [ "//third_party:freetype_harfbuzz" ]
   }
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index a464024..8a3842a8 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -2308,8 +2308,15 @@
 }
 #endif  // !defined(OS_WIN)
 
+// TODO(865527): Chinese and Japanese tokenization doesn't work on mobile.
+#if defined(OS_ANDROID)
+#define MAYBE_MoveLeftRightByWordInChineseText \
+  DISABLED_MoveLeftRightByWordInChineseText
+#else
+#define MAYBE_MoveLeftRightByWordInChineseText MoveLeftRightByWordInChineseText
+#endif
 // TODO(asvitkine): RenderTextMac cursor movements. http://crbug.com/131618
-TEST_P(RenderTextHarfBuzzTest, MoveLeftRightByWordInChineseText) {
+TEST_P(RenderTextHarfBuzzTest, MAYBE_MoveLeftRightByWordInChineseText) {
   RenderText* render_text = GetRenderText();
   render_text->SetText(UTF8ToUTF16("\u6211\u4EEC\u53BB\u516C\u56ED\u73A9"));
   render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, SELECTION_NONE);
@@ -2480,7 +2487,17 @@
   EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
 }
 
-TEST_P(RenderTextTest, StringSizeRespectsFontListMetrics) {
+// TODO(865540): Find two system fonts on Android with different baseline and
+// different height.
+// See also: FontListTest::Fonts_GetHeight_GetBaseline.
+#if defined(OS_ANDROID)
+#define MAYBE_StringSizeRespectsFontListMetrics \
+  DISABLED_StringSizeRespectsFontListMetrics
+#else
+#define MAYBE_StringSizeRespectsFontListMetrics \
+  StringSizeRespectsFontListMetrics
+#endif
+TEST_P(RenderTextTest, MAYBE_StringSizeRespectsFontListMetrics) {
   // Check that the test font and the CJK font have different font metrics.
   Font test_font(kTestFontName, 16);
   ASSERT_EQ(base::ToLowerASCII(kTestFontName),
@@ -4041,6 +4058,11 @@
     return;
 #endif
 
+#if defined(OS_ANDROID)
+  // TODO(865709): make this work on Android.
+  return;
+#endif
+
   // Jump over the telephone: two codepoints, but a single glyph.
   render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, SELECTION_NONE);
   EXPECT_EQ(gfx::Range(3, 3), render_text->selection());
@@ -4235,21 +4257,17 @@
 }
 
 // TODO(derat): Figure out why this fails on Windows: http://crbug.com/427184
-#if !defined(OS_WIN)
+// TODO(865715): Figure out why this fails on Android.
+#if !defined(OS_WIN) && !defined(OS_ANDROID)
 // Ensure that RenderText examines all of the fonts in its FontList before
 // falling back to other fonts.
 TEST_P(RenderTextHarfBuzzTest, HarfBuzz_FontListFallback) {
-#if defined(OS_LINUX)
-  const char kTestFont[] = "Arimo";
-#else
-  const char kTestFont[] = "Arial";
-#endif
   // Double-check that the requested fonts are present.
-  std::string format = std::string(kTestFont) + ", %s, 12px";
+  std::string format = std::string(kTestFontName) + ", %s, 12px";
   FontList font_list(base::StringPrintf(format.c_str(), kSymbolFontName));
   const std::vector<Font>& fonts = font_list.GetFonts();
   ASSERT_EQ(2u, fonts.size());
-  ASSERT_EQ(base::ToLowerASCII(kTestFont),
+  ASSERT_EQ(base::ToLowerASCII(kTestFontName),
             base::ToLowerASCII(fonts[0].GetActualFontNameForTesting()));
   ASSERT_EQ(base::ToLowerASCII(kSymbolFontName),
             base::ToLowerASCII(fonts[1].GetActualFontNameForTesting()));
@@ -4264,7 +4282,7 @@
   ASSERT_EQ(static_cast<size_t>(1), spans.size());
   EXPECT_STRCASEEQ(kSymbolFontName, spans[0].first.GetFontName().c_str());
 }
-#endif  // !defined(OS_WIN)
+#endif  // !defined(OS_WIN) && !defined(OS_ANDROID)
 
 // Ensure that the fallback fonts of the Uniscribe font are tried for shaping.
 #if defined(OS_WIN)
@@ -4289,8 +4307,8 @@
 // Ensure that the fallback fonts offered by GetFallbackFonts() are tried. Note
 // this test assumes the font "Arial" doesn't provide a unicode glyph for a
 // particular character, and that there is a system fallback font which does.
-// TODO(msw): Fallback doesn't find a glyph on Linux.
-#if !defined(OS_LINUX)
+// TODO(msw): Fallback doesn't find a glyph on Linux and Android.
+#if !defined(OS_LINUX) && !defined(OS_ANDROID)
 TEST_P(RenderTextHarfBuzzTest, HarfBuzz_UnicodeFallback) {
   RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
   render_text->SetFontList(FontList("Arial, 12px"));
@@ -4364,12 +4382,12 @@
     {
       SCOPED_TRACE("TextDoesntClip Left Side");
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
-    defined(ARCH_CPU_MIPS_FAMILY)
-      // TODO(dschuyler): On Windows, Chrome OS, Linux, and Mac smoothing draws
-      // to the left of text.  This appears to be a preexisting issue that
-      // wasn't revealed by the prior unit tests.  RenderText currently only
-      // uses origins and advances and ignores bounding boxes so cannot account
-      // for under- and over-hang.
+    defined(OS_ANDROID) || defined(ARCH_CPU_MIPS_FAMILY)
+      // TODO(dschuyler): On Windows, Chrome OS, Linux, Android, and Mac
+      // smoothing draws to the left of text.  This appears to be a preexisting
+      // issue that wasn't revealed by the prior unit tests.  RenderText
+      // currently only uses origins and advances and ignores bounding boxes so
+      // cannot account for under- and over-hang.
       rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, kTestSize, kTestSize - 1,
                                   string_size.height());
 #else
@@ -4380,12 +4398,12 @@
     {
       SCOPED_TRACE("TextDoesntClip Right Side");
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
-    defined(ARCH_CPU_MIPS_FAMILY)
-      // TODO(dschuyler): On Windows, Chrome OS, Linux, and Mac smoothing draws
-      // to the right of text.  This appears to be a preexisting issue that
-      // wasn't revealed by the prior unit tests.  RenderText currently only
-      // uses origins and advances and ignores bounding boxes so cannot account
-      // for under- and over-hang.
+    defined(OS_ANDROID) || defined(ARCH_CPU_MIPS_FAMILY)
+      // TODO(dschuyler): On Windows, Chrome OS, Linux, Android, and Mac
+      // smoothing draws to the right of text.  This appears to be a preexisting
+      // issue that wasn't revealed by the prior unit tests.  RenderText
+      // currently only uses origins and advances and ignores bounding boxes so
+      // cannot account for under- and over-hang.
       rect_buffer.EnsureSolidRect(SK_ColorWHITE,
                                   kTestSize + string_size.width() + 1,
                                   kTestSize, kTestSize - 1,
@@ -4544,7 +4562,7 @@
   render_text->SetText(UTF8ToUTF16("x"));
 
   DrawVisualText();
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_ANDROID)
   // On Linux, whether subpixel AA is supported is determined by the platform
   // FontConfig. Force it into a particular style after computing runs. Other
   // platforms use a known default FontRenderParams from a static local.
@@ -4556,16 +4574,16 @@
 
   render_text->set_subpixel_rendering_suppressed(true);
   DrawVisualText();
-#if defined(OS_LINUX)
-    // For Linux, runs shouldn't be re-calculated, and the suppression of the
-    // SUBPIXEL_RENDERING_RGB set above should now take effect. But, after
-    // checking, apply the override anyway to be explicit that it is suppressed.
-    EXPECT_FALSE(GetRendererPaint().isLCDRenderText());
-    GetHarfBuzzRunList()->runs()[0]->common.render_params.subpixel_rendering =
-        FontRenderParams::SUBPIXEL_RENDERING_RGB;
-    DrawVisualText();
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  // For Linux, runs shouldn't be re-calculated, and the suppression of the
+  // SUBPIXEL_RENDERING_RGB set above should now take effect. But, after
+  // checking, apply the override anyway to be explicit that it is suppressed.
+  EXPECT_FALSE(GetRendererPaint().isLCDRenderText());
+  GetHarfBuzzRunList()->runs()[0]->common.render_params.subpixel_rendering =
+      FontRenderParams::SUBPIXEL_RENDERING_RGB;
+  DrawVisualText();
 #endif
-    EXPECT_FALSE(GetRendererPaint().isLCDRenderText());
+  EXPECT_FALSE(GetRendererPaint().isLCDRenderText());
 }
 
 // Verify GetWordLookupDataAtPoint returns the correct baseline point and
diff --git a/ui/gl/egl_bindings_autogen_mock.h b/ui/gl/egl_bindings_autogen_mock.h
index e891a5c3..e3e97c8 100644
--- a/ui/gl/egl_bindings_autogen_mock.h
+++ b/ui/gl/egl_bindings_autogen_mock.h
@@ -8,6 +8,10 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
 static EGLBoolean GL_BINDING_CALL Mock_eglBindAPI(EGLenum api);
 static EGLBoolean GL_BINDING_CALL Mock_eglBindTexImage(EGLDisplay dpy,
                                                        EGLSurface surface,
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 665eb72..f0f2916 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -48,6 +48,9 @@
 """
 GL_FUNCTIONS = [
 { 'return_type': 'void',
+  'names': ['glActiveShaderProgram'],
+  'arguments': 'GLuint pipeline, GLuint program', },
+{ 'return_type': 'void',
   'names': ['glActiveTexture'],
   'arguments': 'GLenum texture', },
 { 'return_type': 'void',
@@ -116,6 +119,9 @@
   'arguments': 'GLuint index, GLuint texture, GLint level, GLboolean layered,'
                'GLint layer, GLenum access, GLint format', },
 { 'return_type': 'void',
+  'names': ['glBindProgramPipeline'],
+  'arguments': 'GLuint pipeline', },
+{ 'return_type': 'void',
   'names': ['glBindRenderbufferEXT', 'glBindRenderbuffer'],
   'arguments': 'GLenum target, GLuint renderbuffer', },
 { 'return_type': 'void',
@@ -142,6 +148,10 @@
                  'extensions': ['GL_APPLE_vertex_array_object'] }],
   'arguments': 'GLuint array' },
 { 'return_type': 'void',
+  'names': ['glBindVertexBuffer'],
+  'arguments': 'GLuint bindingindex, GLuint buffer, GLintptr offset, '
+               'GLsizei stride', },
+{ 'return_type': 'void',
   'known_as': 'glBlendBarrierKHR',
   'versions': [{ 'name': 'glBlendBarrierNV',
                  'extensions': ['GL_NV_blend_equation_advanced'] },
@@ -364,6 +374,9 @@
 { 'return_type': 'GLuint',
   'names': ['glCreateShader'],
   'arguments': 'GLenum type', },
+{ 'return_type': 'GLuint',
+  'names': ['glCreateShaderProgramv'],
+  'arguments': 'GLenum type, GLsizei count, const char* const* strings', },
 { 'return_type': 'void',
   'names': ['glCullFace'],
   'arguments': 'GLenum mode', },
@@ -412,6 +425,9 @@
   'names': ['glDeleteProgram'],
   'arguments': 'GLuint program', },
 { 'return_type': 'void',
+  'names': ['glDeleteProgramPipelines'],
+  'arguments': 'GLsizei n, const GLuint* pipelines', },
+{ 'return_type': 'void',
   'versions': [{ 'name': 'glDeleteQueries' },
                { 'name': 'glDeleteQueriesARB'},
                { 'name': 'glDeleteQueriesEXT',
@@ -474,9 +490,18 @@
   'arguments': 'GLenum target, GLsizei numAttachments, '
       'const GLenum* attachments' },
 { 'return_type': 'void',
+  'names': ['glDispatchCompute'],
+  'arguments': 'GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ', },
+{ 'return_type': 'void',
+  'names': ['glDispatchComputeIndirect'],
+  'arguments': 'GLintptr indirect', },
+{ 'return_type': 'void',
   'names': ['glDrawArrays'],
   'arguments': 'GLenum mode, GLint first, GLsizei count', },
 { 'return_type': 'void',
+  'names': ['glDrawArraysIndirect'],
+  'arguments': 'GLenum mode, const void* indirect', },
+{ 'return_type': 'void',
   'known_as': 'glDrawArraysInstancedANGLE',
   'names': ['glDrawArraysInstancedARB', 'glDrawArraysInstancedANGLE',
             'glDrawArraysInstanced'],
@@ -492,6 +517,9 @@
   'arguments':
       'GLenum mode, GLsizei count, GLenum type, const void* indices', },
 { 'return_type': 'void',
+  'names': ['glDrawElementsIndirect'],
+  'arguments': 'GLenum mode, GLenum type, const void* indirect', },
+{ 'return_type': 'void',
   'known_as': 'glDrawElementsInstancedANGLE',
   'names': ['glDrawElementsInstancedARB', 'glDrawElementsInstancedANGLE',
             'glDrawElementsInstanced'],
@@ -599,6 +627,9 @@
                { 'name': 'glGenPathsCHROMIUM',
                  'extensions': ['GL_CHROMIUM_path_rendering'] }],
   'arguments': 'GLsizei range' },
+{ 'return_type': 'GLuint',
+  'names': ['glGenProgramPipelines'],
+  'arguments': 'GLsizei n, GLuint* pipelines' },
 { 'return_type': 'void',
   'versions': [{ 'name': 'glGenQueries' },
                { 'name': 'glGenQueriesARB', },
@@ -663,6 +694,9 @@
   'names': ['glGetAttribLocation'],
   'arguments': 'GLuint program, const char* name', },
 { 'return_type': 'void',
+  'names': ['glGetBooleani_v'],
+  'arguments': 'GLenum target, GLuint index, GLboolean* data', },
+{ 'return_type': 'void',
   'versions': [{'name': 'glGetBooleani_vRobustANGLE',
                 'extensions': ['GL_ANGLE_robust_client_memory']}],
   'arguments':
@@ -742,6 +776,9 @@
       'GLenum target, GLenum attachment, GLenum pname, GLsizei bufSize, '
       'GLsizei* length, GLint* params', },
 { 'return_type': 'void',
+  'names': ['glGetFramebufferParameteriv'],
+  'arguments': 'GLenum target, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
   'versions': [{'name': 'glGetFramebufferParameterivRobustANGLE',
                 'extensions': ['GL_ANGLE_robust_client_memory']}],
   'arguments':
@@ -880,6 +917,18 @@
       'GLuint program, GLenum pname, GLsizei bufSize, GLsizei* length, '
       'GLint* params', },
 { 'return_type': 'void',
+  'names': ['glGetProgramPipelineInfoLog'],
+  'arguments':
+      'GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog', },
+{ 'return_type': 'void',
+  'names': ['glGetProgramPipelineiv'],
+  'arguments':
+      'GLuint pipeline, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+  'names': ['glGetProgramResourceIndex'],
+  'arguments':
+      'GLuint program, GLenum programInterface, const GLchar* name', },
+{ 'return_type': 'void',
   'versions': [{'name': 'glGetProgramResourceiv',
                 'extensions': ['GL_ARB_program_interface_query']}],
   'arguments': 'GLuint program, GLenum programInterface, GLuint index, '
@@ -1204,6 +1253,9 @@
   'names': ['glIsProgram'],
   'arguments': 'GLuint program', },
 { 'return_type': 'GLboolean',
+  'names': ['glIsProgramPipeline'],
+  'arguments': 'GLuint pipeline', },
+{ 'return_type': 'GLboolean',
   'versions': [{ 'name': 'glIsQuery' },
                { 'name': 'glIsQueryARB' },
                { 'name': 'glIsQueryEXT',
@@ -1273,6 +1325,9 @@
                  'extensions': ['GL_CHROMIUM_path_rendering'] }],
   'arguments': 'GLenum matrixMode' },
 { 'return_type': 'void',
+  'names': ['glMemoryBarrierByRegion'],
+  'arguments': 'GLbitfield barriers', },
+{ 'return_type': 'void',
   'known_as': 'glMemoryBarrierEXT',
   'versions': [{ 'name': 'glMemoryBarrier',
                  'extensions': ['GL_ARB_shader_image_load_store'] },
@@ -1367,6 +1422,131 @@
   'GLint components, const GLfloat* coeffs',
   'is_optional': True, },
 { 'return_type': 'void',
+  'names': ['glProgramUniform1f'],
+  'arguments': 'GLuint program, GLint location, GLfloat v0' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform1fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform1i'],
+  'arguments': 'GLuint program, GLint location, GLint v0' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform1iv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform1ui'],
+  'arguments': 'GLuint program, GLint location, GLuint v0' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform1uiv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLuint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform2f'],
+  'arguments': 'GLuint program, GLint location, GLfloat v0, GLfloat v1' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform2fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform2i'],
+  'arguments': 'GLuint program, GLint location, GLint v0, GLint v1' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform2iv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform2ui'],
+  'arguments': 'GLuint program, GLint location, GLuint v0, GLuint v1' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform2uiv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLuint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform3f'],
+  'arguments': 'GLuint program, GLint location, GLfloat v0, GLfloat v1, '
+               'GLfloat v2' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform3fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform3i'],
+  'arguments': 'GLuint program, GLint location, GLint v0, GLint v1, GLint v2' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform3iv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform3ui'],
+  'arguments': 'GLuint program, GLint location, GLuint v0, GLuint v1, '
+               'GLuint v2' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform3uiv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLuint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform4f'],
+  'arguments': 'GLuint program, GLint location, GLfloat v0, GLfloat v1, '
+               'GLfloat v2, GLfloat v3' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform4fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform4i'],
+  'arguments': 'GLuint program, GLint location, GLint v0, GLint v1, GLint v2, '
+               'GLint v3' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform4iv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform4ui'],
+  'arguments': 'GLuint program, GLint location, GLuint v0, GLuint v1, '
+               'GLuint v2, GLuint v3' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniform4uiv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'const GLuint* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix2fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix2x3fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix2x4fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix3fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix3x2fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix3x4fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix4fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix4x2fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
+  'names': ['glProgramUniformMatrix4x3fv'],
+  'arguments': 'GLuint program, GLint location, GLsizei count, '
+               'GLboolean transpose, const GLfloat* value' },
+{ 'return_type': 'void',
   'versions': [{ 'name': 'glPushDebugGroup' },
                { 'name': 'glPushDebugGroupKHR',
                  'extensions': ['GL_KHR_debug'] }],
@@ -1437,6 +1617,9 @@
   'names': ['glSampleCoverage'],
   'arguments': 'GLclampf value, GLboolean invert', },
 { 'return_type': 'void',
+  'names': ['glSampleMaski'],
+  'arguments': 'GLuint maskNumber, GLbitfield mask', },
+{ 'return_type': 'void',
   'versions': [{ 'name': 'glSamplerParameterf',
                  'extensions': ['GL_ARB_sampler_objects'] }],
   'arguments': 'GLuint sampler, GLenum pname, GLfloat param', },
@@ -1676,6 +1859,11 @@
   'arguments': 'GLenum target, GLsizei levels, GLenum internalformat, '
                'GLsizei width, GLsizei height', },
 { 'return_type': 'void',
+  'names': ['glTexStorage2DMultisample'],
+  'arguments':
+      'GLenum target, GLsizei samples, GLenum internalformat, '
+      'GLsizei width, GLsizei height, GLboolean fixedsamplelocations', },
+{ 'return_type': 'void',
   'versions': [{ 'name': 'glTexStorage3D',
                  'extensions': ['GL_ARB_texture_storage'] }],
   'arguments': 'GLenum target, GLsizei levels, GLenum internalformat, '
@@ -1832,9 +2020,15 @@
   'names': ['glUseProgram'],
   'arguments': 'GLuint program', },
 { 'return_type': 'void',
+  'names': ['glUseProgramStages'],
+  'arguments': 'GLuint pipeline, GLbitfield stages, GLuint program', },
+{ 'return_type': 'void',
   'names': ['glValidateProgram'],
   'arguments': 'GLuint program', },
 { 'return_type': 'void',
+  'names': ['glValidateProgramPipeline'],
+  'arguments': 'GLuint pipeline', },
+{ 'return_type': 'void',
   'names': ['glVertexAttrib1f'],
   'arguments': 'GLuint indx, GLfloat x', },
 { 'return_type': 'void',
@@ -1859,12 +2053,19 @@
   'names': ['glVertexAttrib4fv'],
   'arguments': 'GLuint indx, const GLfloat* values', },
 { 'return_type': 'void',
+  'names': ['glVertexAttribBinding'],
+  'arguments': 'GLuint attribindex, GLuint bindingindex', },
+{ 'return_type': 'void',
   'known_as': 'glVertexAttribDivisorANGLE',
   'names': ['glVertexAttribDivisorARB', 'glVertexAttribDivisorANGLE',
             'glVertexAttribDivisorEXT', 'glVertexAttribDivisor'],
   'arguments':
       'GLuint index, GLuint divisor', },
 { 'return_type': 'void',
+  'names': ['glVertexAttribFormat'],
+  'arguments': 'GLuint attribindex, GLint size, GLenum type, '
+               'GLboolean normalized, GLuint relativeoffset', },
+{ 'return_type': 'void',
   'versions': [{ 'name': 'glVertexAttribI4i' }],
   'arguments': 'GLuint indx, GLint x, GLint y, GLint z, GLint w', },
 { 'return_type': 'void',
@@ -1877,6 +2078,10 @@
   'versions': [{ 'name': 'glVertexAttribI4uiv' }],
   'arguments': 'GLuint indx, const GLuint* values', },
 { 'return_type': 'void',
+  'names': ['glVertexAttribIFormat'],
+  'arguments': 'GLuint attribindex, GLint size, GLenum type, '
+               'GLuint relativeoffset', },
+{ 'return_type': 'void',
   'versions': [{ 'name': 'glVertexAttribIPointer' }],
   'arguments': 'GLuint indx, GLint size, GLenum type, GLsizei stride, '
                'const void* ptr', },
@@ -1885,6 +2090,9 @@
   'arguments': 'GLuint indx, GLint size, GLenum type, GLboolean normalized, '
                'GLsizei stride, const void* ptr', },
 { 'return_type': 'void',
+  'names': ['glVertexBindingDivisor'],
+  'arguments': 'GLuint bindingindex, GLuint divisor', },
+{ 'return_type': 'void',
   'names': ['glViewport'],
   'arguments': 'GLint x, GLint y, GLsizei width, GLsizei height', },
 { 'return_type': 'void',
@@ -2548,6 +2756,7 @@
   'GLES2/gl2chromium.h',
   'GLES2/gl2extchromium.h',
   'GLES3/gl3.h',
+  'GLES3/gl31.h',
 ]
 
 SELF_LOCATION = os.path.dirname(os.path.abspath(__file__))
@@ -2690,7 +2899,14 @@
   """Generates gl_bindings_api_autogen_x.h"""
 
   # Write file header.
-  file.write(LICENSE_AND_HEADER)
+  file.write(LICENSE_AND_HEADER +
+"""
+
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
+""")
 
   # Write API declaration.
   for func in functions:
@@ -2704,7 +2920,14 @@
   """Generates gl_mock_autogen_x.h"""
 
   # Write file header.
-  file.write(LICENSE_AND_HEADER)
+  file.write(LICENSE_AND_HEADER +
+"""
+
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
+""")
 
   # Write API declaration.
   for func in functions:
@@ -2731,7 +2954,14 @@
   """Generates gl_stub_autogen_gl.h"""
 
   # Write file header.
-  file.write(LICENSE_AND_HEADER)
+  file.write(LICENSE_AND_HEADER +
+"""
+
+#ifndef UI_GL_GL_STUB_AUTOGEN_H_
+#define UI_GL_GL_STUB_AUTOGEN_H_
+
+""")
+
 
   # Write API declaration.
   for func in functions:
@@ -2747,6 +2977,7 @@
       file.write(';\n');
 
   file.write('\n')
+  file.write('#endif  //  UI_GL_GL_STUB_AUTOGEN_H_')
 
 def GenerateStubSource(file, functions):
   """Generates gl_stub_autogen_gl.cc"""
@@ -3157,7 +3388,14 @@
 def GenerateMockBindingsHeader(file, functions):
   """Headers for functions that invoke MockGLInterface members"""
 
-  file.write(LICENSE_AND_HEADER)
+  file.write(LICENSE_AND_HEADER +
+"""
+
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
+""")
   uniquely_named_functions = GetUniquelyNamedFunctions(functions)
 
   for key in sorted(uniquely_named_functions.iterkeys()):
@@ -3264,7 +3502,13 @@
             raise RuntimeError("code collision: %s and %s have the same code %s"
                                %  (dict[value], name, value))
 
-  out_file.write(LICENSE_AND_HEADER)
+  out_file.write(LICENSE_AND_HEADER +
+"""
+
+#ifndef UI_GL_GL_ENUMS_IMPLEMENTATION_AUTOGEN_H_
+#define UI_GL_GL_ENUMS_IMPLEMENTATION_AUTOGEN_H_
+
+""")
   out_file.write("static const GLEnums::EnumToString "
                  "enum_to_string_table[] = {\n")
   for value in sorted(dict):
@@ -3277,6 +3521,7 @@
   sizeof(enum_to_string_table) / sizeof(enum_to_string_table[0]);
 
 """)
+  out_file.write('#endif  //  UI_GL_GL_ENUMS_IMPLEMENTATION_AUTOGEN_H_')
 
 
 def ParseFunctionsFromHeader(header_file, extensions, versions):
diff --git a/ui/gl/gl_bindings_api_autogen_egl.h b/ui/gl/gl_bindings_api_autogen_egl.h
index f00c418..8b1fa45 100644
--- a/ui/gl/gl_bindings_api_autogen_egl.h
+++ b/ui/gl/gl_bindings_api_autogen_egl.h
@@ -8,6 +8,10 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
 EGLBoolean eglBindAPIFn(EGLenum api) override;
 EGLBoolean eglBindTexImageFn(EGLDisplay dpy,
                              EGLSurface surface,
diff --git a/ui/gl/gl_bindings_api_autogen_gl.h b/ui/gl/gl_bindings_api_autogen_gl.h
index 5b427c0..f99f68c 100644
--- a/ui/gl/gl_bindings_api_autogen_gl.h
+++ b/ui/gl/gl_bindings_api_autogen_gl.h
@@ -8,6 +8,11 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
+void glActiveShaderProgramFn(GLuint pipeline, GLuint program) override;
 void glActiveTextureFn(GLenum texture) override;
 void glApplyFramebufferAttachmentCMAAINTELFn(void) override;
 void glAttachShaderFn(GLuint program, GLuint shader) override;
@@ -41,6 +46,7 @@
                              GLint layer,
                              GLenum access,
                              GLint format) override;
+void glBindProgramPipelineFn(GLuint pipeline) override;
 void glBindRenderbufferEXTFn(GLenum target, GLuint renderbuffer) override;
 void glBindSamplerFn(GLuint unit, GLuint sampler) override;
 void glBindTextureFn(GLenum target, GLuint texture) override;
@@ -49,6 +55,10 @@
                                      GLint location,
                                      const char* name) override;
 void glBindVertexArrayOESFn(GLuint array) override;
+void glBindVertexBufferFn(GLuint bindingindex,
+                          GLuint buffer,
+                          GLintptr offset,
+                          GLsizei stride) override;
 void glBlendBarrierKHRFn(void) override;
 void glBlendColorFn(GLclampf red,
                     GLclampf green,
@@ -261,6 +271,9 @@
 void glCoverStrokePathNVFn(GLuint name, GLenum coverMode) override;
 GLuint glCreateProgramFn(void) override;
 GLuint glCreateShaderFn(GLenum type) override;
+GLuint glCreateShaderProgramvFn(GLenum type,
+                                GLsizei count,
+                                const char* const* strings) override;
 void glCullFaceFn(GLenum mode) override;
 void glDebugMessageCallbackFn(GLDEBUGPROC callback,
                               const void* userParam) override;
@@ -282,6 +295,7 @@
 void glDeleteFramebuffersEXTFn(GLsizei n, const GLuint* framebuffers) override;
 void glDeletePathsNVFn(GLuint path, GLsizei range) override;
 void glDeleteProgramFn(GLuint program) override;
+void glDeleteProgramPipelinesFn(GLsizei n, const GLuint* pipelines) override;
 void glDeleteQueriesFn(GLsizei n, const GLuint* ids) override;
 void glDeleteRenderbuffersEXTFn(GLsizei n,
                                 const GLuint* renderbuffers) override;
@@ -301,7 +315,12 @@
 void glDiscardFramebufferEXTFn(GLenum target,
                                GLsizei numAttachments,
                                const GLenum* attachments) override;
+void glDispatchComputeFn(GLuint numGroupsX,
+                         GLuint numGroupsY,
+                         GLuint numGroupsZ) override;
+void glDispatchComputeIndirectFn(GLintptr indirect) override;
 void glDrawArraysFn(GLenum mode, GLint first, GLsizei count) override;
+void glDrawArraysIndirectFn(GLenum mode, const void* indirect) override;
 void glDrawArraysInstancedANGLEFn(GLenum mode,
                                   GLint first,
                                   GLsizei count,
@@ -312,6 +331,9 @@
                       GLsizei count,
                       GLenum type,
                       const void* indices) override;
+void glDrawElementsIndirectFn(GLenum mode,
+                              GLenum type,
+                              const void* indirect) override;
 void glDrawElementsInstancedANGLEFn(GLenum mode,
                                     GLsizei count,
                                     GLenum type,
@@ -369,6 +391,7 @@
 void glGenFencesNVFn(GLsizei n, GLuint* fences) override;
 void glGenFramebuffersEXTFn(GLsizei n, GLuint* framebuffers) override;
 GLuint glGenPathsNVFn(GLsizei range) override;
+GLuint glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) override;
 void glGenQueriesFn(GLsizei n, GLuint* ids) override;
 void glGenRenderbuffersEXTFn(GLsizei n, GLuint* renderbuffers) override;
 void glGenSamplersFn(GLsizei n, GLuint* samplers) override;
@@ -414,6 +437,7 @@
                             GLsizei* count,
                             GLuint* shaders) override;
 GLint glGetAttribLocationFn(GLuint program, const char* name) override;
+void glGetBooleani_vFn(GLenum target, GLuint index, GLboolean* data) override;
 void glGetBooleani_vRobustANGLEFn(GLenum target,
                                   GLuint index,
                                   GLsizei bufSize,
@@ -469,6 +493,9 @@
                                                         GLsizei bufSize,
                                                         GLsizei* length,
                                                         GLint* params) override;
+void glGetFramebufferParameterivFn(GLenum target,
+                                   GLenum pname,
+                                   GLint* params) override;
 void glGetFramebufferParameterivRobustANGLEFn(GLenum target,
                                               GLenum pname,
                                               GLsizei bufSize,
@@ -568,6 +595,16 @@
                                  GLsizei bufSize,
                                  GLsizei* length,
                                  GLint* params) override;
+void glGetProgramPipelineInfoLogFn(GLuint pipeline,
+                                   GLsizei bufSize,
+                                   GLsizei* length,
+                                   GLchar* infoLog) override;
+void glGetProgramPipelineivFn(GLuint pipeline,
+                              GLenum pname,
+                              GLint* params) override;
+void glGetProgramResourceIndexFn(GLuint program,
+                                 GLenum programInterface,
+                                 const GLchar* name) override;
 void glGetProgramResourceivFn(GLuint program,
                               GLenum programInterface,
                               GLuint index,
@@ -807,6 +844,7 @@
 GLboolean glIsFramebufferEXTFn(GLuint framebuffer) override;
 GLboolean glIsPathNVFn(GLuint path) override;
 GLboolean glIsProgramFn(GLuint program) override;
+GLboolean glIsProgramPipelineFn(GLuint pipeline) override;
 GLboolean glIsQueryFn(GLuint query) override;
 GLboolean glIsRenderbufferEXTFn(GLuint renderbuffer) override;
 GLboolean glIsSamplerFn(GLuint sampler) override;
@@ -824,6 +862,7 @@
                          GLbitfield access) override;
 void glMatrixLoadfEXTFn(GLenum matrixMode, const GLfloat* m) override;
 void glMatrixLoadIdentityEXTFn(GLenum matrixMode) override;
+void glMemoryBarrierByRegionFn(GLbitfield barriers) override;
 void glMemoryBarrierEXTFn(GLbitfield barriers) override;
 void glObjectLabelFn(GLenum identifier,
                      GLuint name,
@@ -857,6 +896,147 @@
                                        GLenum genMode,
                                        GLint components,
                                        const GLfloat* coeffs) override;
+void glProgramUniform1fFn(GLuint program, GLint location, GLfloat v0) override;
+void glProgramUniform1fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override;
+void glProgramUniform1iFn(GLuint program, GLint location, GLint v0) override;
+void glProgramUniform1ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override;
+void glProgramUniform1uiFn(GLuint program, GLint location, GLuint v0) override;
+void glProgramUniform1uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override;
+void glProgramUniform2fFn(GLuint program,
+                          GLint location,
+                          GLfloat v0,
+                          GLfloat v1) override;
+void glProgramUniform2fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override;
+void glProgramUniform2iFn(GLuint program,
+                          GLint location,
+                          GLint v0,
+                          GLint v1) override;
+void glProgramUniform2ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override;
+void glProgramUniform2uiFn(GLuint program,
+                           GLint location,
+                           GLuint v0,
+                           GLuint v1) override;
+void glProgramUniform2uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override;
+void glProgramUniform3fFn(GLuint program,
+                          GLint location,
+                          GLfloat v0,
+                          GLfloat v1,
+                          GLfloat v2) override;
+void glProgramUniform3fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override;
+void glProgramUniform3iFn(GLuint program,
+                          GLint location,
+                          GLint v0,
+                          GLint v1,
+                          GLint v2) override;
+void glProgramUniform3ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override;
+void glProgramUniform3uiFn(GLuint program,
+                           GLint location,
+                           GLuint v0,
+                           GLuint v1,
+                           GLuint v2) override;
+void glProgramUniform3uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override;
+void glProgramUniform4fFn(GLuint program,
+                          GLint location,
+                          GLfloat v0,
+                          GLfloat v1,
+                          GLfloat v2,
+                          GLfloat v3) override;
+void glProgramUniform4fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override;
+void glProgramUniform4iFn(GLuint program,
+                          GLint location,
+                          GLint v0,
+                          GLint v1,
+                          GLint v2,
+                          GLint v3) override;
+void glProgramUniform4ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override;
+void glProgramUniform4uiFn(GLuint program,
+                           GLint location,
+                           GLuint v0,
+                           GLuint v1,
+                           GLuint v2,
+                           GLuint v3) override;
+void glProgramUniform4uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override;
+void glProgramUniformMatrix2fvFn(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value) override;
+void glProgramUniformMatrix2x3fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override;
+void glProgramUniformMatrix2x4fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override;
+void glProgramUniformMatrix3fvFn(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value) override;
+void glProgramUniformMatrix3x2fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override;
+void glProgramUniformMatrix3x4fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override;
+void glProgramUniformMatrix4fvFn(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value) override;
+void glProgramUniformMatrix4x2fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override;
+void glProgramUniformMatrix4x3fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override;
 void glPushDebugGroupFn(GLenum source,
                         GLuint id,
                         GLsizei length,
@@ -911,6 +1091,7 @@
 void glRequestExtensionANGLEFn(const char* name) override;
 void glResumeTransformFeedbackFn(void) override;
 void glSampleCoverageFn(GLclampf value, GLboolean invert) override;
+void glSampleMaskiFn(GLuint maskNumber, GLbitfield mask) override;
 void glSamplerParameterfFn(GLuint sampler,
                            GLenum pname,
                            GLfloat param) override;
@@ -1088,6 +1269,12 @@
                          GLenum internalformat,
                          GLsizei width,
                          GLsizei height) override;
+void glTexStorage2DMultisampleFn(GLenum target,
+                                 GLsizei samples,
+                                 GLenum internalformat,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 GLboolean fixedsamplelocations) override;
 void glTexStorage3DFn(GLenum target,
                       GLsizei levels,
                       GLenum internalformat,
@@ -1213,7 +1400,11 @@
                             const GLfloat* value) override;
 GLboolean glUnmapBufferFn(GLenum target) override;
 void glUseProgramFn(GLuint program) override;
+void glUseProgramStagesFn(GLuint pipeline,
+                          GLbitfield stages,
+                          GLuint program) override;
 void glValidateProgramFn(GLuint program) override;
+void glValidateProgramPipelineFn(GLuint pipeline) override;
 void glVertexAttrib1fFn(GLuint indx, GLfloat x) override;
 void glVertexAttrib1fvFn(GLuint indx, const GLfloat* values) override;
 void glVertexAttrib2fFn(GLuint indx, GLfloat x, GLfloat y) override;
@@ -1226,7 +1417,13 @@
                         GLfloat z,
                         GLfloat w) override;
 void glVertexAttrib4fvFn(GLuint indx, const GLfloat* values) override;
+void glVertexAttribBindingFn(GLuint attribindex, GLuint bindingindex) override;
 void glVertexAttribDivisorANGLEFn(GLuint index, GLuint divisor) override;
+void glVertexAttribFormatFn(GLuint attribindex,
+                            GLint size,
+                            GLenum type,
+                            GLboolean normalized,
+                            GLuint relativeoffset) override;
 void glVertexAttribI4iFn(GLuint indx,
                          GLint x,
                          GLint y,
@@ -1239,6 +1436,10 @@
                           GLuint z,
                           GLuint w) override;
 void glVertexAttribI4uivFn(GLuint indx, const GLuint* values) override;
+void glVertexAttribIFormatFn(GLuint attribindex,
+                             GLint size,
+                             GLenum type,
+                             GLuint relativeoffset) override;
 void glVertexAttribIPointerFn(GLuint indx,
                               GLint size,
                               GLenum type,
@@ -1250,6 +1451,7 @@
                              GLboolean normalized,
                              GLsizei stride,
                              const void* ptr) override;
+void glVertexBindingDivisorFn(GLuint bindingindex, GLuint divisor) override;
 void glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) override;
 void glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) override;
 void glWindowRectanglesEXTFn(GLenum mode, GLsizei n, const GLint* box) override;
diff --git a/ui/gl/gl_bindings_api_autogen_glx.h b/ui/gl/gl_bindings_api_autogen_glx.h
index 15e5c9f4..4ac732b 100644
--- a/ui/gl/gl_bindings_api_autogen_glx.h
+++ b/ui/gl/gl_bindings_api_autogen_glx.h
@@ -8,6 +8,10 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
 void glXBindTexImageEXTFn(Display* dpy,
                           GLXDrawable drawable,
                           int buffer,
diff --git a/ui/gl/gl_bindings_api_autogen_osmesa.h b/ui/gl/gl_bindings_api_autogen_osmesa.h
index 46ce5c3d..be97f2f 100644
--- a/ui/gl/gl_bindings_api_autogen_osmesa.h
+++ b/ui/gl/gl_bindings_api_autogen_osmesa.h
@@ -8,6 +8,10 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
 void OSMesaColorClampFn(GLboolean enable) override;
 OSMesaContext OSMesaCreateContextFn(GLenum format,
                                     OSMesaContext sharelist) override;
diff --git a/ui/gl/gl_bindings_api_autogen_wgl.h b/ui/gl/gl_bindings_api_autogen_wgl.h
index 8a2edc1..0b54c72 100644
--- a/ui/gl/gl_bindings_api_autogen_wgl.h
+++ b/ui/gl/gl_bindings_api_autogen_wgl.h
@@ -8,6 +8,10 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
 BOOL wglChoosePixelFormatARBFn(HDC dc,
                                const int* int_attrib_list,
                                const float* float_attrib_list,
diff --git a/ui/gl/gl_bindings_autogen_gl.cc b/ui/gl/gl_bindings_autogen_gl.cc
index 8e1938b..dac774b 100644
--- a/ui/gl/gl_bindings_autogen_gl.cc
+++ b/ui/gl/gl_bindings_autogen_gl.cc
@@ -415,6 +415,11 @@
   ext.b_GL_OES_vertex_array_object =
       gfx::HasExtension(extensions, "GL_OES_vertex_array_object");
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glActiveShaderProgramFn = reinterpret_cast<glActiveShaderProgramProc>(
+        GetGLProcAddress("glActiveShaderProgram"));
+  }
+
   if (ext.b_GL_INTEL_framebuffer_CMAA) {
     fn.glApplyFramebufferAttachmentCMAAINTELFn =
         reinterpret_cast<glApplyFramebufferAttachmentCMAAINTELProc>(
@@ -500,6 +505,11 @@
         GetGLProcAddress("glBindImageTextureEXT"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glBindProgramPipelineFn = reinterpret_cast<glBindProgramPipelineProc>(
+        GetGLProcAddress("glBindProgramPipeline"));
+  }
+
   if (ver->IsAtLeastGL(3u, 0u) || ver->is_es) {
     fn.glBindRenderbufferEXTFn = reinterpret_cast<glBindRenderbufferEXTProc>(
         GetGLProcAddress("glBindRenderbuffer"));
@@ -539,6 +549,11 @@
         GetGLProcAddress("glBindVertexArrayAPPLE"));
   }
 
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glBindVertexBufferFn = reinterpret_cast<glBindVertexBufferProc>(
+        GetGLProcAddress("glBindVertexBuffer"));
+  }
+
   if (ext.b_GL_NV_blend_equation_advanced) {
     fn.glBlendBarrierKHRFn = reinterpret_cast<glBlendBarrierKHRProc>(
         GetGLProcAddress("glBlendBarrierNV"));
@@ -707,6 +722,11 @@
         GetGLProcAddress("glCoverStrokePathCHROMIUM"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glCreateShaderProgramvFn = reinterpret_cast<glCreateShaderProgramvProc>(
+        GetGLProcAddress("glCreateShaderProgramv"));
+  }
+
   if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 2u)) {
     fn.glDebugMessageCallbackFn = reinterpret_cast<glDebugMessageCallbackProc>(
         GetGLProcAddress("glDebugMessageCallback"));
@@ -759,6 +779,12 @@
         GetGLProcAddress("glDeletePathsCHROMIUM"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glDeleteProgramPipelinesFn =
+        reinterpret_cast<glDeleteProgramPipelinesProc>(
+            GetGLProcAddress("glDeleteProgramPipelines"));
+  }
+
   if (!ver->is_es || ver->IsAtLeastGLES(3u, 0u)) {
     fn.glDeleteQueriesFn = reinterpret_cast<glDeleteQueriesProc>(
         GetGLProcAddress("glDeleteQueries"));
@@ -826,6 +852,22 @@
             GetGLProcAddress("glDiscardFramebufferEXT"));
   }
 
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glDispatchComputeFn = reinterpret_cast<glDispatchComputeProc>(
+        GetGLProcAddress("glDispatchCompute"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glDispatchComputeIndirectFn =
+        reinterpret_cast<glDispatchComputeIndirectProc>(
+            GetGLProcAddress("glDispatchComputeIndirect"));
+  }
+
+  if (ver->IsAtLeastGLES(3u, 1u) || ver->IsAtLeastGL(4u, 0u)) {
+    fn.glDrawArraysIndirectFn = reinterpret_cast<glDrawArraysIndirectProc>(
+        GetGLProcAddress("glDrawArraysIndirect"));
+  }
+
   if (ver->IsAtLeastGLES(3u, 0u) || ver->IsAtLeastGL(3u, 1u)) {
     fn.glDrawArraysInstancedANGLEFn =
         reinterpret_cast<glDrawArraysInstancedANGLEProc>(
@@ -856,6 +898,11 @@
         GetGLProcAddress("glDrawBuffersEXT"));
   }
 
+  if (ver->IsAtLeastGLES(3u, 1u) || ver->IsAtLeastGL(4u, 0u)) {
+    fn.glDrawElementsIndirectFn = reinterpret_cast<glDrawElementsIndirectProc>(
+        GetGLProcAddress("glDrawElementsIndirect"));
+  }
+
   if (ver->IsAtLeastGLES(3u, 0u) || ver->IsAtLeastGL(3u, 1u)) {
     fn.glDrawElementsInstancedANGLEFn =
         reinterpret_cast<glDrawElementsInstancedANGLEProc>(
@@ -1010,6 +1057,11 @@
         GetGLProcAddress("glGenPathsCHROMIUM"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glGenProgramPipelinesFn = reinterpret_cast<glGenProgramPipelinesProc>(
+        GetGLProcAddress("glGenProgramPipelines"));
+  }
+
   if (!ver->is_es || ver->IsAtLeastGLES(3u, 0u)) {
     fn.glGenQueriesFn =
         reinterpret_cast<glGenQueriesProc>(GetGLProcAddress("glGenQueries"));
@@ -1078,6 +1130,11 @@
         GetGLProcAddress("glGetActiveUniformsiv"));
   }
 
+  if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glGetBooleani_vFn = reinterpret_cast<glGetBooleani_vProc>(
+        GetGLProcAddress("glGetBooleani_v"));
+  }
+
   if (ext.b_GL_ANGLE_robust_client_memory) {
     fn.glGetBooleani_vRobustANGLEFn =
         reinterpret_cast<glGetBooleani_vRobustANGLEProc>(
@@ -1156,6 +1213,12 @@
                 "glGetFramebufferAttachmentParameterivRobustANGLE"));
   }
 
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glGetFramebufferParameterivFn =
+        reinterpret_cast<glGetFramebufferParameterivProc>(
+            GetGLProcAddress("glGetFramebufferParameteriv"));
+  }
+
   if (ext.b_GL_ANGLE_robust_client_memory) {
     fn.glGetFramebufferParameterivRobustANGLEFn =
         reinterpret_cast<glGetFramebufferParameterivRobustANGLEProc>(
@@ -1319,6 +1382,23 @@
             GetGLProcAddress("glGetProgramivRobustANGLE"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glGetProgramPipelineInfoLogFn =
+        reinterpret_cast<glGetProgramPipelineInfoLogProc>(
+            GetGLProcAddress("glGetProgramPipelineInfoLog"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glGetProgramPipelineivFn = reinterpret_cast<glGetProgramPipelineivProc>(
+        GetGLProcAddress("glGetProgramPipelineiv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glGetProgramResourceIndexFn =
+        reinterpret_cast<glGetProgramResourceIndexProc>(
+            GetGLProcAddress("glGetProgramResourceIndex"));
+  }
+
   if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u) ||
       ext.b_GL_ARB_program_interface_query) {
     fn.glGetProgramResourceivFn = reinterpret_cast<glGetProgramResourceivProc>(
@@ -1661,6 +1741,11 @@
         reinterpret_cast<glIsPathNVProc>(GetGLProcAddress("glIsPathCHROMIUM"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glIsProgramPipelineFn = reinterpret_cast<glIsProgramPipelineProc>(
+        GetGLProcAddress("glIsProgramPipeline"));
+  }
+
   if (!ver->is_es || ver->IsAtLeastGLES(3u, 0u)) {
     fn.glIsQueryFn =
         reinterpret_cast<glIsQueryProc>(GetGLProcAddress("glIsQuery"));
@@ -1746,6 +1831,12 @@
             GetGLProcAddress("glMatrixLoadIdentityCHROMIUM"));
   }
 
+  if (ver->IsAtLeastGLES(3u, 1u) || ver->IsAtLeastGL(4u, 5u)) {
+    fn.glMemoryBarrierByRegionFn =
+        reinterpret_cast<glMemoryBarrierByRegionProc>(
+            GetGLProcAddress("glMemoryBarrierByRegion"));
+  }
+
   if (ver->IsAtLeastGL(4u, 2u) || ver->IsAtLeastGLES(3u, 1u) ||
       ext.b_GL_ARB_shader_image_load_store) {
     fn.glMemoryBarrierEXTFn = reinterpret_cast<glMemoryBarrierEXTProc>(
@@ -1864,6 +1955,180 @@
             GetGLProcAddress("glProgramPathFragmentInputGenCHROMIUM"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform1fFn = reinterpret_cast<glProgramUniform1fProc>(
+        GetGLProcAddress("glProgramUniform1f"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform1fvFn = reinterpret_cast<glProgramUniform1fvProc>(
+        GetGLProcAddress("glProgramUniform1fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform1iFn = reinterpret_cast<glProgramUniform1iProc>(
+        GetGLProcAddress("glProgramUniform1i"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform1ivFn = reinterpret_cast<glProgramUniform1ivProc>(
+        GetGLProcAddress("glProgramUniform1iv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform1uiFn = reinterpret_cast<glProgramUniform1uiProc>(
+        GetGLProcAddress("glProgramUniform1ui"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform1uivFn = reinterpret_cast<glProgramUniform1uivProc>(
+        GetGLProcAddress("glProgramUniform1uiv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform2fFn = reinterpret_cast<glProgramUniform2fProc>(
+        GetGLProcAddress("glProgramUniform2f"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform2fvFn = reinterpret_cast<glProgramUniform2fvProc>(
+        GetGLProcAddress("glProgramUniform2fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform2iFn = reinterpret_cast<glProgramUniform2iProc>(
+        GetGLProcAddress("glProgramUniform2i"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform2ivFn = reinterpret_cast<glProgramUniform2ivProc>(
+        GetGLProcAddress("glProgramUniform2iv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform2uiFn = reinterpret_cast<glProgramUniform2uiProc>(
+        GetGLProcAddress("glProgramUniform2ui"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform2uivFn = reinterpret_cast<glProgramUniform2uivProc>(
+        GetGLProcAddress("glProgramUniform2uiv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform3fFn = reinterpret_cast<glProgramUniform3fProc>(
+        GetGLProcAddress("glProgramUniform3f"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform3fvFn = reinterpret_cast<glProgramUniform3fvProc>(
+        GetGLProcAddress("glProgramUniform3fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform3iFn = reinterpret_cast<glProgramUniform3iProc>(
+        GetGLProcAddress("glProgramUniform3i"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform3ivFn = reinterpret_cast<glProgramUniform3ivProc>(
+        GetGLProcAddress("glProgramUniform3iv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform3uiFn = reinterpret_cast<glProgramUniform3uiProc>(
+        GetGLProcAddress("glProgramUniform3ui"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform3uivFn = reinterpret_cast<glProgramUniform3uivProc>(
+        GetGLProcAddress("glProgramUniform3uiv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform4fFn = reinterpret_cast<glProgramUniform4fProc>(
+        GetGLProcAddress("glProgramUniform4f"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform4fvFn = reinterpret_cast<glProgramUniform4fvProc>(
+        GetGLProcAddress("glProgramUniform4fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform4iFn = reinterpret_cast<glProgramUniform4iProc>(
+        GetGLProcAddress("glProgramUniform4i"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform4ivFn = reinterpret_cast<glProgramUniform4ivProc>(
+        GetGLProcAddress("glProgramUniform4iv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform4uiFn = reinterpret_cast<glProgramUniform4uiProc>(
+        GetGLProcAddress("glProgramUniform4ui"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniform4uivFn = reinterpret_cast<glProgramUniform4uivProc>(
+        GetGLProcAddress("glProgramUniform4uiv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix2fvFn =
+        reinterpret_cast<glProgramUniformMatrix2fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix2fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix2x3fvFn =
+        reinterpret_cast<glProgramUniformMatrix2x3fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix2x3fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix2x4fvFn =
+        reinterpret_cast<glProgramUniformMatrix2x4fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix2x4fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix3fvFn =
+        reinterpret_cast<glProgramUniformMatrix3fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix3fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix3x2fvFn =
+        reinterpret_cast<glProgramUniformMatrix3x2fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix3x2fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix3x4fvFn =
+        reinterpret_cast<glProgramUniformMatrix3x4fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix3x4fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix4fvFn =
+        reinterpret_cast<glProgramUniformMatrix4fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix4fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix4x2fvFn =
+        reinterpret_cast<glProgramUniformMatrix4x2fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix4x2fv"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glProgramUniformMatrix4x3fvFn =
+        reinterpret_cast<glProgramUniformMatrix4x3fvProc>(
+            GetGLProcAddress("glProgramUniformMatrix4x3fv"));
+  }
+
   if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 2u)) {
     fn.glPushDebugGroupFn = reinterpret_cast<glPushDebugGroupProc>(
         GetGLProcAddress("glPushDebugGroup"));
@@ -1956,6 +2221,11 @@
             GetGLProcAddress("glResumeTransformFeedback"));
   }
 
+  if (ver->IsAtLeastGL(3u, 2u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glSampleMaskiFn =
+        reinterpret_cast<glSampleMaskiProc>(GetGLProcAddress("glSampleMaski"));
+  }
+
   if (ver->IsAtLeastGL(3u, 3u) || ver->IsAtLeastGLES(3u, 0u) ||
       ext.b_GL_ARB_sampler_objects) {
     fn.glSamplerParameterfFn = reinterpret_cast<glSamplerParameterfProc>(
@@ -2178,6 +2448,12 @@
         GetGLProcAddress("glTexStorage2DEXT"));
   }
 
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glTexStorage2DMultisampleFn =
+        reinterpret_cast<glTexStorage2DMultisampleProc>(
+            GetGLProcAddress("glTexStorage2DMultisample"));
+  }
+
   if (ver->IsAtLeastGL(4u, 2u) || ver->IsAtLeastGLES(3u, 0u) ||
       ext.b_GL_ARB_texture_storage) {
     fn.glTexStorage3DFn = reinterpret_cast<glTexStorage3DProc>(
@@ -2294,6 +2570,22 @@
         GetGLProcAddress("glUnmapBufferOES"));
   }
 
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glUseProgramStagesFn = reinterpret_cast<glUseProgramStagesProc>(
+        GetGLProcAddress("glUseProgramStages"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glValidateProgramPipelineFn =
+        reinterpret_cast<glValidateProgramPipelineProc>(
+            GetGLProcAddress("glValidateProgramPipeline"));
+  }
+
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glVertexAttribBindingFn = reinterpret_cast<glVertexAttribBindingProc>(
+        GetGLProcAddress("glVertexAttribBinding"));
+  }
+
   if (ver->IsAtLeastGL(3u, 3u) || ver->IsAtLeastGLES(3u, 0u)) {
     fn.glVertexAttribDivisorANGLEFn =
         reinterpret_cast<glVertexAttribDivisorANGLEProc>(
@@ -2312,6 +2604,11 @@
             GetGLProcAddress("glVertexAttribDivisorEXT"));
   }
 
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glVertexAttribFormatFn = reinterpret_cast<glVertexAttribFormatProc>(
+        GetGLProcAddress("glVertexAttribFormat"));
+  }
+
   if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) {
     fn.glVertexAttribI4iFn = reinterpret_cast<glVertexAttribI4iProc>(
         GetGLProcAddress("glVertexAttribI4i"));
@@ -2332,11 +2629,21 @@
         GetGLProcAddress("glVertexAttribI4uiv"));
   }
 
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glVertexAttribIFormatFn = reinterpret_cast<glVertexAttribIFormatProc>(
+        GetGLProcAddress("glVertexAttribIFormat"));
+  }
+
   if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) {
     fn.glVertexAttribIPointerFn = reinterpret_cast<glVertexAttribIPointerProc>(
         GetGLProcAddress("glVertexAttribIPointer"));
   }
 
+  if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 1u)) {
+    fn.glVertexBindingDivisorFn = reinterpret_cast<glVertexBindingDivisorProc>(
+        GetGLProcAddress("glVertexBindingDivisor"));
+  }
+
   if (ver->IsAtLeastGL(3u, 2u) || ver->IsAtLeastGLES(3u, 0u) ||
       ext.b_GL_ARB_sync) {
     fn.glWaitSyncFn =
@@ -2353,6 +2660,10 @@
   memset(this, 0, sizeof(*this));
 }
 
+void GLApiBase::glActiveShaderProgramFn(GLuint pipeline, GLuint program) {
+  driver_->fn.glActiveShaderProgramFn(pipeline, program);
+}
+
 void GLApiBase::glActiveTextureFn(GLenum texture) {
   driver_->fn.glActiveTextureFn(texture);
 }
@@ -2430,6 +2741,10 @@
                                       access, format);
 }
 
+void GLApiBase::glBindProgramPipelineFn(GLuint pipeline) {
+  driver_->fn.glBindProgramPipelineFn(pipeline);
+}
+
 void GLApiBase::glBindRenderbufferEXTFn(GLenum target, GLuint renderbuffer) {
   driver_->fn.glBindRenderbufferEXTFn(target, renderbuffer);
 }
@@ -2456,6 +2771,13 @@
   driver_->fn.glBindVertexArrayOESFn(array);
 }
 
+void GLApiBase::glBindVertexBufferFn(GLuint bindingindex,
+                                     GLuint buffer,
+                                     GLintptr offset,
+                                     GLsizei stride) {
+  driver_->fn.glBindVertexBufferFn(bindingindex, buffer, offset, stride);
+}
+
 void GLApiBase::glBlendBarrierKHRFn(void) {
   driver_->fn.glBlendBarrierKHRFn();
 }
@@ -2828,6 +3150,12 @@
   return driver_->fn.glCreateShaderFn(type);
 }
 
+GLuint GLApiBase::glCreateShaderProgramvFn(GLenum type,
+                                           GLsizei count,
+                                           const char* const* strings) {
+  return driver_->fn.glCreateShaderProgramvFn(type, count, strings);
+}
+
 void GLApiBase::glCullFaceFn(GLenum mode) {
   driver_->fn.glCullFaceFn(mode);
 }
@@ -2881,6 +3209,10 @@
   driver_->fn.glDeleteProgramFn(program);
 }
 
+void GLApiBase::glDeleteProgramPipelinesFn(GLsizei n, const GLuint* pipelines) {
+  driver_->fn.glDeleteProgramPipelinesFn(n, pipelines);
+}
+
 void GLApiBase::glDeleteQueriesFn(GLsizei n, const GLuint* ids) {
   driver_->fn.glDeleteQueriesFn(n, ids);
 }
@@ -2948,10 +3280,24 @@
   driver_->fn.glDiscardFramebufferEXTFn(target, numAttachments, attachments);
 }
 
+void GLApiBase::glDispatchComputeFn(GLuint numGroupsX,
+                                    GLuint numGroupsY,
+                                    GLuint numGroupsZ) {
+  driver_->fn.glDispatchComputeFn(numGroupsX, numGroupsY, numGroupsZ);
+}
+
+void GLApiBase::glDispatchComputeIndirectFn(GLintptr indirect) {
+  driver_->fn.glDispatchComputeIndirectFn(indirect);
+}
+
 void GLApiBase::glDrawArraysFn(GLenum mode, GLint first, GLsizei count) {
   driver_->fn.glDrawArraysFn(mode, first, count);
 }
 
+void GLApiBase::glDrawArraysIndirectFn(GLenum mode, const void* indirect) {
+  driver_->fn.glDrawArraysIndirectFn(mode, indirect);
+}
+
 void GLApiBase::glDrawArraysInstancedANGLEFn(GLenum mode,
                                              GLint first,
                                              GLsizei count,
@@ -2974,6 +3320,12 @@
   driver_->fn.glDrawElementsFn(mode, count, type, indices);
 }
 
+void GLApiBase::glDrawElementsIndirectFn(GLenum mode,
+                                         GLenum type,
+                                         const void* indirect) {
+  driver_->fn.glDrawElementsIndirectFn(mode, type, indirect);
+}
+
 void GLApiBase::glDrawElementsInstancedANGLEFn(GLenum mode,
                                                GLsizei count,
                                                GLenum type,
@@ -3114,6 +3466,10 @@
   return driver_->fn.glGenPathsNVFn(range);
 }
 
+GLuint GLApiBase::glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) {
+  return driver_->fn.glGenProgramPipelinesFn(n, pipelines);
+}
+
 void GLApiBase::glGenQueriesFn(GLsizei n, GLuint* ids) {
   driver_->fn.glGenQueriesFn(n, ids);
 }
@@ -3207,6 +3563,12 @@
   return driver_->fn.glGetAttribLocationFn(program, name);
 }
 
+void GLApiBase::glGetBooleani_vFn(GLenum target,
+                                  GLuint index,
+                                  GLboolean* data) {
+  driver_->fn.glGetBooleani_vFn(target, index, data);
+}
+
 void GLApiBase::glGetBooleani_vRobustANGLEFn(GLenum target,
                                              GLuint index,
                                              GLsizei bufSize,
@@ -3318,6 +3680,12 @@
       target, attachment, pname, bufSize, length, params);
 }
 
+void GLApiBase::glGetFramebufferParameterivFn(GLenum target,
+                                              GLenum pname,
+                                              GLint* params) {
+  driver_->fn.glGetFramebufferParameterivFn(target, pname, params);
+}
+
 void GLApiBase::glGetFramebufferParameterivRobustANGLEFn(GLenum target,
                                                          GLenum pname,
                                                          GLsizei bufSize,
@@ -3514,6 +3882,25 @@
                                           params);
 }
 
+void GLApiBase::glGetProgramPipelineInfoLogFn(GLuint pipeline,
+                                              GLsizei bufSize,
+                                              GLsizei* length,
+                                              GLchar* infoLog) {
+  driver_->fn.glGetProgramPipelineInfoLogFn(pipeline, bufSize, length, infoLog);
+}
+
+void GLApiBase::glGetProgramPipelineivFn(GLuint pipeline,
+                                         GLenum pname,
+                                         GLint* params) {
+  driver_->fn.glGetProgramPipelineivFn(pipeline, pname, params);
+}
+
+void GLApiBase::glGetProgramResourceIndexFn(GLuint program,
+                                            GLenum programInterface,
+                                            const GLchar* name) {
+  driver_->fn.glGetProgramResourceIndexFn(program, programInterface, name);
+}
+
 void GLApiBase::glGetProgramResourceivFn(GLuint program,
                                          GLenum programInterface,
                                          GLuint index,
@@ -4005,6 +4392,10 @@
   return driver_->fn.glIsProgramFn(program);
 }
 
+GLboolean GLApiBase::glIsProgramPipelineFn(GLuint pipeline) {
+  return driver_->fn.glIsProgramPipelineFn(pipeline);
+}
+
 GLboolean GLApiBase::glIsQueryFn(GLuint query) {
   return driver_->fn.glIsQueryFn(query);
 }
@@ -4064,6 +4455,10 @@
   driver_->fn.glMatrixLoadIdentityEXTFn(matrixMode);
 }
 
+void GLApiBase::glMemoryBarrierByRegionFn(GLbitfield barriers) {
+  driver_->fn.glMemoryBarrierByRegionFn(barriers);
+}
+
 void GLApiBase::glMemoryBarrierEXTFn(GLbitfield barriers) {
   driver_->fn.glMemoryBarrierEXTFn(barriers);
 }
@@ -4157,6 +4552,259 @@
                                                 components, coeffs);
 }
 
+void GLApiBase::glProgramUniform1fFn(GLuint program,
+                                     GLint location,
+                                     GLfloat v0) {
+  driver_->fn.glProgramUniform1fFn(program, location, v0);
+}
+
+void GLApiBase::glProgramUniform1fvFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLfloat* value) {
+  driver_->fn.glProgramUniform1fvFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform1iFn(GLuint program, GLint location, GLint v0) {
+  driver_->fn.glProgramUniform1iFn(program, location, v0);
+}
+
+void GLApiBase::glProgramUniform1ivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLint* value) {
+  driver_->fn.glProgramUniform1ivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform1uiFn(GLuint program,
+                                      GLint location,
+                                      GLuint v0) {
+  driver_->fn.glProgramUniform1uiFn(program, location, v0);
+}
+
+void GLApiBase::glProgramUniform1uivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLuint* value) {
+  driver_->fn.glProgramUniform1uivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform2fFn(GLuint program,
+                                     GLint location,
+                                     GLfloat v0,
+                                     GLfloat v1) {
+  driver_->fn.glProgramUniform2fFn(program, location, v0, v1);
+}
+
+void GLApiBase::glProgramUniform2fvFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLfloat* value) {
+  driver_->fn.glProgramUniform2fvFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform2iFn(GLuint program,
+                                     GLint location,
+                                     GLint v0,
+                                     GLint v1) {
+  driver_->fn.glProgramUniform2iFn(program, location, v0, v1);
+}
+
+void GLApiBase::glProgramUniform2ivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLint* value) {
+  driver_->fn.glProgramUniform2ivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform2uiFn(GLuint program,
+                                      GLint location,
+                                      GLuint v0,
+                                      GLuint v1) {
+  driver_->fn.glProgramUniform2uiFn(program, location, v0, v1);
+}
+
+void GLApiBase::glProgramUniform2uivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLuint* value) {
+  driver_->fn.glProgramUniform2uivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform3fFn(GLuint program,
+                                     GLint location,
+                                     GLfloat v0,
+                                     GLfloat v1,
+                                     GLfloat v2) {
+  driver_->fn.glProgramUniform3fFn(program, location, v0, v1, v2);
+}
+
+void GLApiBase::glProgramUniform3fvFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLfloat* value) {
+  driver_->fn.glProgramUniform3fvFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform3iFn(GLuint program,
+                                     GLint location,
+                                     GLint v0,
+                                     GLint v1,
+                                     GLint v2) {
+  driver_->fn.glProgramUniform3iFn(program, location, v0, v1, v2);
+}
+
+void GLApiBase::glProgramUniform3ivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLint* value) {
+  driver_->fn.glProgramUniform3ivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform3uiFn(GLuint program,
+                                      GLint location,
+                                      GLuint v0,
+                                      GLuint v1,
+                                      GLuint v2) {
+  driver_->fn.glProgramUniform3uiFn(program, location, v0, v1, v2);
+}
+
+void GLApiBase::glProgramUniform3uivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLuint* value) {
+  driver_->fn.glProgramUniform3uivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform4fFn(GLuint program,
+                                     GLint location,
+                                     GLfloat v0,
+                                     GLfloat v1,
+                                     GLfloat v2,
+                                     GLfloat v3) {
+  driver_->fn.glProgramUniform4fFn(program, location, v0, v1, v2, v3);
+}
+
+void GLApiBase::glProgramUniform4fvFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLfloat* value) {
+  driver_->fn.glProgramUniform4fvFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform4iFn(GLuint program,
+                                     GLint location,
+                                     GLint v0,
+                                     GLint v1,
+                                     GLint v2,
+                                     GLint v3) {
+  driver_->fn.glProgramUniform4iFn(program, location, v0, v1, v2, v3);
+}
+
+void GLApiBase::glProgramUniform4ivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLint* value) {
+  driver_->fn.glProgramUniform4ivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniform4uiFn(GLuint program,
+                                      GLint location,
+                                      GLuint v0,
+                                      GLuint v1,
+                                      GLuint v2,
+                                      GLuint v3) {
+  driver_->fn.glProgramUniform4uiFn(program, location, v0, v1, v2, v3);
+}
+
+void GLApiBase::glProgramUniform4uivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLuint* value) {
+  driver_->fn.glProgramUniform4uivFn(program, location, count, value);
+}
+
+void GLApiBase::glProgramUniformMatrix2fvFn(GLuint program,
+                                            GLint location,
+                                            GLsizei count,
+                                            GLboolean transpose,
+                                            const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix2fvFn(program, location, count, transpose,
+                                          value);
+}
+
+void GLApiBase::glProgramUniformMatrix2x3fvFn(GLuint program,
+                                              GLint location,
+                                              GLsizei count,
+                                              GLboolean transpose,
+                                              const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix2x3fvFn(program, location, count, transpose,
+                                            value);
+}
+
+void GLApiBase::glProgramUniformMatrix2x4fvFn(GLuint program,
+                                              GLint location,
+                                              GLsizei count,
+                                              GLboolean transpose,
+                                              const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix2x4fvFn(program, location, count, transpose,
+                                            value);
+}
+
+void GLApiBase::glProgramUniformMatrix3fvFn(GLuint program,
+                                            GLint location,
+                                            GLsizei count,
+                                            GLboolean transpose,
+                                            const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix3fvFn(program, location, count, transpose,
+                                          value);
+}
+
+void GLApiBase::glProgramUniformMatrix3x2fvFn(GLuint program,
+                                              GLint location,
+                                              GLsizei count,
+                                              GLboolean transpose,
+                                              const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix3x2fvFn(program, location, count, transpose,
+                                            value);
+}
+
+void GLApiBase::glProgramUniformMatrix3x4fvFn(GLuint program,
+                                              GLint location,
+                                              GLsizei count,
+                                              GLboolean transpose,
+                                              const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix3x4fvFn(program, location, count, transpose,
+                                            value);
+}
+
+void GLApiBase::glProgramUniformMatrix4fvFn(GLuint program,
+                                            GLint location,
+                                            GLsizei count,
+                                            GLboolean transpose,
+                                            const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix4fvFn(program, location, count, transpose,
+                                          value);
+}
+
+void GLApiBase::glProgramUniformMatrix4x2fvFn(GLuint program,
+                                              GLint location,
+                                              GLsizei count,
+                                              GLboolean transpose,
+                                              const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix4x2fvFn(program, location, count, transpose,
+                                            value);
+}
+
+void GLApiBase::glProgramUniformMatrix4x3fvFn(GLuint program,
+                                              GLint location,
+                                              GLsizei count,
+                                              GLboolean transpose,
+                                              const GLfloat* value) {
+  driver_->fn.glProgramUniformMatrix4x3fvFn(program, location, count, transpose,
+                                            value);
+}
+
 void GLApiBase::glPushDebugGroupFn(GLenum source,
                                    GLuint id,
                                    GLsizei length,
@@ -4257,6 +4905,10 @@
   driver_->fn.glSampleCoverageFn(value, invert);
 }
 
+void GLApiBase::glSampleMaskiFn(GLuint maskNumber, GLbitfield mask) {
+  driver_->fn.glSampleMaskiFn(maskNumber, mask);
+}
+
 void GLApiBase::glSamplerParameterfFn(GLuint sampler,
                                       GLenum pname,
                                       GLfloat param) {
@@ -4589,6 +5241,16 @@
                                   height);
 }
 
+void GLApiBase::glTexStorage2DMultisampleFn(GLenum target,
+                                            GLsizei samples,
+                                            GLenum internalformat,
+                                            GLsizei width,
+                                            GLsizei height,
+                                            GLboolean fixedsamplelocations) {
+  driver_->fn.glTexStorage2DMultisampleFn(target, samples, internalformat,
+                                          width, height, fixedsamplelocations);
+}
+
 void GLApiBase::glTexStorage3DFn(GLenum target,
                                  GLsizei levels,
                                  GLenum internalformat,
@@ -4872,10 +5534,20 @@
   driver_->fn.glUseProgramFn(program);
 }
 
+void GLApiBase::glUseProgramStagesFn(GLuint pipeline,
+                                     GLbitfield stages,
+                                     GLuint program) {
+  driver_->fn.glUseProgramStagesFn(pipeline, stages, program);
+}
+
 void GLApiBase::glValidateProgramFn(GLuint program) {
   driver_->fn.glValidateProgramFn(program);
 }
 
+void GLApiBase::glValidateProgramPipelineFn(GLuint pipeline) {
+  driver_->fn.glValidateProgramPipelineFn(pipeline);
+}
+
 void GLApiBase::glVertexAttrib1fFn(GLuint indx, GLfloat x) {
   driver_->fn.glVertexAttrib1fFn(indx, x);
 }
@@ -4915,10 +5587,24 @@
   driver_->fn.glVertexAttrib4fvFn(indx, values);
 }
 
+void GLApiBase::glVertexAttribBindingFn(GLuint attribindex,
+                                        GLuint bindingindex) {
+  driver_->fn.glVertexAttribBindingFn(attribindex, bindingindex);
+}
+
 void GLApiBase::glVertexAttribDivisorANGLEFn(GLuint index, GLuint divisor) {
   driver_->fn.glVertexAttribDivisorANGLEFn(index, divisor);
 }
 
+void GLApiBase::glVertexAttribFormatFn(GLuint attribindex,
+                                       GLint size,
+                                       GLenum type,
+                                       GLboolean normalized,
+                                       GLuint relativeoffset) {
+  driver_->fn.glVertexAttribFormatFn(attribindex, size, type, normalized,
+                                     relativeoffset);
+}
+
 void GLApiBase::glVertexAttribI4iFn(GLuint indx,
                                     GLint x,
                                     GLint y,
@@ -4943,6 +5629,13 @@
   driver_->fn.glVertexAttribI4uivFn(indx, values);
 }
 
+void GLApiBase::glVertexAttribIFormatFn(GLuint attribindex,
+                                        GLint size,
+                                        GLenum type,
+                                        GLuint relativeoffset) {
+  driver_->fn.glVertexAttribIFormatFn(attribindex, size, type, relativeoffset);
+}
+
 void GLApiBase::glVertexAttribIPointerFn(GLuint indx,
                                          GLint size,
                                          GLenum type,
@@ -4961,6 +5654,10 @@
                                       ptr);
 }
 
+void GLApiBase::glVertexBindingDivisorFn(GLuint bindingindex, GLuint divisor) {
+  driver_->fn.glVertexBindingDivisorFn(bindingindex, divisor);
+}
+
 void GLApiBase::glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) {
   driver_->fn.glViewportFn(x, y, width, height);
 }
@@ -4975,6 +5672,11 @@
   driver_->fn.glWindowRectanglesEXTFn(mode, n, box);
 }
 
+void TraceGLApi::glActiveShaderProgramFn(GLuint pipeline, GLuint program) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glActiveShaderProgram")
+  gl_api_->glActiveShaderProgramFn(pipeline, program);
+}
+
 void TraceGLApi::glActiveTextureFn(GLenum texture) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glActiveTexture")
   gl_api_->glActiveTextureFn(texture);
@@ -5070,6 +5772,11 @@
                                    access, format);
 }
 
+void TraceGLApi::glBindProgramPipelineFn(GLuint pipeline) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glBindProgramPipeline")
+  gl_api_->glBindProgramPipelineFn(pipeline);
+}
+
 void TraceGLApi::glBindRenderbufferEXTFn(GLenum target, GLuint renderbuffer) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glBindRenderbufferEXT")
   gl_api_->glBindRenderbufferEXTFn(target, renderbuffer);
@@ -5103,6 +5810,14 @@
   gl_api_->glBindVertexArrayOESFn(array);
 }
 
+void TraceGLApi::glBindVertexBufferFn(GLuint bindingindex,
+                                      GLuint buffer,
+                                      GLintptr offset,
+                                      GLsizei stride) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glBindVertexBuffer")
+  gl_api_->glBindVertexBufferFn(bindingindex, buffer, offset, stride);
+}
+
 void TraceGLApi::glBlendBarrierKHRFn(void) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glBlendBarrierKHR")
   gl_api_->glBlendBarrierKHRFn();
@@ -5527,6 +6242,13 @@
   return gl_api_->glCreateShaderFn(type);
 }
 
+GLuint TraceGLApi::glCreateShaderProgramvFn(GLenum type,
+                                            GLsizei count,
+                                            const char* const* strings) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glCreateShaderProgramv")
+  return gl_api_->glCreateShaderProgramvFn(type, count, strings);
+}
+
 void TraceGLApi::glCullFaceFn(GLenum mode) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glCullFace")
   gl_api_->glCullFaceFn(mode);
@@ -5589,6 +6311,12 @@
   gl_api_->glDeleteProgramFn(program);
 }
 
+void TraceGLApi::glDeleteProgramPipelinesFn(GLsizei n,
+                                            const GLuint* pipelines) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glDeleteProgramPipelines")
+  gl_api_->glDeleteProgramPipelinesFn(n, pipelines);
+}
+
 void TraceGLApi::glDeleteQueriesFn(GLsizei n, const GLuint* ids) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glDeleteQueries")
   gl_api_->glDeleteQueriesFn(n, ids);
@@ -5672,11 +6400,28 @@
   gl_api_->glDiscardFramebufferEXTFn(target, numAttachments, attachments);
 }
 
+void TraceGLApi::glDispatchComputeFn(GLuint numGroupsX,
+                                     GLuint numGroupsY,
+                                     GLuint numGroupsZ) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glDispatchCompute")
+  gl_api_->glDispatchComputeFn(numGroupsX, numGroupsY, numGroupsZ);
+}
+
+void TraceGLApi::glDispatchComputeIndirectFn(GLintptr indirect) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glDispatchComputeIndirect")
+  gl_api_->glDispatchComputeIndirectFn(indirect);
+}
+
 void TraceGLApi::glDrawArraysFn(GLenum mode, GLint first, GLsizei count) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glDrawArrays")
   gl_api_->glDrawArraysFn(mode, first, count);
 }
 
+void TraceGLApi::glDrawArraysIndirectFn(GLenum mode, const void* indirect) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glDrawArraysIndirect")
+  gl_api_->glDrawArraysIndirectFn(mode, indirect);
+}
+
 void TraceGLApi::glDrawArraysInstancedANGLEFn(GLenum mode,
                                               GLint first,
                                               GLsizei count,
@@ -5703,6 +6448,13 @@
   gl_api_->glDrawElementsFn(mode, count, type, indices);
 }
 
+void TraceGLApi::glDrawElementsIndirectFn(GLenum mode,
+                                          GLenum type,
+                                          const void* indirect) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glDrawElementsIndirect")
+  gl_api_->glDrawElementsIndirectFn(mode, type, indirect);
+}
+
 void TraceGLApi::glDrawElementsInstancedANGLEFn(GLenum mode,
                                                 GLsizei count,
                                                 GLenum type,
@@ -5874,6 +6626,11 @@
   return gl_api_->glGenPathsNVFn(range);
 }
 
+GLuint TraceGLApi::glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGenProgramPipelines")
+  return gl_api_->glGenProgramPipelinesFn(n, pipelines);
+}
+
 void TraceGLApi::glGenQueriesFn(GLsizei n, GLuint* ids) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGenQueries")
   gl_api_->glGenQueriesFn(n, ids);
@@ -5984,6 +6741,13 @@
   return gl_api_->glGetAttribLocationFn(program, name);
 }
 
+void TraceGLApi::glGetBooleani_vFn(GLenum target,
+                                   GLuint index,
+                                   GLboolean* data) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetBooleani_v")
+  gl_api_->glGetBooleani_vFn(target, index, data);
+}
+
 void TraceGLApi::glGetBooleani_vRobustANGLEFn(GLenum target,
                                               GLuint index,
                                               GLsizei bufSize,
@@ -6115,6 +6879,14 @@
       target, attachment, pname, bufSize, length, params);
 }
 
+void TraceGLApi::glGetFramebufferParameterivFn(GLenum target,
+                                               GLenum pname,
+                                               GLint* params) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glGetFramebufferParameteriv")
+  gl_api_->glGetFramebufferParameterivFn(target, pname, params);
+}
+
 void TraceGLApi::glGetFramebufferParameterivRobustANGLEFn(GLenum target,
                                                           GLenum pname,
                                                           GLsizei bufSize,
@@ -6342,6 +7114,29 @@
   gl_api_->glGetProgramivRobustANGLEFn(program, pname, bufSize, length, params);
 }
 
+void TraceGLApi::glGetProgramPipelineInfoLogFn(GLuint pipeline,
+                                               GLsizei bufSize,
+                                               GLsizei* length,
+                                               GLchar* infoLog) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glGetProgramPipelineInfoLog")
+  gl_api_->glGetProgramPipelineInfoLogFn(pipeline, bufSize, length, infoLog);
+}
+
+void TraceGLApi::glGetProgramPipelineivFn(GLuint pipeline,
+                                          GLenum pname,
+                                          GLint* params) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetProgramPipelineiv")
+  gl_api_->glGetProgramPipelineivFn(pipeline, pname, params);
+}
+
+void TraceGLApi::glGetProgramResourceIndexFn(GLuint program,
+                                             GLenum programInterface,
+                                             const GLchar* name) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetProgramResourceIndex")
+  gl_api_->glGetProgramResourceIndexFn(program, programInterface, name);
+}
+
 void TraceGLApi::glGetProgramResourceivFn(GLuint program,
                                           GLenum programInterface,
                                           GLuint index,
@@ -6923,6 +7718,11 @@
   return gl_api_->glIsProgramFn(program);
 }
 
+GLboolean TraceGLApi::glIsProgramPipelineFn(GLuint pipeline) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glIsProgramPipeline")
+  return gl_api_->glIsProgramPipelineFn(pipeline);
+}
+
 GLboolean TraceGLApi::glIsQueryFn(GLuint query) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glIsQuery")
   return gl_api_->glIsQueryFn(query);
@@ -6996,6 +7796,11 @@
   gl_api_->glMatrixLoadIdentityEXTFn(matrixMode);
 }
 
+void TraceGLApi::glMemoryBarrierByRegionFn(GLbitfield barriers) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glMemoryBarrierByRegion")
+  gl_api_->glMemoryBarrierByRegionFn(barriers);
+}
+
 void TraceGLApi::glMemoryBarrierEXTFn(GLbitfield barriers) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glMemoryBarrierEXT")
   gl_api_->glMemoryBarrierEXTFn(barriers);
@@ -7110,6 +7915,300 @@
                                              components, coeffs);
 }
 
+void TraceGLApi::glProgramUniform1fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform1f")
+  gl_api_->glProgramUniform1fFn(program, location, v0);
+}
+
+void TraceGLApi::glProgramUniform1fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform1fv")
+  gl_api_->glProgramUniform1fvFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform1iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform1i")
+  gl_api_->glProgramUniform1iFn(program, location, v0);
+}
+
+void TraceGLApi::glProgramUniform1ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform1iv")
+  gl_api_->glProgramUniform1ivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform1uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform1ui")
+  gl_api_->glProgramUniform1uiFn(program, location, v0);
+}
+
+void TraceGLApi::glProgramUniform1uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform1uiv")
+  gl_api_->glProgramUniform1uivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform2fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0,
+                                      GLfloat v1) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform2f")
+  gl_api_->glProgramUniform2fFn(program, location, v0, v1);
+}
+
+void TraceGLApi::glProgramUniform2fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform2fv")
+  gl_api_->glProgramUniform2fvFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform2iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0,
+                                      GLint v1) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform2i")
+  gl_api_->glProgramUniform2iFn(program, location, v0, v1);
+}
+
+void TraceGLApi::glProgramUniform2ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform2iv")
+  gl_api_->glProgramUniform2ivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform2uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0,
+                                       GLuint v1) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform2ui")
+  gl_api_->glProgramUniform2uiFn(program, location, v0, v1);
+}
+
+void TraceGLApi::glProgramUniform2uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform2uiv")
+  gl_api_->glProgramUniform2uivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform3fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0,
+                                      GLfloat v1,
+                                      GLfloat v2) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform3f")
+  gl_api_->glProgramUniform3fFn(program, location, v0, v1, v2);
+}
+
+void TraceGLApi::glProgramUniform3fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform3fv")
+  gl_api_->glProgramUniform3fvFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform3iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0,
+                                      GLint v1,
+                                      GLint v2) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform3i")
+  gl_api_->glProgramUniform3iFn(program, location, v0, v1, v2);
+}
+
+void TraceGLApi::glProgramUniform3ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform3iv")
+  gl_api_->glProgramUniform3ivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform3uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0,
+                                       GLuint v1,
+                                       GLuint v2) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform3ui")
+  gl_api_->glProgramUniform3uiFn(program, location, v0, v1, v2);
+}
+
+void TraceGLApi::glProgramUniform3uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform3uiv")
+  gl_api_->glProgramUniform3uivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform4fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0,
+                                      GLfloat v1,
+                                      GLfloat v2,
+                                      GLfloat v3) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform4f")
+  gl_api_->glProgramUniform4fFn(program, location, v0, v1, v2, v3);
+}
+
+void TraceGLApi::glProgramUniform4fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform4fv")
+  gl_api_->glProgramUniform4fvFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform4iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0,
+                                      GLint v1,
+                                      GLint v2,
+                                      GLint v3) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform4i")
+  gl_api_->glProgramUniform4iFn(program, location, v0, v1, v2, v3);
+}
+
+void TraceGLApi::glProgramUniform4ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform4iv")
+  gl_api_->glProgramUniform4ivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniform4uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0,
+                                       GLuint v1,
+                                       GLuint v2,
+                                       GLuint v3) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform4ui")
+  gl_api_->glProgramUniform4uiFn(program, location, v0, v1, v2, v3);
+}
+
+void TraceGLApi::glProgramUniform4uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniform4uiv")
+  gl_api_->glProgramUniform4uivFn(program, location, count, value);
+}
+
+void TraceGLApi::glProgramUniformMatrix2fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniformMatrix2fv")
+  gl_api_->glProgramUniformMatrix2fvFn(program, location, count, transpose,
+                                       value);
+}
+
+void TraceGLApi::glProgramUniformMatrix2x3fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glProgramUniformMatrix2x3fv")
+  gl_api_->glProgramUniformMatrix2x3fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void TraceGLApi::glProgramUniformMatrix2x4fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glProgramUniformMatrix2x4fv")
+  gl_api_->glProgramUniformMatrix2x4fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void TraceGLApi::glProgramUniformMatrix3fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniformMatrix3fv")
+  gl_api_->glProgramUniformMatrix3fvFn(program, location, count, transpose,
+                                       value);
+}
+
+void TraceGLApi::glProgramUniformMatrix3x2fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glProgramUniformMatrix3x2fv")
+  gl_api_->glProgramUniformMatrix3x2fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void TraceGLApi::glProgramUniformMatrix3x4fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glProgramUniformMatrix3x4fv")
+  gl_api_->glProgramUniformMatrix3x4fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void TraceGLApi::glProgramUniformMatrix4fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glProgramUniformMatrix4fv")
+  gl_api_->glProgramUniformMatrix4fvFn(program, location, count, transpose,
+                                       value);
+}
+
+void TraceGLApi::glProgramUniformMatrix4x2fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glProgramUniformMatrix4x2fv")
+  gl_api_->glProgramUniformMatrix4x2fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void TraceGLApi::glProgramUniformMatrix4x3fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "TraceGLAPI::glProgramUniformMatrix4x3fv")
+  gl_api_->glProgramUniformMatrix4x3fvFn(program, location, count, transpose,
+                                         value);
+}
+
 void TraceGLApi::glPushDebugGroupFn(GLenum source,
                                     GLuint id,
                                     GLsizei length,
@@ -7226,6 +8325,11 @@
   gl_api_->glSampleCoverageFn(value, invert);
 }
 
+void TraceGLApi::glSampleMaskiFn(GLuint maskNumber, GLbitfield mask) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glSampleMaski")
+  gl_api_->glSampleMaskiFn(maskNumber, mask);
+}
+
 void TraceGLApi::glSamplerParameterfFn(GLuint sampler,
                                        GLenum pname,
                                        GLfloat param) {
@@ -7613,6 +8717,17 @@
   gl_api_->glTexStorage2DEXTFn(target, levels, internalformat, width, height);
 }
 
+void TraceGLApi::glTexStorage2DMultisampleFn(GLenum target,
+                                             GLsizei samples,
+                                             GLenum internalformat,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLboolean fixedsamplelocations) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glTexStorage2DMultisample")
+  gl_api_->glTexStorage2DMultisampleFn(target, samples, internalformat, width,
+                                       height, fixedsamplelocations);
+}
+
 void TraceGLApi::glTexStorage3DFn(GLenum target,
                                   GLsizei levels,
                                   GLenum internalformat,
@@ -7940,11 +9055,23 @@
   gl_api_->glUseProgramFn(program);
 }
 
+void TraceGLApi::glUseProgramStagesFn(GLuint pipeline,
+                                      GLbitfield stages,
+                                      GLuint program) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glUseProgramStages")
+  gl_api_->glUseProgramStagesFn(pipeline, stages, program);
+}
+
 void TraceGLApi::glValidateProgramFn(GLuint program) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glValidateProgram")
   gl_api_->glValidateProgramFn(program);
 }
 
+void TraceGLApi::glValidateProgramPipelineFn(GLuint pipeline) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glValidateProgramPipeline")
+  gl_api_->glValidateProgramPipelineFn(pipeline);
+}
+
 void TraceGLApi::glVertexAttrib1fFn(GLuint indx, GLfloat x) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glVertexAttrib1f")
   gl_api_->glVertexAttrib1fFn(indx, x);
@@ -7992,11 +9119,27 @@
   gl_api_->glVertexAttrib4fvFn(indx, values);
 }
 
+void TraceGLApi::glVertexAttribBindingFn(GLuint attribindex,
+                                         GLuint bindingindex) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glVertexAttribBinding")
+  gl_api_->glVertexAttribBindingFn(attribindex, bindingindex);
+}
+
 void TraceGLApi::glVertexAttribDivisorANGLEFn(GLuint index, GLuint divisor) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glVertexAttribDivisorANGLE")
   gl_api_->glVertexAttribDivisorANGLEFn(index, divisor);
 }
 
+void TraceGLApi::glVertexAttribFormatFn(GLuint attribindex,
+                                        GLint size,
+                                        GLenum type,
+                                        GLboolean normalized,
+                                        GLuint relativeoffset) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glVertexAttribFormat")
+  gl_api_->glVertexAttribFormatFn(attribindex, size, type, normalized,
+                                  relativeoffset);
+}
+
 void TraceGLApi::glVertexAttribI4iFn(GLuint indx,
                                      GLint x,
                                      GLint y,
@@ -8025,6 +9168,14 @@
   gl_api_->glVertexAttribI4uivFn(indx, values);
 }
 
+void TraceGLApi::glVertexAttribIFormatFn(GLuint attribindex,
+                                         GLint size,
+                                         GLenum type,
+                                         GLuint relativeoffset) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glVertexAttribIFormat")
+  gl_api_->glVertexAttribIFormatFn(attribindex, size, type, relativeoffset);
+}
+
 void TraceGLApi::glVertexAttribIPointerFn(GLuint indx,
                                           GLint size,
                                           GLenum type,
@@ -8044,6 +9195,11 @@
   gl_api_->glVertexAttribPointerFn(indx, size, type, normalized, stride, ptr);
 }
 
+void TraceGLApi::glVertexBindingDivisorFn(GLuint bindingindex, GLuint divisor) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glVertexBindingDivisor")
+  gl_api_->glVertexBindingDivisorFn(bindingindex, divisor);
+}
+
 void TraceGLApi::glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glViewport")
   gl_api_->glViewportFn(x, y, width, height);
@@ -8061,6 +9217,12 @@
   gl_api_->glWindowRectanglesEXTFn(mode, n, box);
 }
 
+void DebugGLApi::glActiveShaderProgramFn(GLuint pipeline, GLuint program) {
+  GL_SERVICE_LOG("glActiveShaderProgram"
+                 << "(" << pipeline << ", " << program << ")");
+  gl_api_->glActiveShaderProgramFn(pipeline, program);
+}
+
 void DebugGLApi::glActiveTextureFn(GLenum texture) {
   GL_SERVICE_LOG("glActiveTexture"
                  << "(" << GLEnums::GetStringEnum(texture) << ")");
@@ -8176,6 +9338,12 @@
                                    access, format);
 }
 
+void DebugGLApi::glBindProgramPipelineFn(GLuint pipeline) {
+  GL_SERVICE_LOG("glBindProgramPipeline"
+                 << "(" << pipeline << ")");
+  gl_api_->glBindProgramPipelineFn(pipeline);
+}
+
 void DebugGLApi::glBindRenderbufferEXTFn(GLenum target, GLuint renderbuffer) {
   GL_SERVICE_LOG("glBindRenderbufferEXT"
                  << "(" << GLEnums::GetStringEnum(target) << ", "
@@ -8216,6 +9384,16 @@
   gl_api_->glBindVertexArrayOESFn(array);
 }
 
+void DebugGLApi::glBindVertexBufferFn(GLuint bindingindex,
+                                      GLuint buffer,
+                                      GLintptr offset,
+                                      GLsizei stride) {
+  GL_SERVICE_LOG("glBindVertexBuffer"
+                 << "(" << bindingindex << ", " << buffer << ", " << offset
+                 << ", " << stride << ")");
+  gl_api_->glBindVertexBufferFn(bindingindex, buffer, offset, stride);
+}
+
 void DebugGLApi::glBlendBarrierKHRFn(void) {
   GL_SERVICE_LOG("glBlendBarrierKHR"
                  << "("
@@ -8774,6 +9952,17 @@
   return result;
 }
 
+GLuint DebugGLApi::glCreateShaderProgramvFn(GLenum type,
+                                            GLsizei count,
+                                            const char* const* strings) {
+  GL_SERVICE_LOG("glCreateShaderProgramv"
+                 << "(" << GLEnums::GetStringEnum(type) << ", " << count << ", "
+                 << static_cast<const void*>(strings) << ")");
+  GLuint result = gl_api_->glCreateShaderProgramvFn(type, count, strings);
+  GL_SERVICE_LOG("GL_RESULT: " << result);
+  return result;
+}
+
 void DebugGLApi::glCullFaceFn(GLenum mode) {
   GL_SERVICE_LOG("glCullFace"
                  << "(" << GLEnums::GetStringEnum(mode) << ")");
@@ -8858,6 +10047,14 @@
   gl_api_->glDeleteProgramFn(program);
 }
 
+void DebugGLApi::glDeleteProgramPipelinesFn(GLsizei n,
+                                            const GLuint* pipelines) {
+  GL_SERVICE_LOG("glDeleteProgramPipelines"
+                 << "(" << n << ", " << static_cast<const void*>(pipelines)
+                 << ")");
+  gl_api_->glDeleteProgramPipelinesFn(n, pipelines);
+}
+
 void DebugGLApi::glDeleteQueriesFn(GLsizei n, const GLuint* ids) {
   GL_SERVICE_LOG("glDeleteQueries"
                  << "(" << n << ", " << static_cast<const void*>(ids) << ")");
@@ -8963,6 +10160,21 @@
   gl_api_->glDiscardFramebufferEXTFn(target, numAttachments, attachments);
 }
 
+void DebugGLApi::glDispatchComputeFn(GLuint numGroupsX,
+                                     GLuint numGroupsY,
+                                     GLuint numGroupsZ) {
+  GL_SERVICE_LOG("glDispatchCompute"
+                 << "(" << numGroupsX << ", " << numGroupsY << ", "
+                 << numGroupsZ << ")");
+  gl_api_->glDispatchComputeFn(numGroupsX, numGroupsY, numGroupsZ);
+}
+
+void DebugGLApi::glDispatchComputeIndirectFn(GLintptr indirect) {
+  GL_SERVICE_LOG("glDispatchComputeIndirect"
+                 << "(" << indirect << ")");
+  gl_api_->glDispatchComputeIndirectFn(indirect);
+}
+
 void DebugGLApi::glDrawArraysFn(GLenum mode, GLint first, GLsizei count) {
   GL_SERVICE_LOG("glDrawArrays"
                  << "(" << GLEnums::GetStringEnum(mode) << ", " << first << ", "
@@ -8970,6 +10182,13 @@
   gl_api_->glDrawArraysFn(mode, first, count);
 }
 
+void DebugGLApi::glDrawArraysIndirectFn(GLenum mode, const void* indirect) {
+  GL_SERVICE_LOG("glDrawArraysIndirect"
+                 << "(" << GLEnums::GetStringEnum(mode) << ", "
+                 << static_cast<const void*>(indirect) << ")");
+  gl_api_->glDrawArraysIndirectFn(mode, indirect);
+}
+
 void DebugGLApi::glDrawArraysInstancedANGLEFn(GLenum mode,
                                               GLint first,
                                               GLsizei count,
@@ -9003,6 +10222,16 @@
   gl_api_->glDrawElementsFn(mode, count, type, indices);
 }
 
+void DebugGLApi::glDrawElementsIndirectFn(GLenum mode,
+                                          GLenum type,
+                                          const void* indirect) {
+  GL_SERVICE_LOG("glDrawElementsIndirect"
+                 << "(" << GLEnums::GetStringEnum(mode) << ", "
+                 << GLEnums::GetStringEnum(type) << ", "
+                 << static_cast<const void*>(indirect) << ")");
+  gl_api_->glDrawElementsIndirectFn(mode, type, indirect);
+}
+
 void DebugGLApi::glDrawElementsInstancedANGLEFn(GLenum mode,
                                                 GLsizei count,
                                                 GLenum type,
@@ -9227,6 +10456,15 @@
   return result;
 }
 
+GLuint DebugGLApi::glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) {
+  GL_SERVICE_LOG("glGenProgramPipelines"
+                 << "(" << n << ", " << static_cast<const void*>(pipelines)
+                 << ")");
+  GLuint result = gl_api_->glGenProgramPipelinesFn(n, pipelines);
+  GL_SERVICE_LOG("GL_RESULT: " << result);
+  return result;
+}
+
 void DebugGLApi::glGenQueriesFn(GLsizei n, GLuint* ids) {
   GL_SERVICE_LOG("glGenQueries"
                  << "(" << n << ", " << static_cast<const void*>(ids) << ")");
@@ -9375,6 +10613,15 @@
   return result;
 }
 
+void DebugGLApi::glGetBooleani_vFn(GLenum target,
+                                   GLuint index,
+                                   GLboolean* data) {
+  GL_SERVICE_LOG("glGetBooleani_v"
+                 << "(" << GLEnums::GetStringEnum(target) << ", " << index
+                 << ", " << static_cast<const void*>(data) << ")");
+  gl_api_->glGetBooleani_vFn(target, index, data);
+}
+
 void DebugGLApi::glGetBooleani_vRobustANGLEFn(GLenum target,
                                               GLuint index,
                                               GLsizei bufSize,
@@ -9560,6 +10807,16 @@
       target, attachment, pname, bufSize, length, params);
 }
 
+void DebugGLApi::glGetFramebufferParameterivFn(GLenum target,
+                                               GLenum pname,
+                                               GLint* params) {
+  GL_SERVICE_LOG("glGetFramebufferParameteriv"
+                 << "(" << GLEnums::GetStringEnum(target) << ", "
+                 << GLEnums::GetStringEnum(pname) << ", "
+                 << static_cast<const void*>(params) << ")");
+  gl_api_->glGetFramebufferParameterivFn(target, pname, params);
+}
+
 void DebugGLApi::glGetFramebufferParameterivRobustANGLEFn(GLenum target,
                                                           GLenum pname,
                                                           GLsizei bufSize,
@@ -9862,6 +11119,36 @@
   gl_api_->glGetProgramivRobustANGLEFn(program, pname, bufSize, length, params);
 }
 
+void DebugGLApi::glGetProgramPipelineInfoLogFn(GLuint pipeline,
+                                               GLsizei bufSize,
+                                               GLsizei* length,
+                                               GLchar* infoLog) {
+  GL_SERVICE_LOG("glGetProgramPipelineInfoLog"
+                 << "(" << pipeline << ", " << bufSize << ", "
+                 << static_cast<const void*>(length) << ", "
+                 << static_cast<const void*>(infoLog) << ")");
+  gl_api_->glGetProgramPipelineInfoLogFn(pipeline, bufSize, length, infoLog);
+}
+
+void DebugGLApi::glGetProgramPipelineivFn(GLuint pipeline,
+                                          GLenum pname,
+                                          GLint* params) {
+  GL_SERVICE_LOG("glGetProgramPipelineiv"
+                 << "(" << pipeline << ", " << GLEnums::GetStringEnum(pname)
+                 << ", " << static_cast<const void*>(params) << ")");
+  gl_api_->glGetProgramPipelineivFn(pipeline, pname, params);
+}
+
+void DebugGLApi::glGetProgramResourceIndexFn(GLuint program,
+                                             GLenum programInterface,
+                                             const GLchar* name) {
+  GL_SERVICE_LOG("glGetProgramResourceIndex"
+                 << "(" << program << ", "
+                 << GLEnums::GetStringEnum(programInterface) << ", "
+                 << static_cast<const void*>(name) << ")");
+  gl_api_->glGetProgramResourceIndexFn(program, programInterface, name);
+}
+
 void DebugGLApi::glGetProgramResourceivFn(GLuint program,
                                           GLenum programInterface,
                                           GLuint index,
@@ -10628,6 +11915,14 @@
   return result;
 }
 
+GLboolean DebugGLApi::glIsProgramPipelineFn(GLuint pipeline) {
+  GL_SERVICE_LOG("glIsProgramPipeline"
+                 << "(" << pipeline << ")");
+  GLboolean result = gl_api_->glIsProgramPipelineFn(pipeline);
+  GL_SERVICE_LOG("GL_RESULT: " << result);
+  return result;
+}
+
 GLboolean DebugGLApi::glIsQueryFn(GLuint query) {
   GL_SERVICE_LOG("glIsQuery"
                  << "(" << query << ")");
@@ -10738,6 +12033,12 @@
   gl_api_->glMatrixLoadIdentityEXTFn(matrixMode);
 }
 
+void DebugGLApi::glMemoryBarrierByRegionFn(GLbitfield barriers) {
+  GL_SERVICE_LOG("glMemoryBarrierByRegion"
+                 << "(" << barriers << ")");
+  gl_api_->glMemoryBarrierByRegionFn(barriers);
+}
+
 void DebugGLApi::glMemoryBarrierEXTFn(GLbitfield barriers) {
   GL_SERVICE_LOG("glMemoryBarrierEXT"
                  << "(" << barriers << ")");
@@ -10888,6 +12189,366 @@
                                              components, coeffs);
 }
 
+void DebugGLApi::glProgramUniform1fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0) {
+  GL_SERVICE_LOG("glProgramUniform1f"
+                 << "(" << program << ", " << location << ", " << v0 << ")");
+  gl_api_->glProgramUniform1fFn(program, location, v0);
+}
+
+void DebugGLApi::glProgramUniform1fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniform1fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform1fvFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform1iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0) {
+  GL_SERVICE_LOG("glProgramUniform1i"
+                 << "(" << program << ", " << location << ", " << v0 << ")");
+  gl_api_->glProgramUniform1iFn(program, location, v0);
+}
+
+void DebugGLApi::glProgramUniform1ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  GL_SERVICE_LOG("glProgramUniform1iv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform1ivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform1uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0) {
+  GL_SERVICE_LOG("glProgramUniform1ui"
+                 << "(" << program << ", " << location << ", " << v0 << ")");
+  gl_api_->glProgramUniform1uiFn(program, location, v0);
+}
+
+void DebugGLApi::glProgramUniform1uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  GL_SERVICE_LOG("glProgramUniform1uiv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform1uivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform2fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0,
+                                      GLfloat v1) {
+  GL_SERVICE_LOG("glProgramUniform2f"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ")");
+  gl_api_->glProgramUniform2fFn(program, location, v0, v1);
+}
+
+void DebugGLApi::glProgramUniform2fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniform2fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform2fvFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform2iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0,
+                                      GLint v1) {
+  GL_SERVICE_LOG("glProgramUniform2i"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ")");
+  gl_api_->glProgramUniform2iFn(program, location, v0, v1);
+}
+
+void DebugGLApi::glProgramUniform2ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  GL_SERVICE_LOG("glProgramUniform2iv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform2ivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform2uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0,
+                                       GLuint v1) {
+  GL_SERVICE_LOG("glProgramUniform2ui"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ")");
+  gl_api_->glProgramUniform2uiFn(program, location, v0, v1);
+}
+
+void DebugGLApi::glProgramUniform2uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  GL_SERVICE_LOG("glProgramUniform2uiv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform2uivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform3fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0,
+                                      GLfloat v1,
+                                      GLfloat v2) {
+  GL_SERVICE_LOG("glProgramUniform3f"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ", " << v2 << ")");
+  gl_api_->glProgramUniform3fFn(program, location, v0, v1, v2);
+}
+
+void DebugGLApi::glProgramUniform3fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniform3fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform3fvFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform3iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0,
+                                      GLint v1,
+                                      GLint v2) {
+  GL_SERVICE_LOG("glProgramUniform3i"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ", " << v2 << ")");
+  gl_api_->glProgramUniform3iFn(program, location, v0, v1, v2);
+}
+
+void DebugGLApi::glProgramUniform3ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  GL_SERVICE_LOG("glProgramUniform3iv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform3ivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform3uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0,
+                                       GLuint v1,
+                                       GLuint v2) {
+  GL_SERVICE_LOG("glProgramUniform3ui"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ", " << v2 << ")");
+  gl_api_->glProgramUniform3uiFn(program, location, v0, v1, v2);
+}
+
+void DebugGLApi::glProgramUniform3uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  GL_SERVICE_LOG("glProgramUniform3uiv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform3uivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform4fFn(GLuint program,
+                                      GLint location,
+                                      GLfloat v0,
+                                      GLfloat v1,
+                                      GLfloat v2,
+                                      GLfloat v3) {
+  GL_SERVICE_LOG("glProgramUniform4f"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ", " << v2 << ", " << v3 << ")");
+  gl_api_->glProgramUniform4fFn(program, location, v0, v1, v2, v3);
+}
+
+void DebugGLApi::glProgramUniform4fvFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniform4fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform4fvFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform4iFn(GLuint program,
+                                      GLint location,
+                                      GLint v0,
+                                      GLint v1,
+                                      GLint v2,
+                                      GLint v3) {
+  GL_SERVICE_LOG("glProgramUniform4i"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ", " << v2 << ", " << v3 << ")");
+  gl_api_->glProgramUniform4iFn(program, location, v0, v1, v2, v3);
+}
+
+void DebugGLApi::glProgramUniform4ivFn(GLuint program,
+                                       GLint location,
+                                       GLsizei count,
+                                       const GLint* value) {
+  GL_SERVICE_LOG("glProgramUniform4iv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform4ivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniform4uiFn(GLuint program,
+                                       GLint location,
+                                       GLuint v0,
+                                       GLuint v1,
+                                       GLuint v2,
+                                       GLuint v3) {
+  GL_SERVICE_LOG("glProgramUniform4ui"
+                 << "(" << program << ", " << location << ", " << v0 << ", "
+                 << v1 << ", " << v2 << ", " << v3 << ")");
+  gl_api_->glProgramUniform4uiFn(program, location, v0, v1, v2, v3);
+}
+
+void DebugGLApi::glProgramUniform4uivFn(GLuint program,
+                                        GLint location,
+                                        GLsizei count,
+                                        const GLuint* value) {
+  GL_SERVICE_LOG("glProgramUniform4uiv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniform4uivFn(program, location, count, value);
+}
+
+void DebugGLApi::glProgramUniformMatrix2fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix2fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix2fvFn(program, location, count, transpose,
+                                       value);
+}
+
+void DebugGLApi::glProgramUniformMatrix2x3fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix2x3fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix2x3fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void DebugGLApi::glProgramUniformMatrix2x4fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix2x4fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix2x4fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void DebugGLApi::glProgramUniformMatrix3fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix3fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix3fvFn(program, location, count, transpose,
+                                       value);
+}
+
+void DebugGLApi::glProgramUniformMatrix3x2fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix3x2fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix3x2fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void DebugGLApi::glProgramUniformMatrix3x4fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix3x4fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix3x4fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void DebugGLApi::glProgramUniformMatrix4fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix4fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix4fvFn(program, location, count, transpose,
+                                       value);
+}
+
+void DebugGLApi::glProgramUniformMatrix4x2fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix4x2fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix4x2fvFn(program, location, count, transpose,
+                                         value);
+}
+
+void DebugGLApi::glProgramUniformMatrix4x3fvFn(GLuint program,
+                                               GLint location,
+                                               GLsizei count,
+                                               GLboolean transpose,
+                                               const GLfloat* value) {
+  GL_SERVICE_LOG("glProgramUniformMatrix4x3fv"
+                 << "(" << program << ", " << location << ", " << count << ", "
+                 << GLEnums::GetStringBool(transpose) << ", "
+                 << static_cast<const void*>(value) << ")");
+  gl_api_->glProgramUniformMatrix4x3fvFn(program, location, count, transpose,
+                                         value);
+}
+
 void DebugGLApi::glPushDebugGroupFn(GLenum source,
                                     GLuint id,
                                     GLsizei length,
@@ -11041,6 +12702,12 @@
   gl_api_->glSampleCoverageFn(value, invert);
 }
 
+void DebugGLApi::glSampleMaskiFn(GLuint maskNumber, GLbitfield mask) {
+  GL_SERVICE_LOG("glSampleMaski"
+                 << "(" << maskNumber << ", " << mask << ")");
+  gl_api_->glSampleMaskiFn(maskNumber, mask);
+}
+
 void DebugGLApi::glSamplerParameterfFn(GLuint sampler,
                                        GLenum pname,
                                        GLfloat param) {
@@ -11565,6 +13232,21 @@
   gl_api_->glTexStorage2DEXTFn(target, levels, internalformat, width, height);
 }
 
+void DebugGLApi::glTexStorage2DMultisampleFn(GLenum target,
+                                             GLsizei samples,
+                                             GLenum internalformat,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             GLboolean fixedsamplelocations) {
+  GL_SERVICE_LOG("glTexStorage2DMultisample"
+                 << "(" << GLEnums::GetStringEnum(target) << ", " << samples
+                 << ", " << GLEnums::GetStringEnum(internalformat) << ", "
+                 << width << ", " << height << ", "
+                 << GLEnums::GetStringBool(fixedsamplelocations) << ")");
+  gl_api_->glTexStorage2DMultisampleFn(target, samples, internalformat, width,
+                                       height, fixedsamplelocations);
+}
+
 void DebugGLApi::glTexStorage3DFn(GLenum target,
                                   GLsizei levels,
                                   GLenum internalformat,
@@ -11994,12 +13676,27 @@
   gl_api_->glUseProgramFn(program);
 }
 
+void DebugGLApi::glUseProgramStagesFn(GLuint pipeline,
+                                      GLbitfield stages,
+                                      GLuint program) {
+  GL_SERVICE_LOG("glUseProgramStages"
+                 << "(" << pipeline << ", " << stages << ", " << program
+                 << ")");
+  gl_api_->glUseProgramStagesFn(pipeline, stages, program);
+}
+
 void DebugGLApi::glValidateProgramFn(GLuint program) {
   GL_SERVICE_LOG("glValidateProgram"
                  << "(" << program << ")");
   gl_api_->glValidateProgramFn(program);
 }
 
+void DebugGLApi::glValidateProgramPipelineFn(GLuint pipeline) {
+  GL_SERVICE_LOG("glValidateProgramPipeline"
+                 << "(" << pipeline << ")");
+  gl_api_->glValidateProgramPipelineFn(pipeline);
+}
+
 void DebugGLApi::glVertexAttrib1fFn(GLuint indx, GLfloat x) {
   GL_SERVICE_LOG("glVertexAttrib1f"
                  << "(" << indx << ", " << x << ")");
@@ -12060,12 +13757,33 @@
   gl_api_->glVertexAttrib4fvFn(indx, values);
 }
 
+void DebugGLApi::glVertexAttribBindingFn(GLuint attribindex,
+                                         GLuint bindingindex) {
+  GL_SERVICE_LOG("glVertexAttribBinding"
+                 << "(" << attribindex << ", " << bindingindex << ")");
+  gl_api_->glVertexAttribBindingFn(attribindex, bindingindex);
+}
+
 void DebugGLApi::glVertexAttribDivisorANGLEFn(GLuint index, GLuint divisor) {
   GL_SERVICE_LOG("glVertexAttribDivisorANGLE"
                  << "(" << index << ", " << divisor << ")");
   gl_api_->glVertexAttribDivisorANGLEFn(index, divisor);
 }
 
+void DebugGLApi::glVertexAttribFormatFn(GLuint attribindex,
+                                        GLint size,
+                                        GLenum type,
+                                        GLboolean normalized,
+                                        GLuint relativeoffset) {
+  GL_SERVICE_LOG("glVertexAttribFormat"
+                 << "(" << attribindex << ", " << size << ", "
+                 << GLEnums::GetStringEnum(type) << ", "
+                 << GLEnums::GetStringBool(normalized) << ", " << relativeoffset
+                 << ")");
+  gl_api_->glVertexAttribFormatFn(attribindex, size, type, normalized,
+                                  relativeoffset);
+}
+
 void DebugGLApi::glVertexAttribI4iFn(GLuint indx,
                                      GLint x,
                                      GLint y,
@@ -12102,6 +13820,17 @@
   gl_api_->glVertexAttribI4uivFn(indx, values);
 }
 
+void DebugGLApi::glVertexAttribIFormatFn(GLuint attribindex,
+                                         GLint size,
+                                         GLenum type,
+                                         GLuint relativeoffset) {
+  GL_SERVICE_LOG("glVertexAttribIFormat"
+                 << "(" << attribindex << ", " << size << ", "
+                 << GLEnums::GetStringEnum(type) << ", " << relativeoffset
+                 << ")");
+  gl_api_->glVertexAttribIFormatFn(attribindex, size, type, relativeoffset);
+}
+
 void DebugGLApi::glVertexAttribIPointerFn(GLuint indx,
                                           GLint size,
                                           GLenum type,
@@ -12128,6 +13857,12 @@
   gl_api_->glVertexAttribPointerFn(indx, size, type, normalized, stride, ptr);
 }
 
+void DebugGLApi::glVertexBindingDivisorFn(GLuint bindingindex, GLuint divisor) {
+  GL_SERVICE_LOG("glVertexBindingDivisor"
+                 << "(" << bindingindex << ", " << divisor << ")");
+  gl_api_->glVertexBindingDivisorFn(bindingindex, divisor);
+}
+
 void DebugGLApi::glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) {
   GL_SERVICE_LOG("glViewport"
                  << "(" << x << ", " << y << ", " << width << ", " << height
@@ -12159,6 +13894,10 @@
 }
 }  // namespace
 
+void NoContextGLApi::glActiveShaderProgramFn(GLuint pipeline, GLuint program) {
+  NoContextHelper("glActiveShaderProgram");
+}
+
 void NoContextGLApi::glActiveTextureFn(GLenum texture) {
   NoContextHelper("glActiveTexture");
 }
@@ -12236,6 +13975,10 @@
   NoContextHelper("glBindImageTextureEXT");
 }
 
+void NoContextGLApi::glBindProgramPipelineFn(GLuint pipeline) {
+  NoContextHelper("glBindProgramPipeline");
+}
+
 void NoContextGLApi::glBindRenderbufferEXTFn(GLenum target,
                                              GLuint renderbuffer) {
   NoContextHelper("glBindRenderbufferEXT");
@@ -12263,6 +14006,13 @@
   NoContextHelper("glBindVertexArrayOES");
 }
 
+void NoContextGLApi::glBindVertexBufferFn(GLuint bindingindex,
+                                          GLuint buffer,
+                                          GLintptr offset,
+                                          GLsizei stride) {
+  NoContextHelper("glBindVertexBuffer");
+}
+
 void NoContextGLApi::glBlendBarrierKHRFn(void) {
   NoContextHelper("glBlendBarrierKHR");
 }
@@ -12616,6 +14366,13 @@
   return 0U;
 }
 
+GLuint NoContextGLApi::glCreateShaderProgramvFn(GLenum type,
+                                                GLsizei count,
+                                                const char* const* strings) {
+  NoContextHelper("glCreateShaderProgramv");
+  return 0U;
+}
+
 void NoContextGLApi::glCullFaceFn(GLenum mode) {
   NoContextHelper("glCullFace");
 }
@@ -12668,6 +14425,11 @@
   NoContextHelper("glDeleteProgram");
 }
 
+void NoContextGLApi::glDeleteProgramPipelinesFn(GLsizei n,
+                                                const GLuint* pipelines) {
+  NoContextHelper("glDeleteProgramPipelines");
+}
+
 void NoContextGLApi::glDeleteQueriesFn(GLsizei n, const GLuint* ids) {
   NoContextHelper("glDeleteQueries");
 }
@@ -12737,10 +14499,24 @@
   NoContextHelper("glDiscardFramebufferEXT");
 }
 
+void NoContextGLApi::glDispatchComputeFn(GLuint numGroupsX,
+                                         GLuint numGroupsY,
+                                         GLuint numGroupsZ) {
+  NoContextHelper("glDispatchCompute");
+}
+
+void NoContextGLApi::glDispatchComputeIndirectFn(GLintptr indirect) {
+  NoContextHelper("glDispatchComputeIndirect");
+}
+
 void NoContextGLApi::glDrawArraysFn(GLenum mode, GLint first, GLsizei count) {
   NoContextHelper("glDrawArrays");
 }
 
+void NoContextGLApi::glDrawArraysIndirectFn(GLenum mode, const void* indirect) {
+  NoContextHelper("glDrawArraysIndirect");
+}
+
 void NoContextGLApi::glDrawArraysInstancedANGLEFn(GLenum mode,
                                                   GLint first,
                                                   GLsizei count,
@@ -12763,6 +14539,12 @@
   NoContextHelper("glDrawElements");
 }
 
+void NoContextGLApi::glDrawElementsIndirectFn(GLenum mode,
+                                              GLenum type,
+                                              const void* indirect) {
+  NoContextHelper("glDrawElementsIndirect");
+}
+
 void NoContextGLApi::glDrawElementsInstancedANGLEFn(GLenum mode,
                                                     GLsizei count,
                                                     GLenum type,
@@ -12901,6 +14683,11 @@
   return 0U;
 }
 
+GLuint NoContextGLApi::glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) {
+  NoContextHelper("glGenProgramPipelines");
+  return 0U;
+}
+
 void NoContextGLApi::glGenQueriesFn(GLsizei n, GLuint* ids) {
   NoContextHelper("glGenQueries");
 }
@@ -12990,6 +14777,12 @@
   return 0;
 }
 
+void NoContextGLApi::glGetBooleani_vFn(GLenum target,
+                                       GLuint index,
+                                       GLboolean* data) {
+  NoContextHelper("glGetBooleani_v");
+}
+
 void NoContextGLApi::glGetBooleani_vRobustANGLEFn(GLenum target,
                                                   GLuint index,
                                                   GLsizei bufSize,
@@ -13102,6 +14895,12 @@
   NoContextHelper("glGetFramebufferAttachmentParameterivRobustANGLE");
 }
 
+void NoContextGLApi::glGetFramebufferParameterivFn(GLenum target,
+                                                   GLenum pname,
+                                                   GLint* params) {
+  NoContextHelper("glGetFramebufferParameteriv");
+}
+
 void NoContextGLApi::glGetFramebufferParameterivRobustANGLEFn(GLenum target,
                                                               GLenum pname,
                                                               GLsizei bufSize,
@@ -13292,6 +15091,25 @@
   NoContextHelper("glGetProgramivRobustANGLE");
 }
 
+void NoContextGLApi::glGetProgramPipelineInfoLogFn(GLuint pipeline,
+                                                   GLsizei bufSize,
+                                                   GLsizei* length,
+                                                   GLchar* infoLog) {
+  NoContextHelper("glGetProgramPipelineInfoLog");
+}
+
+void NoContextGLApi::glGetProgramPipelineivFn(GLuint pipeline,
+                                              GLenum pname,
+                                              GLint* params) {
+  NoContextHelper("glGetProgramPipelineiv");
+}
+
+void NoContextGLApi::glGetProgramResourceIndexFn(GLuint program,
+                                                 GLenum programInterface,
+                                                 const GLchar* name) {
+  NoContextHelper("glGetProgramResourceIndex");
+}
+
 void NoContextGLApi::glGetProgramResourceivFn(GLuint program,
                                               GLenum programInterface,
                                               GLuint index,
@@ -13771,6 +15589,11 @@
   return GL_FALSE;
 }
 
+GLboolean NoContextGLApi::glIsProgramPipelineFn(GLuint pipeline) {
+  NoContextHelper("glIsProgramPipeline");
+  return GL_FALSE;
+}
+
 GLboolean NoContextGLApi::glIsQueryFn(GLuint query) {
   NoContextHelper("glIsQuery");
   return GL_FALSE;
@@ -13840,6 +15663,10 @@
   NoContextHelper("glMatrixLoadIdentityEXT");
 }
 
+void NoContextGLApi::glMemoryBarrierByRegionFn(GLbitfield barriers) {
+  NoContextHelper("glMemoryBarrierByRegion");
+}
+
 void NoContextGLApi::glMemoryBarrierEXTFn(GLbitfield barriers) {
   NoContextHelper("glMemoryBarrierEXT");
 }
@@ -13937,6 +15764,252 @@
   NoContextHelper("glProgramPathFragmentInputGenNV");
 }
 
+void NoContextGLApi::glProgramUniform1fFn(GLuint program,
+                                          GLint location,
+                                          GLfloat v0) {
+  NoContextHelper("glProgramUniform1f");
+}
+
+void NoContextGLApi::glProgramUniform1fvFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLfloat* value) {
+  NoContextHelper("glProgramUniform1fv");
+}
+
+void NoContextGLApi::glProgramUniform1iFn(GLuint program,
+                                          GLint location,
+                                          GLint v0) {
+  NoContextHelper("glProgramUniform1i");
+}
+
+void NoContextGLApi::glProgramUniform1ivFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLint* value) {
+  NoContextHelper("glProgramUniform1iv");
+}
+
+void NoContextGLApi::glProgramUniform1uiFn(GLuint program,
+                                           GLint location,
+                                           GLuint v0) {
+  NoContextHelper("glProgramUniform1ui");
+}
+
+void NoContextGLApi::glProgramUniform1uivFn(GLuint program,
+                                            GLint location,
+                                            GLsizei count,
+                                            const GLuint* value) {
+  NoContextHelper("glProgramUniform1uiv");
+}
+
+void NoContextGLApi::glProgramUniform2fFn(GLuint program,
+                                          GLint location,
+                                          GLfloat v0,
+                                          GLfloat v1) {
+  NoContextHelper("glProgramUniform2f");
+}
+
+void NoContextGLApi::glProgramUniform2fvFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLfloat* value) {
+  NoContextHelper("glProgramUniform2fv");
+}
+
+void NoContextGLApi::glProgramUniform2iFn(GLuint program,
+                                          GLint location,
+                                          GLint v0,
+                                          GLint v1) {
+  NoContextHelper("glProgramUniform2i");
+}
+
+void NoContextGLApi::glProgramUniform2ivFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLint* value) {
+  NoContextHelper("glProgramUniform2iv");
+}
+
+void NoContextGLApi::glProgramUniform2uiFn(GLuint program,
+                                           GLint location,
+                                           GLuint v0,
+                                           GLuint v1) {
+  NoContextHelper("glProgramUniform2ui");
+}
+
+void NoContextGLApi::glProgramUniform2uivFn(GLuint program,
+                                            GLint location,
+                                            GLsizei count,
+                                            const GLuint* value) {
+  NoContextHelper("glProgramUniform2uiv");
+}
+
+void NoContextGLApi::glProgramUniform3fFn(GLuint program,
+                                          GLint location,
+                                          GLfloat v0,
+                                          GLfloat v1,
+                                          GLfloat v2) {
+  NoContextHelper("glProgramUniform3f");
+}
+
+void NoContextGLApi::glProgramUniform3fvFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLfloat* value) {
+  NoContextHelper("glProgramUniform3fv");
+}
+
+void NoContextGLApi::glProgramUniform3iFn(GLuint program,
+                                          GLint location,
+                                          GLint v0,
+                                          GLint v1,
+                                          GLint v2) {
+  NoContextHelper("glProgramUniform3i");
+}
+
+void NoContextGLApi::glProgramUniform3ivFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLint* value) {
+  NoContextHelper("glProgramUniform3iv");
+}
+
+void NoContextGLApi::glProgramUniform3uiFn(GLuint program,
+                                           GLint location,
+                                           GLuint v0,
+                                           GLuint v1,
+                                           GLuint v2) {
+  NoContextHelper("glProgramUniform3ui");
+}
+
+void NoContextGLApi::glProgramUniform3uivFn(GLuint program,
+                                            GLint location,
+                                            GLsizei count,
+                                            const GLuint* value) {
+  NoContextHelper("glProgramUniform3uiv");
+}
+
+void NoContextGLApi::glProgramUniform4fFn(GLuint program,
+                                          GLint location,
+                                          GLfloat v0,
+                                          GLfloat v1,
+                                          GLfloat v2,
+                                          GLfloat v3) {
+  NoContextHelper("glProgramUniform4f");
+}
+
+void NoContextGLApi::glProgramUniform4fvFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLfloat* value) {
+  NoContextHelper("glProgramUniform4fv");
+}
+
+void NoContextGLApi::glProgramUniform4iFn(GLuint program,
+                                          GLint location,
+                                          GLint v0,
+                                          GLint v1,
+                                          GLint v2,
+                                          GLint v3) {
+  NoContextHelper("glProgramUniform4i");
+}
+
+void NoContextGLApi::glProgramUniform4ivFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLint* value) {
+  NoContextHelper("glProgramUniform4iv");
+}
+
+void NoContextGLApi::glProgramUniform4uiFn(GLuint program,
+                                           GLint location,
+                                           GLuint v0,
+                                           GLuint v1,
+                                           GLuint v2,
+                                           GLuint v3) {
+  NoContextHelper("glProgramUniform4ui");
+}
+
+void NoContextGLApi::glProgramUniform4uivFn(GLuint program,
+                                            GLint location,
+                                            GLsizei count,
+                                            const GLuint* value) {
+  NoContextHelper("glProgramUniform4uiv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix2fvFn(GLuint program,
+                                                 GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix2fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix2x3fvFn(GLuint program,
+                                                   GLint location,
+                                                   GLsizei count,
+                                                   GLboolean transpose,
+                                                   const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix2x3fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix2x4fvFn(GLuint program,
+                                                   GLint location,
+                                                   GLsizei count,
+                                                   GLboolean transpose,
+                                                   const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix2x4fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix3fvFn(GLuint program,
+                                                 GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix3fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix3x2fvFn(GLuint program,
+                                                   GLint location,
+                                                   GLsizei count,
+                                                   GLboolean transpose,
+                                                   const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix3x2fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix3x4fvFn(GLuint program,
+                                                   GLint location,
+                                                   GLsizei count,
+                                                   GLboolean transpose,
+                                                   const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix3x4fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix4fvFn(GLuint program,
+                                                 GLint location,
+                                                 GLsizei count,
+                                                 GLboolean transpose,
+                                                 const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix4fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix4x2fvFn(GLuint program,
+                                                   GLint location,
+                                                   GLsizei count,
+                                                   GLboolean transpose,
+                                                   const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix4x2fv");
+}
+
+void NoContextGLApi::glProgramUniformMatrix4x3fvFn(GLuint program,
+                                                   GLint location,
+                                                   GLsizei count,
+                                                   GLboolean transpose,
+                                                   const GLfloat* value) {
+  NoContextHelper("glProgramUniformMatrix4x3fv");
+}
+
 void NoContextGLApi::glPushDebugGroupFn(GLenum source,
                                         GLuint id,
                                         GLsizei length,
@@ -14035,6 +16108,10 @@
   NoContextHelper("glSampleCoverage");
 }
 
+void NoContextGLApi::glSampleMaskiFn(GLuint maskNumber, GLbitfield mask) {
+  NoContextHelper("glSampleMaski");
+}
+
 void NoContextGLApi::glSamplerParameterfFn(GLuint sampler,
                                            GLenum pname,
                                            GLfloat param) {
@@ -14359,6 +16436,16 @@
   NoContextHelper("glTexStorage2DEXT");
 }
 
+void NoContextGLApi::glTexStorage2DMultisampleFn(
+    GLenum target,
+    GLsizei samples,
+    GLenum internalformat,
+    GLsizei width,
+    GLsizei height,
+    GLboolean fixedsamplelocations) {
+  NoContextHelper("glTexStorage2DMultisample");
+}
+
 void NoContextGLApi::glTexStorage3DFn(GLenum target,
                                       GLsizei levels,
                                       GLenum internalformat,
@@ -14645,10 +16732,20 @@
   NoContextHelper("glUseProgram");
 }
 
+void NoContextGLApi::glUseProgramStagesFn(GLuint pipeline,
+                                          GLbitfield stages,
+                                          GLuint program) {
+  NoContextHelper("glUseProgramStages");
+}
+
 void NoContextGLApi::glValidateProgramFn(GLuint program) {
   NoContextHelper("glValidateProgram");
 }
 
+void NoContextGLApi::glValidateProgramPipelineFn(GLuint pipeline) {
+  NoContextHelper("glValidateProgramPipeline");
+}
+
 void NoContextGLApi::glVertexAttrib1fFn(GLuint indx, GLfloat x) {
   NoContextHelper("glVertexAttrib1f");
 }
@@ -14688,11 +16785,24 @@
   NoContextHelper("glVertexAttrib4fv");
 }
 
+void NoContextGLApi::glVertexAttribBindingFn(GLuint attribindex,
+                                             GLuint bindingindex) {
+  NoContextHelper("glVertexAttribBinding");
+}
+
 void NoContextGLApi::glVertexAttribDivisorANGLEFn(GLuint index,
                                                   GLuint divisor) {
   NoContextHelper("glVertexAttribDivisorANGLE");
 }
 
+void NoContextGLApi::glVertexAttribFormatFn(GLuint attribindex,
+                                            GLint size,
+                                            GLenum type,
+                                            GLboolean normalized,
+                                            GLuint relativeoffset) {
+  NoContextHelper("glVertexAttribFormat");
+}
+
 void NoContextGLApi::glVertexAttribI4iFn(GLuint indx,
                                          GLint x,
                                          GLint y,
@@ -14717,6 +16827,13 @@
   NoContextHelper("glVertexAttribI4uiv");
 }
 
+void NoContextGLApi::glVertexAttribIFormatFn(GLuint attribindex,
+                                             GLint size,
+                                             GLenum type,
+                                             GLuint relativeoffset) {
+  NoContextHelper("glVertexAttribIFormat");
+}
+
 void NoContextGLApi::glVertexAttribIPointerFn(GLuint indx,
                                               GLint size,
                                               GLenum type,
@@ -14734,6 +16851,11 @@
   NoContextHelper("glVertexAttribPointer");
 }
 
+void NoContextGLApi::glVertexBindingDivisorFn(GLuint bindingindex,
+                                              GLuint divisor) {
+  NoContextHelper("glVertexBindingDivisor");
+}
+
 void NoContextGLApi::glViewportFn(GLint x,
                                   GLint y,
                                   GLsizei width,
diff --git a/ui/gl/gl_bindings_autogen_gl.h b/ui/gl/gl_bindings_autogen_gl.h
index 03b3a2b9..4a253f7 100644
--- a/ui/gl/gl_bindings_autogen_gl.h
+++ b/ui/gl/gl_bindings_autogen_gl.h
@@ -17,6 +17,8 @@
 
 class GLContext;
 
+typedef void(GL_BINDING_CALL* glActiveShaderProgramProc)(GLuint pipeline,
+                                                         GLuint program);
 typedef void(GL_BINDING_CALL* glActiveTextureProc)(GLenum texture);
 typedef void(GL_BINDING_CALL* glApplyFramebufferAttachmentCMAAINTELProc)(void);
 typedef void(GL_BINDING_CALL* glAttachShaderProc)(GLuint program,
@@ -57,6 +59,7 @@
                                                          GLint layer,
                                                          GLenum access,
                                                          GLint format);
+typedef void(GL_BINDING_CALL* glBindProgramPipelineProc)(GLuint pipeline);
 typedef void(GL_BINDING_CALL* glBindRenderbufferEXTProc)(GLenum target,
                                                          GLuint renderbuffer);
 typedef void(GL_BINDING_CALL* glBindSamplerProc)(GLuint unit, GLuint sampler);
@@ -68,6 +71,10 @@
     GLint location,
     const char* name);
 typedef void(GL_BINDING_CALL* glBindVertexArrayOESProc)(GLuint array);
+typedef void(GL_BINDING_CALL* glBindVertexBufferProc)(GLuint bindingindex,
+                                                      GLuint buffer,
+                                                      GLintptr offset,
+                                                      GLsizei stride);
 typedef void(GL_BINDING_CALL* glBlendBarrierKHRProc)(void);
 typedef void(GL_BINDING_CALL* glBlendColorProc)(GLclampf red,
                                                 GLclampf green,
@@ -293,6 +300,10 @@
                                                        GLenum coverMode);
 typedef GLuint(GL_BINDING_CALL* glCreateProgramProc)(void);
 typedef GLuint(GL_BINDING_CALL* glCreateShaderProc)(GLenum type);
+typedef GLuint(GL_BINDING_CALL* glCreateShaderProgramvProc)(
+    GLenum type,
+    GLsizei count,
+    const char* const* strings);
 typedef void(GL_BINDING_CALL* glCullFaceProc)(GLenum mode);
 typedef void(GL_BINDING_CALL* glDebugMessageCallbackProc)(
     GLDEBUGPROC callback,
@@ -320,6 +331,9 @@
     const GLuint* framebuffers);
 typedef void(GL_BINDING_CALL* glDeletePathsNVProc)(GLuint path, GLsizei range);
 typedef void(GL_BINDING_CALL* glDeleteProgramProc)(GLuint program);
+typedef void(GL_BINDING_CALL* glDeleteProgramPipelinesProc)(
+    GLsizei n,
+    const GLuint* pipelines);
 typedef void(GL_BINDING_CALL* glDeleteQueriesProc)(GLsizei n,
                                                    const GLuint* ids);
 typedef void(GL_BINDING_CALL* glDeleteRenderbuffersEXTProc)(
@@ -349,9 +363,15 @@
     GLenum target,
     GLsizei numAttachments,
     const GLenum* attachments);
+typedef void(GL_BINDING_CALL* glDispatchComputeProc)(GLuint numGroupsX,
+                                                     GLuint numGroupsY,
+                                                     GLuint numGroupsZ);
+typedef void(GL_BINDING_CALL* glDispatchComputeIndirectProc)(GLintptr indirect);
 typedef void(GL_BINDING_CALL* glDrawArraysProc)(GLenum mode,
                                                 GLint first,
                                                 GLsizei count);
+typedef void(GL_BINDING_CALL* glDrawArraysIndirectProc)(GLenum mode,
+                                                        const void* indirect);
 typedef void(GL_BINDING_CALL* glDrawArraysInstancedANGLEProc)(
     GLenum mode,
     GLint first,
@@ -364,6 +384,9 @@
                                                   GLsizei count,
                                                   GLenum type,
                                                   const void* indices);
+typedef void(GL_BINDING_CALL* glDrawElementsIndirectProc)(GLenum mode,
+                                                          GLenum type,
+                                                          const void* indirect);
 typedef void(GL_BINDING_CALL* glDrawElementsInstancedANGLEProc)(
     GLenum mode,
     GLsizei count,
@@ -428,6 +451,8 @@
 typedef void(GL_BINDING_CALL* glGenFramebuffersEXTProc)(GLsizei n,
                                                         GLuint* framebuffers);
 typedef GLuint(GL_BINDING_CALL* glGenPathsNVProc)(GLsizei range);
+typedef GLuint(GL_BINDING_CALL* glGenProgramPipelinesProc)(GLsizei n,
+                                                           GLuint* pipelines);
 typedef void(GL_BINDING_CALL* glGenQueriesProc)(GLsizei n, GLuint* ids);
 typedef void(GL_BINDING_CALL* glGenRenderbuffersEXTProc)(GLsizei n,
                                                          GLuint* renderbuffers);
@@ -481,6 +506,9 @@
                                                         GLuint* shaders);
 typedef GLint(GL_BINDING_CALL* glGetAttribLocationProc)(GLuint program,
                                                         const char* name);
+typedef void(GL_BINDING_CALL* glGetBooleani_vProc)(GLenum target,
+                                                   GLuint index,
+                                                   GLboolean* data);
 typedef void(GL_BINDING_CALL* glGetBooleani_vRobustANGLEProc)(GLenum target,
                                                               GLuint index,
                                                               GLsizei bufSize,
@@ -547,6 +575,9 @@
     GLsizei bufSize,
     GLsizei* length,
     GLint* params);
+typedef void(GL_BINDING_CALL* glGetFramebufferParameterivProc)(GLenum target,
+                                                               GLenum pname,
+                                                               GLint* params);
 typedef void(GL_BINDING_CALL* glGetFramebufferParameterivRobustANGLEProc)(
     GLenum target,
     GLenum pname,
@@ -661,6 +692,17 @@
                                                              GLsizei bufSize,
                                                              GLsizei* length,
                                                              GLint* params);
+typedef void(GL_BINDING_CALL* glGetProgramPipelineInfoLogProc)(GLuint pipeline,
+                                                               GLsizei bufSize,
+                                                               GLsizei* length,
+                                                               GLchar* infoLog);
+typedef void(GL_BINDING_CALL* glGetProgramPipelineivProc)(GLuint pipeline,
+                                                          GLenum pname,
+                                                          GLint* params);
+typedef void(GL_BINDING_CALL* glGetProgramResourceIndexProc)(
+    GLuint program,
+    GLenum programInterface,
+    const GLchar* name);
 typedef void(GL_BINDING_CALL* glGetProgramResourceivProc)(
     GLuint program,
     GLenum programInterface,
@@ -954,6 +996,7 @@
 typedef GLboolean(GL_BINDING_CALL* glIsFramebufferEXTProc)(GLuint framebuffer);
 typedef GLboolean(GL_BINDING_CALL* glIsPathNVProc)(GLuint path);
 typedef GLboolean(GL_BINDING_CALL* glIsProgramProc)(GLuint program);
+typedef GLboolean(GL_BINDING_CALL* glIsProgramPipelineProc)(GLuint pipeline);
 typedef GLboolean(GL_BINDING_CALL* glIsQueryProc)(GLuint query);
 typedef GLboolean(GL_BINDING_CALL* glIsRenderbufferEXTProc)(
     GLuint renderbuffer);
@@ -973,6 +1016,7 @@
 typedef void(GL_BINDING_CALL* glMatrixLoadfEXTProc)(GLenum matrixMode,
                                                     const GLfloat* m);
 typedef void(GL_BINDING_CALL* glMatrixLoadIdentityEXTProc)(GLenum matrixMode);
+typedef void(GL_BINDING_CALL* glMemoryBarrierByRegionProc)(GLbitfield barriers);
 typedef void(GL_BINDING_CALL* glMemoryBarrierEXTProc)(GLbitfield barriers);
 typedef void(GL_BINDING_CALL* glObjectLabelProc)(GLenum identifier,
                                                  GLuint name,
@@ -1018,6 +1062,162 @@
     GLenum genMode,
     GLint components,
     const GLfloat* coeffs);
+typedef void(GL_BINDING_CALL* glProgramUniform1fProc)(GLuint program,
+                                                      GLint location,
+                                                      GLfloat v0);
+typedef void(GL_BINDING_CALL* glProgramUniform1fvProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniform1iProc)(GLuint program,
+                                                      GLint location,
+                                                      GLint v0);
+typedef void(GL_BINDING_CALL* glProgramUniform1ivProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLint* value);
+typedef void(GL_BINDING_CALL* glProgramUniform1uiProc)(GLuint program,
+                                                       GLint location,
+                                                       GLuint v0);
+typedef void(GL_BINDING_CALL* glProgramUniform1uivProc)(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        const GLuint* value);
+typedef void(GL_BINDING_CALL* glProgramUniform2fProc)(GLuint program,
+                                                      GLint location,
+                                                      GLfloat v0,
+                                                      GLfloat v1);
+typedef void(GL_BINDING_CALL* glProgramUniform2fvProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniform2iProc)(GLuint program,
+                                                      GLint location,
+                                                      GLint v0,
+                                                      GLint v1);
+typedef void(GL_BINDING_CALL* glProgramUniform2ivProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLint* value);
+typedef void(GL_BINDING_CALL* glProgramUniform2uiProc)(GLuint program,
+                                                       GLint location,
+                                                       GLuint v0,
+                                                       GLuint v1);
+typedef void(GL_BINDING_CALL* glProgramUniform2uivProc)(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        const GLuint* value);
+typedef void(GL_BINDING_CALL* glProgramUniform3fProc)(GLuint program,
+                                                      GLint location,
+                                                      GLfloat v0,
+                                                      GLfloat v1,
+                                                      GLfloat v2);
+typedef void(GL_BINDING_CALL* glProgramUniform3fvProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniform3iProc)(GLuint program,
+                                                      GLint location,
+                                                      GLint v0,
+                                                      GLint v1,
+                                                      GLint v2);
+typedef void(GL_BINDING_CALL* glProgramUniform3ivProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLint* value);
+typedef void(GL_BINDING_CALL* glProgramUniform3uiProc)(GLuint program,
+                                                       GLint location,
+                                                       GLuint v0,
+                                                       GLuint v1,
+                                                       GLuint v2);
+typedef void(GL_BINDING_CALL* glProgramUniform3uivProc)(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        const GLuint* value);
+typedef void(GL_BINDING_CALL* glProgramUniform4fProc)(GLuint program,
+                                                      GLint location,
+                                                      GLfloat v0,
+                                                      GLfloat v1,
+                                                      GLfloat v2,
+                                                      GLfloat v3);
+typedef void(GL_BINDING_CALL* glProgramUniform4fvProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniform4iProc)(GLuint program,
+                                                      GLint location,
+                                                      GLint v0,
+                                                      GLint v1,
+                                                      GLint v2,
+                                                      GLint v3);
+typedef void(GL_BINDING_CALL* glProgramUniform4ivProc)(GLuint program,
+                                                       GLint location,
+                                                       GLsizei count,
+                                                       const GLint* value);
+typedef void(GL_BINDING_CALL* glProgramUniform4uiProc)(GLuint program,
+                                                       GLint location,
+                                                       GLuint v0,
+                                                       GLuint v1,
+                                                       GLuint v2,
+                                                       GLuint v3);
+typedef void(GL_BINDING_CALL* glProgramUniform4uivProc)(GLuint program,
+                                                        GLint location,
+                                                        GLsizei count,
+                                                        const GLuint* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix2fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix2x3fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix2x4fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix3fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix3x2fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix3x4fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix4fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix4x2fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
+typedef void(GL_BINDING_CALL* glProgramUniformMatrix4x3fvProc)(
+    GLuint program,
+    GLint location,
+    GLsizei count,
+    GLboolean transpose,
+    const GLfloat* value);
 typedef void(GL_BINDING_CALL* glPushDebugGroupProc)(GLenum source,
                                                     GLuint id,
                                                     GLsizei length,
@@ -1077,6 +1277,8 @@
 typedef void(GL_BINDING_CALL* glResumeTransformFeedbackProc)(void);
 typedef void(GL_BINDING_CALL* glSampleCoverageProc)(GLclampf value,
                                                     GLboolean invert);
+typedef void(GL_BINDING_CALL* glSampleMaskiProc)(GLuint maskNumber,
+                                                 GLbitfield mask);
 typedef void(GL_BINDING_CALL* glSamplerParameterfProc)(GLuint sampler,
                                                        GLenum pname,
                                                        GLfloat param);
@@ -1282,6 +1484,13 @@
                                                      GLenum internalformat,
                                                      GLsizei width,
                                                      GLsizei height);
+typedef void(GL_BINDING_CALL* glTexStorage2DMultisampleProc)(
+    GLenum target,
+    GLsizei samples,
+    GLenum internalformat,
+    GLsizei width,
+    GLsizei height,
+    GLboolean fixedsamplelocations);
 typedef void(GL_BINDING_CALL* glTexStorage3DProc)(GLenum target,
                                                   GLsizei levels,
                                                   GLenum internalformat,
@@ -1454,7 +1663,11 @@
                                                         const GLfloat* value);
 typedef GLboolean(GL_BINDING_CALL* glUnmapBufferProc)(GLenum target);
 typedef void(GL_BINDING_CALL* glUseProgramProc)(GLuint program);
+typedef void(GL_BINDING_CALL* glUseProgramStagesProc)(GLuint pipeline,
+                                                      GLbitfield stages,
+                                                      GLuint program);
 typedef void(GL_BINDING_CALL* glValidateProgramProc)(GLuint program);
+typedef void(GL_BINDING_CALL* glValidateProgramPipelineProc)(GLuint pipeline);
 typedef void(GL_BINDING_CALL* glVertexAttrib1fProc)(GLuint indx, GLfloat x);
 typedef void(GL_BINDING_CALL* glVertexAttrib1fvProc)(GLuint indx,
                                                      const GLfloat* values);
@@ -1476,8 +1689,15 @@
                                                     GLfloat w);
 typedef void(GL_BINDING_CALL* glVertexAttrib4fvProc)(GLuint indx,
                                                      const GLfloat* values);
+typedef void(GL_BINDING_CALL* glVertexAttribBindingProc)(GLuint attribindex,
+                                                         GLuint bindingindex);
 typedef void(GL_BINDING_CALL* glVertexAttribDivisorANGLEProc)(GLuint index,
                                                               GLuint divisor);
+typedef void(GL_BINDING_CALL* glVertexAttribFormatProc)(GLuint attribindex,
+                                                        GLint size,
+                                                        GLenum type,
+                                                        GLboolean normalized,
+                                                        GLuint relativeoffset);
 typedef void(GL_BINDING_CALL* glVertexAttribI4iProc)(GLuint indx,
                                                      GLint x,
                                                      GLint y,
@@ -1492,6 +1712,10 @@
                                                       GLuint w);
 typedef void(GL_BINDING_CALL* glVertexAttribI4uivProc)(GLuint indx,
                                                        const GLuint* values);
+typedef void(GL_BINDING_CALL* glVertexAttribIFormatProc)(GLuint attribindex,
+                                                         GLint size,
+                                                         GLenum type,
+                                                         GLuint relativeoffset);
 typedef void(GL_BINDING_CALL* glVertexAttribIPointerProc)(GLuint indx,
                                                           GLint size,
                                                           GLenum type,
@@ -1503,6 +1727,8 @@
                                                          GLboolean normalized,
                                                          GLsizei stride,
                                                          const void* ptr);
+typedef void(GL_BINDING_CALL* glVertexBindingDivisorProc)(GLuint bindingindex,
+                                                          GLuint divisor);
 typedef void(GL_BINDING_CALL* glViewportProc)(GLint x,
                                               GLint y,
                                               GLsizei width,
@@ -1590,6 +1816,7 @@
 };
 
 struct ProcsGL {
+  glActiveShaderProgramProc glActiveShaderProgramFn;
   glActiveTextureProc glActiveTextureFn;
   glApplyFramebufferAttachmentCMAAINTELProc
       glApplyFramebufferAttachmentCMAAINTELFn;
@@ -1605,12 +1832,14 @@
   glBindFragmentInputLocationCHROMIUMProc glBindFragmentInputLocationCHROMIUMFn;
   glBindFramebufferEXTProc glBindFramebufferEXTFn;
   glBindImageTextureEXTProc glBindImageTextureEXTFn;
+  glBindProgramPipelineProc glBindProgramPipelineFn;
   glBindRenderbufferEXTProc glBindRenderbufferEXTFn;
   glBindSamplerProc glBindSamplerFn;
   glBindTextureProc glBindTextureFn;
   glBindTransformFeedbackProc glBindTransformFeedbackFn;
   glBindUniformLocationCHROMIUMProc glBindUniformLocationCHROMIUMFn;
   glBindVertexArrayOESProc glBindVertexArrayOESFn;
+  glBindVertexBufferProc glBindVertexBufferFn;
   glBlendBarrierKHRProc glBlendBarrierKHRFn;
   glBlendColorProc glBlendColorFn;
   glBlendEquationProc glBlendEquationFn;
@@ -1657,6 +1886,7 @@
   glCoverStrokePathNVProc glCoverStrokePathNVFn;
   glCreateProgramProc glCreateProgramFn;
   glCreateShaderProc glCreateShaderFn;
+  glCreateShaderProgramvProc glCreateShaderProgramvFn;
   glCullFaceProc glCullFaceFn;
   glDebugMessageCallbackProc glDebugMessageCallbackFn;
   glDebugMessageControlProc glDebugMessageControlFn;
@@ -1667,6 +1897,7 @@
   glDeleteFramebuffersEXTProc glDeleteFramebuffersEXTFn;
   glDeletePathsNVProc glDeletePathsNVFn;
   glDeleteProgramProc glDeleteProgramFn;
+  glDeleteProgramPipelinesProc glDeleteProgramPipelinesFn;
   glDeleteQueriesProc glDeleteQueriesFn;
   glDeleteRenderbuffersEXTProc glDeleteRenderbuffersEXTFn;
   glDeleteSamplersProc glDeleteSamplersFn;
@@ -1683,11 +1914,15 @@
   glDisableProc glDisableFn;
   glDisableVertexAttribArrayProc glDisableVertexAttribArrayFn;
   glDiscardFramebufferEXTProc glDiscardFramebufferEXTFn;
+  glDispatchComputeProc glDispatchComputeFn;
+  glDispatchComputeIndirectProc glDispatchComputeIndirectFn;
   glDrawArraysProc glDrawArraysFn;
+  glDrawArraysIndirectProc glDrawArraysIndirectFn;
   glDrawArraysInstancedANGLEProc glDrawArraysInstancedANGLEFn;
   glDrawBufferProc glDrawBufferFn;
   glDrawBuffersARBProc glDrawBuffersARBFn;
   glDrawElementsProc glDrawElementsFn;
+  glDrawElementsIndirectProc glDrawElementsIndirectFn;
   glDrawElementsInstancedANGLEProc glDrawElementsInstancedANGLEFn;
   glDrawRangeElementsProc glDrawRangeElementsFn;
   glEGLImageTargetRenderbufferStorageOESProc
@@ -1716,6 +1951,7 @@
   glGenFencesNVProc glGenFencesNVFn;
   glGenFramebuffersEXTProc glGenFramebuffersEXTFn;
   glGenPathsNVProc glGenPathsNVFn;
+  glGenProgramPipelinesProc glGenProgramPipelinesFn;
   glGenQueriesProc glGenQueriesFn;
   glGenRenderbuffersEXTProc glGenRenderbuffersEXTFn;
   glGenSamplersProc glGenSamplersFn;
@@ -1731,6 +1967,7 @@
   glGetActiveUniformsivProc glGetActiveUniformsivFn;
   glGetAttachedShadersProc glGetAttachedShadersFn;
   glGetAttribLocationProc glGetAttribLocationFn;
+  glGetBooleani_vProc glGetBooleani_vFn;
   glGetBooleani_vRobustANGLEProc glGetBooleani_vRobustANGLEFn;
   glGetBooleanvProc glGetBooleanvFn;
   glGetBooleanvRobustANGLEProc glGetBooleanvRobustANGLEFn;
@@ -1749,6 +1986,7 @@
       glGetFramebufferAttachmentParameterivEXTFn;
   glGetFramebufferAttachmentParameterivRobustANGLEProc
       glGetFramebufferAttachmentParameterivRobustANGLEFn;
+  glGetFramebufferParameterivProc glGetFramebufferParameterivFn;
   glGetFramebufferParameterivRobustANGLEProc
       glGetFramebufferParameterivRobustANGLEFn;
   glGetGraphicsResetStatusARBProc glGetGraphicsResetStatusARBFn;
@@ -1777,6 +2015,9 @@
   glGetProgramInterfaceivRobustANGLEProc glGetProgramInterfaceivRobustANGLEFn;
   glGetProgramivProc glGetProgramivFn;
   glGetProgramivRobustANGLEProc glGetProgramivRobustANGLEFn;
+  glGetProgramPipelineInfoLogProc glGetProgramPipelineInfoLogFn;
+  glGetProgramPipelineivProc glGetProgramPipelineivFn;
+  glGetProgramResourceIndexProc glGetProgramResourceIndexFn;
   glGetProgramResourceivProc glGetProgramResourceivFn;
   glGetProgramResourceLocationProc glGetProgramResourceLocationFn;
   glGetProgramResourceNameProc glGetProgramResourceNameFn;
@@ -1849,6 +2090,7 @@
   glIsFramebufferEXTProc glIsFramebufferEXTFn;
   glIsPathNVProc glIsPathNVFn;
   glIsProgramProc glIsProgramFn;
+  glIsProgramPipelineProc glIsProgramPipelineFn;
   glIsQueryProc glIsQueryFn;
   glIsRenderbufferEXTProc glIsRenderbufferEXTFn;
   glIsSamplerProc glIsSamplerFn;
@@ -1863,6 +2105,7 @@
   glMapBufferRangeProc glMapBufferRangeFn;
   glMatrixLoadfEXTProc glMatrixLoadfEXTFn;
   glMatrixLoadIdentityEXTProc glMatrixLoadIdentityEXTFn;
+  glMemoryBarrierByRegionProc glMemoryBarrierByRegionFn;
   glMemoryBarrierEXTProc glMemoryBarrierEXTFn;
   glObjectLabelProc glObjectLabelFn;
   glObjectPtrLabelProc glObjectPtrLabelFn;
@@ -1881,6 +2124,39 @@
   glProgramBinaryProc glProgramBinaryFn;
   glProgramParameteriProc glProgramParameteriFn;
   glProgramPathFragmentInputGenNVProc glProgramPathFragmentInputGenNVFn;
+  glProgramUniform1fProc glProgramUniform1fFn;
+  glProgramUniform1fvProc glProgramUniform1fvFn;
+  glProgramUniform1iProc glProgramUniform1iFn;
+  glProgramUniform1ivProc glProgramUniform1ivFn;
+  glProgramUniform1uiProc glProgramUniform1uiFn;
+  glProgramUniform1uivProc glProgramUniform1uivFn;
+  glProgramUniform2fProc glProgramUniform2fFn;
+  glProgramUniform2fvProc glProgramUniform2fvFn;
+  glProgramUniform2iProc glProgramUniform2iFn;
+  glProgramUniform2ivProc glProgramUniform2ivFn;
+  glProgramUniform2uiProc glProgramUniform2uiFn;
+  glProgramUniform2uivProc glProgramUniform2uivFn;
+  glProgramUniform3fProc glProgramUniform3fFn;
+  glProgramUniform3fvProc glProgramUniform3fvFn;
+  glProgramUniform3iProc glProgramUniform3iFn;
+  glProgramUniform3ivProc glProgramUniform3ivFn;
+  glProgramUniform3uiProc glProgramUniform3uiFn;
+  glProgramUniform3uivProc glProgramUniform3uivFn;
+  glProgramUniform4fProc glProgramUniform4fFn;
+  glProgramUniform4fvProc glProgramUniform4fvFn;
+  glProgramUniform4iProc glProgramUniform4iFn;
+  glProgramUniform4ivProc glProgramUniform4ivFn;
+  glProgramUniform4uiProc glProgramUniform4uiFn;
+  glProgramUniform4uivProc glProgramUniform4uivFn;
+  glProgramUniformMatrix2fvProc glProgramUniformMatrix2fvFn;
+  glProgramUniformMatrix2x3fvProc glProgramUniformMatrix2x3fvFn;
+  glProgramUniformMatrix2x4fvProc glProgramUniformMatrix2x4fvFn;
+  glProgramUniformMatrix3fvProc glProgramUniformMatrix3fvFn;
+  glProgramUniformMatrix3x2fvProc glProgramUniformMatrix3x2fvFn;
+  glProgramUniformMatrix3x4fvProc glProgramUniformMatrix3x4fvFn;
+  glProgramUniformMatrix4fvProc glProgramUniformMatrix4fvFn;
+  glProgramUniformMatrix4x2fvProc glProgramUniformMatrix4x2fvFn;
+  glProgramUniformMatrix4x3fvProc glProgramUniformMatrix4x3fvFn;
   glPushDebugGroupProc glPushDebugGroupFn;
   glPushGroupMarkerEXTProc glPushGroupMarkerEXTFn;
   glQueryCounterProc glQueryCounterFn;
@@ -1895,6 +2171,7 @@
   glRequestExtensionANGLEProc glRequestExtensionANGLEFn;
   glResumeTransformFeedbackProc glResumeTransformFeedbackFn;
   glSampleCoverageProc glSampleCoverageFn;
+  glSampleMaskiProc glSampleMaskiFn;
   glSamplerParameterfProc glSamplerParameterfFn;
   glSamplerParameterfvProc glSamplerParameterfvFn;
   glSamplerParameterfvRobustANGLEProc glSamplerParameterfvRobustANGLEFn;
@@ -1941,6 +2218,7 @@
   glTexParameterivProc glTexParameterivFn;
   glTexParameterivRobustANGLEProc glTexParameterivRobustANGLEFn;
   glTexStorage2DEXTProc glTexStorage2DEXTFn;
+  glTexStorage2DMultisampleProc glTexStorage2DMultisampleFn;
   glTexStorage3DProc glTexStorage3DFn;
   glTexSubImage2DProc glTexSubImage2DFn;
   glTexSubImage2DRobustANGLEProc glTexSubImage2DRobustANGLEFn;
@@ -1983,7 +2261,9 @@
   glUniformMatrix4x3fvProc glUniformMatrix4x3fvFn;
   glUnmapBufferProc glUnmapBufferFn;
   glUseProgramProc glUseProgramFn;
+  glUseProgramStagesProc glUseProgramStagesFn;
   glValidateProgramProc glValidateProgramFn;
+  glValidateProgramPipelineProc glValidateProgramPipelineFn;
   glVertexAttrib1fProc glVertexAttrib1fFn;
   glVertexAttrib1fvProc glVertexAttrib1fvFn;
   glVertexAttrib2fProc glVertexAttrib2fFn;
@@ -1992,13 +2272,17 @@
   glVertexAttrib3fvProc glVertexAttrib3fvFn;
   glVertexAttrib4fProc glVertexAttrib4fFn;
   glVertexAttrib4fvProc glVertexAttrib4fvFn;
+  glVertexAttribBindingProc glVertexAttribBindingFn;
   glVertexAttribDivisorANGLEProc glVertexAttribDivisorANGLEFn;
+  glVertexAttribFormatProc glVertexAttribFormatFn;
   glVertexAttribI4iProc glVertexAttribI4iFn;
   glVertexAttribI4ivProc glVertexAttribI4ivFn;
   glVertexAttribI4uiProc glVertexAttribI4uiFn;
   glVertexAttribI4uivProc glVertexAttribI4uivFn;
+  glVertexAttribIFormatProc glVertexAttribIFormatFn;
   glVertexAttribIPointerProc glVertexAttribIPointerFn;
   glVertexAttribPointerProc glVertexAttribPointerFn;
+  glVertexBindingDivisorProc glVertexBindingDivisorFn;
   glViewportProc glViewportFn;
   glWaitSyncProc glWaitSyncFn;
   glWindowRectanglesEXTProc glWindowRectanglesEXTFn;
@@ -2011,6 +2295,7 @@
 
   virtual void SetDisabledExtensions(const std::string& disabled_extensions) {}
 
+  virtual void glActiveShaderProgramFn(GLuint pipeline, GLuint program) = 0;
   virtual void glActiveTextureFn(GLenum texture) = 0;
   virtual void glApplyFramebufferAttachmentCMAAINTELFn(void) = 0;
   virtual void glAttachShaderFn(GLuint program, GLuint shader) = 0;
@@ -2046,6 +2331,7 @@
                                        GLint layer,
                                        GLenum access,
                                        GLint format) = 0;
+  virtual void glBindProgramPipelineFn(GLuint pipeline) = 0;
   virtual void glBindRenderbufferEXTFn(GLenum target, GLuint renderbuffer) = 0;
   virtual void glBindSamplerFn(GLuint unit, GLuint sampler) = 0;
   virtual void glBindTextureFn(GLenum target, GLuint texture) = 0;
@@ -2054,6 +2340,10 @@
                                                GLint location,
                                                const char* name) = 0;
   virtual void glBindVertexArrayOESFn(GLuint array) = 0;
+  virtual void glBindVertexBufferFn(GLuint bindingindex,
+                                    GLuint buffer,
+                                    GLintptr offset,
+                                    GLsizei stride) = 0;
   virtual void glBlendBarrierKHRFn(void) = 0;
   virtual void glBlendColorFn(GLclampf red,
                               GLclampf green,
@@ -2268,6 +2558,9 @@
   virtual void glCoverStrokePathNVFn(GLuint name, GLenum coverMode) = 0;
   virtual GLuint glCreateProgramFn(void) = 0;
   virtual GLuint glCreateShaderFn(GLenum type) = 0;
+  virtual GLuint glCreateShaderProgramvFn(GLenum type,
+                                          GLsizei count,
+                                          const char* const* strings) = 0;
   virtual void glCullFaceFn(GLenum mode) = 0;
   virtual void glDebugMessageCallbackFn(GLDEBUGPROC callback,
                                         const void* userParam) = 0;
@@ -2290,6 +2583,8 @@
                                          const GLuint* framebuffers) = 0;
   virtual void glDeletePathsNVFn(GLuint path, GLsizei range) = 0;
   virtual void glDeleteProgramFn(GLuint program) = 0;
+  virtual void glDeleteProgramPipelinesFn(GLsizei n,
+                                          const GLuint* pipelines) = 0;
   virtual void glDeleteQueriesFn(GLsizei n, const GLuint* ids) = 0;
   virtual void glDeleteRenderbuffersEXTFn(GLsizei n,
                                           const GLuint* renderbuffers) = 0;
@@ -2309,7 +2604,12 @@
   virtual void glDiscardFramebufferEXTFn(GLenum target,
                                          GLsizei numAttachments,
                                          const GLenum* attachments) = 0;
+  virtual void glDispatchComputeFn(GLuint numGroupsX,
+                                   GLuint numGroupsY,
+                                   GLuint numGroupsZ) = 0;
+  virtual void glDispatchComputeIndirectFn(GLintptr indirect) = 0;
   virtual void glDrawArraysFn(GLenum mode, GLint first, GLsizei count) = 0;
+  virtual void glDrawArraysIndirectFn(GLenum mode, const void* indirect) = 0;
   virtual void glDrawArraysInstancedANGLEFn(GLenum mode,
                                             GLint first,
                                             GLsizei count,
@@ -2320,6 +2620,9 @@
                                 GLsizei count,
                                 GLenum type,
                                 const void* indices) = 0;
+  virtual void glDrawElementsIndirectFn(GLenum mode,
+                                        GLenum type,
+                                        const void* indirect) = 0;
   virtual void glDrawElementsInstancedANGLEFn(GLenum mode,
                                               GLsizei count,
                                               GLenum type,
@@ -2378,6 +2681,7 @@
   virtual void glGenFencesNVFn(GLsizei n, GLuint* fences) = 0;
   virtual void glGenFramebuffersEXTFn(GLsizei n, GLuint* framebuffers) = 0;
   virtual GLuint glGenPathsNVFn(GLsizei range) = 0;
+  virtual GLuint glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) = 0;
   virtual void glGenQueriesFn(GLsizei n, GLuint* ids) = 0;
   virtual void glGenRenderbuffersEXTFn(GLsizei n, GLuint* renderbuffers) = 0;
   virtual void glGenSamplersFn(GLsizei n, GLuint* samplers) = 0;
@@ -2423,6 +2727,9 @@
                                       GLsizei* count,
                                       GLuint* shaders) = 0;
   virtual GLint glGetAttribLocationFn(GLuint program, const char* name) = 0;
+  virtual void glGetBooleani_vFn(GLenum target,
+                                 GLuint index,
+                                 GLboolean* data) = 0;
   virtual void glGetBooleani_vRobustANGLEFn(GLenum target,
                                             GLuint index,
                                             GLsizei bufSize,
@@ -2479,6 +2786,9 @@
       GLsizei bufSize,
       GLsizei* length,
       GLint* params) = 0;
+  virtual void glGetFramebufferParameterivFn(GLenum target,
+                                             GLenum pname,
+                                             GLint* params) = 0;
   virtual void glGetFramebufferParameterivRobustANGLEFn(GLenum target,
                                                         GLenum pname,
                                                         GLsizei bufSize,
@@ -2584,6 +2894,16 @@
                                            GLsizei bufSize,
                                            GLsizei* length,
                                            GLint* params) = 0;
+  virtual void glGetProgramPipelineInfoLogFn(GLuint pipeline,
+                                             GLsizei bufSize,
+                                             GLsizei* length,
+                                             GLchar* infoLog) = 0;
+  virtual void glGetProgramPipelineivFn(GLuint pipeline,
+                                        GLenum pname,
+                                        GLint* params) = 0;
+  virtual void glGetProgramResourceIndexFn(GLuint program,
+                                           GLenum programInterface,
+                                           const GLchar* name) = 0;
   virtual void glGetProgramResourceivFn(GLuint program,
                                         GLenum programInterface,
                                         GLuint index,
@@ -2837,6 +3157,7 @@
   virtual GLboolean glIsFramebufferEXTFn(GLuint framebuffer) = 0;
   virtual GLboolean glIsPathNVFn(GLuint path) = 0;
   virtual GLboolean glIsProgramFn(GLuint program) = 0;
+  virtual GLboolean glIsProgramPipelineFn(GLuint pipeline) = 0;
   virtual GLboolean glIsQueryFn(GLuint query) = 0;
   virtual GLboolean glIsRenderbufferEXTFn(GLuint renderbuffer) = 0;
   virtual GLboolean glIsSamplerFn(GLuint sampler) = 0;
@@ -2854,6 +3175,7 @@
                                    GLbitfield access) = 0;
   virtual void glMatrixLoadfEXTFn(GLenum matrixMode, const GLfloat* m) = 0;
   virtual void glMatrixLoadIdentityEXTFn(GLenum matrixMode) = 0;
+  virtual void glMemoryBarrierByRegionFn(GLbitfield barriers) = 0;
   virtual void glMemoryBarrierEXTFn(GLbitfield barriers) = 0;
   virtual void glObjectLabelFn(GLenum identifier,
                                GLuint name,
@@ -2893,6 +3215,153 @@
                                                  GLenum genMode,
                                                  GLint components,
                                                  const GLfloat* coeffs) = 0;
+  virtual void glProgramUniform1fFn(GLuint program,
+                                    GLint location,
+                                    GLfloat v0) = 0;
+  virtual void glProgramUniform1fvFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat* value) = 0;
+  virtual void glProgramUniform1iFn(GLuint program,
+                                    GLint location,
+                                    GLint v0) = 0;
+  virtual void glProgramUniform1ivFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint* value) = 0;
+  virtual void glProgramUniform1uiFn(GLuint program,
+                                     GLint location,
+                                     GLuint v0) = 0;
+  virtual void glProgramUniform1uivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint* value) = 0;
+  virtual void glProgramUniform2fFn(GLuint program,
+                                    GLint location,
+                                    GLfloat v0,
+                                    GLfloat v1) = 0;
+  virtual void glProgramUniform2fvFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat* value) = 0;
+  virtual void glProgramUniform2iFn(GLuint program,
+                                    GLint location,
+                                    GLint v0,
+                                    GLint v1) = 0;
+  virtual void glProgramUniform2ivFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint* value) = 0;
+  virtual void glProgramUniform2uiFn(GLuint program,
+                                     GLint location,
+                                     GLuint v0,
+                                     GLuint v1) = 0;
+  virtual void glProgramUniform2uivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint* value) = 0;
+  virtual void glProgramUniform3fFn(GLuint program,
+                                    GLint location,
+                                    GLfloat v0,
+                                    GLfloat v1,
+                                    GLfloat v2) = 0;
+  virtual void glProgramUniform3fvFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat* value) = 0;
+  virtual void glProgramUniform3iFn(GLuint program,
+                                    GLint location,
+                                    GLint v0,
+                                    GLint v1,
+                                    GLint v2) = 0;
+  virtual void glProgramUniform3ivFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint* value) = 0;
+  virtual void glProgramUniform3uiFn(GLuint program,
+                                     GLint location,
+                                     GLuint v0,
+                                     GLuint v1,
+                                     GLuint v2) = 0;
+  virtual void glProgramUniform3uivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint* value) = 0;
+  virtual void glProgramUniform4fFn(GLuint program,
+                                    GLint location,
+                                    GLfloat v0,
+                                    GLfloat v1,
+                                    GLfloat v2,
+                                    GLfloat v3) = 0;
+  virtual void glProgramUniform4fvFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLfloat* value) = 0;
+  virtual void glProgramUniform4iFn(GLuint program,
+                                    GLint location,
+                                    GLint v0,
+                                    GLint v1,
+                                    GLint v2,
+                                    GLint v3) = 0;
+  virtual void glProgramUniform4ivFn(GLuint program,
+                                     GLint location,
+                                     GLsizei count,
+                                     const GLint* value) = 0;
+  virtual void glProgramUniform4uiFn(GLuint program,
+                                     GLint location,
+                                     GLuint v0,
+                                     GLuint v1,
+                                     GLuint v2,
+                                     GLuint v3) = 0;
+  virtual void glProgramUniform4uivFn(GLuint program,
+                                      GLint location,
+                                      GLsizei count,
+                                      const GLuint* value) = 0;
+  virtual void glProgramUniformMatrix2fvFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix2x3fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix2x4fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix3fvFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix3x2fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix3x4fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix4fvFn(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           GLboolean transpose,
+                                           const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix4x2fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) = 0;
+  virtual void glProgramUniformMatrix4x3fvFn(GLuint program,
+                                             GLint location,
+                                             GLsizei count,
+                                             GLboolean transpose,
+                                             const GLfloat* value) = 0;
   virtual void glPushDebugGroupFn(GLenum source,
                                   GLuint id,
                                   GLsizei length,
@@ -2947,6 +3416,7 @@
   virtual void glRequestExtensionANGLEFn(const char* name) = 0;
   virtual void glResumeTransformFeedbackFn(void) = 0;
   virtual void glSampleCoverageFn(GLclampf value, GLboolean invert) = 0;
+  virtual void glSampleMaskiFn(GLuint maskNumber, GLbitfield mask) = 0;
   virtual void glSamplerParameterfFn(GLuint sampler,
                                      GLenum pname,
                                      GLfloat param) = 0;
@@ -3132,6 +3602,12 @@
                                    GLenum internalformat,
                                    GLsizei width,
                                    GLsizei height) = 0;
+  virtual void glTexStorage2DMultisampleFn(GLenum target,
+                                           GLsizei samples,
+                                           GLenum internalformat,
+                                           GLsizei width,
+                                           GLsizei height,
+                                           GLboolean fixedsamplelocations) = 0;
   virtual void glTexStorage3DFn(GLenum target,
                                 GLsizei levels,
                                 GLenum internalformat,
@@ -3291,7 +3767,11 @@
                                       const GLfloat* value) = 0;
   virtual GLboolean glUnmapBufferFn(GLenum target) = 0;
   virtual void glUseProgramFn(GLuint program) = 0;
+  virtual void glUseProgramStagesFn(GLuint pipeline,
+                                    GLbitfield stages,
+                                    GLuint program) = 0;
   virtual void glValidateProgramFn(GLuint program) = 0;
+  virtual void glValidateProgramPipelineFn(GLuint pipeline) = 0;
   virtual void glVertexAttrib1fFn(GLuint indx, GLfloat x) = 0;
   virtual void glVertexAttrib1fvFn(GLuint indx, const GLfloat* values) = 0;
   virtual void glVertexAttrib2fFn(GLuint indx, GLfloat x, GLfloat y) = 0;
@@ -3307,7 +3787,14 @@
                                   GLfloat z,
                                   GLfloat w) = 0;
   virtual void glVertexAttrib4fvFn(GLuint indx, const GLfloat* values) = 0;
+  virtual void glVertexAttribBindingFn(GLuint attribindex,
+                                       GLuint bindingindex) = 0;
   virtual void glVertexAttribDivisorANGLEFn(GLuint index, GLuint divisor) = 0;
+  virtual void glVertexAttribFormatFn(GLuint attribindex,
+                                      GLint size,
+                                      GLenum type,
+                                      GLboolean normalized,
+                                      GLuint relativeoffset) = 0;
   virtual void glVertexAttribI4iFn(GLuint indx,
                                    GLint x,
                                    GLint y,
@@ -3320,6 +3807,10 @@
                                     GLuint z,
                                     GLuint w) = 0;
   virtual void glVertexAttribI4uivFn(GLuint indx, const GLuint* values) = 0;
+  virtual void glVertexAttribIFormatFn(GLuint attribindex,
+                                       GLint size,
+                                       GLenum type,
+                                       GLuint relativeoffset) = 0;
   virtual void glVertexAttribIPointerFn(GLuint indx,
                                         GLint size,
                                         GLenum type,
@@ -3331,6 +3822,8 @@
                                        GLboolean normalized,
                                        GLsizei stride,
                                        const void* ptr) = 0;
+  virtual void glVertexBindingDivisorFn(GLuint bindingindex,
+                                        GLuint divisor) = 0;
   virtual void glViewportFn(GLint x,
                             GLint y,
                             GLsizei width,
@@ -3345,6 +3838,8 @@
 
 }  // namespace gl
 
+#define glActiveShaderProgram \
+  ::gl::g_current_gl_context->glActiveShaderProgramFn
 #define glActiveTexture ::gl::g_current_gl_context->glActiveTextureFn
 #define glApplyFramebufferAttachmentCMAAINTEL \
   ::gl::g_current_gl_context->glApplyFramebufferAttachmentCMAAINTELFn
@@ -3365,6 +3860,8 @@
 #define glBindFramebufferEXT ::gl::g_current_gl_context->glBindFramebufferEXTFn
 #define glBindImageTextureEXT \
   ::gl::g_current_gl_context->glBindImageTextureEXTFn
+#define glBindProgramPipeline \
+  ::gl::g_current_gl_context->glBindProgramPipelineFn
 #define glBindRenderbufferEXT \
   ::gl::g_current_gl_context->glBindRenderbufferEXTFn
 #define glBindSampler ::gl::g_current_gl_context->glBindSamplerFn
@@ -3374,6 +3871,7 @@
 #define glBindUniformLocationCHROMIUM \
   ::gl::g_current_gl_context->glBindUniformLocationCHROMIUMFn
 #define glBindVertexArrayOES ::gl::g_current_gl_context->glBindVertexArrayOESFn
+#define glBindVertexBuffer ::gl::g_current_gl_context->glBindVertexBufferFn
 #define glBlendBarrierKHR ::gl::g_current_gl_context->glBlendBarrierKHRFn
 #define glBlendColor ::gl::g_current_gl_context->glBlendColorFn
 #define glBlendEquation ::gl::g_current_gl_context->glBlendEquationFn
@@ -3434,6 +3932,8 @@
 #define glCoverStrokePathNV ::gl::g_current_gl_context->glCoverStrokePathNVFn
 #define glCreateProgram ::gl::g_current_gl_context->glCreateProgramFn
 #define glCreateShader ::gl::g_current_gl_context->glCreateShaderFn
+#define glCreateShaderProgramv \
+  ::gl::g_current_gl_context->glCreateShaderProgramvFn
 #define glCullFace ::gl::g_current_gl_context->glCullFaceFn
 #define glDebugMessageCallback \
   ::gl::g_current_gl_context->glDebugMessageCallbackFn
@@ -3447,6 +3947,8 @@
   ::gl::g_current_gl_context->glDeleteFramebuffersEXTFn
 #define glDeletePathsNV ::gl::g_current_gl_context->glDeletePathsNVFn
 #define glDeleteProgram ::gl::g_current_gl_context->glDeleteProgramFn
+#define glDeleteProgramPipelines \
+  ::gl::g_current_gl_context->glDeleteProgramPipelinesFn
 #define glDeleteQueries ::gl::g_current_gl_context->glDeleteQueriesFn
 #define glDeleteRenderbuffersEXT \
   ::gl::g_current_gl_context->glDeleteRenderbuffersEXTFn
@@ -3468,12 +3970,18 @@
   ::gl::g_current_gl_context->glDisableVertexAttribArrayFn
 #define glDiscardFramebufferEXT \
   ::gl::g_current_gl_context->glDiscardFramebufferEXTFn
+#define glDispatchCompute ::gl::g_current_gl_context->glDispatchComputeFn
+#define glDispatchComputeIndirect \
+  ::gl::g_current_gl_context->glDispatchComputeIndirectFn
 #define glDrawArrays ::gl::g_current_gl_context->glDrawArraysFn
+#define glDrawArraysIndirect ::gl::g_current_gl_context->glDrawArraysIndirectFn
 #define glDrawArraysInstancedANGLE \
   ::gl::g_current_gl_context->glDrawArraysInstancedANGLEFn
 #define glDrawBuffer ::gl::g_current_gl_context->glDrawBufferFn
 #define glDrawBuffersARB ::gl::g_current_gl_context->glDrawBuffersARBFn
 #define glDrawElements ::gl::g_current_gl_context->glDrawElementsFn
+#define glDrawElementsIndirect \
+  ::gl::g_current_gl_context->glDrawElementsIndirectFn
 #define glDrawElementsInstancedANGLE \
   ::gl::g_current_gl_context->glDrawElementsInstancedANGLEFn
 #define glDrawRangeElements ::gl::g_current_gl_context->glDrawRangeElementsFn
@@ -3511,6 +4019,8 @@
 #define glGenFencesNV ::gl::g_current_gl_context->glGenFencesNVFn
 #define glGenFramebuffersEXT ::gl::g_current_gl_context->glGenFramebuffersEXTFn
 #define glGenPathsNV ::gl::g_current_gl_context->glGenPathsNVFn
+#define glGenProgramPipelines \
+  ::gl::g_current_gl_context->glGenProgramPipelinesFn
 #define glGenQueries ::gl::g_current_gl_context->glGenQueriesFn
 #define glGenRenderbuffersEXT \
   ::gl::g_current_gl_context->glGenRenderbuffersEXTFn
@@ -3531,6 +4041,7 @@
   ::gl::g_current_gl_context->glGetActiveUniformsivFn
 #define glGetAttachedShaders ::gl::g_current_gl_context->glGetAttachedShadersFn
 #define glGetAttribLocation ::gl::g_current_gl_context->glGetAttribLocationFn
+#define glGetBooleani_v ::gl::g_current_gl_context->glGetBooleani_vFn
 #define glGetBooleani_vRobustANGLE \
   ::gl::g_current_gl_context->glGetBooleani_vRobustANGLEFn
 #define glGetBooleanv ::gl::g_current_gl_context->glGetBooleanvFn
@@ -3557,6 +4068,8 @@
   ::gl::g_current_gl_context->glGetFramebufferAttachmentParameterivEXTFn
 #define glGetFramebufferAttachmentParameterivRobustANGLE \
   ::gl::g_current_gl_context->glGetFramebufferAttachmentParameterivRobustANGLEFn
+#define glGetFramebufferParameteriv \
+  ::gl::g_current_gl_context->glGetFramebufferParameterivFn
 #define glGetFramebufferParameterivRobustANGLE \
   ::gl::g_current_gl_context->glGetFramebufferParameterivRobustANGLEFn
 #define glGetGraphicsResetStatusARB \
@@ -3600,6 +4113,12 @@
 #define glGetProgramiv ::gl::g_current_gl_context->glGetProgramivFn
 #define glGetProgramivRobustANGLE \
   ::gl::g_current_gl_context->glGetProgramivRobustANGLEFn
+#define glGetProgramPipelineInfoLog \
+  ::gl::g_current_gl_context->glGetProgramPipelineInfoLogFn
+#define glGetProgramPipelineiv \
+  ::gl::g_current_gl_context->glGetProgramPipelineivFn
+#define glGetProgramResourceIndex \
+  ::gl::g_current_gl_context->glGetProgramResourceIndexFn
 #define glGetProgramResourceiv \
   ::gl::g_current_gl_context->glGetProgramResourceivFn
 #define glGetProgramResourceLocation \
@@ -3711,6 +4230,7 @@
 #define glIsFramebufferEXT ::gl::g_current_gl_context->glIsFramebufferEXTFn
 #define glIsPathNV ::gl::g_current_gl_context->glIsPathNVFn
 #define glIsProgram ::gl::g_current_gl_context->glIsProgramFn
+#define glIsProgramPipeline ::gl::g_current_gl_context->glIsProgramPipelineFn
 #define glIsQuery ::gl::g_current_gl_context->glIsQueryFn
 #define glIsRenderbufferEXT ::gl::g_current_gl_context->glIsRenderbufferEXTFn
 #define glIsSampler ::gl::g_current_gl_context->glIsSamplerFn
@@ -3727,6 +4247,8 @@
 #define glMatrixLoadfEXT ::gl::g_current_gl_context->glMatrixLoadfEXTFn
 #define glMatrixLoadIdentityEXT \
   ::gl::g_current_gl_context->glMatrixLoadIdentityEXTFn
+#define glMemoryBarrierByRegion \
+  ::gl::g_current_gl_context->glMemoryBarrierByRegionFn
 #define glMemoryBarrierEXT ::gl::g_current_gl_context->glMemoryBarrierEXTFn
 #define glObjectLabel ::gl::g_current_gl_context->glObjectLabelFn
 #define glObjectPtrLabel ::gl::g_current_gl_context->glObjectPtrLabelFn
@@ -3748,6 +4270,48 @@
 #define glProgramParameteri ::gl::g_current_gl_context->glProgramParameteriFn
 #define glProgramPathFragmentInputGenNV \
   ::gl::g_current_gl_context->glProgramPathFragmentInputGenNVFn
+#define glProgramUniform1f ::gl::g_current_gl_context->glProgramUniform1fFn
+#define glProgramUniform1fv ::gl::g_current_gl_context->glProgramUniform1fvFn
+#define glProgramUniform1i ::gl::g_current_gl_context->glProgramUniform1iFn
+#define glProgramUniform1iv ::gl::g_current_gl_context->glProgramUniform1ivFn
+#define glProgramUniform1ui ::gl::g_current_gl_context->glProgramUniform1uiFn
+#define glProgramUniform1uiv ::gl::g_current_gl_context->glProgramUniform1uivFn
+#define glProgramUniform2f ::gl::g_current_gl_context->glProgramUniform2fFn
+#define glProgramUniform2fv ::gl::g_current_gl_context->glProgramUniform2fvFn
+#define glProgramUniform2i ::gl::g_current_gl_context->glProgramUniform2iFn
+#define glProgramUniform2iv ::gl::g_current_gl_context->glProgramUniform2ivFn
+#define glProgramUniform2ui ::gl::g_current_gl_context->glProgramUniform2uiFn
+#define glProgramUniform2uiv ::gl::g_current_gl_context->glProgramUniform2uivFn
+#define glProgramUniform3f ::gl::g_current_gl_context->glProgramUniform3fFn
+#define glProgramUniform3fv ::gl::g_current_gl_context->glProgramUniform3fvFn
+#define glProgramUniform3i ::gl::g_current_gl_context->glProgramUniform3iFn
+#define glProgramUniform3iv ::gl::g_current_gl_context->glProgramUniform3ivFn
+#define glProgramUniform3ui ::gl::g_current_gl_context->glProgramUniform3uiFn
+#define glProgramUniform3uiv ::gl::g_current_gl_context->glProgramUniform3uivFn
+#define glProgramUniform4f ::gl::g_current_gl_context->glProgramUniform4fFn
+#define glProgramUniform4fv ::gl::g_current_gl_context->glProgramUniform4fvFn
+#define glProgramUniform4i ::gl::g_current_gl_context->glProgramUniform4iFn
+#define glProgramUniform4iv ::gl::g_current_gl_context->glProgramUniform4ivFn
+#define glProgramUniform4ui ::gl::g_current_gl_context->glProgramUniform4uiFn
+#define glProgramUniform4uiv ::gl::g_current_gl_context->glProgramUniform4uivFn
+#define glProgramUniformMatrix2fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix2fvFn
+#define glProgramUniformMatrix2x3fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix2x3fvFn
+#define glProgramUniformMatrix2x4fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix2x4fvFn
+#define glProgramUniformMatrix3fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix3fvFn
+#define glProgramUniformMatrix3x2fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix3x2fvFn
+#define glProgramUniformMatrix3x4fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix3x4fvFn
+#define glProgramUniformMatrix4fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix4fvFn
+#define glProgramUniformMatrix4x2fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix4x2fvFn
+#define glProgramUniformMatrix4x3fv \
+  ::gl::g_current_gl_context->glProgramUniformMatrix4x3fvFn
 #define glPushDebugGroup ::gl::g_current_gl_context->glPushDebugGroupFn
 #define glPushGroupMarkerEXT ::gl::g_current_gl_context->glPushGroupMarkerEXTFn
 #define glQueryCounter ::gl::g_current_gl_context->glQueryCounterFn
@@ -3770,6 +4334,7 @@
 #define glResumeTransformFeedback \
   ::gl::g_current_gl_context->glResumeTransformFeedbackFn
 #define glSampleCoverage ::gl::g_current_gl_context->glSampleCoverageFn
+#define glSampleMaski ::gl::g_current_gl_context->glSampleMaskiFn
 #define glSamplerParameterf ::gl::g_current_gl_context->glSamplerParameterfFn
 #define glSamplerParameterfv ::gl::g_current_gl_context->glSamplerParameterfvFn
 #define glSamplerParameterfvRobustANGLE \
@@ -3833,6 +4398,8 @@
 #define glTexParameterivRobustANGLE \
   ::gl::g_current_gl_context->glTexParameterivRobustANGLEFn
 #define glTexStorage2DEXT ::gl::g_current_gl_context->glTexStorage2DEXTFn
+#define glTexStorage2DMultisample \
+  ::gl::g_current_gl_context->glTexStorage2DMultisampleFn
 #define glTexStorage3D ::gl::g_current_gl_context->glTexStorage3DFn
 #define glTexSubImage2D ::gl::g_current_gl_context->glTexSubImage2DFn
 #define glTexSubImage2DRobustANGLE \
@@ -3879,7 +4446,10 @@
 #define glUniformMatrix4x3fv ::gl::g_current_gl_context->glUniformMatrix4x3fvFn
 #define glUnmapBuffer ::gl::g_current_gl_context->glUnmapBufferFn
 #define glUseProgram ::gl::g_current_gl_context->glUseProgramFn
+#define glUseProgramStages ::gl::g_current_gl_context->glUseProgramStagesFn
 #define glValidateProgram ::gl::g_current_gl_context->glValidateProgramFn
+#define glValidateProgramPipeline \
+  ::gl::g_current_gl_context->glValidateProgramPipelineFn
 #define glVertexAttrib1f ::gl::g_current_gl_context->glVertexAttrib1fFn
 #define glVertexAttrib1fv ::gl::g_current_gl_context->glVertexAttrib1fvFn
 #define glVertexAttrib2f ::gl::g_current_gl_context->glVertexAttrib2fFn
@@ -3888,16 +4458,23 @@
 #define glVertexAttrib3fv ::gl::g_current_gl_context->glVertexAttrib3fvFn
 #define glVertexAttrib4f ::gl::g_current_gl_context->glVertexAttrib4fFn
 #define glVertexAttrib4fv ::gl::g_current_gl_context->glVertexAttrib4fvFn
+#define glVertexAttribBinding \
+  ::gl::g_current_gl_context->glVertexAttribBindingFn
 #define glVertexAttribDivisorANGLE \
   ::gl::g_current_gl_context->glVertexAttribDivisorANGLEFn
+#define glVertexAttribFormat ::gl::g_current_gl_context->glVertexAttribFormatFn
 #define glVertexAttribI4i ::gl::g_current_gl_context->glVertexAttribI4iFn
 #define glVertexAttribI4iv ::gl::g_current_gl_context->glVertexAttribI4ivFn
 #define glVertexAttribI4ui ::gl::g_current_gl_context->glVertexAttribI4uiFn
 #define glVertexAttribI4uiv ::gl::g_current_gl_context->glVertexAttribI4uivFn
+#define glVertexAttribIFormat \
+  ::gl::g_current_gl_context->glVertexAttribIFormatFn
 #define glVertexAttribIPointer \
   ::gl::g_current_gl_context->glVertexAttribIPointerFn
 #define glVertexAttribPointer \
   ::gl::g_current_gl_context->glVertexAttribPointerFn
+#define glVertexBindingDivisor \
+  ::gl::g_current_gl_context->glVertexBindingDivisorFn
 #define glViewport ::gl::g_current_gl_context->glViewportFn
 #define glWaitSync ::gl::g_current_gl_context->glWaitSyncFn
 #define glWindowRectanglesEXT \
diff --git a/ui/gl/gl_bindings_autogen_mock.cc b/ui/gl/gl_bindings_autogen_mock.cc
index f9bd00fb..80fd6c7d 100644
--- a/ui/gl/gl_bindings_autogen_mock.cc
+++ b/ui/gl/gl_bindings_autogen_mock.cc
@@ -23,6 +23,12 @@
 
 namespace gl {
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glActiveShaderProgram(GLuint pipeline, GLuint program) {
+  MakeFunctionUnique("glActiveShaderProgram");
+  interface_->ActiveShaderProgram(pipeline, program);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glActiveTexture(GLenum texture) {
   MakeFunctionUnique("glActiveTexture");
   interface_->ActiveTexture(texture);
@@ -197,6 +203,12 @@
 }
 
 void GL_BINDING_CALL
+MockGLInterface::Mock_glBindProgramPipeline(GLuint pipeline) {
+  MakeFunctionUnique("glBindProgramPipeline");
+  interface_->BindProgramPipeline(pipeline);
+}
+
+void GL_BINDING_CALL
 MockGLInterface::Mock_glBindRenderbuffer(GLenum target, GLuint renderbuffer) {
   MakeFunctionUnique("glBindRenderbuffer");
   interface_->BindRenderbufferEXT(target, renderbuffer);
@@ -251,6 +263,15 @@
   interface_->BindVertexArrayOES(array);
 }
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glBindVertexBuffer(GLuint bindingindex,
+                                         GLuint buffer,
+                                         GLintptr offset,
+                                         GLsizei stride) {
+  MakeFunctionUnique("glBindVertexBuffer");
+  interface_->BindVertexBuffer(bindingindex, buffer, offset, stride);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glBlendBarrierKHR(void) {
   MakeFunctionUnique("glBlendBarrierKHR");
   interface_->BlendBarrierKHR();
@@ -781,6 +802,14 @@
   return interface_->CreateShader(type);
 }
 
+GLuint GL_BINDING_CALL
+MockGLInterface::Mock_glCreateShaderProgramv(GLenum type,
+                                             GLsizei count,
+                                             const char* const* strings) {
+  MakeFunctionUnique("glCreateShaderProgramv");
+  return interface_->CreateShaderProgramv(type, count, strings);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glCullFace(GLenum mode) {
   MakeFunctionUnique("glCullFace");
   interface_->CullFace(mode);
@@ -893,6 +922,13 @@
   interface_->DeleteProgram(program);
 }
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glDeleteProgramPipelines(GLsizei n,
+                                               const GLuint* pipelines) {
+  MakeFunctionUnique("glDeleteProgramPipelines");
+  interface_->DeleteProgramPipelines(n, pipelines);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glDeleteQueries(GLsizei n,
                                                            const GLuint* ids) {
   MakeFunctionUnique("glDeleteQueries");
@@ -1019,6 +1055,20 @@
   interface_->DiscardFramebufferEXT(target, numAttachments, attachments);
 }
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glDispatchCompute(GLuint numGroupsX,
+                                        GLuint numGroupsY,
+                                        GLuint numGroupsZ) {
+  MakeFunctionUnique("glDispatchCompute");
+  interface_->DispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glDispatchComputeIndirect(GLintptr indirect) {
+  MakeFunctionUnique("glDispatchComputeIndirect");
+  interface_->DispatchComputeIndirect(indirect);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glDrawArrays(GLenum mode,
                                                         GLint first,
                                                         GLsizei count) {
@@ -1027,6 +1077,12 @@
 }
 
 void GL_BINDING_CALL
+MockGLInterface::Mock_glDrawArraysIndirect(GLenum mode, const void* indirect) {
+  MakeFunctionUnique("glDrawArraysIndirect");
+  interface_->DrawArraysIndirect(mode, indirect);
+}
+
+void GL_BINDING_CALL
 MockGLInterface::Mock_glDrawArraysInstanced(GLenum mode,
                                             GLint first,
                                             GLsizei count,
@@ -1085,6 +1141,14 @@
 }
 
 void GL_BINDING_CALL
+MockGLInterface::Mock_glDrawElementsIndirect(GLenum mode,
+                                             GLenum type,
+                                             const void* indirect) {
+  MakeFunctionUnique("glDrawElementsIndirect");
+  interface_->DrawElementsIndirect(mode, type, indirect);
+}
+
+void GL_BINDING_CALL
 MockGLInterface::Mock_glDrawElementsInstanced(GLenum mode,
                                               GLsizei count,
                                               GLenum type,
@@ -1348,6 +1412,12 @@
   return interface_->GenPathsNV(range);
 }
 
+GLuint GL_BINDING_CALL
+MockGLInterface::Mock_glGenProgramPipelines(GLsizei n, GLuint* pipelines) {
+  MakeFunctionUnique("glGenProgramPipelines");
+  return interface_->GenProgramPipelines(n, pipelines);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glGenQueries(GLsizei n,
                                                         GLuint* ids) {
   MakeFunctionUnique("glGenQueries");
@@ -1507,6 +1577,13 @@
   return interface_->GetAttribLocation(program, name);
 }
 
+void GL_BINDING_CALL MockGLInterface::Mock_glGetBooleani_v(GLenum target,
+                                                           GLuint index,
+                                                           GLboolean* data) {
+  MakeFunctionUnique("glGetBooleani_v");
+  interface_->GetBooleani_v(target, index, data);
+}
+
 void GL_BINDING_CALL
 MockGLInterface::Mock_glGetBooleani_vRobustANGLE(GLenum target,
                                                  GLuint index,
@@ -1681,6 +1758,14 @@
 }
 
 void GL_BINDING_CALL
+MockGLInterface::Mock_glGetFramebufferParameteriv(GLenum target,
+                                                  GLenum pname,
+                                                  GLint* params) {
+  MakeFunctionUnique("glGetFramebufferParameteriv");
+  interface_->GetFramebufferParameteriv(target, pname, params);
+}
+
+void GL_BINDING_CALL
 MockGLInterface::Mock_glGetFramebufferParameterivRobustANGLE(GLenum target,
                                                              GLenum pname,
                                                              GLsizei bufSize,
@@ -1921,6 +2006,31 @@
                                                bufSize, length, params);
 }
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glGetProgramPipelineInfoLog(GLuint pipeline,
+                                                  GLsizei bufSize,
+                                                  GLsizei* length,
+                                                  GLchar* infoLog) {
+  MakeFunctionUnique("glGetProgramPipelineInfoLog");
+  interface_->GetProgramPipelineInfoLog(pipeline, bufSize, length, infoLog);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glGetProgramPipelineiv(GLuint pipeline,
+                                             GLenum pname,
+                                             GLint* params) {
+  MakeFunctionUnique("glGetProgramPipelineiv");
+  interface_->GetProgramPipelineiv(pipeline, pname, params);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glGetProgramResourceIndex(GLuint program,
+                                                GLenum programInterface,
+                                                const GLchar* name) {
+  MakeFunctionUnique("glGetProgramResourceIndex");
+  interface_->GetProgramResourceIndex(program, programInterface, name);
+}
+
 GLint GL_BINDING_CALL
 MockGLInterface::Mock_glGetProgramResourceLocation(GLuint program,
                                                    GLenum programInterface,
@@ -2677,6 +2787,12 @@
   return interface_->IsProgram(program);
 }
 
+GLboolean GL_BINDING_CALL
+MockGLInterface::Mock_glIsProgramPipeline(GLuint pipeline) {
+  MakeFunctionUnique("glIsProgramPipeline");
+  return interface_->IsProgramPipeline(pipeline);
+}
+
 GLboolean GL_BINDING_CALL MockGLInterface::Mock_glIsQuery(GLuint query) {
   MakeFunctionUnique("glIsQuery");
   return interface_->IsQuery(query);
@@ -2819,6 +2935,12 @@
 }
 
 void GL_BINDING_CALL
+MockGLInterface::Mock_glMemoryBarrierByRegion(GLbitfield barriers) {
+  MakeFunctionUnique("glMemoryBarrierByRegion");
+  interface_->MemoryBarrierByRegion(barriers);
+}
+
+void GL_BINDING_CALL
 MockGLInterface::Mock_glMemoryBarrierEXT(GLbitfield barriers) {
   MakeFunctionUnique("glMemoryBarrierEXT");
   interface_->MemoryBarrierEXT(barriers);
@@ -3021,6 +3143,315 @@
                                             components, coeffs);
 }
 
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform1f(GLuint program,
+                                                              GLint location,
+                                                              GLfloat v0) {
+  MakeFunctionUnique("glProgramUniform1f");
+  interface_->ProgramUniform1f(program, location, v0);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform1fv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniform1fv");
+  interface_->ProgramUniform1fv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform1i(GLuint program,
+                                                              GLint location,
+                                                              GLint v0) {
+  MakeFunctionUnique("glProgramUniform1i");
+  interface_->ProgramUniform1i(program, location, v0);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform1iv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLint* value) {
+  MakeFunctionUnique("glProgramUniform1iv");
+  interface_->ProgramUniform1iv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform1ui(GLuint program,
+                                                               GLint location,
+                                                               GLuint v0) {
+  MakeFunctionUnique("glProgramUniform1ui");
+  interface_->ProgramUniform1ui(program, location, v0);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform1uiv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLuint* value) {
+  MakeFunctionUnique("glProgramUniform1uiv");
+  interface_->ProgramUniform1uiv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform2f(GLuint program,
+                                                              GLint location,
+                                                              GLfloat v0,
+                                                              GLfloat v1) {
+  MakeFunctionUnique("glProgramUniform2f");
+  interface_->ProgramUniform2f(program, location, v0, v1);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform2fv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniform2fv");
+  interface_->ProgramUniform2fv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform2i(GLuint program,
+                                                              GLint location,
+                                                              GLint v0,
+                                                              GLint v1) {
+  MakeFunctionUnique("glProgramUniform2i");
+  interface_->ProgramUniform2i(program, location, v0, v1);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform2iv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLint* value) {
+  MakeFunctionUnique("glProgramUniform2iv");
+  interface_->ProgramUniform2iv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform2ui(GLuint program,
+                                                               GLint location,
+                                                               GLuint v0,
+                                                               GLuint v1) {
+  MakeFunctionUnique("glProgramUniform2ui");
+  interface_->ProgramUniform2ui(program, location, v0, v1);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform2uiv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLuint* value) {
+  MakeFunctionUnique("glProgramUniform2uiv");
+  interface_->ProgramUniform2uiv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform3f(GLuint program,
+                                                              GLint location,
+                                                              GLfloat v0,
+                                                              GLfloat v1,
+                                                              GLfloat v2) {
+  MakeFunctionUnique("glProgramUniform3f");
+  interface_->ProgramUniform3f(program, location, v0, v1, v2);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform3fv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniform3fv");
+  interface_->ProgramUniform3fv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform3i(GLuint program,
+                                                              GLint location,
+                                                              GLint v0,
+                                                              GLint v1,
+                                                              GLint v2) {
+  MakeFunctionUnique("glProgramUniform3i");
+  interface_->ProgramUniform3i(program, location, v0, v1, v2);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform3iv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLint* value) {
+  MakeFunctionUnique("glProgramUniform3iv");
+  interface_->ProgramUniform3iv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform3ui(GLuint program,
+                                                               GLint location,
+                                                               GLuint v0,
+                                                               GLuint v1,
+                                                               GLuint v2) {
+  MakeFunctionUnique("glProgramUniform3ui");
+  interface_->ProgramUniform3ui(program, location, v0, v1, v2);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform3uiv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLuint* value) {
+  MakeFunctionUnique("glProgramUniform3uiv");
+  interface_->ProgramUniform3uiv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform4f(GLuint program,
+                                                              GLint location,
+                                                              GLfloat v0,
+                                                              GLfloat v1,
+                                                              GLfloat v2,
+                                                              GLfloat v3) {
+  MakeFunctionUnique("glProgramUniform4f");
+  interface_->ProgramUniform4f(program, location, v0, v1, v2, v3);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform4fv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniform4fv");
+  interface_->ProgramUniform4fv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform4i(GLuint program,
+                                                              GLint location,
+                                                              GLint v0,
+                                                              GLint v1,
+                                                              GLint v2,
+                                                              GLint v3) {
+  MakeFunctionUnique("glProgramUniform4i");
+  interface_->ProgramUniform4i(program, location, v0, v1, v2, v3);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform4iv(GLuint program,
+                                          GLint location,
+                                          GLsizei count,
+                                          const GLint* value) {
+  MakeFunctionUnique("glProgramUniform4iv");
+  interface_->ProgramUniform4iv(program, location, count, value);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glProgramUniform4ui(GLuint program,
+                                                               GLint location,
+                                                               GLuint v0,
+                                                               GLuint v1,
+                                                               GLuint v2,
+                                                               GLuint v3) {
+  MakeFunctionUnique("glProgramUniform4ui");
+  interface_->ProgramUniform4ui(program, location, v0, v1, v2, v3);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniform4uiv(GLuint program,
+                                           GLint location,
+                                           GLsizei count,
+                                           const GLuint* value) {
+  MakeFunctionUnique("glProgramUniform4uiv");
+  interface_->ProgramUniform4uiv(program, location, count, value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix2fv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                GLboolean transpose,
+                                                const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix2fv");
+  interface_->ProgramUniformMatrix2fv(program, location, count, transpose,
+                                      value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix2x3fv(GLuint program,
+                                                  GLint location,
+                                                  GLsizei count,
+                                                  GLboolean transpose,
+                                                  const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix2x3fv");
+  interface_->ProgramUniformMatrix2x3fv(program, location, count, transpose,
+                                        value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix2x4fv(GLuint program,
+                                                  GLint location,
+                                                  GLsizei count,
+                                                  GLboolean transpose,
+                                                  const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix2x4fv");
+  interface_->ProgramUniformMatrix2x4fv(program, location, count, transpose,
+                                        value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix3fv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                GLboolean transpose,
+                                                const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix3fv");
+  interface_->ProgramUniformMatrix3fv(program, location, count, transpose,
+                                      value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix3x2fv(GLuint program,
+                                                  GLint location,
+                                                  GLsizei count,
+                                                  GLboolean transpose,
+                                                  const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix3x2fv");
+  interface_->ProgramUniformMatrix3x2fv(program, location, count, transpose,
+                                        value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix3x4fv(GLuint program,
+                                                  GLint location,
+                                                  GLsizei count,
+                                                  GLboolean transpose,
+                                                  const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix3x4fv");
+  interface_->ProgramUniformMatrix3x4fv(program, location, count, transpose,
+                                        value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix4fv(GLuint program,
+                                                GLint location,
+                                                GLsizei count,
+                                                GLboolean transpose,
+                                                const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix4fv");
+  interface_->ProgramUniformMatrix4fv(program, location, count, transpose,
+                                      value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix4x2fv(GLuint program,
+                                                  GLint location,
+                                                  GLsizei count,
+                                                  GLboolean transpose,
+                                                  const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix4x2fv");
+  interface_->ProgramUniformMatrix4x2fv(program, location, count, transpose,
+                                        value);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glProgramUniformMatrix4x3fv(GLuint program,
+                                                  GLint location,
+                                                  GLsizei count,
+                                                  GLboolean transpose,
+                                                  const GLfloat* value) {
+  MakeFunctionUnique("glProgramUniformMatrix4x3fv");
+  interface_->ProgramUniformMatrix4x3fv(program, location, count, transpose,
+                                        value);
+}
+
 void GL_BINDING_CALL
 MockGLInterface::Mock_glPushDebugGroup(GLenum source,
                                        GLuint id,
@@ -3192,6 +3623,12 @@
   interface_->SampleCoverage(value, invert);
 }
 
+void GL_BINDING_CALL MockGLInterface::Mock_glSampleMaski(GLuint maskNumber,
+                                                         GLbitfield mask) {
+  MakeFunctionUnique("glSampleMaski");
+  interface_->SampleMaski(maskNumber, mask);
+}
+
 void GL_BINDING_CALL
 MockGLInterface::Mock_glSamplerParameterIivRobustANGLE(GLuint sampler,
                                                        GLenum pname,
@@ -3741,6 +4178,18 @@
   interface_->TexStorage2DEXT(target, levels, internalformat, width, height);
 }
 
+void GL_BINDING_CALL MockGLInterface::Mock_glTexStorage2DMultisample(
+    GLenum target,
+    GLsizei samples,
+    GLenum internalformat,
+    GLsizei width,
+    GLsizei height,
+    GLboolean fixedsamplelocations) {
+  MakeFunctionUnique("glTexStorage2DMultisample");
+  interface_->TexStorage2DMultisample(target, samples, internalformat, width,
+                                      height, fixedsamplelocations);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glTexStorage3D(GLenum target,
                                                           GLsizei levels,
                                                           GLenum internalformat,
@@ -4115,11 +4564,24 @@
   interface_->UseProgram(program);
 }
 
+void GL_BINDING_CALL MockGLInterface::Mock_glUseProgramStages(GLuint pipeline,
+                                                              GLbitfield stages,
+                                                              GLuint program) {
+  MakeFunctionUnique("glUseProgramStages");
+  interface_->UseProgramStages(pipeline, stages, program);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glValidateProgram(GLuint program) {
   MakeFunctionUnique("glValidateProgram");
   interface_->ValidateProgram(program);
 }
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glValidateProgramPipeline(GLuint pipeline) {
+  MakeFunctionUnique("glValidateProgramPipeline");
+  interface_->ValidateProgramPipeline(pipeline);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glVertexAttrib1f(GLuint indx,
                                                             GLfloat x) {
   MakeFunctionUnique("glVertexAttrib1f");
@@ -4175,6 +4637,13 @@
 }
 
 void GL_BINDING_CALL
+MockGLInterface::Mock_glVertexAttribBinding(GLuint attribindex,
+                                            GLuint bindingindex) {
+  MakeFunctionUnique("glVertexAttribBinding");
+  interface_->VertexAttribBinding(attribindex, bindingindex);
+}
+
+void GL_BINDING_CALL
 MockGLInterface::Mock_glVertexAttribDivisor(GLuint index, GLuint divisor) {
   MakeFunctionUnique("glVertexAttribDivisor");
   interface_->VertexAttribDivisorANGLE(index, divisor);
@@ -4198,6 +4667,17 @@
   interface_->VertexAttribDivisorANGLE(index, divisor);
 }
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glVertexAttribFormat(GLuint attribindex,
+                                           GLint size,
+                                           GLenum type,
+                                           GLboolean normalized,
+                                           GLuint relativeoffset) {
+  MakeFunctionUnique("glVertexAttribFormat");
+  interface_->VertexAttribFormat(attribindex, size, type, normalized,
+                                 relativeoffset);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glVertexAttribI4i(GLuint indx,
                                                              GLint x,
                                                              GLint y,
@@ -4229,6 +4709,15 @@
 }
 
 void GL_BINDING_CALL
+MockGLInterface::Mock_glVertexAttribIFormat(GLuint attribindex,
+                                            GLint size,
+                                            GLenum type,
+                                            GLuint relativeoffset) {
+  MakeFunctionUnique("glVertexAttribIFormat");
+  interface_->VertexAttribIFormat(attribindex, size, type, relativeoffset);
+}
+
+void GL_BINDING_CALL
 MockGLInterface::Mock_glVertexAttribIPointer(GLuint indx,
                                              GLint size,
                                              GLenum type,
@@ -4249,6 +4738,13 @@
   interface_->VertexAttribPointer(indx, size, type, normalized, stride, ptr);
 }
 
+void GL_BINDING_CALL
+MockGLInterface::Mock_glVertexBindingDivisor(GLuint bindingindex,
+                                             GLuint divisor) {
+  MakeFunctionUnique("glVertexBindingDivisor");
+  interface_->VertexBindingDivisor(bindingindex, divisor);
+}
+
 void GL_BINDING_CALL MockGLInterface::Mock_glViewport(GLint x,
                                                       GLint y,
                                                       GLsizei width,
@@ -4278,6 +4774,8 @@
 
 GLFunctionPointerType GL_BINDING_CALL
 MockGLInterface::GetGLProcAddress(const char* name) {
+  if (strcmp(name, "glActiveShaderProgram") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glActiveShaderProgram);
   if (strcmp(name, "glActiveTexture") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glActiveTexture);
   if (strcmp(name, "glApplyFramebufferAttachmentCMAAINTEL") == 0)
@@ -4331,6 +4829,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glBindImageTexture);
   if (strcmp(name, "glBindImageTextureEXT") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glBindImageTextureEXT);
+  if (strcmp(name, "glBindProgramPipeline") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glBindProgramPipeline);
   if (strcmp(name, "glBindRenderbuffer") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glBindRenderbuffer);
   if (strcmp(name, "glBindRenderbufferEXT") == 0)
@@ -4351,6 +4851,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glBindVertexArrayAPPLE);
   if (strcmp(name, "glBindVertexArrayOES") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glBindVertexArrayOES);
+  if (strcmp(name, "glBindVertexBuffer") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glBindVertexBuffer);
   if (strcmp(name, "glBlendBarrierKHR") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glBlendBarrierKHR);
   if (strcmp(name, "glBlendBarrierNV") == 0)
@@ -4475,6 +4977,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glCreateProgram);
   if (strcmp(name, "glCreateShader") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glCreateShader);
+  if (strcmp(name, "glCreateShaderProgramv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glCreateShaderProgramv);
   if (strcmp(name, "glCullFace") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glCullFace);
   if (strcmp(name, "glDebugMessageCallback") == 0)
@@ -4509,6 +5013,9 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glDeletePathsNV);
   if (strcmp(name, "glDeleteProgram") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glDeleteProgram);
+  if (strcmp(name, "glDeleteProgramPipelines") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glDeleteProgramPipelines);
   if (strcmp(name, "glDeleteQueries") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glDeleteQueries);
   if (strcmp(name, "glDeleteQueriesARB") == 0)
@@ -4557,8 +5064,15 @@
   if (strcmp(name, "glDiscardFramebufferEXT") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glDiscardFramebufferEXT);
+  if (strcmp(name, "glDispatchCompute") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glDispatchCompute);
+  if (strcmp(name, "glDispatchComputeIndirect") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glDispatchComputeIndirect);
   if (strcmp(name, "glDrawArrays") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glDrawArrays);
+  if (strcmp(name, "glDrawArraysIndirect") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glDrawArraysIndirect);
   if (strcmp(name, "glDrawArraysInstanced") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glDrawArraysInstanced);
   if (strcmp(name, "glDrawArraysInstancedANGLE") == 0)
@@ -4577,6 +5091,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glDrawBuffersEXT);
   if (strcmp(name, "glDrawElements") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glDrawElements);
+  if (strcmp(name, "glDrawElementsIndirect") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glDrawElementsIndirect);
   if (strcmp(name, "glDrawElementsInstanced") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glDrawElementsInstanced);
@@ -4665,6 +5181,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glGenPathsCHROMIUM);
   if (strcmp(name, "glGenPathsNV") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glGenPathsNV);
+  if (strcmp(name, "glGenProgramPipelines") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glGenProgramPipelines);
   if (strcmp(name, "glGenQueries") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glGenQueries);
   if (strcmp(name, "glGenQueriesARB") == 0)
@@ -4711,6 +5229,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glGetAttachedShaders);
   if (strcmp(name, "glGetAttribLocation") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glGetAttribLocation);
+  if (strcmp(name, "glGetBooleani_v") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glGetBooleani_v);
   if (strcmp(name, "glGetBooleani_vRobustANGLE") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glGetBooleani_vRobustANGLE);
@@ -4758,6 +5278,9 @@
   if (strcmp(name, "glGetFramebufferAttachmentParameterivRobustANGLE") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glGetFramebufferAttachmentParameterivRobustANGLE);
+  if (strcmp(name, "glGetFramebufferParameteriv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glGetFramebufferParameteriv);
   if (strcmp(name, "glGetFramebufferParameterivRobustANGLE") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glGetFramebufferParameterivRobustANGLE);
@@ -4830,6 +5353,14 @@
   if (strcmp(name, "glGetProgramInterfaceivRobustANGLE") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glGetProgramInterfaceivRobustANGLE);
+  if (strcmp(name, "glGetProgramPipelineInfoLog") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glGetProgramPipelineInfoLog);
+  if (strcmp(name, "glGetProgramPipelineiv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glGetProgramPipelineiv);
+  if (strcmp(name, "glGetProgramResourceIndex") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glGetProgramResourceIndex);
   if (strcmp(name, "glGetProgramResourceLocation") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glGetProgramResourceLocation);
@@ -5048,6 +5579,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glIsPathNV);
   if (strcmp(name, "glIsProgram") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glIsProgram);
+  if (strcmp(name, "glIsProgramPipeline") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glIsProgramPipeline);
   if (strcmp(name, "glIsQuery") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glIsQuery);
   if (strcmp(name, "glIsQueryARB") == 0)
@@ -5098,6 +5631,9 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glMatrixLoadfEXT);
   if (strcmp(name, "glMemoryBarrier") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glMemoryBarrier);
+  if (strcmp(name, "glMemoryBarrierByRegion") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glMemoryBarrierByRegion);
   if (strcmp(name, "glMemoryBarrierEXT") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glMemoryBarrierEXT);
   if (strcmp(name, "glObjectLabel") == 0)
@@ -5159,6 +5695,81 @@
   if (strcmp(name, "glProgramPathFragmentInputGenNV") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glProgramPathFragmentInputGenNV);
+  if (strcmp(name, "glProgramUniform1f") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform1f);
+  if (strcmp(name, "glProgramUniform1fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform1fv);
+  if (strcmp(name, "glProgramUniform1i") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform1i);
+  if (strcmp(name, "glProgramUniform1iv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform1iv);
+  if (strcmp(name, "glProgramUniform1ui") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform1ui);
+  if (strcmp(name, "glProgramUniform1uiv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform1uiv);
+  if (strcmp(name, "glProgramUniform2f") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform2f);
+  if (strcmp(name, "glProgramUniform2fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform2fv);
+  if (strcmp(name, "glProgramUniform2i") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform2i);
+  if (strcmp(name, "glProgramUniform2iv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform2iv);
+  if (strcmp(name, "glProgramUniform2ui") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform2ui);
+  if (strcmp(name, "glProgramUniform2uiv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform2uiv);
+  if (strcmp(name, "glProgramUniform3f") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform3f);
+  if (strcmp(name, "glProgramUniform3fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform3fv);
+  if (strcmp(name, "glProgramUniform3i") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform3i);
+  if (strcmp(name, "glProgramUniform3iv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform3iv);
+  if (strcmp(name, "glProgramUniform3ui") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform3ui);
+  if (strcmp(name, "glProgramUniform3uiv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform3uiv);
+  if (strcmp(name, "glProgramUniform4f") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform4f);
+  if (strcmp(name, "glProgramUniform4fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform4fv);
+  if (strcmp(name, "glProgramUniform4i") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform4i);
+  if (strcmp(name, "glProgramUniform4iv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform4iv);
+  if (strcmp(name, "glProgramUniform4ui") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform4ui);
+  if (strcmp(name, "glProgramUniform4uiv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glProgramUniform4uiv);
+  if (strcmp(name, "glProgramUniformMatrix2fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix2fv);
+  if (strcmp(name, "glProgramUniformMatrix2x3fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix2x3fv);
+  if (strcmp(name, "glProgramUniformMatrix2x4fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix2x4fv);
+  if (strcmp(name, "glProgramUniformMatrix3fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix3fv);
+  if (strcmp(name, "glProgramUniformMatrix3x2fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix3x2fv);
+  if (strcmp(name, "glProgramUniformMatrix3x4fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix3x4fv);
+  if (strcmp(name, "glProgramUniformMatrix4fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix4fv);
+  if (strcmp(name, "glProgramUniformMatrix4x2fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix4x2fv);
+  if (strcmp(name, "glProgramUniformMatrix4x3fv") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glProgramUniformMatrix4x3fv);
   if (strcmp(name, "glPushDebugGroup") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glPushDebugGroup);
   if (strcmp(name, "glPushDebugGroupKHR") == 0)
@@ -5207,6 +5818,8 @@
         Mock_glResumeTransformFeedback);
   if (strcmp(name, "glSampleCoverage") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glSampleCoverage);
+  if (strcmp(name, "glSampleMaski") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glSampleMaski);
   if (strcmp(name, "glSamplerParameterIivRobustANGLE") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glSamplerParameterIivRobustANGLE);
@@ -5345,6 +5958,9 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glTexStorage2D);
   if (strcmp(name, "glTexStorage2DEXT") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glTexStorage2DEXT);
+  if (strcmp(name, "glTexStorage2DMultisample") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glTexStorage2DMultisample);
   if (strcmp(name, "glTexStorage3D") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glTexStorage3D);
   if (strcmp(name, "glTexSubImage2D") == 0)
@@ -5437,8 +6053,13 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glUnmapBufferOES);
   if (strcmp(name, "glUseProgram") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glUseProgram);
+  if (strcmp(name, "glUseProgramStages") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glUseProgramStages);
   if (strcmp(name, "glValidateProgram") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glValidateProgram);
+  if (strcmp(name, "glValidateProgramPipeline") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_glValidateProgramPipeline);
   if (strcmp(name, "glVertexAttrib1f") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttrib1f);
   if (strcmp(name, "glVertexAttrib1fv") == 0)
@@ -5455,6 +6076,8 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttrib4f);
   if (strcmp(name, "glVertexAttrib4fv") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttrib4fv);
+  if (strcmp(name, "glVertexAttribBinding") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribBinding);
   if (strcmp(name, "glVertexAttribDivisor") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribDivisor);
   if (strcmp(name, "glVertexAttribDivisorANGLE") == 0)
@@ -5466,6 +6089,8 @@
   if (strcmp(name, "glVertexAttribDivisorEXT") == 0)
     return reinterpret_cast<GLFunctionPointerType>(
         Mock_glVertexAttribDivisorEXT);
+  if (strcmp(name, "glVertexAttribFormat") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribFormat);
   if (strcmp(name, "glVertexAttribI4i") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribI4i);
   if (strcmp(name, "glVertexAttribI4iv") == 0)
@@ -5474,10 +6099,14 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribI4ui);
   if (strcmp(name, "glVertexAttribI4uiv") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribI4uiv);
+  if (strcmp(name, "glVertexAttribIFormat") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribIFormat);
   if (strcmp(name, "glVertexAttribIPointer") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribIPointer);
   if (strcmp(name, "glVertexAttribPointer") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribPointer);
+  if (strcmp(name, "glVertexBindingDivisor") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexBindingDivisor);
   if (strcmp(name, "glViewport") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_glViewport);
   if (strcmp(name, "glWaitSync") == 0)
diff --git a/ui/gl/gl_bindings_autogen_mock.h b/ui/gl/gl_bindings_autogen_mock.h
index 2d3dd877..52c7be6 100644
--- a/ui/gl/gl_bindings_autogen_mock.h
+++ b/ui/gl/gl_bindings_autogen_mock.h
@@ -8,6 +8,12 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
+static void GL_BINDING_CALL Mock_glActiveShaderProgram(GLuint pipeline,
+                                                       GLuint program);
 static void GL_BINDING_CALL Mock_glActiveTexture(GLenum texture);
 static void GL_BINDING_CALL Mock_glApplyFramebufferAttachmentCMAAINTEL(void);
 static void GL_BINDING_CALL Mock_glAttachShader(GLuint program, GLuint shader);
@@ -75,6 +81,7 @@
                                                        GLint layer,
                                                        GLenum access,
                                                        GLint format);
+static void GL_BINDING_CALL Mock_glBindProgramPipeline(GLuint pipeline);
 static void GL_BINDING_CALL Mock_glBindRenderbuffer(GLenum target,
                                                     GLuint renderbuffer);
 static void GL_BINDING_CALL Mock_glBindRenderbufferEXT(GLenum target,
@@ -90,6 +97,10 @@
 static void GL_BINDING_CALL Mock_glBindVertexArray(GLuint array);
 static void GL_BINDING_CALL Mock_glBindVertexArrayAPPLE(GLuint array);
 static void GL_BINDING_CALL Mock_glBindVertexArrayOES(GLuint array);
+static void GL_BINDING_CALL Mock_glBindVertexBuffer(GLuint bindingindex,
+                                                    GLuint buffer,
+                                                    GLintptr offset,
+                                                    GLsizei stride);
 static void GL_BINDING_CALL Mock_glBlendBarrierKHR(void);
 static void GL_BINDING_CALL Mock_glBlendBarrierNV(void);
 static void GL_BINDING_CALL Mock_glBlendColor(GLclampf red,
@@ -358,6 +369,10 @@
 static void GL_BINDING_CALL Mock_glCoverageModulationNV(GLenum components);
 static GLuint GL_BINDING_CALL Mock_glCreateProgram(void);
 static GLuint GL_BINDING_CALL Mock_glCreateShader(GLenum type);
+static GLuint GL_BINDING_CALL
+Mock_glCreateShaderProgramv(GLenum type,
+                            GLsizei count,
+                            const char* const* strings);
 static void GL_BINDING_CALL Mock_glCullFace(GLenum mode);
 static void GL_BINDING_CALL Mock_glDebugMessageCallback(GLDEBUGPROC callback,
                                                         const void* userParam);
@@ -401,6 +416,8 @@
                                                        GLsizei range);
 static void GL_BINDING_CALL Mock_glDeletePathsNV(GLuint path, GLsizei range);
 static void GL_BINDING_CALL Mock_glDeleteProgram(GLuint program);
+static void GL_BINDING_CALL
+Mock_glDeleteProgramPipelines(GLsizei n, const GLuint* pipelines);
 static void GL_BINDING_CALL Mock_glDeleteQueries(GLsizei n, const GLuint* ids);
 static void GL_BINDING_CALL Mock_glDeleteQueriesARB(GLsizei n,
                                                     const GLuint* ids);
@@ -435,9 +452,15 @@
 Mock_glDiscardFramebufferEXT(GLenum target,
                              GLsizei numAttachments,
                              const GLenum* attachments);
+static void GL_BINDING_CALL Mock_glDispatchCompute(GLuint numGroupsX,
+                                                   GLuint numGroupsY,
+                                                   GLuint numGroupsZ);
+static void GL_BINDING_CALL Mock_glDispatchComputeIndirect(GLintptr indirect);
 static void GL_BINDING_CALL Mock_glDrawArrays(GLenum mode,
                                               GLint first,
                                               GLsizei count);
+static void GL_BINDING_CALL Mock_glDrawArraysIndirect(GLenum mode,
+                                                      const void* indirect);
 static void GL_BINDING_CALL Mock_glDrawArraysInstanced(GLenum mode,
                                                        GLint first,
                                                        GLsizei count,
@@ -460,6 +483,9 @@
                                                 GLsizei count,
                                                 GLenum type,
                                                 const void* indices);
+static void GL_BINDING_CALL Mock_glDrawElementsIndirect(GLenum mode,
+                                                        GLenum type,
+                                                        const void* indirect);
 static void GL_BINDING_CALL Mock_glDrawElementsInstanced(GLenum mode,
                                                          GLsizei count,
                                                          GLenum type,
@@ -557,6 +583,8 @@
                                                       GLuint* framebuffers);
 static GLuint GL_BINDING_CALL Mock_glGenPathsCHROMIUM(GLsizei range);
 static GLuint GL_BINDING_CALL Mock_glGenPathsNV(GLsizei range);
+static GLuint GL_BINDING_CALL Mock_glGenProgramPipelines(GLsizei n,
+                                                         GLuint* pipelines);
 static void GL_BINDING_CALL Mock_glGenQueries(GLsizei n, GLuint* ids);
 static void GL_BINDING_CALL Mock_glGenQueriesARB(GLsizei n, GLuint* ids);
 static void GL_BINDING_CALL Mock_glGenQueriesEXT(GLsizei n, GLuint* ids);
@@ -619,6 +647,9 @@
                                                       GLuint* shaders);
 static GLint GL_BINDING_CALL Mock_glGetAttribLocation(GLuint program,
                                                       const char* name);
+static void GL_BINDING_CALL Mock_glGetBooleani_v(GLenum target,
+                                                 GLuint index,
+                                                 GLboolean* data);
 static void GL_BINDING_CALL Mock_glGetBooleani_vRobustANGLE(GLenum target,
                                                             GLuint index,
                                                             GLsizei bufSize,
@@ -697,6 +728,9 @@
                                                       GLsizei bufSize,
                                                       GLsizei* length,
                                                       GLint* params);
+static void GL_BINDING_CALL Mock_glGetFramebufferParameteriv(GLenum target,
+                                                             GLenum pname,
+                                                             GLint* params);
 static void GL_BINDING_CALL
 Mock_glGetFramebufferParameterivRobustANGLE(GLenum target,
                                             GLenum pname,
@@ -804,6 +838,17 @@
                                         GLsizei bufSize,
                                         GLsizei* length,
                                         GLint* params);
+static void GL_BINDING_CALL Mock_glGetProgramPipelineInfoLog(GLuint pipeline,
+                                                             GLsizei bufSize,
+                                                             GLsizei* length,
+                                                             GLchar* infoLog);
+static void GL_BINDING_CALL Mock_glGetProgramPipelineiv(GLuint pipeline,
+                                                        GLenum pname,
+                                                        GLint* params);
+static void GL_BINDING_CALL
+Mock_glGetProgramResourceIndex(GLuint program,
+                               GLenum programInterface,
+                               const GLchar* name);
 static GLint GL_BINDING_CALL
 Mock_glGetProgramResourceLocation(GLuint program,
                                   GLenum programInterface,
@@ -1149,6 +1194,7 @@
 static GLboolean GL_BINDING_CALL Mock_glIsPathCHROMIUM(GLuint path);
 static GLboolean GL_BINDING_CALL Mock_glIsPathNV(GLuint path);
 static GLboolean GL_BINDING_CALL Mock_glIsProgram(GLuint program);
+static GLboolean GL_BINDING_CALL Mock_glIsProgramPipeline(GLuint pipeline);
 static GLboolean GL_BINDING_CALL Mock_glIsQuery(GLuint query);
 static GLboolean GL_BINDING_CALL Mock_glIsQueryARB(GLuint query);
 static GLboolean GL_BINDING_CALL Mock_glIsQueryEXT(GLuint query);
@@ -1182,6 +1228,7 @@
 static void GL_BINDING_CALL Mock_glMatrixLoadfEXT(GLenum matrixMode,
                                                   const GLfloat* m);
 static void GL_BINDING_CALL Mock_glMemoryBarrier(GLbitfield barriers);
+static void GL_BINDING_CALL Mock_glMemoryBarrierByRegion(GLbitfield barriers);
 static void GL_BINDING_CALL Mock_glMemoryBarrierEXT(GLbitfield barriers);
 static void GL_BINDING_CALL Mock_glObjectLabel(GLenum identifier,
                                                GLuint name,
@@ -1259,6 +1306,162 @@
                                      GLenum genMode,
                                      GLint components,
                                      const GLfloat* coeffs);
+static void GL_BINDING_CALL Mock_glProgramUniform1f(GLuint program,
+                                                    GLint location,
+                                                    GLfloat v0);
+static void GL_BINDING_CALL Mock_glProgramUniform1fv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLfloat* value);
+static void GL_BINDING_CALL Mock_glProgramUniform1i(GLuint program,
+                                                    GLint location,
+                                                    GLint v0);
+static void GL_BINDING_CALL Mock_glProgramUniform1iv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLint* value);
+static void GL_BINDING_CALL Mock_glProgramUniform1ui(GLuint program,
+                                                     GLint location,
+                                                     GLuint v0);
+static void GL_BINDING_CALL Mock_glProgramUniform1uiv(GLuint program,
+                                                      GLint location,
+                                                      GLsizei count,
+                                                      const GLuint* value);
+static void GL_BINDING_CALL Mock_glProgramUniform2f(GLuint program,
+                                                    GLint location,
+                                                    GLfloat v0,
+                                                    GLfloat v1);
+static void GL_BINDING_CALL Mock_glProgramUniform2fv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLfloat* value);
+static void GL_BINDING_CALL Mock_glProgramUniform2i(GLuint program,
+                                                    GLint location,
+                                                    GLint v0,
+                                                    GLint v1);
+static void GL_BINDING_CALL Mock_glProgramUniform2iv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLint* value);
+static void GL_BINDING_CALL Mock_glProgramUniform2ui(GLuint program,
+                                                     GLint location,
+                                                     GLuint v0,
+                                                     GLuint v1);
+static void GL_BINDING_CALL Mock_glProgramUniform2uiv(GLuint program,
+                                                      GLint location,
+                                                      GLsizei count,
+                                                      const GLuint* value);
+static void GL_BINDING_CALL Mock_glProgramUniform3f(GLuint program,
+                                                    GLint location,
+                                                    GLfloat v0,
+                                                    GLfloat v1,
+                                                    GLfloat v2);
+static void GL_BINDING_CALL Mock_glProgramUniform3fv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLfloat* value);
+static void GL_BINDING_CALL Mock_glProgramUniform3i(GLuint program,
+                                                    GLint location,
+                                                    GLint v0,
+                                                    GLint v1,
+                                                    GLint v2);
+static void GL_BINDING_CALL Mock_glProgramUniform3iv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLint* value);
+static void GL_BINDING_CALL Mock_glProgramUniform3ui(GLuint program,
+                                                     GLint location,
+                                                     GLuint v0,
+                                                     GLuint v1,
+                                                     GLuint v2);
+static void GL_BINDING_CALL Mock_glProgramUniform3uiv(GLuint program,
+                                                      GLint location,
+                                                      GLsizei count,
+                                                      const GLuint* value);
+static void GL_BINDING_CALL Mock_glProgramUniform4f(GLuint program,
+                                                    GLint location,
+                                                    GLfloat v0,
+                                                    GLfloat v1,
+                                                    GLfloat v2,
+                                                    GLfloat v3);
+static void GL_BINDING_CALL Mock_glProgramUniform4fv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLfloat* value);
+static void GL_BINDING_CALL Mock_glProgramUniform4i(GLuint program,
+                                                    GLint location,
+                                                    GLint v0,
+                                                    GLint v1,
+                                                    GLint v2,
+                                                    GLint v3);
+static void GL_BINDING_CALL Mock_glProgramUniform4iv(GLuint program,
+                                                     GLint location,
+                                                     GLsizei count,
+                                                     const GLint* value);
+static void GL_BINDING_CALL Mock_glProgramUniform4ui(GLuint program,
+                                                     GLint location,
+                                                     GLuint v0,
+                                                     GLuint v1,
+                                                     GLuint v2,
+                                                     GLuint v3);
+static void GL_BINDING_CALL Mock_glProgramUniform4uiv(GLuint program,
+                                                      GLint location,
+                                                      GLsizei count,
+                                                      const GLuint* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix2fv(GLuint program,
+                               GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix2x3fv(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix2x4fv(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix3fv(GLuint program,
+                               GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix3x2fv(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix3x4fv(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix4fv(GLuint program,
+                               GLint location,
+                               GLsizei count,
+                               GLboolean transpose,
+                               const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix4x2fv(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value);
+static void GL_BINDING_CALL
+Mock_glProgramUniformMatrix4x3fv(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value);
 static void GL_BINDING_CALL Mock_glPushDebugGroup(GLenum source,
                                                   GLuint id,
                                                   GLsizei length,
@@ -1338,6 +1541,8 @@
 static void GL_BINDING_CALL Mock_glResumeTransformFeedback(void);
 static void GL_BINDING_CALL Mock_glSampleCoverage(GLclampf value,
                                                   GLboolean invert);
+static void GL_BINDING_CALL Mock_glSampleMaski(GLuint maskNumber,
+                                               GLbitfield mask);
 static void GL_BINDING_CALL
 Mock_glSamplerParameterIivRobustANGLE(GLuint sampler,
                                       GLenum pname,
@@ -1617,6 +1822,13 @@
                                                    GLenum internalformat,
                                                    GLsizei width,
                                                    GLsizei height);
+static void GL_BINDING_CALL
+Mock_glTexStorage2DMultisample(GLenum target,
+                               GLsizei samples,
+                               GLenum internalformat,
+                               GLsizei width,
+                               GLsizei height,
+                               GLboolean fixedsamplelocations);
 static void GL_BINDING_CALL Mock_glTexStorage3D(GLenum target,
                                                 GLsizei levels,
                                                 GLenum internalformat,
@@ -1782,7 +1994,11 @@
 static GLboolean GL_BINDING_CALL Mock_glUnmapBuffer(GLenum target);
 static GLboolean GL_BINDING_CALL Mock_glUnmapBufferOES(GLenum target);
 static void GL_BINDING_CALL Mock_glUseProgram(GLuint program);
+static void GL_BINDING_CALL Mock_glUseProgramStages(GLuint pipeline,
+                                                    GLbitfield stages,
+                                                    GLuint program);
 static void GL_BINDING_CALL Mock_glValidateProgram(GLuint program);
+static void GL_BINDING_CALL Mock_glValidateProgramPipeline(GLuint pipeline);
 static void GL_BINDING_CALL Mock_glVertexAttrib1f(GLuint indx, GLfloat x);
 static void GL_BINDING_CALL Mock_glVertexAttrib1fv(GLuint indx,
                                                    const GLfloat* values);
@@ -1801,6 +2017,8 @@
 Mock_glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 static void GL_BINDING_CALL Mock_glVertexAttrib4fv(GLuint indx,
                                                    const GLfloat* values);
+static void GL_BINDING_CALL Mock_glVertexAttribBinding(GLuint attribindex,
+                                                       GLuint bindingindex);
 static void GL_BINDING_CALL Mock_glVertexAttribDivisor(GLuint index,
                                                        GLuint divisor);
 static void GL_BINDING_CALL Mock_glVertexAttribDivisorANGLE(GLuint index,
@@ -1809,6 +2027,11 @@
                                                           GLuint divisor);
 static void GL_BINDING_CALL Mock_glVertexAttribDivisorEXT(GLuint index,
                                                           GLuint divisor);
+static void GL_BINDING_CALL Mock_glVertexAttribFormat(GLuint attribindex,
+                                                      GLint size,
+                                                      GLenum type,
+                                                      GLboolean normalized,
+                                                      GLuint relativeoffset);
 static void GL_BINDING_CALL
 Mock_glVertexAttribI4i(GLuint indx, GLint x, GLint y, GLint z, GLint w);
 static void GL_BINDING_CALL Mock_glVertexAttribI4iv(GLuint indx,
@@ -1817,6 +2040,10 @@
 Mock_glVertexAttribI4ui(GLuint indx, GLuint x, GLuint y, GLuint z, GLuint w);
 static void GL_BINDING_CALL Mock_glVertexAttribI4uiv(GLuint indx,
                                                      const GLuint* values);
+static void GL_BINDING_CALL Mock_glVertexAttribIFormat(GLuint attribindex,
+                                                       GLint size,
+                                                       GLenum type,
+                                                       GLuint relativeoffset);
 static void GL_BINDING_CALL Mock_glVertexAttribIPointer(GLuint indx,
                                                         GLint size,
                                                         GLenum type,
@@ -1828,6 +2055,8 @@
                                                        GLboolean normalized,
                                                        GLsizei stride,
                                                        const void* ptr);
+static void GL_BINDING_CALL Mock_glVertexBindingDivisor(GLuint bindingindex,
+                                                        GLuint divisor);
 static void GL_BINDING_CALL Mock_glViewport(GLint x,
                                             GLint y,
                                             GLsizei width,
diff --git a/ui/gl/gl_enums_implementation_autogen.h b/ui/gl/gl_enums_implementation_autogen.h
index 622d2c2..1aaf6900 100644
--- a/ui/gl/gl_enums_implementation_autogen.h
+++ b/ui/gl/gl_enums_implementation_autogen.h
@@ -8,6 +8,9 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+#ifndef UI_GL_GL_ENUMS_IMPLEMENTATION_AUTOGEN_H_
+#define UI_GL_GL_ENUMS_IMPLEMENTATION_AUTOGEN_H_
+
 static const GLEnums::EnumToString enum_to_string_table[] = {
     {
         0, "GL_FALSE",
@@ -472,9 +475,18 @@
         0x100, "GL_GLYPH_HAS_KERNING_BIT_NV",
     },
     {
+        0x1000, "GL_TEXTURE_WIDTH",
+    },
+    {
         0x10000000, "GL_FONT_HAS_KERNING_BIT_NV",
     },
     {
+        0x1001, "GL_TEXTURE_HEIGHT",
+    },
+    {
+        0x1003, "GL_TEXTURE_INTERNAL_FORMAT",
+    },
+    {
         0x1004, "GL_TEXTURE_BORDER_COLOR_OES",
     },
     {
@@ -862,6 +874,18 @@
         0x805B, "GL_RGBA16_EXT",
     },
     {
+        0x805C, "GL_TEXTURE_RED_SIZE",
+    },
+    {
+        0x805D, "GL_TEXTURE_GREEN_SIZE",
+    },
+    {
+        0x805E, "GL_TEXTURE_BLUE_SIZE",
+    },
+    {
+        0x805F, "GL_TEXTURE_ALPHA_SIZE",
+    },
+    {
         0x8069, "GL_TEXTURE_BINDING_2D",
     },
     {
@@ -877,6 +901,9 @@
         0x806F, "GL_TEXTURE_3D_OES",
     },
     {
+        0x8071, "GL_TEXTURE_DEPTH",
+    },
+    {
         0x8072, "GL_TEXTURE_WRAP_R_OES",
     },
     {
@@ -1174,6 +1201,24 @@
         0x8261, "GL_NO_RESET_NOTIFICATION_KHR",
     },
     {
+        0x8262, "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE",
+    },
+    {
+        0x8263, "GL_MAX_COMPUTE_UNIFORM_COMPONENTS",
+    },
+    {
+        0x8264, "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS",
+    },
+    {
+        0x8265, "GL_MAX_COMPUTE_ATOMIC_COUNTERS",
+    },
+    {
+        0x8266, "GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS",
+    },
+    {
+        0x8267, "GL_COMPUTE_WORK_GROUP_SIZE",
+    },
+    {
         0x8268, "GL_DEBUG_TYPE_MARKER_KHR",
     },
     {
@@ -1192,6 +1237,30 @@
         0x826D, "GL_DEBUG_GROUP_STACK_DEPTH_KHR",
     },
     {
+        0x826E, "GL_MAX_UNIFORM_LOCATIONS",
+    },
+    {
+        0x82D4, "GL_VERTEX_ATTRIB_BINDING",
+    },
+    {
+        0x82D5, "GL_VERTEX_ATTRIB_RELATIVE_OFFSET",
+    },
+    {
+        0x82D6, "GL_VERTEX_BINDING_DIVISOR",
+    },
+    {
+        0x82D7, "GL_VERTEX_BINDING_OFFSET",
+    },
+    {
+        0x82D8, "GL_VERTEX_BINDING_STRIDE",
+    },
+    {
+        0x82D9, "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET",
+    },
+    {
+        0x82DA, "GL_MAX_VERTEX_ATTRIB_BINDINGS",
+    },
+    {
         0x82DB, "GL_TEXTURE_VIEW_MIN_LEVEL_OES",
     },
     {
@@ -1222,6 +1291,9 @@
         0x82E4, "GL_PROGRAM_PIPELINE_KHR",
     },
     {
+        0x82E5, "GL_MAX_VERTEX_ATTRIB_STRIDE",
+    },
+    {
         0x82E6, "GL_SAMPLER_KHR",
     },
     {
@@ -1495,6 +1567,9 @@
         0x8645, "GL_VERTEX_ATTRIB_ARRAY_POINTER",
     },
     {
+        0x86A1, "GL_TEXTURE_COMPRESSED",
+    },
+    {
         0x86A2, "GL_NUM_COMPRESSED_TEXTURE_FORMATS",
     },
     {
@@ -1627,6 +1702,9 @@
         0x883D, "GL_BLEND_EQUATION_ALPHA",
     },
     {
+        0x884A, "GL_TEXTURE_DEPTH_SIZE",
+    },
+    {
         0x884C, "GL_TEXTURE_COMPARE_MODE_EXT",
     },
     {
@@ -1687,6 +1765,9 @@
         0x88B9, "GL_WRITE_ONLY_OES",
     },
     {
+        0x88BA, "GL_READ_WRITE",
+    },
+    {
         0x88BB, "GL_BUFFER_ACCESS_OES",
     },
     {
@@ -1744,6 +1825,9 @@
         0x88F0, "GL_DEPTH24_STENCIL8_OES",
     },
     {
+        0x88F1, "GL_TEXTURE_STENCIL_SIZE",
+    },
+    {
         0x88F9, "GL_SRC1_COLOR_EXT",
     },
     {
@@ -2188,6 +2272,21 @@
         0x8C0A, "GL_SGX_BINARY_IMG",
     },
     {
+        0x8C10, "GL_TEXTURE_RED_TYPE",
+    },
+    {
+        0x8C11, "GL_TEXTURE_GREEN_TYPE",
+    },
+    {
+        0x8C12, "GL_TEXTURE_BLUE_TYPE",
+    },
+    {
+        0x8C13, "GL_TEXTURE_ALPHA_TYPE",
+    },
+    {
+        0x8C16, "GL_TEXTURE_DEPTH_TYPE",
+    },
+    {
         0x8C17, "GL_UNSIGNED_NORMALIZED_EXT",
     },
     {
@@ -2233,6 +2332,9 @@
         0x8C3E, "GL_UNSIGNED_INT_5_9_9_9_REV_APPLE",
     },
     {
+        0x8C3F, "GL_TEXTURE_SHARED_SIZE",
+    },
+    {
         0x8C40, "GL_SRGB_EXT",
     },
     {
@@ -2797,6 +2899,15 @@
         0x8E50, "GL_SAMPLE_LOCATION_NV",
     },
     {
+        0x8E51, "GL_SAMPLE_MASK",
+    },
+    {
+        0x8E52, "GL_SAMPLE_MASK_VALUE",
+    },
+    {
+        0x8E59, "GL_MAX_SAMPLE_MASK_WORDS",
+    },
+    {
         0x8E5A, "GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES",
     },
     {
@@ -2809,6 +2920,12 @@
         0x8E5D, "GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES",
     },
     {
+        0x8E5E, "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET",
+    },
+    {
+        0x8E5F, "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET",
+    },
+    {
         0x8E72, "GL_PATCH_VERTICES_OES",
     },
     {
@@ -2926,6 +3043,36 @@
         0x8F37, "GL_COPY_WRITE_BUFFER_NV",
     },
     {
+        0x8F38, "GL_MAX_IMAGE_UNITS",
+    },
+    {
+        0x8F39, "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES",
+    },
+    {
+        0x8F3A, "GL_IMAGE_BINDING_NAME",
+    },
+    {
+        0x8F3B, "GL_IMAGE_BINDING_LEVEL",
+    },
+    {
+        0x8F3C, "GL_IMAGE_BINDING_LAYERED",
+    },
+    {
+        0x8F3D, "GL_IMAGE_BINDING_LAYER",
+    },
+    {
+        0x8F3E, "GL_IMAGE_BINDING_ACCESS",
+    },
+    {
+        0x8F3F, "GL_DRAW_INDIRECT_BUFFER",
+    },
+    {
+        0x8F43, "GL_DRAW_INDIRECT_BUFFER_BINDING",
+    },
+    {
+        0x8F4F, "GL_VERTEX_BINDING_BUFFER",
+    },
+    {
         0x8F60, "GL_MALI_SHADER_BINARY_ARM",
     },
     {
@@ -3100,24 +3247,63 @@
         0x900F, "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES",
     },
     {
+        0x904D, "GL_IMAGE_2D",
+    },
+    {
+        0x904E, "GL_IMAGE_3D",
+    },
+    {
+        0x9050, "GL_IMAGE_CUBE",
+    },
+    {
         0x9051, "GL_IMAGE_BUFFER_OES",
     },
     {
+        0x9053, "GL_IMAGE_2D_ARRAY",
+    },
+    {
         0x9054, "GL_IMAGE_CUBE_MAP_ARRAY_OES",
     },
     {
+        0x9058, "GL_INT_IMAGE_2D",
+    },
+    {
+        0x9059, "GL_INT_IMAGE_3D",
+    },
+    {
+        0x905B, "GL_INT_IMAGE_CUBE",
+    },
+    {
         0x905C, "GL_INT_IMAGE_BUFFER_OES",
     },
     {
+        0x905E, "GL_INT_IMAGE_2D_ARRAY",
+    },
+    {
         0x905F, "GL_INT_IMAGE_CUBE_MAP_ARRAY_OES",
     },
     {
+        0x9063, "GL_UNSIGNED_INT_IMAGE_2D",
+    },
+    {
+        0x9064, "GL_UNSIGNED_INT_IMAGE_3D",
+    },
+    {
+        0x9066, "GL_UNSIGNED_INT_IMAGE_CUBE",
+    },
+    {
         0x9067, "GL_UNSIGNED_INT_IMAGE_BUFFER_OES",
     },
     {
+        0x9069, "GL_UNSIGNED_INT_IMAGE_2D_ARRAY",
+    },
+    {
         0x906A, "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES",
     },
     {
+        0x906E, "GL_IMAGE_BINDING_FORMAT",
+    },
+    {
         0x906F, "GL_RGB10_A2UI",
     },
     {
@@ -3328,6 +3514,18 @@
         0x90BF, "GL_PATH_COVER_DEPTH_FUNC_NV",
     },
     {
+        0x90C7, "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE",
+    },
+    {
+        0x90C8, "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE",
+    },
+    {
+        0x90C9, "GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS",
+    },
+    {
+        0x90CA, "GL_MAX_VERTEX_IMAGE_UNIFORMS",
+    },
+    {
         0x90CB, "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES",
     },
     {
@@ -3337,6 +3535,27 @@
         0x90CD, "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES",
     },
     {
+        0x90CE, "GL_MAX_FRAGMENT_IMAGE_UNIFORMS",
+    },
+    {
+        0x90CF, "GL_MAX_COMBINED_IMAGE_UNIFORMS",
+    },
+    {
+        0x90D2, "GL_SHADER_STORAGE_BUFFER",
+    },
+    {
+        0x90D3, "GL_SHADER_STORAGE_BUFFER_BINDING",
+    },
+    {
+        0x90D4, "GL_SHADER_STORAGE_BUFFER_START",
+    },
+    {
+        0x90D5, "GL_SHADER_STORAGE_BUFFER_SIZE",
+    },
+    {
+        0x90D6, "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS",
+    },
+    {
         0x90D7, "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES",
     },
     {
@@ -3346,6 +3565,36 @@
         0x90D9, "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES",
     },
     {
+        0x90DA, "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS",
+    },
+    {
+        0x90DB, "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS",
+    },
+    {
+        0x90DC, "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS",
+    },
+    {
+        0x90DD, "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS",
+    },
+    {
+        0x90DE, "GL_MAX_SHADER_STORAGE_BLOCK_SIZE",
+    },
+    {
+        0x90DF, "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT",
+    },
+    {
+        0x90EA, "GL_DEPTH_STENCIL_TEXTURE_MODE",
+    },
+    {
+        0x90EB, "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS",
+    },
+    {
+        0x90EE, "GL_DISPATCH_INDIRECT_BUFFER",
+    },
+    {
+        0x90EF, "GL_DISPATCH_INDIRECT_BUFFER_BINDING",
+    },
+    {
         0x90F0, "GL_COLOR_ATTACHMENT_EXT",
     },
     {
@@ -3370,9 +3619,27 @@
         0x9102, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES",
     },
     {
+        0x9104, "GL_TEXTURE_BINDING_2D_MULTISAMPLE",
+    },
+    {
         0x9105, "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES",
     },
     {
+        0x9106, "GL_TEXTURE_SAMPLES",
+    },
+    {
+        0x9107, "GL_TEXTURE_FIXED_SAMPLE_LOCATIONS",
+    },
+    {
+        0x9108, "GL_SAMPLER_2D_MULTISAMPLE",
+    },
+    {
+        0x9109, "GL_INT_SAMPLER_2D_MULTISAMPLE",
+    },
+    {
+        0x910A, "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE",
+    },
+    {
         0x910B, "GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
     },
     {
@@ -3382,6 +3649,15 @@
         0x910D, "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
     },
     {
+        0x910E, "GL_MAX_COLOR_TEXTURE_SAMPLES",
+    },
+    {
+        0x910F, "GL_MAX_DEPTH_TEXTURE_SAMPLES",
+    },
+    {
+        0x9110, "GL_MAX_INTEGER_SAMPLES",
+    },
+    {
         0x9111, "GL_MAX_SERVER_WAIT_TIMEOUT_APPLE",
     },
     {
@@ -3556,6 +3832,24 @@
         0x91AA, "GL_NUM_SPARSE_LEVELS_EXT",
     },
     {
+        0x91B9, "GL_COMPUTE_SHADER",
+    },
+    {
+        0x91BB, "GL_MAX_COMPUTE_UNIFORM_BLOCKS",
+    },
+    {
+        0x91BC, "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS",
+    },
+    {
+        0x91BD, "GL_MAX_COMPUTE_IMAGE_UNIFORMS",
+    },
+    {
+        0x91BE, "GL_MAX_COMPUTE_WORK_GROUP_COUNT",
+    },
+    {
+        0x91BF, "GL_MAX_COMPUTE_WORK_GROUP_SIZE",
+    },
+    {
         0x9243, "GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM",
     },
     {
@@ -3766,6 +4060,21 @@
         0x92BE, "GL_PRIMITIVE_BOUNDING_BOX_OES",
     },
     {
+        0x92C0, "GL_ATOMIC_COUNTER_BUFFER",
+    },
+    {
+        0x92C1, "GL_ATOMIC_COUNTER_BUFFER_BINDING",
+    },
+    {
+        0x92C2, "GL_ATOMIC_COUNTER_BUFFER_START",
+    },
+    {
+        0x92C3, "GL_ATOMIC_COUNTER_BUFFER_SIZE",
+    },
+    {
+        0x92CC, "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS",
+    },
+    {
         0x92CD, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES",
     },
     {
@@ -3775,6 +4084,15 @@
         0x92CF, "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES",
     },
     {
+        0x92D0, "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS",
+    },
+    {
+        0x92D1, "GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS",
+    },
+    {
+        0x92D2, "GL_MAX_VERTEX_ATOMIC_COUNTERS",
+    },
+    {
         0x92D3, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES",
     },
     {
@@ -3784,6 +4102,24 @@
         0x92D5, "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES",
     },
     {
+        0x92D6, "GL_MAX_FRAGMENT_ATOMIC_COUNTERS",
+    },
+    {
+        0x92D7, "GL_MAX_COMBINED_ATOMIC_COUNTERS",
+    },
+    {
+        0x92D8, "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE",
+    },
+    {
+        0x92D9, "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS",
+    },
+    {
+        0x92DB, "GL_UNSIGNED_INT_ATOMIC_COUNTER",
+    },
+    {
+        0x92DC, "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS",
+    },
+    {
         0x92DD, "GL_FRAGMENT_COVERAGE_TO_COLOR_NV",
     },
     {
@@ -3793,9 +4129,81 @@
         0x92E0, "GL_DEBUG_OUTPUT_KHR",
     },
     {
+        0x92E1, "GL_UNIFORM",
+    },
+    {
+        0x92E2, "GL_UNIFORM_BLOCK",
+    },
+    {
+        0x92E3, "GL_PROGRAM_INPUT",
+    },
+    {
+        0x92E4, "GL_PROGRAM_OUTPUT",
+    },
+    {
+        0x92E5, "GL_BUFFER_VARIABLE",
+    },
+    {
+        0x92E6, "GL_SHADER_STORAGE_BLOCK",
+    },
+    {
         0x92E7, "GL_IS_PER_PATCH_OES",
     },
     {
+        0x92F4, "GL_TRANSFORM_FEEDBACK_VARYING",
+    },
+    {
+        0x92F5, "GL_ACTIVE_RESOURCES",
+    },
+    {
+        0x92F6, "GL_MAX_NAME_LENGTH",
+    },
+    {
+        0x92F7, "GL_MAX_NUM_ACTIVE_VARIABLES",
+    },
+    {
+        0x92F9, "GL_NAME_LENGTH",
+    },
+    {
+        0x92FA, "GL_TYPE",
+    },
+    {
+        0x92FB, "GL_ARRAY_SIZE",
+    },
+    {
+        0x92FC, "GL_OFFSET",
+    },
+    {
+        0x92FD, "GL_BLOCK_INDEX",
+    },
+    {
+        0x92FE, "GL_ARRAY_STRIDE",
+    },
+    {
+        0x92FF, "GL_MATRIX_STRIDE",
+    },
+    {
+        0x9300, "GL_IS_ROW_MAJOR",
+    },
+    {
+        0x9301, "GL_ATOMIC_COUNTER_BUFFER_INDEX",
+    },
+    {
+        0x9302, "GL_BUFFER_BINDING",
+    },
+    {
+        0x9303, "GL_BUFFER_DATA_SIZE",
+    },
+    {
+        0x9304, "GL_NUM_ACTIVE_VARIABLES",
+    },
+    {
+        0x9305, "GL_ACTIVE_VARIABLES",
+    },
+    {
+        0x9306, "GL_REFERENCED_BY_VERTEX_SHADER",
+    },
+    {
         0x9307, "GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES",
     },
     {
@@ -3805,15 +4213,51 @@
         0x9309, "GL_REFERENCED_BY_GEOMETRY_SHADER_OES",
     },
     {
+        0x930A, "GL_REFERENCED_BY_FRAGMENT_SHADER",
+    },
+    {
+        0x930B, "GL_REFERENCED_BY_COMPUTE_SHADER",
+    },
+    {
+        0x930C, "GL_TOP_LEVEL_ARRAY_SIZE",
+    },
+    {
+        0x930D, "GL_TOP_LEVEL_ARRAY_STRIDE",
+    },
+    {
+        0x930E, "GL_LOCATION",
+    },
+    {
         0x930F, "GL_LOCATION_INDEX_EXT",
     },
     {
+        0x9310, "GL_FRAMEBUFFER_DEFAULT_WIDTH",
+    },
+    {
+        0x9311, "GL_FRAMEBUFFER_DEFAULT_HEIGHT",
+    },
+    {
         0x9312, "GL_FRAMEBUFFER_DEFAULT_LAYERS_OES",
     },
     {
+        0x9313, "GL_FRAMEBUFFER_DEFAULT_SAMPLES",
+    },
+    {
+        0x9314, "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS",
+    },
+    {
+        0x9315, "GL_MAX_FRAMEBUFFER_WIDTH",
+    },
+    {
+        0x9316, "GL_MAX_FRAMEBUFFER_HEIGHT",
+    },
+    {
         0x9317, "GL_MAX_FRAMEBUFFER_LAYERS_OES",
     },
     {
+        0x9318, "GL_MAX_FRAMEBUFFER_SAMPLES",
+    },
+    {
         0x9327, "GL_RASTER_MULTISAMPLE_EXT",
     },
     {
@@ -4277,3 +4721,5 @@
     enum_to_string_table;
 const size_t GLEnums::enum_to_string_table_len_ =
     sizeof(enum_to_string_table) / sizeof(enum_to_string_table[0]);
+
+#endif  //  UI_GL_GL_ENUMS_IMPLEMENTATION_AUTOGEN_H_
\ No newline at end of file
diff --git a/ui/gl/gl_mock_autogen_egl.h b/ui/gl/gl_mock_autogen_egl.h
index d1aa7da..4718f66c 100644
--- a/ui/gl/gl_mock_autogen_egl.h
+++ b/ui/gl/gl_mock_autogen_egl.h
@@ -8,6 +8,10 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
 MOCK_METHOD1(BindAPI, EGLBoolean(EGLenum api));
 MOCK_METHOD3(BindTexImage,
              EGLBoolean(EGLDisplay dpy, EGLSurface surface, EGLint buffer));
diff --git a/ui/gl/gl_mock_autogen_gl.h b/ui/gl/gl_mock_autogen_gl.h
index 18b04c1..76b60258 100644
--- a/ui/gl/gl_mock_autogen_gl.h
+++ b/ui/gl/gl_mock_autogen_gl.h
@@ -8,6 +8,11 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
+
+MOCK_METHOD2(ActiveShaderProgram, void(GLuint pipeline, GLuint program));
 MOCK_METHOD1(ActiveTexture, void(GLenum texture));
 MOCK_METHOD0(ApplyFramebufferAttachmentCMAAINTEL, void());
 MOCK_METHOD2(AttachShader, void(GLuint program, GLuint shader));
@@ -39,6 +44,7 @@
                   GLint layer,
                   GLenum access,
                   GLint format));
+MOCK_METHOD1(BindProgramPipeline, void(GLuint pipeline));
 MOCK_METHOD2(BindRenderbufferEXT, void(GLenum target, GLuint renderbuffer));
 MOCK_METHOD2(BindSampler, void(GLuint unit, GLuint sampler));
 MOCK_METHOD2(BindTexture, void(GLenum target, GLuint texture));
@@ -46,6 +52,9 @@
 MOCK_METHOD3(BindUniformLocationCHROMIUM,
              void(GLuint program, GLint location, const char* name));
 MOCK_METHOD1(BindVertexArrayOES, void(GLuint array));
+MOCK_METHOD4(
+    BindVertexBuffer,
+    void(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride));
 MOCK_METHOD0(BlendBarrierKHR, void());
 MOCK_METHOD4(BlendColor,
              void(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
@@ -229,6 +238,8 @@
 MOCK_METHOD2(CoverStrokePathNV, void(GLuint name, GLenum coverMode));
 MOCK_METHOD0(CreateProgram, GLuint());
 MOCK_METHOD1(CreateShader, GLuint(GLenum type));
+MOCK_METHOD3(CreateShaderProgramv,
+             GLuint(GLenum type, GLsizei count, const char* const* strings));
 MOCK_METHOD1(CullFace, void(GLenum mode));
 MOCK_METHOD2(DebugMessageCallback,
              void(GLDEBUGPROC callback, const void* userParam));
@@ -253,6 +264,7 @@
              void(GLsizei n, const GLuint* framebuffers));
 MOCK_METHOD2(DeletePathsNV, void(GLuint path, GLsizei range));
 MOCK_METHOD1(DeleteProgram, void(GLuint program));
+MOCK_METHOD2(DeleteProgramPipelines, void(GLsizei n, const GLuint* pipelines));
 MOCK_METHOD2(DeleteQueries, void(GLsizei n, const GLuint* ids));
 MOCK_METHOD2(DeleteRenderbuffersEXT,
              void(GLsizei n, const GLuint* renderbuffers));
@@ -273,7 +285,11 @@
              void(GLenum target,
                   GLsizei numAttachments,
                   const GLenum* attachments));
+MOCK_METHOD3(DispatchCompute,
+             void(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ));
+MOCK_METHOD1(DispatchComputeIndirect, void(GLintptr indirect));
 MOCK_METHOD3(DrawArrays, void(GLenum mode, GLint first, GLsizei count));
+MOCK_METHOD2(DrawArraysIndirect, void(GLenum mode, const void* indirect));
 MOCK_METHOD4(DrawArraysInstancedANGLE,
              void(GLenum mode, GLint first, GLsizei count, GLsizei primcount));
 MOCK_METHOD1(DrawBuffer, void(GLenum mode));
@@ -281,6 +297,8 @@
 MOCK_METHOD4(
     DrawElements,
     void(GLenum mode, GLsizei count, GLenum type, const void* indices));
+MOCK_METHOD3(DrawElementsIndirect,
+             void(GLenum mode, GLenum type, const void* indirect));
 MOCK_METHOD5(DrawElementsInstancedANGLE,
              void(GLenum mode,
                   GLsizei count,
@@ -342,6 +360,7 @@
 MOCK_METHOD2(GenFencesNV, void(GLsizei n, GLuint* fences));
 MOCK_METHOD2(GenFramebuffersEXT, void(GLsizei n, GLuint* framebuffers));
 MOCK_METHOD1(GenPathsNV, GLuint(GLsizei range));
+MOCK_METHOD2(GenProgramPipelines, GLuint(GLsizei n, GLuint* pipelines));
 MOCK_METHOD2(GenQueries, void(GLsizei n, GLuint* ids));
 MOCK_METHOD2(GenRenderbuffersEXT, void(GLsizei n, GLuint* renderbuffers));
 MOCK_METHOD2(GenSamplers, void(GLsizei n, GLuint* samplers));
@@ -392,6 +411,7 @@
     GetAttachedShaders,
     void(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders));
 MOCK_METHOD2(GetAttribLocation, GLint(GLuint program, const char* name));
+MOCK_METHOD3(GetBooleani_v, void(GLenum target, GLuint index, GLboolean* data));
 MOCK_METHOD5(GetBooleani_vRobustANGLE,
              void(GLenum target,
                   GLuint index,
@@ -449,6 +469,8 @@
                   GLsizei bufSize,
                   GLsizei* length,
                   GLint* params));
+MOCK_METHOD3(GetFramebufferParameteriv,
+             void(GLenum target, GLenum pname, GLint* params));
 MOCK_METHOD5(GetFramebufferParameterivRobustANGLE,
              void(GLenum target,
                   GLenum pname,
@@ -553,6 +575,13 @@
                   GLsizei bufSize,
                   GLsizei* length,
                   GLint* params));
+MOCK_METHOD4(
+    GetProgramPipelineInfoLog,
+    void(GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog));
+MOCK_METHOD3(GetProgramPipelineiv,
+             void(GLuint pipeline, GLenum pname, GLint* params));
+MOCK_METHOD3(GetProgramResourceIndex,
+             void(GLuint program, GLenum programInterface, const GLchar* name));
 MOCK_METHOD8(GetProgramResourceiv,
              void(GLuint program,
                   GLenum programInterface,
@@ -815,6 +844,7 @@
 MOCK_METHOD1(IsFramebufferEXT, GLboolean(GLuint framebuffer));
 MOCK_METHOD1(IsPathNV, GLboolean(GLuint path));
 MOCK_METHOD1(IsProgram, GLboolean(GLuint program));
+MOCK_METHOD1(IsProgramPipeline, GLboolean(GLuint pipeline));
 MOCK_METHOD1(IsQuery, GLboolean(GLuint query));
 MOCK_METHOD1(IsRenderbufferEXT, GLboolean(GLuint renderbuffer));
 MOCK_METHOD1(IsSampler, GLboolean(GLuint sampler));
@@ -833,6 +863,7 @@
                    GLbitfield access));
 MOCK_METHOD2(MatrixLoadfEXT, void(GLenum matrixMode, const GLfloat* m));
 MOCK_METHOD1(MatrixLoadIdentityEXT, void(GLenum matrixMode));
+MOCK_METHOD1(MemoryBarrierByRegion, void(GLbitfield barriers));
 MOCK_METHOD1(MemoryBarrierEXT, void(GLbitfield barriers));
 MOCK_METHOD4(
     ObjectLabel,
@@ -870,6 +901,137 @@
                   GLenum genMode,
                   GLint components,
                   const GLfloat* coeffs));
+MOCK_METHOD3(ProgramUniform1f,
+             void(GLuint program, GLint location, GLfloat v0));
+MOCK_METHOD4(
+    ProgramUniform1fv,
+    void(GLuint program, GLint location, GLsizei count, const GLfloat* value));
+MOCK_METHOD3(ProgramUniform1i, void(GLuint program, GLint location, GLint v0));
+MOCK_METHOD4(
+    ProgramUniform1iv,
+    void(GLuint program, GLint location, GLsizei count, const GLint* value));
+MOCK_METHOD3(ProgramUniform1ui,
+             void(GLuint program, GLint location, GLuint v0));
+MOCK_METHOD4(
+    ProgramUniform1uiv,
+    void(GLuint program, GLint location, GLsizei count, const GLuint* value));
+MOCK_METHOD4(ProgramUniform2f,
+             void(GLuint program, GLint location, GLfloat v0, GLfloat v1));
+MOCK_METHOD4(
+    ProgramUniform2fv,
+    void(GLuint program, GLint location, GLsizei count, const GLfloat* value));
+MOCK_METHOD4(ProgramUniform2i,
+             void(GLuint program, GLint location, GLint v0, GLint v1));
+MOCK_METHOD4(
+    ProgramUniform2iv,
+    void(GLuint program, GLint location, GLsizei count, const GLint* value));
+MOCK_METHOD4(ProgramUniform2ui,
+             void(GLuint program, GLint location, GLuint v0, GLuint v1));
+MOCK_METHOD4(
+    ProgramUniform2uiv,
+    void(GLuint program, GLint location, GLsizei count, const GLuint* value));
+MOCK_METHOD5(
+    ProgramUniform3f,
+    void(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2));
+MOCK_METHOD4(
+    ProgramUniform3fv,
+    void(GLuint program, GLint location, GLsizei count, const GLfloat* value));
+MOCK_METHOD5(
+    ProgramUniform3i,
+    void(GLuint program, GLint location, GLint v0, GLint v1, GLint v2));
+MOCK_METHOD4(
+    ProgramUniform3iv,
+    void(GLuint program, GLint location, GLsizei count, const GLint* value));
+MOCK_METHOD5(
+    ProgramUniform3ui,
+    void(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2));
+MOCK_METHOD4(
+    ProgramUniform3uiv,
+    void(GLuint program, GLint location, GLsizei count, const GLuint* value));
+MOCK_METHOD6(ProgramUniform4f,
+             void(GLuint program,
+                  GLint location,
+                  GLfloat v0,
+                  GLfloat v1,
+                  GLfloat v2,
+                  GLfloat v3));
+MOCK_METHOD4(
+    ProgramUniform4fv,
+    void(GLuint program, GLint location, GLsizei count, const GLfloat* value));
+MOCK_METHOD6(ProgramUniform4i,
+             void(GLuint program,
+                  GLint location,
+                  GLint v0,
+                  GLint v1,
+                  GLint v2,
+                  GLint v3));
+MOCK_METHOD4(
+    ProgramUniform4iv,
+    void(GLuint program, GLint location, GLsizei count, const GLint* value));
+MOCK_METHOD6(ProgramUniform4ui,
+             void(GLuint program,
+                  GLint location,
+                  GLuint v0,
+                  GLuint v1,
+                  GLuint v2,
+                  GLuint v3));
+MOCK_METHOD4(
+    ProgramUniform4uiv,
+    void(GLuint program, GLint location, GLsizei count, const GLuint* value));
+MOCK_METHOD5(ProgramUniformMatrix2fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix2x3fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix2x4fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix3fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix3x2fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix3x4fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix4fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix4x2fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
+MOCK_METHOD5(ProgramUniformMatrix4x3fv,
+             void(GLuint program,
+                  GLint location,
+                  GLsizei count,
+                  GLboolean transpose,
+                  const GLfloat* value));
 MOCK_METHOD4(
     PushDebugGroup,
     void(GLenum source, GLuint id, GLsizei length, const char* message));
@@ -907,6 +1069,7 @@
 MOCK_METHOD1(RequestExtensionANGLE, void(const char* name));
 MOCK_METHOD0(ResumeTransformFeedback, void());
 MOCK_METHOD2(SampleCoverage, void(GLclampf value, GLboolean invert));
+MOCK_METHOD2(SampleMaski, void(GLuint maskNumber, GLbitfield mask));
 MOCK_METHOD3(SamplerParameterf,
              void(GLuint sampler, GLenum pname, GLfloat param));
 MOCK_METHOD3(SamplerParameterfv,
@@ -1063,6 +1226,13 @@
                   GLenum internalformat,
                   GLsizei width,
                   GLsizei height));
+MOCK_METHOD6(TexStorage2DMultisample,
+             void(GLenum target,
+                  GLsizei samples,
+                  GLenum internalformat,
+                  GLsizei width,
+                  GLsizei height,
+                  GLboolean fixedsamplelocations));
 MOCK_METHOD6(TexStorage3D,
              void(GLenum target,
                   GLsizei levels,
@@ -1178,7 +1348,10 @@
                   const GLfloat* value));
 MOCK_METHOD1(UnmapBuffer, GLboolean(GLenum target));
 MOCK_METHOD1(UseProgram, void(GLuint program));
+MOCK_METHOD3(UseProgramStages,
+             void(GLuint pipeline, GLbitfield stages, GLuint program));
 MOCK_METHOD1(ValidateProgram, void(GLuint program));
+MOCK_METHOD1(ValidateProgramPipeline, void(GLuint pipeline));
 MOCK_METHOD2(VertexAttrib1f, void(GLuint indx, GLfloat x));
 MOCK_METHOD2(VertexAttrib1fv, void(GLuint indx, const GLfloat* values));
 MOCK_METHOD3(VertexAttrib2f, void(GLuint indx, GLfloat x, GLfloat y));
@@ -1189,13 +1362,24 @@
 MOCK_METHOD5(VertexAttrib4f,
              void(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w));
 MOCK_METHOD2(VertexAttrib4fv, void(GLuint indx, const GLfloat* values));
+MOCK_METHOD2(VertexAttribBinding,
+             void(GLuint attribindex, GLuint bindingindex));
 MOCK_METHOD2(VertexAttribDivisorANGLE, void(GLuint index, GLuint divisor));
+MOCK_METHOD5(VertexAttribFormat,
+             void(GLuint attribindex,
+                  GLint size,
+                  GLenum type,
+                  GLboolean normalized,
+                  GLuint relativeoffset));
 MOCK_METHOD5(VertexAttribI4i,
              void(GLuint indx, GLint x, GLint y, GLint z, GLint w));
 MOCK_METHOD2(VertexAttribI4iv, void(GLuint indx, const GLint* values));
 MOCK_METHOD5(VertexAttribI4ui,
              void(GLuint indx, GLuint x, GLuint y, GLuint z, GLuint w));
 MOCK_METHOD2(VertexAttribI4uiv, void(GLuint indx, const GLuint* values));
+MOCK_METHOD4(
+    VertexAttribIFormat,
+    void(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset));
 MOCK_METHOD5(VertexAttribIPointer,
              void(GLuint indx,
                   GLint size,
@@ -1209,6 +1393,7 @@
                   GLboolean normalized,
                   GLsizei stride,
                   const void* ptr));
+MOCK_METHOD2(VertexBindingDivisor, void(GLuint bindingindex, GLuint divisor));
 MOCK_METHOD4(Viewport, void(GLint x, GLint y, GLsizei width, GLsizei height));
 MOCK_METHOD3(WaitSync, void(GLsync sync, GLbitfield flags, GLuint64 timeout));
 MOCK_METHOD3(WindowRectanglesEXT,
diff --git a/ui/gl/gl_stub_autogen_gl.cc b/ui/gl/gl_stub_autogen_gl.cc
index 80d35bd..cf0fc52 100644
--- a/ui/gl/gl_stub_autogen_gl.cc
+++ b/ui/gl/gl_stub_autogen_gl.cc
@@ -30,6 +30,12 @@
   return 0;
 }
 
+GLuint GLStubApiBase::glCreateShaderProgramvFn(GLenum type,
+                                               GLsizei count,
+                                               const char* const* strings) {
+  return 0;
+}
+
 GLsync GLStubApiBase::glFenceSyncFn(GLenum condition, GLbitfield flags) {
   return 0;
 }
@@ -38,6 +44,10 @@
   return 0;
 }
 
+GLuint GLStubApiBase::glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) {
+  return 0;
+}
+
 GLint GLStubApiBase::glGetAttribLocationFn(GLuint program, const char* name) {
   return 0;
 }
@@ -120,6 +130,10 @@
   return 0;
 }
 
+GLboolean GLStubApiBase::glIsProgramPipelineFn(GLuint pipeline) {
+  return 0;
+}
+
 GLboolean GLStubApiBase::glIsQueryFn(GLuint query) {
   return 0;
 }
diff --git a/ui/gl/gl_stub_autogen_gl.h b/ui/gl/gl_stub_autogen_gl.h
index 9dbeca9..c0589a5 100644
--- a/ui/gl/gl_stub_autogen_gl.h
+++ b/ui/gl/gl_stub_autogen_gl.h
@@ -8,6 +8,10 @@
 //    clang-format -i -style=chromium filename
 // DO NOT EDIT!
 
+#ifndef UI_GL_GL_STUB_AUTOGEN_H_
+#define UI_GL_GL_STUB_AUTOGEN_H_
+
+void glActiveShaderProgramFn(GLuint pipeline, GLuint program) override {}
 void glActiveTextureFn(GLenum texture) override {}
 void glApplyFramebufferAttachmentCMAAINTELFn() override {}
 void glAttachShaderFn(GLuint program, GLuint shader) override {}
@@ -41,6 +45,7 @@
                              GLint layer,
                              GLenum access,
                              GLint format) override {}
+void glBindProgramPipelineFn(GLuint pipeline) override {}
 void glBindRenderbufferEXTFn(GLenum target, GLuint renderbuffer) override {}
 void glBindSamplerFn(GLuint unit, GLuint sampler) override {}
 void glBindTextureFn(GLenum target, GLuint texture) override {}
@@ -49,6 +54,10 @@
                                      GLint location,
                                      const char* name) override {}
 void glBindVertexArrayOESFn(GLuint array) override {}
+void glBindVertexBufferFn(GLuint bindingindex,
+                          GLuint buffer,
+                          GLintptr offset,
+                          GLsizei stride) override {}
 void glBlendBarrierKHRFn() override {}
 void glBlendColorFn(GLclampf red,
                     GLclampf green,
@@ -262,6 +271,9 @@
 void glCoverStrokePathNVFn(GLuint name, GLenum coverMode) override {}
 GLuint glCreateProgramFn() override;
 GLuint glCreateShaderFn(GLenum type) override;
+GLuint glCreateShaderProgramvFn(GLenum type,
+                                GLsizei count,
+                                const char* const* strings) override;
 void glCullFaceFn(GLenum mode) override {}
 void glDebugMessageCallbackFn(GLDEBUGPROC callback,
                               const void* userParam) override {}
@@ -284,6 +296,7 @@
 }
 void glDeletePathsNVFn(GLuint path, GLsizei range) override {}
 void glDeleteProgramFn(GLuint program) override {}
+void glDeleteProgramPipelinesFn(GLsizei n, const GLuint* pipelines) override {}
 void glDeleteQueriesFn(GLsizei n, const GLuint* ids) override {}
 void glDeleteRenderbuffersEXTFn(GLsizei n,
                                 const GLuint* renderbuffers) override {}
@@ -303,7 +316,12 @@
 void glDiscardFramebufferEXTFn(GLenum target,
                                GLsizei numAttachments,
                                const GLenum* attachments) override {}
+void glDispatchComputeFn(GLuint numGroupsX,
+                         GLuint numGroupsY,
+                         GLuint numGroupsZ) override {}
+void glDispatchComputeIndirectFn(GLintptr indirect) override {}
 void glDrawArraysFn(GLenum mode, GLint first, GLsizei count) override {}
+void glDrawArraysIndirectFn(GLenum mode, const void* indirect) override {}
 void glDrawArraysInstancedANGLEFn(GLenum mode,
                                   GLint first,
                                   GLsizei count,
@@ -314,6 +332,9 @@
                       GLsizei count,
                       GLenum type,
                       const void* indices) override {}
+void glDrawElementsIndirectFn(GLenum mode,
+                              GLenum type,
+                              const void* indirect) override {}
 void glDrawElementsInstancedANGLEFn(GLenum mode,
                                     GLsizei count,
                                     GLenum type,
@@ -371,6 +392,7 @@
 void glGenFencesNVFn(GLsizei n, GLuint* fences) override {}
 void glGenFramebuffersEXTFn(GLsizei n, GLuint* framebuffers) override {}
 GLuint glGenPathsNVFn(GLsizei range) override;
+GLuint glGenProgramPipelinesFn(GLsizei n, GLuint* pipelines) override;
 void glGenQueriesFn(GLsizei n, GLuint* ids) override {}
 void glGenRenderbuffersEXTFn(GLsizei n, GLuint* renderbuffers) override {}
 void glGenSamplersFn(GLsizei n, GLuint* samplers) override {}
@@ -416,6 +438,7 @@
                             GLsizei* count,
                             GLuint* shaders) override {}
 GLint glGetAttribLocationFn(GLuint program, const char* name) override;
+void glGetBooleani_vFn(GLenum target, GLuint index, GLboolean* data) override {}
 void glGetBooleani_vRobustANGLEFn(GLenum target,
                                   GLuint index,
                                   GLsizei bufSize,
@@ -472,6 +495,9 @@
     GLsizei bufSize,
     GLsizei* length,
     GLint* params) override {}
+void glGetFramebufferParameterivFn(GLenum target,
+                                   GLenum pname,
+                                   GLint* params) override {}
 void glGetFramebufferParameterivRobustANGLEFn(GLenum target,
                                               GLenum pname,
                                               GLsizei bufSize,
@@ -571,6 +597,16 @@
                                  GLsizei bufSize,
                                  GLsizei* length,
                                  GLint* params) override {}
+void glGetProgramPipelineInfoLogFn(GLuint pipeline,
+                                   GLsizei bufSize,
+                                   GLsizei* length,
+                                   GLchar* infoLog) override {}
+void glGetProgramPipelineivFn(GLuint pipeline,
+                              GLenum pname,
+                              GLint* params) override {}
+void glGetProgramResourceIndexFn(GLuint program,
+                                 GLenum programInterface,
+                                 const GLchar* name) override {}
 void glGetProgramResourceivFn(GLuint program,
                               GLenum programInterface,
                               GLuint index,
@@ -818,6 +854,7 @@
 GLboolean glIsFramebufferEXTFn(GLuint framebuffer) override;
 GLboolean glIsPathNVFn(GLuint path) override;
 GLboolean glIsProgramFn(GLuint program) override;
+GLboolean glIsProgramPipelineFn(GLuint pipeline) override;
 GLboolean glIsQueryFn(GLuint query) override;
 GLboolean glIsRenderbufferEXTFn(GLuint renderbuffer) override;
 GLboolean glIsSamplerFn(GLuint sampler) override;
@@ -835,6 +872,7 @@
                          GLbitfield access) override;
 void glMatrixLoadfEXTFn(GLenum matrixMode, const GLfloat* m) override {}
 void glMatrixLoadIdentityEXTFn(GLenum matrixMode) override {}
+void glMemoryBarrierByRegionFn(GLbitfield barriers) override {}
 void glMemoryBarrierEXTFn(GLbitfield barriers) override {}
 void glObjectLabelFn(GLenum identifier,
                      GLuint name,
@@ -870,6 +908,149 @@
                                        GLenum genMode,
                                        GLint components,
                                        const GLfloat* coeffs) override {}
+void glProgramUniform1fFn(GLuint program, GLint location, GLfloat v0) override {
+}
+void glProgramUniform1fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override {}
+void glProgramUniform1iFn(GLuint program, GLint location, GLint v0) override {}
+void glProgramUniform1ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override {}
+void glProgramUniform1uiFn(GLuint program, GLint location, GLuint v0) override {
+}
+void glProgramUniform1uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override {}
+void glProgramUniform2fFn(GLuint program,
+                          GLint location,
+                          GLfloat v0,
+                          GLfloat v1) override {}
+void glProgramUniform2fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override {}
+void glProgramUniform2iFn(GLuint program,
+                          GLint location,
+                          GLint v0,
+                          GLint v1) override {}
+void glProgramUniform2ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override {}
+void glProgramUniform2uiFn(GLuint program,
+                           GLint location,
+                           GLuint v0,
+                           GLuint v1) override {}
+void glProgramUniform2uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override {}
+void glProgramUniform3fFn(GLuint program,
+                          GLint location,
+                          GLfloat v0,
+                          GLfloat v1,
+                          GLfloat v2) override {}
+void glProgramUniform3fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override {}
+void glProgramUniform3iFn(GLuint program,
+                          GLint location,
+                          GLint v0,
+                          GLint v1,
+                          GLint v2) override {}
+void glProgramUniform3ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override {}
+void glProgramUniform3uiFn(GLuint program,
+                           GLint location,
+                           GLuint v0,
+                           GLuint v1,
+                           GLuint v2) override {}
+void glProgramUniform3uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override {}
+void glProgramUniform4fFn(GLuint program,
+                          GLint location,
+                          GLfloat v0,
+                          GLfloat v1,
+                          GLfloat v2,
+                          GLfloat v3) override {}
+void glProgramUniform4fvFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLfloat* value) override {}
+void glProgramUniform4iFn(GLuint program,
+                          GLint location,
+                          GLint v0,
+                          GLint v1,
+                          GLint v2,
+                          GLint v3) override {}
+void glProgramUniform4ivFn(GLuint program,
+                           GLint location,
+                           GLsizei count,
+                           const GLint* value) override {}
+void glProgramUniform4uiFn(GLuint program,
+                           GLint location,
+                           GLuint v0,
+                           GLuint v1,
+                           GLuint v2,
+                           GLuint v3) override {}
+void glProgramUniform4uivFn(GLuint program,
+                            GLint location,
+                            GLsizei count,
+                            const GLuint* value) override {}
+void glProgramUniformMatrix2fvFn(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value) override {}
+void glProgramUniformMatrix2x3fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override {}
+void glProgramUniformMatrix2x4fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override {}
+void glProgramUniformMatrix3fvFn(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value) override {}
+void glProgramUniformMatrix3x2fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override {}
+void glProgramUniformMatrix3x4fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override {}
+void glProgramUniformMatrix4fvFn(GLuint program,
+                                 GLint location,
+                                 GLsizei count,
+                                 GLboolean transpose,
+                                 const GLfloat* value) override {}
+void glProgramUniformMatrix4x2fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override {}
+void glProgramUniformMatrix4x3fvFn(GLuint program,
+                                   GLint location,
+                                   GLsizei count,
+                                   GLboolean transpose,
+                                   const GLfloat* value) override {}
 void glPushDebugGroupFn(GLenum source,
                         GLuint id,
                         GLsizei length,
@@ -924,6 +1105,7 @@
 void glRequestExtensionANGLEFn(const char* name) override {}
 void glResumeTransformFeedbackFn() override {}
 void glSampleCoverageFn(GLclampf value, GLboolean invert) override {}
+void glSampleMaskiFn(GLuint maskNumber, GLbitfield mask) override {}
 void glSamplerParameterfFn(GLuint sampler,
                            GLenum pname,
                            GLfloat param) override {}
@@ -1104,6 +1286,12 @@
                          GLenum internalformat,
                          GLsizei width,
                          GLsizei height) override {}
+void glTexStorage2DMultisampleFn(GLenum target,
+                                 GLsizei samples,
+                                 GLenum internalformat,
+                                 GLsizei width,
+                                 GLsizei height,
+                                 GLboolean fixedsamplelocations) override {}
 void glTexStorage3DFn(GLenum target,
                       GLsizei levels,
                       GLenum internalformat,
@@ -1233,7 +1421,11 @@
                             const GLfloat* value) override {}
 GLboolean glUnmapBufferFn(GLenum target) override;
 void glUseProgramFn(GLuint program) override {}
+void glUseProgramStagesFn(GLuint pipeline,
+                          GLbitfield stages,
+                          GLuint program) override {}
 void glValidateProgramFn(GLuint program) override {}
+void glValidateProgramPipelineFn(GLuint pipeline) override {}
 void glVertexAttrib1fFn(GLuint indx, GLfloat x) override {}
 void glVertexAttrib1fvFn(GLuint indx, const GLfloat* values) override {}
 void glVertexAttrib2fFn(GLuint indx, GLfloat x, GLfloat y) override {}
@@ -1247,7 +1439,14 @@
                         GLfloat z,
                         GLfloat w) override {}
 void glVertexAttrib4fvFn(GLuint indx, const GLfloat* values) override {}
+void glVertexAttribBindingFn(GLuint attribindex, GLuint bindingindex) override {
+}
 void glVertexAttribDivisorANGLEFn(GLuint index, GLuint divisor) override {}
+void glVertexAttribFormatFn(GLuint attribindex,
+                            GLint size,
+                            GLenum type,
+                            GLboolean normalized,
+                            GLuint relativeoffset) override {}
 void glVertexAttribI4iFn(GLuint indx,
                          GLint x,
                          GLint y,
@@ -1260,6 +1459,10 @@
                           GLuint z,
                           GLuint w) override {}
 void glVertexAttribI4uivFn(GLuint indx, const GLuint* values) override {}
+void glVertexAttribIFormatFn(GLuint attribindex,
+                             GLint size,
+                             GLenum type,
+                             GLuint relativeoffset) override {}
 void glVertexAttribIPointerFn(GLuint indx,
                               GLint size,
                               GLenum type,
@@ -1271,8 +1474,11 @@
                              GLboolean normalized,
                              GLsizei stride,
                              const void* ptr) override {}
+void glVertexBindingDivisorFn(GLuint bindingindex, GLuint divisor) override {}
 void glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) override {}
 void glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) override {}
 void glWindowRectanglesEXTFn(GLenum mode,
                              GLsizei n,
                              const GLint* box) override {}
+
+#endif  //  UI_GL_GL_STUB_AUTOGEN_H_
\ No newline at end of file
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index 42b24e51..cdae45a 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -473,7 +473,12 @@
 
 void KeyboardController::ShowAnimationFinished() {
   MarkKeyboardLoadFinished();
-  NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea();
+
+  // Notify observers after animation finished to prevent reveal desktop
+  // background during animation.
+  NotifyKeyboardBoundsChanging(GetKeyboardWindow()->bounds());
+  ui_->EnsureCaretInWorkArea(
+      container_behavior_->GetOccludedBounds(GetKeyboardWindow()->bounds()));
 }
 
 void KeyboardController::SetContainerBehaviorInternal(
@@ -698,15 +703,6 @@
   return res;
 }
 
-void KeyboardController::
-    NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea() {
-  // Notify observers after animation finished to prevent reveal desktop
-  // background during animation.
-  NotifyKeyboardBoundsChanging(GetKeyboardWindow()->bounds());
-  ui_->EnsureCaretInWorkArea(
-      container_behavior_->GetOccludedBounds(GetKeyboardWindow()->bounds()));
-}
-
 void KeyboardController::NotifyKeyboardConfigChanged() {
   for (KeyboardControllerObserver& observer : observer_list_)
     observer.OnKeyboardConfigChanged();
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h
index 275a3fae..02bbc6c 100644
--- a/ui/keyboard/keyboard_controller.h
+++ b/ui/keyboard/keyboard_controller.h
@@ -300,8 +300,6 @@
   // Called when the show animation finished.
   void ShowAnimationFinished();
 
-  void NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea();
-
   // Notifies keyboard config change to the observers.
   // Only called from |UpdateKeyboardConfig| in keyboard_util.
   void NotifyKeyboardConfigChanged();
diff --git a/ui/keyboard/notification_manager.cc b/ui/keyboard/notification_manager.cc
index 91e4f51..978e029 100644
--- a/ui/keyboard/notification_manager.cc
+++ b/ui/keyboard/notification_manager.cc
@@ -27,7 +27,7 @@
 NotificationManager::NotificationManager() {}
 
 void NotificationManager::SendNotifications(
-    bool bounds_affect_layout,
+    bool does_occluded_bounds_affect_layout,
     bool is_locked,
     const gfx::Rect& visual_bounds,
     const gfx::Rect& occluded_bounds,
@@ -43,7 +43,7 @@
       ShouldSendOccludedBoundsNotification(occluded_bounds);
 
   const gfx::Rect workspace_layout_offset_region =
-      bounds_affect_layout ? visual_bounds : gfx::Rect();
+      does_occluded_bounds_affect_layout ? occluded_bounds : gfx::Rect();
   bool send_displaced_bounds_notification =
       ShouldSendWorkspaceDisplacementBoundsNotification(
           workspace_layout_offset_region);
diff --git a/ui/keyboard/notification_manager.h b/ui/keyboard/notification_manager.h
index ecc2b80..a86cf12 100644
--- a/ui/keyboard/notification_manager.h
+++ b/ui/keyboard/notification_manager.h
@@ -38,7 +38,7 @@
   // - layout displacement bounds change
   // - general visibility change
   void SendNotifications(
-      bool bounds_affect_layout,
+      bool does_occluded_bounds_affect_layout,
       bool is_locked,
       const gfx::Rect& visual_bounds,
       const gfx::Rect& occluded_bounds,
diff --git a/ui/ozone/platform/wayland/OWNERS b/ui/ozone/platform/wayland/OWNERS
new file mode 100644
index 0000000..ac018fd
--- /dev/null
+++ b/ui/ozone/platform/wayland/OWNERS
@@ -0,0 +1,2 @@
+msisov@igalia.com
+tonikitoo@igalia.com
diff --git a/ui/views/layout/box_layout.cc b/ui/views/layout/box_layout.cc
index d0d5624..f9c1b6d 100644
--- a/ui/views/layout/box_layout.cc
+++ b/ui/views/layout/box_layout.cc
@@ -165,19 +165,19 @@
   total_main_axis_size -= between_child_spacing_;
   // Free space can be negative indicating that the views want to overflow.
   int main_free_space = MainAxisSize(child_area) - total_main_axis_size;
+  int main_position = MainAxisPosition(child_area);
   {
-    int position = MainAxisPosition(child_area);
     int size = MainAxisSize(child_area);
     if (!flex_sum) {
       switch (main_axis_alignment_) {
         case MAIN_AXIS_ALIGNMENT_START:
           break;
         case MAIN_AXIS_ALIGNMENT_CENTER:
-          position += main_free_space / 2;
+          main_position += main_free_space / 2;
           size = total_main_axis_size;
           break;
         case MAIN_AXIS_ALIGNMENT_END:
-          position += main_free_space;
+          main_position += main_free_space;
           size = total_main_axis_size;
           break;
         default:
@@ -186,12 +186,11 @@
       }
     }
     gfx::Rect new_child_area(child_area);
-    SetMainAxisPosition(position, &new_child_area);
+    SetMainAxisPosition(main_position, &new_child_area);
     SetMainAxisSize(size, &new_child_area);
     child_area.Intersect(new_child_area);
   }
 
-  int main_position = MainAxisPosition(child_area);
   int total_padding = 0;
   int current_flex = 0;
   for (int i = 0; i < host->child_count(); ++i) {
diff --git a/ui/views/layout/box_layout.h b/ui/views/layout/box_layout.h
index 315ac56..653d810e 100644
--- a/ui/views/layout/box_layout.h
+++ b/ui/views/layout/box_layout.h
@@ -33,9 +33,10 @@
     kVertical,
   };
 
-  // This specifies where along the main axis the children should be laid out.
-  // e.g. a horizontal layout of MAIN_AXIS_ALIGNMENT_END will result in the
-  // child views being right-aligned.
+  // This specifies that the start/center/end of the collective child views is
+  // aligned with the start/center/end of the host view. e.g. a horizontal
+  // layout of MAIN_AXIS_ALIGNMENT_END will result in the child views being
+  // right-aligned.
   enum MainAxisAlignment {
     MAIN_AXIS_ALIGNMENT_START,
     MAIN_AXIS_ALIGNMENT_CENTER,
diff --git a/ui/views/layout/box_layout_unittest.cc b/ui/views/layout/box_layout_unittest.cc
index 676109d..b500e89 100644
--- a/ui/views/layout/box_layout_unittest.cc
+++ b/ui/views/layout/box_layout_unittest.cc
@@ -102,29 +102,30 @@
   host_->AddChildView(v1);
   View* v2 = new StaticSizedView(gfx::Size(10, 20));
   host_->AddChildView(v2);
-  host_->SetBounds(0, 0, 10, 10);
+  host_->SetBounds(0, 0, 15, 10);
 
   // Overflows by positioning views at the start and truncating anything that
   // doesn't fit.
   host_->Layout();
-  EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
+  EXPECT_EQ(gfx::Rect(0, 0, 15, 10), v1->bounds());
   EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
 
-  // All values of main axis alignment should overflow in the same manner.
+  // Clipping of children should occur at the opposite end(s) to the main axis
+  // alignment position.
   layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START);
   host_->Layout();
-  EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
+  EXPECT_EQ(gfx::Rect(0, 0, 15, 10), v1->bounds());
   EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
 
   layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
   host_->Layout();
-  EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
-  EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
+  EXPECT_EQ(gfx::Rect(0, 0, 13, 10), v1->bounds());
+  EXPECT_EQ(gfx::Rect(13, 0, 2, 10), v2->bounds());
 
   layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_END);
   host_->Layout();
-  EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
-  EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
+  EXPECT_EQ(gfx::Rect(0, 0, 5, 10), v1->bounds());
+  EXPECT_EQ(gfx::Rect(5, 0, 10, 10), v2->bounds());
 }
 
 TEST_F(BoxLayoutTest, NoSpace) {