Submitted By: Ken Moffat <ken at linuxfromscratch dot org>
Date: 2021-06-20
Initial Package Version: 20210401-git
Upstream Status: Applied
Origin: The 5.15 branch of qtwebengine as at 20210602
Description: Consolidated fixes, with various security issues.
This matches what is in version 5.15.5, including fixes for:

CVE-2021-30518: Heap buffer overflow in Reader Mode
CVE-2021-30516: Heap buffer overflow in History.
CVE-2021-30515: Use after free in File API
CVE-2021-30513: Type Confusion in V8
CVE-2021-30512: Use after free in Notifications
CVE-2021-30510: Race in Aura
CVE-2021-30508: Heap buffer overflow in Media Feeds
CVE-2021-21233: Heap buffer overflow in ANGLE
CVE-2021-21231: Insufficient data validation in V8
CVE-2021-21230: Type Confusion in V8
CVE-2021-21227: Insufficient data validation in V8
CVE-2021-21225: Out of bounds memory access in V8
CVE-2021-21224: Type Confusion in V8
CVE-2021-21223: Integer overflow in Mojo
CVE-2021-21222: Heap buffer overflow in V8
CVE-2021-21221: Insufficient validation of untrusted input in Mojo
CVE-2021-21220: Insufficient validation of untrusted input in V8 for x86_64
CVE-2021-21219: Uninitialized Use in PDFium
CVE-2021-21218: Uninitialized Use in PDFium
CVE-2021-21217: Uninitialized Use in PDFium
CVE-2021-21214: Use after free in Network API
CVE-2021-21213: Use after free in WebMIDI
CVE-2021-21209: Inappropriate implementation in storage
CVE-2021-21207: Use after free in IndexedDB
CVE-2021-21206: Use after free in Blink
CVE-2021-21204: Use after free in Blink.
CVE-2021-21203: Use after free in Blink
CVE-2021-21202: Use after free in extensions.
CVE-2021-21201: Use after free in permissions

diff -Naur a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml	2021-06-18 16:26:16.693760812 +0100
@@ -624,6 +624,18 @@
             tabs.currentIndex = tabs.count - 1;
             request.openIn(tab.item);
         }
+
+        Timer {
+            id: hideTimer
+            interval: 0
+            running: false
+            repeat: false
+            onTriggered: devToolsEnabled.checked = false
+        }
+        onWindowCloseRequested: function(request) {
+            // Delay hiding for keep the inspectedView set to receive the ACK message of close.
+            hideTimer.running = true;
+        }
     }
     MessageDialog {
         id: sslDialog
diff -Naur a/examples/webenginewidgets/printme/printhandler.cpp b/examples/webenginewidgets/printme/printhandler.cpp
--- a/examples/webenginewidgets/printme/printhandler.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/examples/webenginewidgets/printme/printhandler.cpp	2021-06-18 16:26:16.693760812 +0100
@@ -107,6 +107,7 @@
         return;
     m_inPrintPreview = true;
     QPrinter printer;
+    printer.setResolution(300);
     QPrintPreviewDialog preview(&printer, m_page->view());
     connect(&preview, &QPrintPreviewDialog::paintRequested,
             this, &PrintHandler::printDocument);
diff -Naur a/GIT-VERSIONS b/GIT-VERSIONS
--- a/GIT-VERSIONS	2021-04-03 00:30:45.000000000 +0100
+++ b/GIT-VERSIONS	2021-06-18 17:22:50.853543637 +0100
@@ -1,47 +1,99 @@
-This is the 5.15 branch of qtwebengine as at 2021-04-01
+This is the 5.15 branch of qtwebengine as at 2021-06-02 (5.15.5)
 
 Specifically, the main qt code is at
 
-commit e0b4b9436033e9bc376597ed90dd1fca9cdc90ff (HEAD -> 5.15, origin/5.15)
-Author: Michael Brüning <michael.bruning@qt.io>
-Date:   Thu Apr 1 13:32:58 2021 +0200
-
-    Update Chromium
-    
-    Submodule update src/3rdparty 8d49f9a2..d13920f2:
-    
-      > [Backport] Security bug 1185482
-      > [Backport] Security bug 1161847
-      > [Backport] Security bug 1161379
-      > [Backport] CVE-2021-21198: Out of bounds read in IPC
-      > [Backport] CVE-2021-21195: Use after free in V8
-    
-    Task-number: QTBUG-92080
-    Change-Id: I638a0fa0285d46736cfbf5406874702bd3600580
-    Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
+commit eafc7b60313d9827f976f1d4fbb5e7f5d54eea7b
+Author: Allan Sandfeld Jensen <allan.jensen@qt.io>
+Date:   Wed Jun 2 15:54:43 2021 +0200
+
+    Always send phased wheel events beginning with Began
+    
+    The input event router does not like MayBegin.
+    
+    Fixes: QTBUG-93082
 
 and the src/3rdparty code is from the 87-based branch at
 
-commit d13920f28c2f3922e0cf793996ea33d02b81a0a4 (HEAD -> 87-based, origin/87-based)
-Author: Scott Violet <sky@chromium.org>
-Date:   Tue Mar 23 18:47:22 2021 +0000
+commit eaffb82d5ee99ea1db8c0d4d359bbc72e77f065b
+Author: ishell@chromium.org <ishell@chromium.org>
+Date:   Fri May 7 12:54:24 2021 +0200
+
+    [Backport] Security bug 1201938
+    
+    Manual cherry-pick of patch originally reviewed on
+    https://chromium-review.googlesource.com/c/v8/v8/+/2880214:
+    Merged: [const-tracking] Generalize constness when delete properties
+    
+    Revision: d570bbe0c74ec4ae40d1abc34bea617ff2d63f26
+    
+    BUG=chromium:1201938
+
+Security fixes since the 20210401 tarball:
+
+    Submodule src/3rdparty dc35950b..eaffb82d:
+      > [Backport] Security bug 1201938
+      > [Backport] Security bug 1201340
+      > [Backport] Security bug 1195331
+      > [Backport] Security bug 1204071
+      > [Backport] CVE-2021-30518: Heap buffer overflow in Reader Mode
+      > [Backport] CVE-2021-30516: Heap buffer overflow in History.
+      > [Backport] CVE-2021-30515: Use after free in File API
+      > [Backport] CVE-2021-30513: Type Confusion in V8
+      > [Backport] CVE-2021-30512: Use after free in Notifications
+      > [Backport] CVE-2021-30510: Race in Aura
+      > [Backport] CVE-2021-30508: Heap buffer overflow in Media Feeds
+      > Workaround revoked certificate check on Linux
+
+    Submodule src/3rdparty 3f594ea1..6c7b4ffb:
+      > FIXUP: Avoid crashing on new window in cross-origin isolated content
+      > [Backport] Security bug 1198309
+      > [Backport] CVE-2021-21231: Insufficient data validation in V8
+      > [Backport] CVE-2021-21230: Type Confusion in V8
+      > [Backport] CVE-2021-21233: Heap buffer overflow in ANGLE
+      > [Backport] CVE-2021-21227: Insufficient data validation in V8
+      > Avoid crashing on new window in cross-origin isolated content
+      > Fix build with system ICU 69
+
+    Submodule src/3rdparty dd45b1a1..3f594ea1:
+      > [Backport] Security bug 1155297 (3/3)
+      > [Backport] Security bug 1155297 (2/3)
+      > [Backport] Security bug 1155297 (1/3)
+      > [Backport] Security bug 1192552
+      > [Backport] CVE-2021-21225: Out of bounds memory access in V8 (2/2)
+      > [Backport] CVE-2021-21225: Out of bounds memory access in V8 (1/2)
+      > [Backport] CVE-2021-21224: Type Confusion in V8
+      > [Backport] CVE-2021-21223: Integer overflow in Mojo
+      > [Backport] CVE-2021-21222: Heap buffer overflow in V8
+
+    Submodule src/3rdparty c38ae3ec..dd45b1a1:
+      > [Backport] CVE-2021-21209: Inappropriate implementation in storage (5/5)
+      > [Backport] CVE-2021-21209: Inappropriate implementation in storage (4/5)
+      > [Backport] CVE-2021-21209: Inappropriate implementation in storage (3/5)
+      > [Backport] CVE-2021-21209: Inappropriate implementation in storage (2/5)
+      > [Backport] CVE-2021-21209: Inappropriate implementation in storage (1/5)
+      > [Backport] Security bug 1184441
+      > [Backport] Security bug 1162424
+
+    Submodule src/3rdparty 6764c29f..c38ae3ec:
+      > [Backport] Security bug 1190525
+      > [Backport] Security bug 1161759
+      > [Backport] Security bug 1175503
+      > [Backport] Security bugs 1175522 and 1181276
+      > [Backport] CVE-2021-21219: Uninitialized Use in PDFium
+      > [Backport] CVE-2021-21217 and CVE-2021-21218: Uninitialized Use in PDFium
+      > [Backport] CVE-2021-21214: Use after free in Network API
+      > [Backport] CVE-2021-21213: Use after free in WebMIDI
+      > [Backport] CVE-2021-21207: Use after free in IndexedDB
+      > [Backport] CVE-2021-21221: Insufficient validation of untrusted input in Mojo
+      > [Backport] CVE-2021-21204: Use after free in Blink.
+      > [Backport] CVE-2021-21203: Use after free in Blink
+      > [Backport] CVE-2021-21202: Use after free in extensions.
+      > [Backport] CVE-2021-21201: Use after free in permissions
+
+    Submodule src/3rdparty d13920f2..048f5e99:
+    
+      > [Backport] CVE-2021-21220: Insufficient validation of untrusted input in V8 for x86_64
+      > [Backport] CVE-2021-21206: Use after free in Blink
+      > Fix build with no extensions on mac
 
-    [Backport] Security bug 1185482
-    
-    Cherry-pick of patch originally reviewed on
-    https://chromium-review.googlesource.com/c/chromium/src/+/2779886:
-    x11/ozone: fix two edge cases
-    
-    WindowTreeHost::OnHostMovedInPixels() may trigger a nested message
-    loop (tab dragging), which when the stack unravels means this may
-    be deleted. This adds an early out if this happens.
-    
-    X11WholeScreenMoveLoop has a similar issue, in so far as notifying
-    the delegate may delete this.
-    
-    BUG=1185482
-    TEST=WindowTreeHostPlatform.DeleteHostFromOnHostMovedInPixels
-    
-    (cherry picked from commit 5e3a738b1204941aab9f15c0eb3d06e20fefd96e)
-    
 
diff -Naur a/.qmake.conf b/.qmake.conf
--- a/.qmake.conf	2021-04-01 15:33:27.000000000 +0100
+++ b/.qmake.conf	2021-06-18 16:45:48.809825075 +0100
@@ -5,4 +5,4 @@
 load(qt_build_config)
 CONFIG += warning_clean
 
-MODULE_VERSION = 5.15.4
+MODULE_VERSION = 5.15.5
diff -Naur a/src/3rdparty/chromium/base/task/thread_pool/thread_group.h b/src/3rdparty/chromium/base/task/thread_pool/thread_group.h
--- a/src/3rdparty/chromium/base/task/thread_pool/thread_group.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/base/task/thread_pool/thread_group.h	2021-06-18 16:53:30.025440333 +0100
@@ -224,7 +224,7 @@
   // PriorityQueue from which all threads of this ThreadGroup get work.
   PriorityQueue priority_queue_ GUARDED_BY(lock_);
 
-  struct YieldSortKey {
+  struct alignas(2) YieldSortKey {
     TaskPriority priority;
     uint8_t worker_count;
   };
diff -Naur a/src/3rdparty/chromium/chrome/common/BUILD.gn b/src/3rdparty/chromium/chrome/common/BUILD.gn
--- a/src/3rdparty/chromium/chrome/common/BUILD.gn	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/chrome/common/BUILD.gn	2021-06-18 16:26:16.693760812 +0100
@@ -330,16 +330,19 @@
   }
 
   if (is_mac) {
-    assert(enable_extensions)
     sources += [
-      "extensions/image_writer/image_writer_util_mac.cc",
-      "extensions/image_writer/image_writer_util_mac.h",
       "mac/launchd.h",
       "mac/launchd.mm",
       "mac/service_management.h",
       "mac/service_management.mm",
       "multi_process_lock_mac.cc",
     ]
+    if (enable_extensions) {
+       sources += [
+        "extensions/image_writer/image_writer_util_mac.cc",
+        "extensions/image_writer/image_writer_util_mac.h",
+       ]
+    }
     public_deps += [ ":app_mode_app_support" ]
   }
 
diff -Naur a/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.cc b/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.cc
--- a/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.cc	2021-06-18 17:00:37.312370731 +0100
@@ -85,7 +85,7 @@
 
 std::unique_ptr<ViewerHandle> TaskTracker::AddViewer(
     ViewRequestDelegate* delegate) {
-  viewers_.push_back(delegate);
+  viewers_.AddObserver(delegate);
   if (content_ready_) {
     // Distillation for this task has already completed, and so the delegate can
     // be immediately told of the result.
@@ -115,7 +115,7 @@
 }
 
 void TaskTracker::RemoveViewer(ViewRequestDelegate* delegate) {
-  base::Erase(viewers_, delegate);
+  viewers_.RemoveObserver(delegate);
   if (viewers_.empty()) {
     MaybeCancel();
   }
@@ -219,8 +219,8 @@
 }
 
 void TaskTracker::NotifyViewersAndCallbacks() {
-  for (auto* viewer : viewers_) {
-    NotifyViewer(viewer);
+  for (auto& viewer : viewers_) {
+    NotifyViewer(&viewer);
   }
 
   // Already inside a callback run SaveCallbacks directly.
@@ -242,8 +242,8 @@
 
 void TaskTracker::OnArticleDistillationUpdated(
     const ArticleDistillationUpdate& article_update) {
-  for (auto* viewer : viewers_) {
-    viewer->OnArticleUpdated(article_update);
+  for (auto& viewer : viewers_) {
+    viewer.OnArticleUpdated(article_update);
   }
 }
 
diff -Naur a/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.h b/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.h
--- a/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/dom_distiller/core/task_tracker.h	2021-06-18 17:00:37.312370731 +0100
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "components/dom_distiller/core/article_distillation_update.h"
 #include "components/dom_distiller/core/article_entry.h"
 #include "components/dom_distiller/core/distiller.h"
@@ -40,9 +41,9 @@
 
 // Interface for a DOM distiller entry viewer. Implement this to make a view
 // request and receive the data for an entry when it becomes available.
-class ViewRequestDelegate {
+class ViewRequestDelegate : public base::CheckedObserver {
  public:
-  virtual ~ViewRequestDelegate() = default;
+  ~ViewRequestDelegate() override = default;
 
   // Called when the distilled article contents are available. The
   // DistilledArticleProto is owned by a TaskTracker instance and is invalidated
@@ -140,7 +141,7 @@
   std::vector<SaveCallback> save_callbacks_;
   // A ViewRequestDelegate will be added to this list when a view request is
   // made and removed when the corresponding ViewerHandle is destroyed.
-  std::vector<ViewRequestDelegate*> viewers_;
+  base::ObserverList<ViewRequestDelegate> viewers_;
 
   std::unique_ptr<Distiller> distiller_;
   bool blob_fetcher_running_;
diff -Naur a/src/3rdparty/chromium/components/favicon/core/favicon_handler.cc b/src/3rdparty/chromium/components/favicon/core/favicon_handler.cc
--- a/src/3rdparty/chromium/components/favicon/core/favicon_handler.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/favicon/core/favicon_handler.cc	2021-06-18 17:00:07.007963275 +0100
@@ -507,6 +507,8 @@
     const GURL& image_url,
     const std::vector<SkBitmap>& bitmaps,
     const std::vector<gfx::Size>& original_bitmap_sizes) {
+  DCHECK_EQ(bitmaps.size(), original_bitmap_sizes.size());
+
   // Mark download as finished.
   image_download_request_.Cancel();
 
diff -Naur a/src/3rdparty/chromium/components/favicon/core/favicon_handler.h b/src/3rdparty/chromium/components/favicon/core/favicon_handler.h
--- a/src/3rdparty/chromium/components/favicon/core/favicon_handler.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/favicon/core/favicon_handler.h	2021-06-18 17:00:07.007963275 +0100
@@ -238,7 +238,9 @@
   void ScheduleImageDownload(const GURL& image_url,
                              favicon_base::IconType icon_type);
 
-  // Triggered when a download of an image has finished.
+  // Triggered when a download of an image has finished. |bitmaps| and
+  // |original_bitmap_sizes| must contain the same number of elements (i.e. same
+  // vector size).
   void OnDidDownloadFavicon(
       favicon_base::IconType icon_type,
       int id,
diff -Naur a/src/3rdparty/chromium/components/favicon/ios/web_favicon_driver.mm b/src/3rdparty/chromium/components/favicon/ios/web_favicon_driver.mm
--- a/src/3rdparty/chromium/components/favicon/ios/web_favicon_driver.mm	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/favicon/ios/web_favicon_driver.mm	2021-06-18 17:00:07.007963275 +0100
@@ -75,6 +75,7 @@
           for (const auto& frame : frames) {
             sizes.push_back(gfx::Size(frame.width(), frame.height()));
           }
+          DCHECK_EQ(frames.size(), sizes.size());
         }
         std::move(local_callback)
             .Run(local_download_id, metadata.http_response_code, local_url,
diff -Naur a/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.cc b/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.cc
--- a/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.cc	2021-06-18 17:00:07.008965007 +0100
@@ -216,6 +216,7 @@
     const std::vector<gfx::Size>& original_sizes,
     int desired_size_in_dip,
     float* score) {
+  DCHECK_EQ(bitmaps.size(), original_sizes.size());
 
   const std::vector<float>& favicon_scales = favicon_base::GetFaviconScales();
   std::vector<int> desired_sizes;
diff -Naur a/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.h b/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.h
--- a/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/favicon_base/select_favicon_frames.h	2021-06-18 17:00:07.008965007 +0100
@@ -38,6 +38,8 @@
 // it inspired by this method.
 // If an unsupported scale (not in the favicon_base::GetFaviconScales())
 // is requested, the ImageSkia will automatically scales using lancoz3.
+// |original_sizes| represents the pixel sizes of the favicon bitmaps in
+// |bitmaps|, which also means both vectors must have the same size.
 gfx::ImageSkia CreateFaviconImageSkia(
     const std::vector<SkBitmap>& bitmaps,
     const std::vector<gfx::Size>& original_sizes,
diff -Naur a/src/3rdparty/chromium/components/permissions/permission_manager.cc b/src/3rdparty/chromium/components/permissions/permission_manager.cc
--- a/src/3rdparty/chromium/components/permissions/permission_manager.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/permissions/permission_manager.cc	2021-06-18 16:26:16.693760812 +0100
@@ -536,14 +536,14 @@
                                                             origin->GetURL());
 }
 
-int PermissionManager::SubscribePermissionStatusChange(
+PermissionManager::SubscriptionId PermissionManager::SubscribePermissionStatusChange(
     PermissionType permission,
     content::RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
     base::RepeatingCallback<void(PermissionStatus)> callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (is_shutting_down_)
-    return 0;
+    return SubscriptionId();
 
   if (subscriptions_.IsEmpty())
     PermissionsClient::Get()
@@ -580,16 +580,20 @@
   subscription->callback =
       base::BindRepeating(&SubscriptionCallbackWrapper, std::move(callback));
 
-  return subscriptions_.Add(std::move(subscription));
+  auto id = subscription_id_generator_.GenerateNextId();
+  subscriptions_.AddWithID(std::move(subscription), id);
+  return id;
 }
 
-void PermissionManager::UnsubscribePermissionStatusChange(int subscription_id) {
+void PermissionManager::UnsubscribePermissionStatusChange(
+    SubscriptionId subscription_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (is_shutting_down_)
     return;
 
-  // Whether |subscription_id| is known will be checked by the Remove() call.
-  subscriptions_.Remove(subscription_id);
+  if (subscriptions_.Lookup(subscription_id)) {
+    subscriptions_.Remove(subscription_id);
+  }
 
   if (subscriptions_.IsEmpty()) {
     PermissionsClient::Get()
diff -Naur a/src/3rdparty/chromium/components/permissions/permission_manager.h b/src/3rdparty/chromium/components/permissions/permission_manager.h
--- a/src/3rdparty/chromium/components/permissions/permission_manager.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/components/permissions/permission_manager.h	2021-06-18 16:26:16.693760812 +0100
@@ -114,13 +114,13 @@
   bool IsPermissionOverridableByDevTools(
       content::PermissionType permission,
       const base::Optional<url::Origin>& origin) override;
-  int SubscribePermissionStatusChange(
+  SubscriptionId SubscribePermissionStatusChange(
       content::PermissionType permission,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin,
       base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
       override;
-  void UnsubscribePermissionStatusChange(int subscription_id) override;
+  void UnsubscribePermissionStatusChange(SubscriptionId subscription_id) override;
 
   // TODO(raymes): Rather than exposing this, use the denial reason from
   // GetPermissionStatus in callers to determine whether a permission is
@@ -153,7 +153,8 @@
   class PermissionResponseCallback;
 
   struct Subscription;
-  using SubscriptionsMap = base::IDMap<std::unique_ptr<Subscription>>;
+  using SubscriptionsMap =
+      base::IDMap<std::unique_ptr<Subscription>, SubscriptionId>;
 
   PermissionContextBase* GetPermissionContext(ContentSettingsType type);
 
@@ -186,6 +187,7 @@
   content::BrowserContext* browser_context_;
   PendingRequestsMap pending_requests_;
   SubscriptionsMap subscriptions_;
+  SubscriptionId::Generator subscription_id_generator_;
 
   PermissionContextMap permission_contexts_;
   using ContentSettingsTypeOverrides =
diff -Naur a/src/3rdparty/chromium/content/browser/appcache/appcache_backfillers.cc b/src/3rdparty/chromium/content/browser/appcache/appcache_backfillers.cc
--- a/src/3rdparty/chromium/content/browser/appcache/appcache_backfillers.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/appcache/appcache_backfillers.cc	2021-06-18 16:26:16.693760812 +0100
@@ -7,7 +7,7 @@
 #include "content/browser/appcache/appcache_update_job.h"
 #include "net/http/http_request_headers.h"
 #include "sql/statement.h"
-#include "storage/browser/quota/padding_key.h"
+#include "storage/common/quota/padding_key.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -18,9 +18,7 @@
                                 std::string manifest_url) {
   if (GURL(response_url).GetOrigin() == GURL(manifest_url).GetOrigin())
     return 0;
-  return storage::ComputeResponsePadding(
-      response_url, storage::GetDefaultPaddingKey(), /*has_metadata=*/false,
-      /*loaded_with_credentials=*/false, net::HttpRequestHeaders::kGetMethod);
+  return storage::ComputeRandomResponsePadding();
 }
 
 // Iterates over each Cache record; execute |callable| on each iteration.
diff -Naur a/src/3rdparty/chromium/content/browser/appcache/appcache_database.cc b/src/3rdparty/chromium/content/browser/appcache/appcache_database.cc
--- a/src/3rdparty/chromium/content/browser/appcache/appcache_database.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/appcache/appcache_database.cc	2021-06-18 16:26:16.694762544 +0100
@@ -19,7 +19,6 @@
 #include "sql/meta_table.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
-#include "storage/browser/quota/padding_key.h"
 #include "third_party/blink/public/common/features.h"
 
 namespace content {
diff -Naur a/src/3rdparty/chromium/content/browser/appcache/appcache_update_job.cc b/src/3rdparty/chromium/content/browser/appcache/appcache_update_job.cc
--- a/src/3rdparty/chromium/content/browser/appcache/appcache_update_job.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/appcache/appcache_update_job.cc	2021-06-18 16:26:16.694762544 +0100
@@ -26,7 +26,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_request_headers.h"
-#include "storage/browser/quota/padding_key.h"
+#include "storage/common/quota/padding_key.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
@@ -207,10 +207,7 @@
   if (response_url.GetOrigin() == manifest_url.GetOrigin())
     return 0;
 
-  return storage::ComputeResponsePadding(
-      response_url.spec(), storage::GetDefaultPaddingKey(),
-      /*has_metadata=*/false, /*loaded_with_credentials=*/false,
-      net::HttpRequestHeaders::kGetMethod);
+  return storage::ComputeRandomResponsePadding();
 }
 
 }  // namespace
diff -Naur a/src/3rdparty/chromium/content/browser/bad_message.h b/src/3rdparty/chromium/content/browser/bad_message.h
--- a/src/3rdparty/chromium/content/browser/bad_message.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/bad_message.h	2021-06-18 17:00:07.008965007 +0100
@@ -260,6 +260,7 @@
   RFH_RECEIVED_ASSOCIATED_MESSAGE_WHILE_BFCACHED = 232,
   RWH_CLOSE_PORTAL = 233,
   MSDH_INVALID_STREAM_TYPE = 234,
+  WCI_INVALID_DOWNLOAD_IMAGE_RESULT = 243,
 
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff -Naur a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_histogram_utils.h b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_histogram_utils.h
--- a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_histogram_utils.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_histogram_utils.h	2021-06-18 16:26:16.694762544 +0100
@@ -37,7 +37,8 @@
   kCreateBackendDidCreateFailed = 22,
   kStorageGetAllMatchedEntriesBackendClosed = 23,
   kStorageHandleNull = 24,
-  kMaxValue = kStorageHandleNull,
+  kWriteSideDataDidWriteMetadataWrongBytes = 25,
+  kMaxValue = kWriteSideDataDidWriteMetadataWrongBytes,
 };
 
 blink::mojom::CacheStorageError MakeErrorStorage(ErrorStorageType type);
diff -Naur a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.cc b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.cc
--- a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.cc	2021-06-18 16:26:16.694762544 +0100
@@ -11,8 +11,7 @@
 CacheStorageIndex::CacheStorageIndex()
     : doomed_cache_metadata_("",
                              CacheStorage::kSizeUnknown,
-                             CacheStorage::kSizeUnknown,
-                             "") {
+                             CacheStorage::kSizeUnknown) {
   ClearDoomedCache();
 }
 
diff -Naur a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.h b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.h
--- a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage_index.h	2021-06-18 16:26:16.694762544 +0100
@@ -21,11 +21,8 @@
 class CONTENT_EXPORT CacheStorageIndex {
  public:
   struct CacheMetadata {
-    CacheMetadata(const std::string& name,
-                  int64_t size,
-                  int64_t padding,
-                  const std::string& padding_key)
-        : name(name), size(size), padding(padding), padding_key(padding_key) {}
+    CacheMetadata(const std::string& name, int64_t size, int64_t padding)
+        : name(name), size(size), padding(padding) {} 
     std::string name;
     // The size (in bytes) of the cache. Set to CacheStorage::kSizeUnknown if
     // size not known.
@@ -35,9 +32,6 @@
     // if padding not known.
     int64_t padding;
 
-    // The raw key used to calculate padding for some cache entries.
-    std::string padding_key;
-
     // The algorithm version used to calculate this padding.
     int32_t padding_version;
   };
diff -Naur a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage.proto b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage.proto
--- a/src/3rdparty/chromium/content/browser/cache_storage/cache_storage.proto	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/cache_storage/cache_storage.proto	2021-06-18 16:26:16.694762544 +0100
@@ -13,7 +13,7 @@
     required string name = 1;
     optional string cache_dir = 2;
     optional int64 size = 3;
-    optional string padding_key = 4;
+    optional string padding_key = 4 [deprecated = true];
     optional int64 padding = 5;
     optional int32 padding_version = 6;
   }
@@ -49,13 +49,15 @@
   optional int64 response_time = 6;
   repeated string cors_exposed_header_names = 7;
   repeated string url_list = 8;
-  optional bool loaded_with_credentials = 9;
+  optional bool loaded_with_credentials = 9 [deprecated = true];
   // Mapped to net::HttpResponseInfo::ConnectionInfo via static casting.
   optional int32 connection_info = 10;
   optional string alpn_negotiated_protocol = 11;
   optional bool was_fetched_via_spdy = 12;
   optional string mime_type = 13;
   optional string request_method = 14;
+  optional int64 padding = 15;
+  optional int64 side_data_padding = 16;
 }
 
 message CacheMetadata {
diff -Naur a/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
--- a/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc	2021-06-18 16:26:16.695764277 +0100
@@ -53,8 +53,8 @@
 #include "net/http/http_status_code.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/quota/padding_key.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/quota/padding_key.h"
 #include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
 #include "third_party/blink/public/common/fetch/fetch_api_request_headers_map.h"
 #include "third_party/blink/public/mojom/loader/referrer.mojom.h"
@@ -79,7 +79,8 @@
 //
 //   1: Uniform random 400K.
 //   2: Uniform random 14,431K.
-const int32_t kCachePaddingAlgorithmVersion = 2;
+//   3: FetchAPIResponse.padding and separate side data padding.
+const int32_t kCachePaddingAlgorithmVersion = 3;
 
 // Maximum number of recursive QueryCacheOpenNextEntry() calls we permit
 // before forcing an asynchronous task.
@@ -374,6 +375,14 @@
   std::move(callback).Run(std::move(metadata));
 }
 
+bool ShouldPadResourceSize(const content::proto::CacheResponse* response) {
+  return storage::ShouldPadResponseType(
+      ProtoResponseTypeToFetchResponseType(response->response_type()));
+}
+bool ShouldPadResourceSize(const blink::mojom::FetchAPIResponse& response) {
+  return storage::ShouldPadResponseType(response.response_type);
+}
+
 blink::mojom::FetchAPIRequestPtr CreateRequest(
     const proto::CacheMetadata& metadata,
     const GURL& request_url) {
@@ -394,6 +403,7 @@
 }
 
 blink::mojom::FetchAPIResponsePtr CreateResponse(
+    const url::Origin& origin,
     const proto::CacheMetadata& metadata,
     const std::string& cache_name) {
   // We no longer support Responses with only a single URL entry.  This field
@@ -427,6 +437,15 @@
   if (metadata.response().has_request_method())
     request_method = metadata.response().request_method();
 
+  auto response_time =
+      base::Time::FromInternalValue(metadata.response().response_time());
+  int64_t padding = 0;
+  if (metadata.response().has_padding()) {
+    padding = metadata.response().padding();
+  } else if (ShouldPadResourceSize(&metadata.response())) {
+    padding = storage::ComputeRandomResponsePadding();
+  }
+
   // Note that |has_range_requested| can be safely set to false since it only
   // affects HTTP 206 (Partial) responses, which are blocked from cache storage.
   // See https://fetch.spec.whatwg.org/#main-fetch for usage of
@@ -435,10 +454,9 @@
       url_list, metadata.response().status_code(),
       metadata.response().status_text(),
       ProtoResponseTypeToFetchResponseType(metadata.response().response_type()),
-      network::mojom::FetchResponseSource::kCacheStorage, headers, mime_type,
-      request_method, nullptr /* blob */,
-      blink::mojom::ServiceWorkerResponseError::kUnknown,
-      base::Time::FromInternalValue(metadata.response().response_time()),
+      padding, network::mojom::FetchResponseSource::kCacheStorage, headers,
+      mime_type, request_method, /*blob=*/nullptr,
+      blink::mojom::ServiceWorkerResponseError::kUnknown, response_time,
       cache_name,
       std::vector<std::string>(
           metadata.response().cors_exposed_header_names().begin(),
@@ -448,55 +466,28 @@
       // Default proto value of 0 maps to CONNECTION_INFO_UNKNOWN.
       static_cast<net::HttpResponseInfo::ConnectionInfo>(
           metadata.response().connection_info()),
-      alpn_negotiated_protocol, metadata.response().loaded_with_credentials(),
-      metadata.response().was_fetched_via_spdy(),
-      /* has_range_requested */ false);
-}
-
-// The size of opaque (non-cors) resource responses are padded in order
-// to obfuscate their actual size.
-bool ShouldPadResponseType(network::mojom::FetchResponseType response_type,
-                           bool has_urls) {
-  switch (response_type) {
-    case network::mojom::FetchResponseType::kBasic:
-    case network::mojom::FetchResponseType::kCors:
-    case network::mojom::FetchResponseType::kDefault:
-    case network::mojom::FetchResponseType::kError:
-      return false;
-    case network::mojom::FetchResponseType::kOpaque:
-    case network::mojom::FetchResponseType::kOpaqueRedirect:
-      return has_urls;
-  }
-  NOTREACHED();
-  return false;
-}
-
-bool ShouldPadResourceSize(const content::proto::CacheResponse* response) {
-  return ShouldPadResponseType(
-      ProtoResponseTypeToFetchResponseType(response->response_type()),
-      response->url_list_size());
-}
-
-bool ShouldPadResourceSize(const blink::mojom::FetchAPIResponse& response) {
-  return ShouldPadResponseType(response.response_type,
-                               !response.url_list.empty());
+      alpn_negotiated_protocol, metadata.response().was_fetched_via_spdy(),
+      /*has_range_requested=*/false);
 }
-
-int64_t CalculateResponsePaddingInternal(
+int64_t CalculateSideDataPadding(
+    const url::Origin& origin,
     const ::content::proto::CacheResponse* response,
-    const crypto::SymmetricKey* padding_key,
     int side_data_size) {
   DCHECK(ShouldPadResourceSize(response));
   DCHECK_GE(side_data_size, 0);
+
+  if (!side_data_size)
+    return 0;
+  // Fallback to random padding if this is for an older entry without
+  // a url list or request method.
+  if (response->url_list_size() == 0 || !response->has_request_method())
+    return storage::ComputeRandomResponsePadding();
+
   const std::string& url = response->url_list(response->url_list_size() - 1);
-  bool loaded_with_credentials = response->has_loaded_with_credentials() &&
-                                 response->loaded_with_credentials();
-  const std::string& request_method = response->has_request_method()
-                                          ? response->request_method()
-                                          : net::HttpRequestHeaders::kGetMethod;
-  return storage::ComputeResponsePadding(url, padding_key, side_data_size > 0,
-                                         loaded_with_credentials,
-                                         request_method);
+  const base::Time response_time =
+      base::Time::FromInternalValue(response->response_time());
+  return storage::ComputeStableResponsePadding(
+      origin, url, response_time, response->request_method(), side_data_size);
 }
 
 net::RequestPriority GetDiskCachePriority(
@@ -508,12 +499,19 @@
 }  // namespace
 
 struct LegacyCacheStorageCache::QueryCacheResult {
-  explicit QueryCacheResult(base::Time entry_time) : entry_time(entry_time) {}
+  QueryCacheResult(base::Time entry_time,
+                   int64_t padding,
+                   int64_t side_data_padding)
+      : entry_time(entry_time),
+        padding(padding),
+        side_data_padding(side_data_padding) {}
 
   blink::mojom::FetchAPIRequestPtr request;
   blink::mojom::FetchAPIResponsePtr response;
   disk_cache::ScopedEntryPtr entry;
   base::Time entry_time;
+  int64_t padding = 0;
+  int64_t side_data_padding = 0;
 };
 
 struct LegacyCacheStorageCache::QueryCacheContext {
@@ -555,13 +553,12 @@
     LegacyCacheStorage* cache_storage,
     scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
     scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
-    scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
-    std::unique_ptr<crypto::SymmetricKey> cache_padding_key) {
+    scoped_refptr<BlobStorageContextWrapper> blob_storage_context) {
   LegacyCacheStorageCache* cache = new LegacyCacheStorageCache(
       origin, owner, cache_name, base::FilePath(), cache_storage,
       std::move(scheduler_task_runner), std::move(quota_manager_proxy),
-      std::move(blob_storage_context), 0 /* cache_size */,
-      0 /* cache_padding */, std::move(cache_padding_key));
+      std::move(blob_storage_context), /*cache_size=*/0,
+      /*cache_padding=*/0);  
   cache->SetObserver(cache_storage);
   cache->InitBackend();
   return base::WrapUnique(cache);
@@ -579,13 +576,11 @@
     scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
     scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
     int64_t cache_size,
-    int64_t cache_padding,
-    std::unique_ptr<crypto::SymmetricKey> cache_padding_key) {
+    int64_t cache_padding) {
   LegacyCacheStorageCache* cache = new LegacyCacheStorageCache(
       origin, owner, cache_name, path, cache_storage,
       std::move(scheduler_task_runner), std::move(quota_manager_proxy),
-      std::move(blob_storage_context), cache_size, cache_padding,
-      std::move(cache_padding_key));
+      std::move(blob_storage_context), cache_size, cache_padding);
   cache->SetObserver(cache_storage);
   cache->InitBackend();
   return base::WrapUnique(cache);
@@ -1031,8 +1026,7 @@
     scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
     scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
     int64_t cache_size,
-    int64_t cache_padding,
-    std::unique_ptr<crypto::SymmetricKey> cache_padding_key)
+    int64_t cache_padding)
     : origin_(origin),
       owner_(owner),
       cache_name_(cache_name),
@@ -1044,7 +1038,6 @@
                                            scheduler_task_runner_)),
       cache_size_(cache_size),
       cache_padding_(cache_padding),
-      cache_padding_key_(std::move(cache_padding_key)),
       max_query_size_bytes_(kMaxQueryCacheResultBytes),
       cache_observer_(nullptr),
       cache_entry_handler_(
@@ -1054,7 +1047,6 @@
       memory_only_(path.empty()) {
   DCHECK(!origin_.opaque());
   DCHECK(quota_manager_proxy_.get());
-  DCHECK(cache_padding_key_.get());
 
   if (cache_size_ != CacheStorage::kSizeUnknown &&
       cache_padding_ != CacheStorage::kSizeUnknown) {
@@ -1248,17 +1240,40 @@
     return;
   }
 
+  // Check for older cache entries that need to be padded, but don't
+  // have any padding stored in the entry.  Upgrade these entries
+  // as we encounter them.  This method will be re-entered once the
+  // new paddings are written back to disk.
+  if (ShouldPadResourceSize(&metadata->response()) &&
+      !metadata->response().has_padding()) {
+    QueryCacheUpgradePadding(std::move(query_cache_context), std::move(entry),
+                             std::move(metadata));
+    return;
+  }
+
   // If the entry was created before we started adding entry times, then
   // default to using the Response object's time for sorting purposes.
   int64_t entry_time = metadata->has_entry_time()
                            ? metadata->entry_time()
                            : metadata->response().response_time();
 
-  query_cache_context->matches->push_back(
-      QueryCacheResult(base::Time::FromInternalValue(entry_time)));
+  // Note, older entries that don't require padding may still not have
+  // a padding value since we don't pay the cost to upgrade these entries.
+  // Treat these as a zero padding.
+  int64_t padding =
+      metadata->response().has_padding() ? metadata->response().padding() : 0;
+  int64_t side_data_padding = metadata->response().has_side_data_padding()
+                                  ? metadata->response().side_data_padding()
+                                  : 0;
+
+  DCHECK(!ShouldPadResourceSize(&metadata->response()) ||
+         (padding + side_data_padding));
+
+  query_cache_context->matches->push_back(QueryCacheResult(
+      base::Time::FromInternalValue(entry_time), padding, side_data_padding));
   QueryCacheResult* match = &query_cache_context->matches->back();
   match->request = CreateRequest(*metadata, GURL(entry->GetKey()));
-  match->response = CreateResponse(*metadata, cache_name_);
+  match->response = CreateResponse(origin_, *metadata, cache_name_);
 
   if (!match->response) {
     entry->Doom();
@@ -1320,6 +1335,49 @@
   QueryCacheOpenNextEntry(std::move(query_cache_context));
 }
 
+void LegacyCacheStorageCache::QueryCacheUpgradePadding(
+    std::unique_ptr<QueryCacheContext> query_cache_context,
+    disk_cache::ScopedEntryPtr entry,
+    std::unique_ptr<proto::CacheMetadata> metadata) {
+  DCHECK(ShouldPadResourceSize(&metadata->response()));
+  // This should only be called while initializing because the padding
+  // version change should trigger an immediate query of all resources
+  // to recompute padding.
+  DCHECK(initializing_);
+  auto* response = metadata->mutable_response();
+  response->set_padding(storage::ComputeRandomResponsePadding());
+  response->set_side_data_padding(CalculateSideDataPadding(
+      origin_, response, entry->GetDataSize(INDEX_SIDE_DATA)));
+  // Get a temporary copy of the entry and metadata pointers before moving them
+  // into base::BindOnce.
+  disk_cache::Entry* temp_entry_ptr = entry.get();
+  auto* temp_metadata_ptr = metadata.get();
+  WriteMetadata(
+      temp_entry_ptr, *temp_metadata_ptr,
+      base::BindOnce(
+          [](base::WeakPtr<LegacyCacheStorageCache> self,
+             std::unique_ptr<QueryCacheContext> query_cache_context,
+             disk_cache::ScopedEntryPtr entry,
+             std::unique_ptr<proto::CacheMetadata> metadata, int expected_bytes,
+             int rv) {
+            if (!self)
+              return;
+            if (expected_bytes != rv) {
+              entry->Doom();
+              self->QueryCacheOpenNextEntry(std::move(query_cache_context));
+              return;
+            }
+            // We must have a padding here in order to avoid infinite
+            // recursion.
+            DCHECK(metadata->response().has_padding());
+            self->QueryCacheDidReadMetadata(std::move(query_cache_context),
+                                            std::move(entry),
+                                            std::move(metadata));
+          },
+          weak_ptr_factory_.GetWeakPtr(), std::move(query_cache_context),
+          std::move(entry), std::move(metadata)));
+}
+
 // static
 bool LegacyCacheStorageCache::QueryCacheResultCompare(
     const QueryCacheResult& lhs,
@@ -1346,26 +1404,6 @@
 }
 
 // static
-int64_t LegacyCacheStorageCache::CalculateResponsePadding(
-    const blink::mojom::FetchAPIResponse& response,
-    const crypto::SymmetricKey* padding_key,
-    int side_data_size) {
-  DCHECK_GE(side_data_size, 0);
-  if (!ShouldPadResourceSize(response))
-    return 0;
-  // Going forward we should always have a request method here since its
-  // impossible to create a no-cors Response via the constructor.  We must
-  // handle a missing method, however, since we may get a Response loaded
-  // from an old cache_storage instance without the data.
-  std::string request_method = response.request_method.has_value()
-                                   ? response.request_method.value()
-                                   : net::HttpRequestHeaders::kGetMethod;
-  return storage::ComputeResponsePadding(
-      response.url_list.back().spec(), padding_key, side_data_size > 0,
-      response.loaded_with_credentials, request_method);
-}
-
-// static
 int32_t LegacyCacheStorageCache::GetResponsePaddingVersion() {
   return kCachePaddingAlgorithmVersion;
 }
@@ -1458,6 +1496,38 @@
                           std::move(out_responses));
 }
 
+void LegacyCacheStorageCache::WriteMetadata(
+    disk_cache::Entry* entry,
+    const proto::CacheMetadata& metadata,
+    WriteMetadataCallback callback) {
+  std::unique_ptr<std::string> serialized = std::make_unique<std::string>();
+  if (!metadata.SerializeToString(serialized.get())) {
+    std::move(callback).Run(0, -1);
+    return;
+  }
+
+  scoped_refptr<net::StringIOBuffer> buffer =
+      base::MakeRefCounted<net::StringIOBuffer>(std::move(serialized));
+
+  auto callback_with_expected_bytes = base::BindOnce(
+      [](WriteMetadataCallback callback, int expected_bytes, int rv) {
+        std::move(callback).Run(expected_bytes, rv);
+      },
+      std::move(callback), buffer->size());
+
+  // Create a callback that is copyable, even though it can only be called once.
+  net::CompletionRepeatingCallback adapted_callback =
+      base::AdaptCallbackForRepeating(std::move(callback_with_expected_bytes));
+
+  DCHECK(scheduler_->IsRunningExclusiveOperation());
+  int rv =
+      entry->WriteData(INDEX_HEADERS, /*offset=*/0, buffer.get(),
+                       buffer->size(), adapted_callback, /*truncate=*/true);
+
+  if (rv != net::ERR_IO_PENDING)
+    std::move(adapted_callback).Run(rv);
+}
+
 void LegacyCacheStorageCache::WriteSideDataDidGetQuota(
     ErrorCallback callback,
     const GURL& url,
@@ -1576,19 +1646,13 @@
   if (!headers || headers->response().response_time() !=
                       expected_response_time.ToInternalValue()) {
     WriteSideDataComplete(std::move(callback), std::move(entry),
+                          /*padding=*/0, /*side_data_padding=*/0,
                           CacheStorageError::kErrorNotFound);
     return;
   }
   // Get a temporary copy of the entry pointer before passing it in base::Bind.
   disk_cache::Entry* temp_entry_ptr = entry.get();
 
-  std::unique_ptr<content::proto::CacheResponse> response(
-      headers->release_response());
-
-  int side_data_size_before_write = 0;
-  if (ShouldPadResourceSize(response.get()))
-    side_data_size_before_write = entry->GetDataSize(INDEX_SIDE_DATA);
-
   // Create a callback that is copyable, even though it can only be called once.
   // BindRepeating() cannot be used directly because |callback|, |entry| and
   // |response| are not copyable.
@@ -1596,7 +1660,7 @@
       base::AdaptCallbackForRepeating(base::BindOnce(
           &LegacyCacheStorageCache::WriteSideDataDidWrite,
           weak_ptr_factory_.GetWeakPtr(), std::move(callback), std::move(entry),
-          buf_len, std::move(response), side_data_size_before_write, trace_id));
+          buf_len, std::move(headers), trace_id));
 
   DCHECK(scheduler_->IsRunningExclusiveOperation());
   int rv = temp_entry_ptr->WriteData(
@@ -1611,8 +1675,7 @@
     ErrorCallback callback,
     ScopedWritableEntry entry,
     int expected_bytes,
-    std::unique_ptr<::content::proto::CacheResponse> response,
-    int side_data_size_before_write,
+    std::unique_ptr<::content::proto::CacheMetadata> metadata,
     int64_t trace_id,
     int rv) {
   TRACE_EVENT_WITH_FLOW0("CacheStorage",
@@ -1620,31 +1683,67 @@
                          TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN);
   if (rv != expected_bytes) {
     WriteSideDataComplete(std::move(callback), std::move(entry),
+                          /*padding=*/0, /*side_data_padding=*/0,
                           CacheStorageError::kErrorStorage);
     return;
   }
 
-  if (ShouldPadResourceSize(response.get())) {
-    cache_padding_ -= CalculateResponsePaddingInternal(
-        response.get(), cache_padding_key_.get(), side_data_size_before_write);
+  auto* response = metadata->mutable_response();
 
-    cache_padding_ += CalculateResponsePaddingInternal(
-        response.get(), cache_padding_key_.get(), rv);
+  if (ShouldPadResourceSize(response)) {
+    cache_padding_ -= response->side_data_padding();
+
+    response->set_side_data_padding(
+        CalculateSideDataPadding(origin_, response, rv));
+    cache_padding_ += response->side_data_padding();
+
+    // Get a temporary copy of the entry pointer before passing it in
+    // base::Bind.
+    disk_cache::Entry* temp_entry_ptr = entry.get();
+
+    WriteMetadata(
+        temp_entry_ptr, *metadata,
+        base::BindOnce(&LegacyCacheStorageCache::WriteSideDataDidWriteMetadata,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+                       std::move(entry), response->padding(),
+                       response->side_data_padding()));
+    return;
   }
 
   WriteSideDataComplete(std::move(callback), std::move(entry),
+                        response->padding(), response->side_data_padding(),
                         CacheStorageError::kSuccess);
 }
 
+void LegacyCacheStorageCache::WriteSideDataDidWriteMetadata(
+    ErrorCallback callback,
+    ScopedWritableEntry entry,
+    int64_t padding,
+    int64_t side_data_padding,
+    int expected_bytes,
+    int rv) {
+  auto result = blink::mojom::CacheStorageError::kSuccess;
+  if (rv != expected_bytes) {
+    result = MakeErrorStorage(
+        ErrorStorageType::kWriteSideDataDidWriteMetadataWrongBytes);
+  }
+  WriteSideDataComplete(std::move(callback), std::move(entry), padding,
+                        side_data_padding, result);
+}
+
 void LegacyCacheStorageCache::WriteSideDataComplete(
     ErrorCallback callback,
     ScopedWritableEntry entry,
+    int64_t padding,
+    int64_t side_data_padding,
     blink::mojom::CacheStorageError error) {
   if (error != CacheStorageError::kSuccess) {
     // If we found the entry, then we possibly wrote something and now we're
     // dooming the entry, causing a change in size, so update the size before
     // returning.
     if (error != CacheStorageError::kErrorNotFound) {
+      entry.reset();
+      cache_padding_ -= (padding + side_data_padding);
       UpdateCacheSize(base::BindOnce(std::move(callback), error));
       return;
     }
@@ -1810,8 +1909,6 @@
       put_context->response->response_type));
   for (const auto& url : put_context->response->url_list)
     response_metadata->add_url_list(url.spec());
-  response_metadata->set_loaded_with_credentials(
-      put_context->response->loaded_with_credentials);
   response_metadata->set_connection_info(
       put_context->response->connection_info);
   response_metadata->set_alpn_negotiated_protocol(
@@ -1838,40 +1935,33 @@
   for (const auto& header : put_context->response->cors_exposed_header_names)
     response_metadata->add_cors_exposed_header_names(header);
 
-  std::unique_ptr<std::string> serialized(new std::string());
-  if (!metadata.SerializeToString(serialized.get())) {
-    PutComplete(
-        std::move(put_context),
-        MakeErrorStorage(ErrorStorageType::kMetadataSerializationFailed));
-    return;
+  DCHECK(!ShouldPadResourceSize(*put_context->response) ||
+         put_context->response->padding);
+  response_metadata->set_padding(put_context->response->padding);
+
+  int64_t side_data_padding = 0;
+  if (ShouldPadResourceSize(*put_context->response) &&
+      put_context->side_data_blob) {
+    side_data_padding = CalculateSideDataPadding(
+        origin_, response_metadata, put_context->side_data_blob_size);
   }
-
-  scoped_refptr<net::StringIOBuffer> buffer =
-      base::MakeRefCounted<net::StringIOBuffer>(std::move(serialized));
+  response_metadata->set_side_data_padding(side_data_padding);
 
   // Get a temporary copy of the entry pointer before passing it in base::Bind.
   disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get();
 
-  // Create a callback that is copyable, even though it can only be called once.
-  // BindRepeating() cannot be used directly because |put_context| is not
-  // copyable.
-  net::CompletionRepeatingCallback write_headers_callback =
-      base::AdaptCallbackForRepeating(
-          base::BindOnce(&LegacyCacheStorageCache::PutDidWriteHeaders,
-                         weak_ptr_factory_.GetWeakPtr(), std::move(put_context),
-                         buffer->size()));
-
-  DCHECK(scheduler_->IsRunningExclusiveOperation());
-  rv = temp_entry_ptr->WriteData(INDEX_HEADERS, 0 /* offset */, buffer.get(),
-                                 buffer->size(), write_headers_callback,
-                                 true /* truncate */);
-
-  if (rv != net::ERR_IO_PENDING)
-    std::move(write_headers_callback).Run(rv);
+  WriteMetadata(
+      temp_entry_ptr, metadata,
+      base::BindOnce(&LegacyCacheStorageCache::PutDidWriteHeaders,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(put_context),
+                     response_metadata->padding(),
+                     response_metadata->side_data_padding()));
 }
 
 void LegacyCacheStorageCache::PutDidWriteHeaders(
     std::unique_ptr<PutContext> put_context,
+    int64_t padding,
+    int64_t side_data_padding,
     int expected_bytes,
     int rv) {
   TRACE_EVENT_WITH_FLOW0("CacheStorage",
@@ -1887,11 +1977,9 @@
     return;
   }
 
-  if (ShouldPadResourceSize(*put_context->response)) {
-    cache_padding_ += CalculateResponsePadding(*put_context->response,
-                                               cache_padding_key_.get(),
-                                               0 /* side_data_size */);
-  }
+  DCHECK(!ShouldPadResourceSize(*put_context->response) ||
+         (padding + side_data_padding));
+  cache_padding_ += padding + side_data_padding;
 
   PutWriteBlobToCache(std::move(put_context), INDEX_RESPONSE_BODY);
 }
@@ -2075,12 +2163,9 @@
   int64_t cache_padding = 0;
   if (error == CacheStorageError::kSuccess) {
     for (const auto& result : *query_cache_results) {
-      if (ShouldPadResourceSize(*result.response)) {
-        int32_t side_data_size =
-            result.entry ? result.entry->GetDataSize(INDEX_SIDE_DATA) : 0;
-        cache_padding += CalculateResponsePadding(
-            *result.response, cache_padding_key_.get(), side_data_size);
-      }
+      DCHECK(!ShouldPadResourceSize(*result.response) ||
+             (result.padding + result.side_data_padding));
+      cache_padding += result.padding + result.side_data_padding;
     }
   }
 
@@ -2281,9 +2366,9 @@
   for (auto& result : *query_cache_results) {
     disk_cache::ScopedEntryPtr entry = std::move(result.entry);
     if (ShouldPadResourceSize(*result.response)) {
-      cache_padding_ -=
-          CalculateResponsePadding(*result.response, cache_padding_key_.get(),
-                                   entry->GetDataSize(INDEX_SIDE_DATA));
+      DCHECK(!ShouldPadResourceSize(*result.response) ||
+             (result.padding + result.side_data_padding));
+      cache_padding_ -= (result.padding + result.side_data_padding);
     }
     entry->Doom();
   }
diff -Naur a/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h b/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h
--- a/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h	2021-06-18 16:26:16.695764277 +0100
@@ -28,10 +28,6 @@
 #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
 #include "url/origin.h"
 
-namespace crypto {
-class SymmetricKey;
-}
-
 namespace storage {
 class QuotaManagerProxy;
 }  // namespace storage
@@ -47,7 +43,6 @@
 
 namespace proto {
 class CacheMetadata;
-class CacheResponse;
 }  // namespace proto
 
 namespace cache_storage_cache_unittest {
@@ -69,8 +64,7 @@
       LegacyCacheStorage* cache_storage,
       scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
       scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
-      scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
-      std::unique_ptr<crypto::SymmetricKey> cache_padding_key);
+      scoped_refptr<BlobStorageContextWrapper> blob_storage_context);
   static std::unique_ptr<LegacyCacheStorageCache> CreatePersistentCache(
       const url::Origin& origin,
       CacheStorageOwner owner,
@@ -81,12 +75,7 @@
       scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
       int64_t cache_size,
-      int64_t cache_padding,
-      std::unique_ptr<crypto::SymmetricKey> cache_padding_key);
-  static int64_t CalculateResponsePadding(
-      const blink::mojom::FetchAPIResponse& response,
-      const crypto::SymmetricKey* padding_key,
-      int side_data_size);
+      int64_t cache_padding);
   static int32_t GetResponsePaddingVersion();
 
   void Match(blink::mojom::FetchAPIRequestPtr request,
@@ -147,11 +136,15 @@
   // will exit early. Close should only be called once per CacheStorageCache.
   void Close(base::OnceClosure callback);
 
-  // The size of the cache's contents.
+  // The size of the cache's contents.  The callback reports the padded
+  // size.  If you want the unpadded size you may call the cache_size()
+  // getter method on the cache object when the callback is invoked; the
+  // getter will have an up-to-date value at that point.
   void Size(SizeCallback callback);
 
   // Gets the cache's size, closes the backend, and then runs |callback| with
-  // the cache's size.
+  // the cache's size.  As per the comment for Size(), this also returns the
+  // padded size.
   void GetSizeThenClose(SizeCallback callback);
 
   void Put(blink::mojom::FetchAPIRequestPtr request,
@@ -177,10 +170,6 @@
 
   int64_t cache_padding() const { return cache_padding_; }
 
-  const crypto::SymmetricKey* cache_padding_key() const {
-    return cache_padding_key_.get();
-  }
-
   // Return the total cache size (actual size + padding). If either is unknown
   // then CacheStorage::kSizeUnknown is returned.
   int64_t PaddedCacheSize() const;
@@ -252,8 +241,7 @@
       scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
       int64_t cache_size,
-      int64_t cache_padding,
-      std::unique_ptr<crypto::SymmetricKey> cache_padding_key);
+      int64_t cache_padding);
 
   // Runs |callback| with matching requests/response data. The data provided
   // in the QueryCacheResults depends on the |query_type|. If |query_type| is
@@ -278,6 +266,10 @@
       std::unique_ptr<QueryCacheContext> query_cache_context,
       disk_cache::ScopedEntryPtr entry,
       std::unique_ptr<proto::CacheMetadata> metadata);
+  void QueryCacheUpgradePadding(
+      std::unique_ptr<QueryCacheContext> query_cache_context,
+      disk_cache::ScopedEntryPtr entry,
+      std::unique_ptr<proto::CacheMetadata> metadata);
   static bool QueryCacheResultCompare(const QueryCacheResult& lhs,
                                       const QueryCacheResult& rhs);
   static size_t EstimatedResponseSizeWithoutBlob(
@@ -306,6 +298,13 @@
       blink::mojom::CacheStorageError error,
       std::unique_ptr<QueryCacheResults> query_cache_results);
 
+  // Utility method to write metadata headers to an entry.
+  using WriteMetadataCallback =
+      base::OnceCallback<void(int exepected_bytes, int rv)>;
+  void WriteMetadata(disk_cache::Entry* entry,
+                     const proto::CacheMetadata& metadata,
+                     WriteMetadataCallback callback);
+
   // WriteSideData callbacks
   void WriteSideDataDidGetQuota(ErrorCallback callback,
                                 const GURL& url,
@@ -351,12 +350,19 @@
       ErrorCallback callback,
       ScopedWritableEntry entry,
       int expected_bytes,
-      std::unique_ptr<content::proto::CacheResponse> response,
-      int side_data_size_before_write,
+      std::unique_ptr<content::proto::CacheMetadata> metadata,  
       int64_t trace_id,
       int rv);
+  void WriteSideDataDidWriteMetadata(ErrorCallback callback,
+                                     ScopedWritableEntry entry,
+                                     int64_t padding,
+                                     int64_t side_data_padding,
+                                     int expected_bytes,
+                                     int rv);
   void WriteSideDataComplete(ErrorCallback callback,
                              ScopedWritableEntry entry,
+                             int64_t padding,
+                             int64_t side_data_padding,
                              blink::mojom::CacheStorageError error);
 
   // Puts the request and response object in the cache. The response body (if
@@ -375,6 +381,8 @@
   void PutDidCreateEntry(std::unique_ptr<PutContext> put_context,
                          disk_cache::EntryResult result);
   void PutDidWriteHeaders(std::unique_ptr<PutContext> put_context,
+                          int64_t padding,
+                          int64_t side_data_padding,
                           int expected_bytes,
                           int rv);
   void PutWriteBlobToCache(std::unique_ptr<PutContext> put_context,
@@ -529,7 +537,6 @@
   // The actual cache size (not including padding).
   int64_t cache_size_;
   int64_t cache_padding_ = 0;
-  std::unique_ptr<crypto::SymmetricKey> cache_padding_key_;
   int64_t last_reported_size_ = 0;
   size_t max_query_size_bytes_;
   size_t handle_ref_count_ = 0;
diff -Naur a/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc b/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc
--- a/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/cache_storage/legacy/legacy_cache_storage.cc	2021-06-18 16:26:16.695764277 +0100
@@ -46,7 +46,6 @@
 #include "net/base/directory_lister.h"
 #include "net/base/net_errors.h"
 #include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/quota/padding_key.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
 
@@ -117,8 +116,7 @@
   virtual std::unique_ptr<LegacyCacheStorageCache> CreateCache(
       const std::string& cache_name,
       int64_t cache_size,
-      int64_t cache_padding,
-      std::unique_ptr<SymmetricKey> cache_padding_key) = 0;
+      int64_t cache_padding) = 0;
 
   // Deletes any pre-existing cache of the same name and then loads it.
   virtual void PrepareNewCacheDestination(const std::string& cache_name,
@@ -186,19 +184,16 @@
   std::unique_ptr<LegacyCacheStorageCache> CreateCache(
       const std::string& cache_name,
       int64_t cache_size,
-      int64_t cache_padding,
-      std::unique_ptr<SymmetricKey> cache_padding_key) override {
+      int64_t cache_padding) override {
     return LegacyCacheStorageCache::CreateMemoryCache(
         origin_, owner_, cache_name, cache_storage_, scheduler_task_runner_,
-        quota_manager_proxy_, blob_storage_context_,
-        storage::CopyDefaultPaddingKey());
+        quota_manager_proxy_, blob_storage_context_);
   }
 
   void PrepareNewCacheDestination(const std::string& cache_name,
                                   CacheAndErrorCallback callback) override {
     std::unique_ptr<LegacyCacheStorageCache> cache =
-        CreateCache(cache_name, 0 /*cache_size*/, 0 /* cache_padding */,
-                    storage::CopyDefaultPaddingKey());
+        CreateCache(cache_name, /*cache_size=*/0, /*cache_padding=*/0);
     std::move(callback).Run(std::move(cache), CacheStorageError::kSuccess);
   }
 
@@ -259,8 +254,7 @@
   std::unique_ptr<LegacyCacheStorageCache> CreateCache(
       const std::string& cache_name,
       int64_t cache_size,
-      int64_t cache_padding,
-      std::unique_ptr<SymmetricKey> cache_padding_key) override {
+      int64_t cache_padding) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     DCHECK(base::Contains(cache_name_to_cache_dir_, cache_name));
 
@@ -269,7 +263,7 @@
     return LegacyCacheStorageCache::CreatePersistentCache(
         origin_, owner_, cache_name, cache_storage_, cache_path,
         scheduler_task_runner_, quota_manager_proxy_, blob_storage_context_,
-        cache_size, cache_padding, std::move(cache_padding_key));
+        cache_size, cache_padding);
   }
 
   void PrepareNewCacheDestination(const std::string& cache_name,
@@ -324,8 +318,7 @@
     cache_name_to_cache_dir_[cache_name] = cache_dir;
     std::move(callback).Run(
         CreateCache(cache_name, LegacyCacheStorage::kSizeUnknown,
-                    LegacyCacheStorage::kSizeUnknown,
-                    storage::CopyDefaultPaddingKey()),
+                    LegacyCacheStorage::kSizeUnknown),
         CacheStorageError::kSuccess);
   }
 
@@ -371,7 +364,6 @@
         index_cache->clear_size();
       else
         index_cache->set_size(cache_metadata.size);
-      index_cache->set_padding_key(cache_metadata.padding_key);
       index_cache->set_padding(cache_metadata.padding);
       index_cache->set_padding_version(
           LegacyCacheStorageCache::GetResponsePaddingVersion());
@@ -449,13 +441,8 @@
         cache_padding = LegacyCacheStorage::kSizeUnknown;
       }
 
-      std::string cache_padding_key =
-          cache.has_padding_key() ? cache.padding_key()
-                                  : storage::SerializeDefaultPaddingKey();
-
-      index->Insert(CacheStorageIndex::CacheMetadata(
-          cache.name(), cache_size, cache_padding,
-          std::move(cache_padding_key)));
+      index->Insert(CacheStorageIndex::CacheMetadata(cache.name(), cache_size,
+                                                     cache_padding));
       cache_name_to_cache_dir_[cache.name()] = cache.cache_dir();
       cache_dirs->insert(cache.cache_dir());
     }
@@ -1058,8 +1045,7 @@
 
   cache_map_.insert(std::make_pair(cache_name, std::move(cache)));
   cache_index_->Insert(CacheStorageIndex::CacheMetadata(
-      cache_name, cache_ptr->cache_size(), cache_ptr->cache_padding(),
-      cache_ptr->cache_padding_key()->key()));
+      cache_name, cache_ptr->cache_size(), cache_ptr->cache_padding()));
 
   CacheStorageCacheHandle handle = cache_ptr->CreateHandle();
   index_write_task_.Cancel();
@@ -1363,8 +1349,7 @@
     DCHECK(metadata);
     std::unique_ptr<LegacyCacheStorageCache> new_cache =
         cache_loader_->CreateCache(
-            cache_name, metadata->size, metadata->padding,
-            storage::DeserializePaddingKey(metadata->padding_key));
+            cache_name, metadata->size, metadata->padding);
     CacheStorageCache* cache_ptr = new_cache.get();
     map_iter->second = std::move(new_cache);
 
@@ -1380,9 +1365,11 @@
     int64_t* accumulator,
     int64_t size) {
   auto* impl = LegacyCacheStorageCache::From(cache_handle);
-  if (doomed_caches_.find(impl) == doomed_caches_.end())
-    cache_index_->SetCacheSize(impl->cache_name(), size);
-  *accumulator += size;
+  if (doomed_caches_.find(impl) == doomed_caches_.end()) {
+    cache_index_->SetCacheSize(impl->cache_name(), impl->cache_size());
+    cache_index_->SetCachePadding(impl->cache_name(), impl->cache_padding());
+  }
+  *accumulator += (impl->cache_size() + impl->cache_padding());
   std::move(closure).Run();
 }
 
@@ -1435,8 +1422,9 @@
                      std::move(callback)));
 
   for (const auto& cache_metadata : cache_index_->ordered_cache_metadata()) {
-    if (cache_metadata.size != LegacyCacheStorage::kSizeUnknown) {
-      *accumulator_ptr += cache_metadata.size;
+    if (cache_metadata.size != LegacyCacheStorage::kSizeUnknown &&
+        cache_metadata.padding != LegacyCacheStorage::kSizeUnknown) {
+      *accumulator_ptr += (cache_metadata.size + cache_metadata.padding);
       barrier_closure.Run();
       continue;
     }
diff -Naur a/src/3rdparty/chromium/content/browser/code_cache/generated_code_cache.cc b/src/3rdparty/chromium/content/browser/code_cache/generated_code_cache.cc
--- a/src/3rdparty/chromium/content/browser/code_cache/generated_code_cache.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/code_cache/generated_code_cache.cc	2021-06-18 16:26:16.695764277 +0100
@@ -384,9 +384,18 @@
     // [stream1] <empty>
     // [stream0 (checksum key entry)] <empty>
     // [stream1 (checksum key entry)] data
+
+    // Make a copy of the data before hashing. A compromised renderer could
+    // change shared memory before we can compute the hash and write the data.
+    // TODO(1135729) Eliminate this copy when the shared memory can't be written
+    // by the sender.
+    mojo_base::BigBuffer copy({data.data(), data.size()});
+    if (copy.size() != data.size())
+      return;
+    data = mojo_base::BigBuffer();  // Release the old buffer.
     uint8_t result[crypto::kSHA256Length];
     crypto::SHA256HashString(
-        base::StringPiece(reinterpret_cast<char*>(data.data()), data.size()),
+        base::StringPiece(reinterpret_cast<char*>(copy.data()), copy.size()),
         result, base::size(result));
     std::string checksum_key = base::HexEncode(result, base::size(result));
     small_buffer = base::MakeRefCounted<net::IOBufferWithSize>(
@@ -401,7 +410,7 @@
     // Issue another write operation for the code, with the checksum as the key
     // and nothing in the header.
     auto small_buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(0);
-    auto large_buffer2 = base::MakeRefCounted<BigIOBuffer>(std::move(data));
+    auto large_buffer2 = base::MakeRefCounted<BigIOBuffer>(std::move(copy));
     auto op2 = std::make_unique<PendingOperation>(Operation::kWriteWithSHAKey,
                                                   checksum_key, small_buffer2,
                                                   large_buffer2);
diff -Naur a/src/3rdparty/chromium/content/browser/devtools/protocol/page_handler.cc b/src/3rdparty/chromium/content/browser/devtools/protocol/page_handler.cc
--- a/src/3rdparty/chromium/content/browser/devtools/protocol/page_handler.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/devtools/protocol/page_handler.cc	2021-06-18 16:26:16.695764277 +0100
@@ -501,8 +501,12 @@
   params.referrer = Referrer(GURL(referrer.fromMaybe("")), policy);
   params.transition_type = type;
   params.frame_tree_node_id = frame_tree_node->frame_tree_node_id();
+  // Handler may be destroyed while navigating if the session
+  // gets disconnected as a result of access checks.
+  base::WeakPtr<PageHandler> weak_self = weak_factory_.GetWeakPtr();
   frame_tree_node->navigator().GetController()->LoadURLWithParams(params);
-
+  if (!weak_self)
+    return;
   base::UnguessableToken frame_token = frame_tree_node->devtools_frame_token();
   auto navigate_callback = navigate_callbacks_.find(frame_token);
   if (navigate_callback != navigate_callbacks_.end()) {
diff -Naur a/src/3rdparty/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc b/src/3rdparty/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
--- a/src/3rdparty/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc	2021-06-18 16:26:16.696766009 +0100
@@ -474,8 +474,11 @@
     if (!ShouldAllowSession(session))
       restricted_sessions.push_back(session);
   }
-  if (!restricted_sessions.empty())
+  scoped_refptr<RenderFrameDevToolsAgentHost> protect;
+  if (!restricted_sessions.empty()) {
+    protect = this;
     ForceDetachRestrictedSessions(restricted_sessions);
+  }
 
   UpdateFrameAlive();
 }
diff -Naur a/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.cc b/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.cc
--- a/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.cc	2021-06-18 16:58:44.903975308 +0100
@@ -39,6 +39,9 @@
     "disabled.";
 const char kBadMessageInvalidNotificationTriggerTimestamp[] =
     "Received an invalid notification trigger timestamp.";
+const char kBadMessageInvalidNotificationActionButtons[] =
+    "Received a notification with a number of action images that does not "
+    "match the number of actions.";
 
 // Returns the implementation of the PlatformNotificationService. May be NULL.
 PlatformNotificationService* GetNotificationService(
@@ -132,7 +135,8 @@
     mojo::PendingRemote<blink::mojom::NonPersistentNotificationListener>
         event_listener_remote) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!ValidateNotificationResources(notification_resources))
+  if (!ValidateNotificationDataAndResources(platform_notification_data,
+                                            notification_resources))
     return;
 
   if (!GetNotificationService(browser_context_))
@@ -187,28 +191,31 @@
                             origin_.GetURL());
 }
 
-bool BlinkNotificationServiceImpl::ValidateNotificationResources(
+bool BlinkNotificationServiceImpl::ValidateNotificationDataAndResources(
+    const blink::PlatformNotificationData& platform_notification_data,
     const blink::NotificationResources& notification_resources) {
-  if (notification_resources.image.drawsNothing() ||
-      base::FeatureList::IsEnabled(features::kNotificationContentImage))
-    return true;
-  receiver_.ReportBadMessage(kBadMessageImproperNotificationImage);
-  // The above ReportBadMessage() closes |binding_| but does not trigger its
-  // connection error handler, so we need to call the error handler explicitly
-  // here to do some necessary work.
-  OnConnectionError();
-  return false;
-}
+  if (platform_notification_data.actions.size() !=
+      notification_resources.action_icons.size()) {
+    receiver_.ReportBadMessage(kBadMessageInvalidNotificationActionButtons);
+    OnConnectionError();
+    return false;
+  }
 
-// Checks if this notification has a valid trigger.
-bool BlinkNotificationServiceImpl::ValidateNotificationData(
-    const blink::PlatformNotificationData& notification_data) {
-  if (!CheckNotificationTriggerRange(notification_data)) {
+  if (!CheckNotificationTriggerRange(platform_notification_data)) {
     receiver_.ReportBadMessage(kBadMessageInvalidNotificationTriggerTimestamp);
     OnConnectionError();
     return false;
   }
 
+  if (!notification_resources.image.drawsNothing() &&
+      !base::FeatureList::IsEnabled(features::kNotificationContentImage)) {
+    receiver_.ReportBadMessage(kBadMessageImproperNotificationImage);
+    // The above ReportBadMessage() closes |binding_| but does not trigger its
+    // connection error handler, so we need to call the error handler explicitly
+    // here to do some necessary work.
+    OnConnectionError();
+    return false;
+  }
   return true;
 }
 
@@ -218,10 +225,8 @@
     const blink::NotificationResources& notification_resources,
     DisplayPersistentNotificationCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!ValidateNotificationResources(notification_resources))
-    return;
-
-  if (!ValidateNotificationData(platform_notification_data))
+  if (!ValidateNotificationDataAndResources(platform_notification_data,
+                                            notification_resources))
     return;
 
   if (!GetNotificationService(browser_context_)) {
diff -Naur a/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.h b/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.h
--- a/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/notifications/blink_notification_service_impl.h	2021-06-18 16:58:44.904977041 +0100
@@ -71,20 +71,15 @@
   // Check the permission status for the current |origin_|.
   blink::mojom::PermissionStatus CheckPermissionStatus();
 
-  // Validate |notification_resources| received in a Mojo IPC message.
-  // If the validation failed, we'd close the Mojo connection |binding_| and
-  // destroy |this| by calling OnConnectionError() directly, then return false.
-  // So, please do not touch |this| again after you got a false return value.
-  bool ValidateNotificationResources(
+  // Validate |notification_data| and |notification_resources| received in a
+  // Mojo IPC message. If the validation failed, we'd close the Mojo connection
+  // |binding_| and destroy |this| by calling OnConnectionError() directly, then
+  // return false. So, please do not touch |this| again after you got a false
+  // return value.
+  bool ValidateNotificationDataAndResources(
+      const blink::PlatformNotificationData& notification_data,
       const blink::NotificationResources& notification_resources);
 
-  // Validate |notification_data| received in a Mojo IPC message.
-  // If the validation failed, we'd close the Mojo connection |binding_| and
-  // destroy |this| by calling OnConnectionError() directly, then return false.
-  // So, please do not touch |this| again after you got a false return value.
-  bool ValidateNotificationData(
-      const blink::PlatformNotificationData& notification_data);
-
   void DidWriteNotificationData(DisplayPersistentNotificationCallback callback,
                                 bool success,
                                 const std::string& notification_id);
diff -Naur a/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.cc b/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.cc
--- a/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.cc	2021-06-18 16:26:16.696766009 +0100
@@ -133,7 +133,8 @@
   int render_frame_id = -1;
   int render_process_id = -1;
   base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback;
-  int delegate_subscription_id;
+  // This is default-initialized to an invalid ID.
+  PermissionControllerDelegate::SubscriptionId delegate_subscription_id;
 };
 
 PermissionControllerImpl::~PermissionControllerImpl() {
@@ -389,7 +390,8 @@
     subscription->callback.Run(status);
 }
 
-int PermissionControllerImpl::SubscribePermissionStatusChange(
+PermissionControllerImpl::SubscriptionId
+PermissionControllerImpl::SubscribePermissionStatusChange(
     PermissionType permission,
     RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
@@ -423,22 +425,22 @@
             base::BindRepeating(
                 &PermissionControllerImpl::OnDelegatePermissionStatusChange,
                 base::Unretained(this), subscription.get()));
-  } else {
-    subscription->delegate_subscription_id = kNoPendingOperation;
   }
-  return subscriptions_.Add(std::move(subscription));
+
+  auto id = subscription_id_generator_.GenerateNextId();
+  subscriptions_.AddWithID(std::move(subscription), id);
+  return id;
 }
 
 void PermissionControllerImpl::UnsubscribePermissionStatusChange(
-    int subscription_id) {
+    SubscriptionId subscription_id) {
   Subscription* subscription = subscriptions_.Lookup(subscription_id);
   if (!subscription)
     return;
   PermissionControllerDelegate* delegate =
       browser_context_->GetPermissionControllerDelegate();
-  if (delegate &&
-      subscription->delegate_subscription_id != kNoPendingOperation) {
-    delegate->UnsubscribePermissionStatusChange(
+  if (delegate) {
+     delegate->UnsubscribePermissionStatusChange(
         subscription->delegate_subscription_id);
   }
   subscriptions_.Remove(subscription_id);
diff -Naur a/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.h b/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.h
--- a/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/permissions/permission_controller_impl.h	2021-06-18 16:26:16.696766009 +0100
@@ -72,18 +72,19 @@
                        const GURL& requesting_origin,
                        const GURL& embedding_origin);
 
-  int SubscribePermissionStatusChange(
+  SubscriptionId SubscribePermissionStatusChange(
       PermissionType permission,
       RenderFrameHost* render_frame_host,
       const GURL& requesting_origin,
       const base::RepeatingCallback<void(blink::mojom::PermissionStatus)>&
           callback);
 
-  void UnsubscribePermissionStatusChange(int subscription_id);
+  void UnsubscribePermissionStatusChange(SubscriptionId subscription_id);
 
  private:
   struct Subscription;
-  using SubscriptionsMap = base::IDMap<std::unique_ptr<Subscription>>;
+  using SubscriptionsMap =
+      base::IDMap<std::unique_ptr<Subscription>, SubscriptionId>;
   using SubscriptionsStatusMap =
       base::flat_map<SubscriptionsMap::KeyType, blink::mojom::PermissionStatus>;
 
@@ -98,7 +99,13 @@
       const base::Optional<url::Origin>& origin);
 
   DevToolsPermissionOverrides devtools_permission_overrides_;
+
+  // Note that SubscriptionId is distinct from
+  // PermissionControllerDelegate::SubscriptionId, and the concrete ID values
+  // may be different as well.
   SubscriptionsMap subscriptions_;
+  SubscriptionId::Generator subscription_id_generator_;
+
   BrowserContext* browser_context_;
 
   DISALLOW_COPY_AND_ASSIGN(PermissionControllerImpl);
diff -Naur a/src/3rdparty/chromium/content/browser/permissions/permission_service_context.cc b/src/3rdparty/chromium/content/browser/permissions/permission_service_context.cc
--- a/src/3rdparty/chromium/content/browser/permissions/permission_service_context.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/permissions/permission_service_context.cc	2021-06-18 16:26:16.696766009 +0100
@@ -32,7 +32,7 @@
   PermissionSubscription& operator=(const PermissionSubscription&) = delete;
 
   ~PermissionSubscription() {
-    DCHECK_NE(id_, 0);
+    DCHECK(id_);
     BrowserContext* browser_context = context_->GetBrowserContext();
     if (browser_context) {
       PermissionControllerImpl::FromBrowserContext(browser_context)
@@ -41,7 +41,7 @@
   }
 
   void OnConnectionError() {
-    DCHECK_NE(id_, 0);
+    DCHECK(id_);
     context_->ObserverHadConnectionError(id_);
   }
 
@@ -49,12 +49,12 @@
     observer_->OnPermissionStatusChange(status);
   }
 
-  void set_id(int id) { id_ = id; }
+  void set_id(PermissionController::SubscriptionId id) { id_ = id; }
 
  private:
   PermissionServiceContext* const context_;
   mojo::Remote<blink::mojom::PermissionObserver> observer_;
-  int id_ = 0;
+  PermissionController::SubscriptionId id_;
 };
 
 PermissionServiceContext::PermissionServiceContext(
@@ -108,7 +108,7 @@
   }
 
   GURL requesting_origin(origin.Serialize());
-  int subscription_id =
+  auto subscription_id =
       PermissionControllerImpl::FromBrowserContext(browser_context)
           ->SubscribePermissionStatusChange(
               permission_type, render_frame_host_, requesting_origin,
@@ -119,7 +119,8 @@
   subscriptions_[subscription_id] = std::move(subscription);
 }
 
-void PermissionServiceContext::ObserverHadConnectionError(int subscription_id) {
+void PermissionServiceContext::ObserverHadConnectionError(
+    PermissionController::SubscriptionId subscription_id) {
   size_t erased = subscriptions_.erase(subscription_id);
   DCHECK_EQ(1u, erased);
 }
diff -Naur a/src/3rdparty/chromium/content/browser/permissions/permission_service_context.h b/src/3rdparty/chromium/content/browser/permissions/permission_service_context.h
--- a/src/3rdparty/chromium/content/browser/permissions/permission_service_context.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/permissions/permission_service_context.h	2021-06-18 16:26:16.696766009 +0100
@@ -9,6 +9,7 @@
 #include <unordered_map>
 
 #include "content/common/content_export.h"
+#include "content/public/browser/permission_controller.h"
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -52,7 +53,8 @@
       mojo::PendingRemote<blink::mojom::PermissionObserver> observer);
 
   // Called when the connection to a PermissionObserver has an error.
-  void ObserverHadConnectionError(int subscription_id);
+  void ObserverHadConnectionError(
+      PermissionController::SubscriptionId subscription_id);
 
   // May return nullptr during teardown, or when showing an interstitial.
   BrowserContext* GetBrowserContext() const;
@@ -78,7 +80,8 @@
   RenderFrameHost* const render_frame_host_;
   RenderProcessHost* const render_process_host_;
   mojo::UniqueReceiverSet<blink::mojom::PermissionService> services_;
-  std::unordered_map<int, std::unique_ptr<PermissionSubscription>>
+  std::unordered_map<PermissionController::SubscriptionId,
+                     std::unique_ptr<PermissionSubscription>>
       subscriptions_;
 };
 
diff -Naur a/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.cc
--- a/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.cc	2021-06-18 16:26:16.696766009 +0100
@@ -668,9 +668,9 @@
 
   std::string tab_capture_device_id;
 
-  int audio_subscription_id = PermissionControllerImpl::kNoPendingOperation;
+  PermissionController::SubscriptionId audio_subscription_id;
 
-  int video_subscription_id = PermissionControllerImpl::kNoPendingOperation;
+  PermissionController::SubscriptionId video_subscription_id;
 
  private:
   std::vector<MediaRequestState> state_;
@@ -2686,8 +2686,8 @@
   if (!controller)
     return;
 
-  int audio_subscription_id = PermissionControllerImpl::kNoPendingOperation;
-  int video_subscription_id = PermissionControllerImpl::kNoPendingOperation;
+  PermissionController::SubscriptionId audio_subscription_id;
+  PermissionController::SubscriptionId video_subscription_id;
 
   if (is_audio_request) {
     // It is safe to bind base::Unretained(this) because MediaStreamManager is
@@ -2729,8 +2729,8 @@
     const std::string& label,
     int requesting_process_id,
     int requesting_frame_id,
-    int audio_subscription_id,
-    int video_subscription_id) {
+    PermissionController::SubscriptionId audio_subscription_id,
+    PermissionController::SubscriptionId video_subscription_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   DeviceRequest* const request = FindRequest(label);
@@ -2757,8 +2757,8 @@
 void MediaStreamManager::UnsubscribeFromPermissionControllerOnUIThread(
     int requesting_process_id,
     int requesting_frame_id,
-    int audio_subscription_id,
-    int video_subscription_id) {
+    PermissionController::SubscriptionId audio_subscription_id,
+    PermissionController::SubscriptionId video_subscription_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   PermissionControllerImpl* controller =
diff -Naur a/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.h b/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.h
--- a/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/renderer_host/media/media_stream_manager.h	2021-06-18 16:26:16.696766009 +0100
@@ -50,6 +50,7 @@
 #include "content/public/browser/desktop_media_id.h"
 #include "content/public/browser/media_request_state.h"
 #include "content/public/browser/media_stream_request.h"
+#include "content/public/browser/permission_controller.h"
 #include "media/base/video_facing.h"
 #include "third_party/blink/public/common/mediastream/media_devices.h"
 #include "third_party/blink/public/common/mediastream/media_stream_controls.h"
@@ -557,19 +558,20 @@
 
   // Store the subscription ids on a DeviceRequest in order to allow
   // unsubscribing when the request is deleted.
-  void SetPermissionSubscriptionIDs(const std::string& label,
-                                    int requesting_process_id,
-                                    int requesting_frame_id,
-                                    int audio_subscription_id,
-                                    int video_subscription_id);
+  void SetPermissionSubscriptionIDs(
+      const std::string& label,
+      int requesting_process_id,
+      int requesting_frame_id,
+      PermissionController::SubscriptionId audio_subscription_id,
+      PermissionController::SubscriptionId video_subscription_id);
 
   // Unsubscribe from following permission updates for the two specified
   // subscription IDs. Called when a request is deleted.
   static void UnsubscribeFromPermissionControllerOnUIThread(
       int requesting_process_id,
       int requesting_frame_id,
-      int audio_subscription_id,
-      int video_subscription_id);
+      PermissionController::SubscriptionId audio_subscription_id,
+      PermissionController::SubscriptionId video_subscription_id);
 
   // Callback that the PermissionController calls when a permission is updated.
   void PermissionChangedCallback(int requesting_process_id,
diff -Naur a/src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc b/src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc
--- a/src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc	2021-06-18 16:26:16.697767741 +0100
@@ -159,10 +159,13 @@
     const GURL& url,
     bool is_coop_coep_cross_origin_isolated,
     bool is_speculative) {
+  SiteInstanceImpl* site_instance_impl =
+      static_cast<SiteInstanceImpl*>(site_instance);
   // We do not want cross-origin-isolated have any impact on SiteInstances until
   // we get an actual COOP value in a redirect or a final response.
   if (is_speculative)
-    return true;
+    return site_instance_impl->IsCoopCoepCrossOriginIsolated() ==
+        is_coop_coep_cross_origin_isolated;
 
   // Note: The about blank case is to accommodate web tests that use COOP. They
   // expect an about:blank page to stay in process, and hang otherwise. In
@@ -172,9 +175,6 @@
   if (url.IsAboutBlank())
     return true;
 
-  SiteInstanceImpl* site_instance_impl =
-      static_cast<SiteInstanceImpl*>(site_instance);
-
   if (is_main_frame) {
     if (site_instance_impl->IsCoopCoepCrossOriginIsolated() !=
         is_coop_coep_cross_origin_isolated) {
diff -Naur a/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc b/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc
--- a/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc	2021-06-18 16:26:16.697767741 +0100
@@ -345,7 +345,7 @@
 
   // Remove this view from the owner_map.
   for (auto entry : owner_map_) {
-    if (entry.second == view) {
+    if (entry.second.get() == view) {
       owner_map_.erase(entry.first);
       // There will only be one instance of a particular view in the map.
       break;
@@ -368,7 +368,7 @@
   // replace it with nullptr so that we maintain the 1:1 correspondence between
   // map entries and the touch sequences that underly them.
   for (auto it : touchscreen_gesture_target_map_) {
-    if (it.second == view)
+    if (it.second.get() == view)
       it.second = nullptr;
   }
 
@@ -417,8 +417,10 @@
 void RenderWidgetHostInputEventRouter::ClearAllObserverRegistrations() {
   // Since we're shutting down, it's safe to call RenderWidgetHostViewBase::
   // RemoveObserver() directly here.
-  for (auto entry : owner_map_)
-    entry.second->RemoveObserver(this);
+  for (auto entry : owner_map_) {
+    if (entry.second)
+      entry.second->RemoveObserver(this);
+  }
   owner_map_.clear();
   viz::HostFrameSinkManager* manager = GetHostFrameSinkManager();
   if (manager)
@@ -840,7 +842,7 @@
                touch_event.unique_touch_event_id) ==
            touchscreen_gesture_target_map_.end());
     touchscreen_gesture_target_map_[touch_event.unique_touch_event_id] =
-        touch_target_;
+        touch_target_->GetWeakPtr();
   } else if (touch_event.GetType() == blink::WebInputEvent::Type::kTouchStart) {
     active_touches_ += CountChangedTouchPoints(touch_event);
   }
@@ -1352,7 +1354,7 @@
   // We want to be notified if the owner is destroyed so we can remove it from
   // our map.
   owner->AddObserver(this);
-  owner_map_.insert(std::make_pair(id, owner));
+  owner_map_.insert(std::make_pair(id, owner->GetWeakPtr()));
 }
 
 void RenderWidgetHostInputEventRouter::RemoveFrameSinkIdOwner(
@@ -1364,7 +1366,8 @@
     // stale values if the view destructs and isn't an observer anymore.
     // Note: the view the iterator points at will be deleted in the following
     // call, and shouldn't be used after this point.
-    OnRenderWidgetHostViewBaseDestroyed(it_to_remove->second);
+    if (it_to_remove->second)
+      OnRenderWidgetHostViewBaseDestroyed(it_to_remove->second.get());
   }
 }
 
@@ -1415,7 +1418,7 @@
 bool RenderWidgetHostInputEventRouter::IsViewInMap(
     const RenderWidgetHostViewBase* view) const {
   DCHECK(!is_registered(view->GetFrameSinkId()) ||
-         owner_map_.find(view->GetFrameSinkId())->second == view);
+         owner_map_.find(view->GetFrameSinkId())->second.get() == view);
   return is_registered(view->GetFrameSinkId());
 }
 
@@ -1522,6 +1525,10 @@
 
   base::Optional<gfx::PointF> fallback_target_location;
 
+  // Adding crash logs to track the reason of stale pointer value of |target|.
+  LogTouchscreenGestureTargetCrashKeys(
+      "RWHIER::DispatchTouchscreenGestureEvent target set from caller");
+
   if (gesture_event.unique_touch_event_id == 0) {
     // On Android it is possible for touchscreen gesture events to arrive that
     // are not associated with touch events, because non-synthetic events can be
@@ -1550,9 +1557,19 @@
     // don't worry about the fact we're ignoring |result.should_query_view|, as
     // this is the best we can do until we fix https://crbug.com/595422.
     target = result.view;
+
+    // Adding crash logs to track the reason of stale pointer value of |target|.
+    LogTouchscreenGestureTargetCrashKeys(
+        "RWHIER::DispatchTouchscreenGestureEvent target from "
+        "FindViewAtLocation");
     fallback_target_location = transformed_point;
   } else if (is_gesture_start) {
-    target = gesture_target_it->second;
+    target = gesture_target_it->second.get();
+
+    // Adding crash logs to track the reason of stale pointer value of |target|.
+    LogTouchscreenGestureTargetCrashKeys(
+        "RWHIER::DispatchTouchscreenGestureEvent target from "
+        "touchscreen_gesture_target_map_");
     touchscreen_gesture_target_map_.erase(gesture_target_it);
 
     // Abort any scroll bubbling in progress to avoid double entry.
@@ -1738,7 +1755,7 @@
   // If the point hit a Surface whose namspace is no longer in the map, then
   // it likely means the RenderWidgetHostView has been destroyed but its
   // parent frame has not sent a new compositor frame since that happened.
-  return iter == owner_map_.end() ? nullptr : iter->second;
+  return iter == owner_map_.end() ? nullptr : iter->second.get();
 }
 
 bool RenderWidgetHostInputEventRouter::ShouldContinueHitTesting(
@@ -1758,8 +1775,10 @@
 std::vector<RenderWidgetHostView*>
 RenderWidgetHostInputEventRouter::GetRenderWidgetHostViewsForTests() const {
   std::vector<RenderWidgetHostView*> hosts;
-  for (auto entry : owner_map_)
-    hosts.push_back(entry.second);
+  for (auto entry : owner_map_) {
+    DCHECK(entry.second);
+    hosts.push_back(entry.second.get());
+  }
 
   return hosts;
 }
@@ -1928,8 +1947,10 @@
   last_device_scale_factor_ =
       last_mouse_move_root_view_->current_device_scale_factor();
   if (auto* cursor_manager = last_mouse_move_root_view_->GetCursorManager()) {
-    for (auto it : owner_map_)
-      cursor_manager->UpdateCursor(it.second, cursor);
+    for (auto it : owner_map_) {
+      if (it.second)
+        cursor_manager->UpdateCursor(it.second.get(), cursor);
+    }
   }
 }
 
@@ -1949,7 +1970,7 @@
     const std::vector<viz::AggregatedHitTestRegion>& hit_test_data) {
   for (auto& region : hit_test_data) {
     auto iter = owner_map_.find(region.frame_sink_id);
-    if (iter != owner_map_.end())
+    if (iter != owner_map_.end() && iter->second)
       iter->second->NotifyHitTestRegionUpdated(region);
   }
 }
@@ -1981,4 +2002,11 @@
   event_targeter_->SetIsAutoScrollInProgress(is_autoscroll_in_progress);
 }
 
+void RenderWidgetHostInputEventRouter::LogTouchscreenGestureTargetCrashKeys(
+    const std::string& log_message) {
+  static auto* target_crash_key = base::debug::AllocateCrashKeyString(
+      "target_crash_key", base::debug::CrashKeySize::Size256);
+  base::debug::SetCrashKeyString(target_crash_key, log_message);
+}
+
 }  // namespace content
diff -Naur a/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h b/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
--- a/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h	2021-06-18 16:26:16.697767741 +0100
@@ -195,10 +195,11 @@
   FRIEND_TEST_ALL_PREFIXES(BrowserSideFlingBrowserTest,
                            InertialGSUBubblingStopsWhenParentCannotScroll);
 
-  using FrameSinkIdOwnerMap = std::unordered_map<viz::FrameSinkId,
-                                                 RenderWidgetHostViewBase*,
-                                                 viz::FrameSinkIdHash>;
-  using TargetMap = std::map<uint32_t, RenderWidgetHostViewBase*>;
+  using FrameSinkIdOwnerMap =
+      std::unordered_map<viz::FrameSinkId,
+                         base::WeakPtr<RenderWidgetHostViewBase>,
+                         viz::FrameSinkIdHash>;
+  using TargetMap = std::map<uint32_t, base::WeakPtr<RenderWidgetHostViewBase>>;
 
   void ClearAllObserverRegistrations();
   RenderWidgetTargetResult FindViewAtLocation(
@@ -332,6 +333,9 @@
   void SetTouchscreenGestureTarget(RenderWidgetHostViewBase* target,
                                    bool moved_recently = false);
 
+  // TODO(crbug.com/1155297): Remove when bug investigation is complete.
+  void LogTouchscreenGestureTargetCrashKeys(const std::string& log_message);
+
   FrameSinkIdOwnerMap owner_map_;
   TargetMap touchscreen_gesture_target_map_;
   RenderWidgetHostViewBase* touch_target_ = nullptr;
diff -Naur a/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.cc b/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.cc
--- a/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.cc	2021-06-18 17:00:07.008965007 +0100
@@ -169,6 +169,7 @@
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
+#include "third_party/blink/public/mojom/image_downloader/image_downloader.mojom.h"
 #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h"
 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -5058,8 +5059,8 @@
     // respond with a 400 HTTP error code to indicate that something went wrong.
     GetUIThreadTaskRunner({})->PostTask(
         FROM_HERE,
-        base::BindOnce(&WebContentsImpl::OnDidDownloadImage,
-                       weak_factory_.GetWeakPtr(), std::move(callback),
+        base::BindOnce(&WebContentsImpl::OnDidDownloadImage, weak_factory_.GetWeakPtr(),
+                       initiator_frame->GetWeakPtr(), std::move(callback),
                        download_id, url, 400, std::vector<SkBitmap>(),
                        std::vector<gfx::Size>()));
     return download_id;
@@ -5068,8 +5069,8 @@
   mojo_image_downloader->DownloadImage(
       url, is_favicon, preferred_size, max_bitmap_size, bypass_cache,
       base::BindOnce(&WebContentsImpl::OnDidDownloadImage,
-                     weak_factory_.GetWeakPtr(), std::move(callback),
-                     download_id, url));
+                     weak_factory_.GetWeakPtr(), initiator_frame->GetWeakPtr(),
+                     std::move(callback), download_id, url));
   return download_id;
 }
 
@@ -8036,6 +8037,7 @@
 }
 
 void WebContentsImpl::OnDidDownloadImage(
+    base::WeakPtr<RenderFrameHostImpl> rfh,
     ImageDownloadCallback callback,
     int id,
     const GURL& image_url,
@@ -8045,6 +8047,21 @@
   OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnDidDownloadImage",
                         "image_url",
                         base::trace_event::ValueToString(image_url));
+
+  // Guard against buggy or compromised renderers that could violate the API
+  // contract that |images| and |original_image_sizes| must have the same
+  // length.
+  if (images.size() != original_image_sizes.size()) {
+    if (rfh) {
+      ReceivedBadMessage(rfh->GetProcess(),
+                         bad_message::WCI_INVALID_DOWNLOAD_IMAGE_RESULT);
+    }
+    // Respond with a 400 to indicate that something went wrong.
+    std::move(callback).Run(id, 400, image_url, std::vector<SkBitmap>(),
+                            std::vector<gfx::Size>());
+    return;
+  }
+
   std::move(callback).Run(id, http_status_code, image_url, images,
                           original_image_sizes);
 }
diff -Naur a/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.h b/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.h
--- a/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.h	2021-06-18 17:00:07.009966740 +0100
@@ -1470,7 +1470,8 @@
       std::set<RenderWidgetHostView*>& result);
 
   // Called with the result of a DownloadImage() request.
-  void OnDidDownloadImage(ImageDownloadCallback callback,
+  void OnDidDownloadImage(base::WeakPtr<RenderFrameHostImpl> rfh,
+                          ImageDownloadCallback callback,
                           int id,
                           const GURL& image_url,
                           int32_t http_status_code,
diff -Naur a/src/3rdparty/chromium/content/common/background_fetch/background_fetch_types.cc b/src/3rdparty/chromium/content/common/background_fetch/background_fetch_types.cc
--- a/src/3rdparty/chromium/content/common/background_fetch/background_fetch_types.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/common/background_fetch/background_fetch_types.cc	2021-06-18 16:26:16.697767741 +0100
@@ -31,16 +31,16 @@
     return nullptr;
   return blink::mojom::FetchAPIResponse::New(
       response->url_list, response->status_code, response->status_text,
-      response->response_type, response->response_source, response->headers,
-      response->mime_type, response->request_method,
+      response->response_type, response->padding, response->response_source,
+      response->headers, response->mime_type, response->request_method,
       CloneSerializedBlob(response->blob), response->error,
       response->response_time, response->cache_storage_cache_name,
       response->cors_exposed_header_names,
       CloneSerializedBlob(response->side_data_blob),
       CloneSerializedBlob(response->side_data_blob_for_cache_put),
       mojo::Clone(response->parsed_headers), response->connection_info,
-      response->alpn_negotiated_protocol, response->loaded_with_credentials,
-      response->was_fetched_via_spdy, response->has_range_requested);
+      response->alpn_negotiated_protocol, response->was_fetched_via_spdy,
+      response->has_range_requested);
 }
 
 // static
diff -Naur a/src/3rdparty/chromium/content/common/service_worker/service_worker_loader_helpers.cc b/src/3rdparty/chromium/content/common/service_worker/service_worker_loader_helpers.cc
--- a/src/3rdparty/chromium/content/common/service_worker/service_worker_loader_helpers.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/common/service_worker/service_worker_loader_helpers.cc	2021-06-18 16:26:16.697767741 +0100
@@ -97,6 +97,7 @@
   out_head->was_fallback_required_by_service_worker = false;
   out_head->url_list_via_service_worker = response.url_list;
   out_head->response_type = response.response_type;
+  out_head->padding = response.padding;
   if (response.mime_type.has_value()) {
     std::string charset;
     bool had_charset = false;
diff -Naur a/src/3rdparty/chromium/content/public/browser/permission_controller_delegate.h b/src/3rdparty/chromium/content/public/browser/permission_controller_delegate.h
--- a/src/3rdparty/chromium/content/public/browser/permission_controller_delegate.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/public/browser/permission_controller_delegate.h	2021-06-18 16:26:16.698769474 +0100
@@ -5,6 +5,7 @@
 #ifndef CONTENT_PUBLIC_BROWSER_PERMISSION_CONTROLLER_DELEGATE_H_
 #define CONTENT_PUBLIC_BROWSER_PERMISSION_CONTROLLER_DELEGATE_H_
 
+#include "base/util/type_safety/id_type.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/devtools_permission_overrides.h"
 #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
@@ -18,6 +19,10 @@
 class CONTENT_EXPORT PermissionControllerDelegate {
  public:
   using PermissionOverrides = DevToolsPermissionOverrides::PermissionOverrides;
+
+  // Identifier for an active subscription.
+  using SubscriptionId = util::IdType64<PermissionControllerDelegate>;
+
   virtual ~PermissionControllerDelegate() = default;
 
   // Requests a permission on behalf of a frame identified by
@@ -80,21 +85,21 @@
 
   // Runs the given |callback| whenever the |permission| associated with the
   // given RenderFrameHost changes. A nullptr should be passed if the request
-  // is from a worker. Returns the subscription_id to be used to unsubscribe.
-  // Can be kNoPendingOperation if the subscribe was not successful.
-  virtual int SubscribePermissionStatusChange(
+  // is from a worker. Returns the ID to be used to unsubscribe, which can be
+  // `is_null()` if the subscribe was not successful.
+  virtual SubscriptionId SubscribePermissionStatusChange(
       content::PermissionType permission,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin,
       base::RepeatingCallback<void(blink::mojom::PermissionStatus)>
           callback) = 0;
 
-  // Unregisters from permission status change notifications.
-  // The |subscription_id| must match the value returned by the
-  // SubscribePermissionStatusChange call. Unsubscribing
-  // an already unsubscribed |subscription_id| or providing the
-  // |subscription_id| kNoPendingOperation is a no-op.
-  virtual void UnsubscribePermissionStatusChange(int subscription_id) = 0;
+  // Unregisters from permission status change notifications. The
+  // |subscription_id| must match the value returned by the
+  // SubscribePermissionStatusChange call. Unsubscribing an already
+  // unsubscribed |subscription_id| or an `is_null()` ID is a no-op.
+  virtual void UnsubscribePermissionStatusChange(
+      SubscriptionId subscription_id) = 0;
 
   // Manually overrides default permission settings of delegate, if overrides
   // are tracked by the delegate. This method should only be called by the
@@ -116,4 +121,17 @@
 
 }  // namespace content
 
+namespace std {
+
+template <>
+struct hash<content::PermissionControllerDelegate::SubscriptionId> {
+  std::size_t operator()(
+      const content::PermissionControllerDelegate::SubscriptionId& v) const {
+    content::PermissionControllerDelegate::SubscriptionId::Hasher hasher;
+    return hasher(v);
+  }
+};
+
+}  // namespace std
+
 #endif  // CONTENT_PUBLIC_BROWSER_PERMISSION_CONTROLLER_DELEGATE_H_
diff -Naur a/src/3rdparty/chromium/content/public/browser/permission_controller.h b/src/3rdparty/chromium/content/public/browser/permission_controller.h
--- a/src/3rdparty/chromium/content/public/browser/permission_controller.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/public/browser/permission_controller.h	2021-06-18 16:26:16.698769474 +0100
@@ -6,6 +6,7 @@
 #define CONTENT_PUBLIC_BROWSER_PERMISSION_CONTROLLER_H_
 
 #include "base/supports_user_data.h"
+#include "base/util/type_safety/id_type.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/permission_type.h"
 #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
@@ -20,8 +21,13 @@
 class CONTENT_EXPORT PermissionController
     : public base::SupportsUserData::Data {
  public:
-  // Constant retured when registering and subscribing if
-  // cancelling/unsubscribing at a later stage would have no effect.
+  // Identifier for an active subscription. This is intentionally a distinct
+  // type from PermissionControllerDelegate::SubscriptionId as the concrete
+  // identifier values may be different.
+  using SubscriptionId = util::IdType64<PermissionController>;
+
+  // Constant returned when requesting a permission if cancelling at a later
+  // stage would have no effect.
   static const int kNoPendingOperation = -1;
 
   ~PermissionController() override {}
@@ -48,4 +54,17 @@
 
 }  // namespace content
 
+namespace std {
+
+template <>
+struct hash<content::PermissionController::SubscriptionId> {
+  std::size_t operator()(
+      const content::PermissionController::SubscriptionId& v) const {
+    content::PermissionController::SubscriptionId::Hasher hasher;
+    return hasher(v);
+  }
+};
+
+}  // namespace std
+
 #endif  // CONTENT_PUBLIC_BROWSER_PERMISSION_CONTROLLER_H_
diff -Naur a/src/3rdparty/chromium/content/public/browser/web_contents.h b/src/3rdparty/chromium/content/public/browser/web_contents.h
--- a/src/3rdparty/chromium/content/public/browser/web_contents.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/public/browser/web_contents.h	2021-06-18 17:00:07.009966740 +0100
@@ -911,8 +911,9 @@
   // |bitmaps| will be empty on download failure.
   // |sizes| are the sizes in pixels of the bitmaps before they were resized due
   // to the max bitmap size passed to DownloadImage(). Each entry in the bitmaps
-  // vector corresponds to an entry in the sizes vector. If a bitmap was
-  // resized, there should be a single returned bitmap.
+  // vector corresponds to an entry in the sizes vector (both vector sizes are
+  // guaranteed to be equal). If a bitmap was resized, there should be a single
+  // returned bitmap.
   using ImageDownloadCallback =
       base::OnceCallback<void(int id,
                               int http_status_code,
diff -Naur a/src/3rdparty/chromium/content/renderer/loader/web_url_loader_impl.cc b/src/3rdparty/chromium/content/renderer/loader/web_url_loader_impl.cc
--- a/src/3rdparty/chromium/content/renderer/loader/web_url_loader_impl.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/renderer/loader/web_url_loader_impl.cc	2021-06-18 16:26:16.698769474 +0100
@@ -929,6 +929,7 @@
   response->SetWasFallbackRequiredByServiceWorker(
       head.was_fallback_required_by_service_worker);
   response->SetType(head.response_type);
+  response->SetPadding(head.padding);
   response->SetUrlListViaServiceWorker(head.url_list_via_service_worker);
   response->SetCacheStorageCacheName(
       head.service_worker_response_source ==
diff -Naur a/src/3rdparty/chromium/content/renderer/render_frame_impl.cc b/src/3rdparty/chromium/content/renderer/render_frame_impl.cc
--- a/src/3rdparty/chromium/content/renderer/render_frame_impl.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/content/renderer/render_frame_impl.cc	2021-06-18 16:26:16.699771206 +0100
@@ -3222,6 +3222,10 @@
     return;
   }
 
+  if (commit_params->origin_to_commit) {
+    commit_params->origin_to_commit->SetFullURL(GetOriginalRequestURL(frame_->GetDocumentLoader()));
+  }
+
   SetOldPageLifecycleStateFromNewPageCommitIfNeeded(
       commit_params->old_page_info.get());
 
diff -Naur a/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.cc b/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.cc
--- a/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.cc	2021-06-18 16:26:16.699771206 +0100
@@ -83,20 +83,21 @@
       permission, url::Origin::Create(requesting_origin));
 }
 
-int WebEnginePermissionDelegate::SubscribePermissionStatusChange(
+WebEnginePermissionDelegate::SubscriptionId
+WebEnginePermissionDelegate::SubscribePermissionStatusChange(
     content::PermissionType permission,
     content::RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
     base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) {
   // TODO(crbug.com/1063094): Implement permission status subscription. It's
   // used in blink to emit PermissionStatus.onchange notifications.
-  NOTIMPLEMENTED() << ": " << static_cast<int>(permission);
-  return content::PermissionController::kNoPendingOperation;
+  NOTIMPLEMENTED_LOG_ONCE() << ": " << static_cast<int>(permission);
+  return SubscriptionId();
 }
 
 void WebEnginePermissionDelegate::UnsubscribePermissionStatusChange(
-    int subscription_id) {
+    SubscriptionId subscription_id) {
   // TODO(crbug.com/1063094): Implement permission status subscription. It's
   // used in blink to emit PermissionStatus.onchange notifications.
-  NOTREACHED();
+  NOTIMPLEMENTED_LOG_ONCE();
 }
diff -Naur a/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.h b/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.h
--- a/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/fuchsia/engine/browser/web_engine_permission_delegate.h	2021-06-18 16:26:16.699771206 +0100
@@ -45,13 +45,14 @@
       content::PermissionType permission,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin) override;
-  int SubscribePermissionStatusChange(
+  SubscriptionId SubscribePermissionStatusChange(
       content::PermissionType permission,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin,
       base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
       override;
-  void UnsubscribePermissionStatusChange(int subscription_id) override;
+  void UnsubscribePermissionStatusChange(
+      SubscriptionId subscription_id) override;
 };
 
 #endif  // FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_PERMISSION_DELEGATE_H_
diff -Naur a/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.cc b/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.cc
--- a/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.cc	2021-06-18 16:26:16.699771206 +0100
@@ -71,15 +71,16 @@
   return blink::mojom::PermissionStatus::ASK;
 }
 
-int HeadlessPermissionManager::SubscribePermissionStatusChange(
+HeadlessPermissionManager::SubscriptionId
+HeadlessPermissionManager::SubscribePermissionStatusChange(
     content::PermissionType permission,
     content::RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
     base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) {
-  return content::PermissionController::kNoPendingOperation;
+  return SubscriptionId();
 }
 
 void HeadlessPermissionManager::UnsubscribePermissionStatusChange(
-    int subscription_id) {}
+    SubscriptionId subscription_id) {}
 
 }  // namespace headless
diff -Naur a/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.h b/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.h
--- a/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/headless/lib/browser/headless_permission_manager.h	2021-06-18 16:26:16.699771206 +0100
@@ -46,13 +46,14 @@
       content::PermissionType permission,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin) override;
-  int SubscribePermissionStatusChange(
+  SubscriptionId SubscribePermissionStatusChange(
       content::PermissionType permission,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin,
       base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
       override;
-  void UnsubscribePermissionStatusChange(int subscription_id) override;
+  void UnsubscribePermissionStatusChange(
+      SubscriptionId subscription_id) override;
 
  private:
   content::BrowserContext* browser_context_;
diff -Naur a/src/3rdparty/chromium/media/base/media_switches.cc b/src/3rdparty/chromium/media/base/media_switches.cc
--- a/src/3rdparty/chromium/media/base/media_switches.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/media/base/media_switches.cc	2021-06-18 16:57:16.392908720 +0100
@@ -730,15 +730,15 @@
 
 // Enables Media Feeds to allow sites to provide specific recommendations for
 // users.
-const base::Feature kMediaFeeds{"MediaFeeds", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kMediaFeeds{"MediaFeeds", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enables fetching Media Feeds periodically in the background.
 const base::Feature kMediaFeedsBackgroundFetching{
-    "MediaFeedsBackgroundFetching", base::FEATURE_ENABLED_BY_DEFAULT};
+    "MediaFeedsBackgroundFetching", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enables checking Media Feeds against safe search to prevent adult content.
 const base::Feature kMediaFeedsSafeSearch{"MediaFeedsSafeSearch",
-                                          base::FEATURE_ENABLED_BY_DEFAULT};
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Send events to devtools rather than to chrome://media-internals
 const base::Feature kMediaInspectorLogging{"MediaInspectorLogging",
diff -Naur a/src/3rdparty/chromium/mojo/core/node_channel.cc b/src/3rdparty/chromium/mojo/core/node_channel.cc
--- a/src/3rdparty/chromium/mojo/core/node_channel.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/mojo/core/node_channel.cc	2021-06-18 16:26:16.699771206 +0100
@@ -191,13 +191,16 @@
 }
 
 // static
-void NodeChannel::GetEventMessageData(Channel::Message* message,
+bool NodeChannel::GetEventMessageData(Channel::Message& message,
                                       void** data,
                                       size_t* num_data_bytes) {
-  // NOTE: OnChannelMessage guarantees that we never accept a Channel::Message
-  // with a payload of fewer than |sizeof(Header)| bytes.
-  *data = reinterpret_cast<Header*>(message->mutable_payload()) + 1;
-  *num_data_bytes = message->payload_size() - sizeof(Header);
+  // NOTE: Callers must guarantee that the payload in `message` must be at least
+  // large enough to hold a Header.
+  if (message.payload_size() < sizeof(Header))
+    return false;
+  *data = reinterpret_cast<Header*>(message.mutable_payload()) + 1;
+  *num_data_bytes = message.payload_size() - sizeof(Header);
+  return true;
 }
 
 void NodeChannel::Start() {
diff -Naur a/src/3rdparty/chromium/mojo/core/node_channel.h b/src/3rdparty/chromium/mojo/core/node_channel.h
--- a/src/3rdparty/chromium/mojo/core/node_channel.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/mojo/core/node_channel.h	2021-06-18 16:26:16.699771206 +0100
@@ -90,7 +90,9 @@
                                                 void** payload,
                                                 size_t num_handles);
 
-  static void GetEventMessageData(Channel::Message* message,
+  // Retrieves address and size of an Event message's underlying message data.
+  // Returns `false` if the message is not a valid Event message.
+  static bool GetEventMessageData(Channel::Message& message,
                                   void** data,
                                   size_t* num_data_bytes);
 
diff -Naur a/src/3rdparty/chromium/mojo/core/node_controller.cc b/src/3rdparty/chromium/mojo/core/node_controller.cc
--- a/src/3rdparty/chromium/mojo/core/node_controller.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/mojo/core/node_controller.cc	2021-06-18 16:26:16.699771206 +0100
@@ -76,7 +76,9 @@
     Channel::MessagePtr channel_message) {
   void* data;
   size_t size;
-  NodeChannel::GetEventMessageData(channel_message.get(), &data, &size);
+  bool valid = NodeChannel::GetEventMessageData(*channel_message, &data, &size);
+  if (!valid)
+    return nullptr;
   auto event = ports::Event::Deserialize(data, size);
   if (!event)
     return nullptr;
@@ -943,7 +945,11 @@
 void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
                                           const ports::NodeName& broker_name,
                                           PlatformHandle broker_channel) {
-  DCHECK(!GetConfiguration().is_broker_process);
+  if (GetConfiguration().is_broker_process) {
+    // The broker should never receive this message from anyone.
+    DropPeer(from_node, nullptr);
+    return;
+  }
 
   // This node should already have an inviter in bootstrap mode.
   ports::NodeName inviter_name;
@@ -954,8 +960,13 @@
     inviter = bootstrap_inviter_channel_;
     bootstrap_inviter_channel_ = nullptr;
   }
-  DCHECK(inviter_name == from_node);
-  DCHECK(inviter);
+
+  if (inviter_name != from_node || !inviter ||
+      broker_name == ports::kInvalidNodeName) {
+    // We are not expecting this message. Assume the source is hostile.
+    DropPeer(from_node, nullptr);
+    return;
+  }
 
   base::queue<ports::NodeName> pending_broker_clients;
   std::unordered_map<ports::NodeName, OutgoingMessageQueue>
@@ -966,22 +977,22 @@
     std::swap(pending_broker_clients, pending_broker_clients_);
     std::swap(pending_relay_messages, pending_relay_messages_);
   }
-  DCHECK(broker_name != ports::kInvalidNodeName);
 
   // It's now possible to add both the broker and the inviter as peers.
   // Note that the broker and inviter may be the same node.
   scoped_refptr<NodeChannel> broker;
   if (broker_name == inviter_name) {
-    DCHECK(!broker_channel.is_valid());
     broker = inviter;
-  } else {
-    DCHECK(broker_channel.is_valid());
+  } else if (broker_channel.is_valid()) {
     broker = NodeChannel::Create(
         this,
         ConnectionParams(PlatformChannelEndpoint(std::move(broker_channel))),
         Channel::HandlePolicy::kAcceptHandles, io_task_runner_,
         ProcessErrorCallback());
     AddPeer(broker_name, broker, true /* start_channel */);
+  } else {
+    DropPeer(from_node, nullptr);
+    return;
   }
 
   AddPeer(inviter_name, inviter, false /* start_channel */);
diff -Naur a/src/3rdparty/chromium/mojo/core/user_message_impl.cc b/src/3rdparty/chromium/mojo/core/user_message_impl.cc
--- a/src/3rdparty/chromium/mojo/core/user_message_impl.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/mojo/core/user_message_impl.cc	2021-06-18 16:26:16.700772938 +0100
@@ -417,7 +417,14 @@
   if (channel_message) {
     void* data;
     size_t size;
-    NodeChannel::GetEventMessageData(channel_message.get(), &data, &size);
+    // The `channel_message` must either be produced locally or must have
+    // already been validated by the caller, as is done for example by
+    // NodeController::DeserializeEventMessage before
+    // NodeController::OnBroadcast re-serializes each copy of the message it
+    // received.
+    bool result =
+        NodeChannel::GetEventMessageData(*channel_message, &data, &size);
+    DCHECK(result);
     message_event->Serialize(data);
   }
 
diff -Naur a/src/3rdparty/chromium/mojo/public/cpp/bindings/receiver_set.h b/src/3rdparty/chromium/mojo/public/cpp/bindings/receiver_set.h
--- a/src/3rdparty/chromium/mojo/public/cpp/bindings/receiver_set.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/mojo/public/cpp/bindings/receiver_set.h	2021-06-18 16:26:16.700772938 +0100
@@ -24,7 +24,7 @@
 
 namespace mojo {
 
-using ReceiverId = size_t;
+using ReceiverId = uint64_t;
 
 template <typename ReceiverType>
 struct ReceiverSetTraits;
@@ -361,11 +361,11 @@
                      Context context,
                      scoped_refptr<base::SequencedTaskRunner> task_runner) {
     ReceiverId id = next_receiver_id_++;
-    DCHECK_GE(next_receiver_id_, 0u);
     auto entry =
         std::make_unique<Entry>(std::move(impl), std::move(receiver), this, id,
                                 std::move(context), std::move(task_runner));
-    receivers_.insert(std::make_pair(id, std::move(entry)));
+    auto result = receivers_.insert(std::make_pair(id, std::move(entry)));
+    CHECK(result.second) << "ReceiverId overflow with collision";
     return id;
   }
 
diff -Naur a/src/3rdparty/chromium/net/cert/crl_set.cc b/src/3rdparty/chromium/net/cert/crl_set.cc
--- a/src/3rdparty/chromium/net/cert/crl_set.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/net/cert/crl_set.cc	2021-06-18 16:56:44.881414344 +0100
@@ -312,7 +312,7 @@
 
 CRLSet::Result CRLSet::CheckSPKI(const base::StringPiece& spki_hash) const {
   if (std::binary_search(blocked_spkis_.begin(), blocked_spkis_.end(),
-                         spki_hash))
+                         spki_hash.data()))
     return REVOKED;
   return GOOD;
 }
diff -Naur a/src/3rdparty/chromium/net/cookies/site_for_cookies.cc b/src/3rdparty/chromium/net/cookies/site_for_cookies.cc
--- a/src/3rdparty/chromium/net/cookies/site_for_cookies.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/net/cookies/site_for_cookies.cc	2021-06-18 16:26:16.700772938 +0100
@@ -37,6 +37,7 @@
 bool SiteForCookies::FromWire(const std::string& scheme,
                               const std::string& registrable_domain,
                               bool schemefully_same,
+                              GURL first_party_url,
                               SiteForCookies* out) {
   // Make sure scheme meets precondition of methods like
   // GURL::SchemeIsCryptographic.
@@ -45,6 +46,8 @@
 
   // registrable_domain_ should also be canonicalized.
   SiteForCookies candidate(scheme, registrable_domain);
+  candidate.first_party_url_ = first_party_url;
+
   if (registrable_domain != candidate.registrable_domain_)
     return false;
 
@@ -60,7 +63,12 @@
   if (origin.opaque())
     return SiteForCookies();
 
-  return SiteForCookies(origin.scheme(), origin.host());
+  SiteForCookies site_for_cookies = SiteForCookies(origin.scheme(), origin.host());
+  if (!origin.GetFullURL().is_empty())
+    site_for_cookies.first_party_url_ = origin.GetFullURL();
+  else
+    site_for_cookies.first_party_url_ = origin.GetURL();
+  return site_for_cookies;
 }
 
 // static
@@ -191,4 +199,11 @@
   return registrable_domain_ == other_registrable_domain;
 }
 
+GURL SiteForCookies::first_party_url() const {
+  if (first_party_url_.is_empty())
+    return RepresentativeUrl();
+
+  return first_party_url_;
+}
+
 }  // namespace net
diff -Naur a/src/3rdparty/chromium/net/cookies/site_for_cookies.h b/src/3rdparty/chromium/net/cookies/site_for_cookies.h
--- a/src/3rdparty/chromium/net/cookies/site_for_cookies.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/net/cookies/site_for_cookies.h	2021-06-18 16:26:16.700772938 +0100
@@ -52,6 +52,7 @@
   static bool FromWire(const std::string& scheme,
                        const std::string& registrable_domain,
                        bool schemefully_same,
+                       GURL first_party_url,
                        SiteForCookies* out);
 
   // If the origin is opaque, returns SiteForCookies that matches nothing.
@@ -112,6 +113,8 @@
 
   const std::string& registrable_domain() const { return registrable_domain_; }
 
+  GURL first_party_url() const;
+
   // Used for serialization/deserialization. This value is irrelevant if
   // IsNull() is true.
   bool schemefully_same() const { return schemefully_same_; }
@@ -162,6 +165,8 @@
   // irrelevant (For tests this value can also be modified by
   // SetSchemefullySameForTesting()).
   bool schemefully_same_;
+
+  GURL first_party_url_;
 };
 
 }  // namespace net
diff -Naur a/src/3rdparty/chromium/pdf/pdfium/pdfium_engine.cc b/src/3rdparty/chromium/pdf/pdfium/pdfium_engine.cc
--- a/src/3rdparty/chromium/pdf/pdfium/pdfium_engine.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/pdf/pdfium/pdfium_engine.cc	2021-06-18 16:26:16.700772938 +0100
@@ -1019,8 +1019,7 @@
       FPDF_ANNOTATION last_focused_annot = nullptr;
       FPDF_BOOL ret = FORM_GetFocusedAnnot(form(), &last_focused_page_,
                                            &last_focused_annot);
-      DCHECK(ret);
-      if (PageIndexInBounds(last_focused_page_) && last_focused_annot) {
+      if (ret && PageIndexInBounds(last_focused_page_) && last_focused_annot) {
         last_focused_annot_index_ = FPDFPage_GetAnnotIndex(
             pages_[last_focused_page_]->GetPage(), last_focused_annot);
       } else {
@@ -1041,8 +1040,8 @@
       break;
     }
     case FocusElementType::kPage: {
-      int page_index;
-      FPDF_ANNOTATION focused_annot;
+      int page_index = -1;
+      FPDF_ANNOTATION focused_annot = nullptr;
       FPDF_BOOL ret = FORM_GetFocusedAnnot(form(), &page_index, &focused_annot);
       DCHECK(ret);
 
@@ -3492,7 +3491,8 @@
                                 const gfx::Point& device_point,
                                 double* page_x,
                                 double* page_y) {
-  *page_x = *page_y = 0;
+  *page_x = 0;
+  *page_y = 0;
   float device_x = device_point.x();
   float device_y = device_point.y();
   int temp_x = static_cast<int>((device_x + position_.x()) / current_zoom_ -
diff -Naur a/src/3rdparty/chromium/pdf/pdfium/pdfium_page.cc b/src/3rdparty/chromium/pdf/pdfium/pdfium_page.cc
--- a/src/3rdparty/chromium/pdf/pdfium/pdfium_page.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/pdf/pdfium/pdfium_page.cc	2021-06-18 16:26:16.701774671 +0100
@@ -766,14 +766,15 @@
                                           LinkTarget* target) {
   if (!available_)
     return NONSELECTABLE_AREA;
+
   gfx::Point device_point = point - rect_.OffsetFromOrigin();
   double new_x;
   double new_y;
-  FPDF_BOOL ret =
-      FPDF_DeviceToPage(GetPage(), 0, 0, rect_.width(), rect_.height(),
-                        ToPDFiumRotation(orientation), device_point.x(),
-                        device_point.y(), &new_x, &new_y);
-  DCHECK(ret);
+  if (!FPDF_DeviceToPage(GetPage(), 0, 0, rect_.width(), rect_.height(),
+                         ToPDFiumRotation(orientation), device_point.x(),
+                         device_point.y(), &new_x, &new_y)) {
+    return NONSELECTABLE_AREA;
+  }
 
   // hit detection tolerance, in points.
   constexpr double kTolerance = 20.0;
@@ -1012,7 +1013,8 @@
       double top;
       double right;
       double bottom;
-      FPDFLink_GetRect(links.get(), i, j, &left, &top, &right, &bottom);
+      if (!FPDFLink_GetRect(links.get(), i, j, &left, &top, &right, &bottom))
+        continue;
       gfx::Rect rect = PageToScreen(gfx::Point(), 1.0, left, top, right, bottom,
                                     PageOrientation::kOriginal);
       if (rect.IsEmpty())
@@ -1095,9 +1097,9 @@
     float top;
     float right;
     float bottom;
-    FPDF_BOOL ret =
-        FPDFPageObj_GetBounds(page_object, &left, &bottom, &right, &top);
-    DCHECK(ret);
+    if (!FPDFPageObj_GetBounds(page_object, &left, &bottom, &right, &top))
+      continue;
+
     Image image;
     image.bounding_rect = PageToScreen(gfx::Point(), 1.0, left, top, right,
                                        bottom, PageOrientation::kOriginal);
diff -Naur a/src/3rdparty/chromium/services/network/public/cpp/net_ipc_param_traits.cc b/src/3rdparty/chromium/services/network/public/cpp/net_ipc_param_traits.cc
--- a/src/3rdparty/chromium/services/network/public/cpp/net_ipc_param_traits.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/services/network/public/cpp/net_ipc_param_traits.cc	2021-06-18 16:26:16.701774671 +0100
@@ -572,20 +572,23 @@
   WriteParam(m, p.scheme());
   WriteParam(m, p.registrable_domain());
   WriteParam(m, p.schemefully_same());
+  WriteParam(m, p.first_party_url().spec());
 }
 
 bool ParamTraits<net::SiteForCookies>::Read(const base::Pickle* m,
                                             base::PickleIterator* iter,
                                             param_type* r) {
-  std::string scheme, registrable_domain;
+  std::string scheme, registrable_domain, first_party_url;
   bool schemefully_same;
   if (!ReadParam(m, iter, &scheme) ||
       !ReadParam(m, iter, &registrable_domain) ||
-      !ReadParam(m, iter, &schemefully_same))
+      !ReadParam(m, iter, &schemefully_same) ||
+      !ReadParam(m, iter, &first_party_url))
     return false;
 
   return net::SiteForCookies::FromWire(scheme, registrable_domain,
-                                       schemefully_same, r);
+                                       schemefully_same,
+                                       GURL(first_party_url), r);
 }
 
 void ParamTraits<net::SiteForCookies>::Log(const param_type& p,
diff -Naur a/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc b/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc
--- a/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc	2021-06-18 16:26:16.701774671 +0100
@@ -11,7 +11,7 @@
 bool StructTraits<network::mojom::SiteForCookiesDataView, net::SiteForCookies>::
     Read(network::mojom::SiteForCookiesDataView data,
          net::SiteForCookies* out) {
-  std::string scheme, registrable_domain;
+  std::string scheme, registrable_domain, first_party_url;
   if (!data.ReadScheme(&scheme)) {
     return false;
   }
@@ -19,8 +19,13 @@
     return false;
   }
 
+  if (!data.ReadFirstPartyUrl(&first_party_url)) {
+    return false;
+  }
+
   bool result = net::SiteForCookies::FromWire(scheme, registrable_domain,
-                                              data.schemefully_same(), out);
+                                              data.schemefully_same(),
+                                              GURL(first_party_url), out);
   if (!result) {
     network::debug::SetDeserializationCrashKeyString("site_for_cookie");
   }
diff -Naur a/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h b/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h
--- a/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.h	2021-06-18 16:26:16.701774671 +0100
@@ -29,6 +29,11 @@
     return input.schemefully_same();
   }
 
+  static std::string first_party_url(
+      const net::SiteForCookies& input) {
+    return input.first_party_url().spec();
+  }
+
   static bool Read(network::mojom::SiteForCookiesDataView data,
                    net::SiteForCookies* out);
 };
diff -Naur a/src/3rdparty/chromium/services/network/public/mojom/site_for_cookies.mojom b/src/3rdparty/chromium/services/network/public/mojom/site_for_cookies.mojom
--- a/src/3rdparty/chromium/services/network/public/mojom/site_for_cookies.mojom	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/services/network/public/mojom/site_for_cookies.mojom	2021-06-18 16:26:16.701774671 +0100
@@ -11,4 +11,5 @@
   string scheme;
   string registrable_domain;
   bool schemefully_same;
+  string first_party_url;
 };
diff -Naur a/src/3rdparty/chromium/services/network/public/mojom/url_response_head.mojom b/src/3rdparty/chromium/services/network/public/mojom/url_response_head.mojom
--- a/src/3rdparty/chromium/services/network/public/mojom/url_response_head.mojom	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/services/network/public/mojom/url_response_head.mojom	2021-06-18 16:26:16.701774671 +0100
@@ -134,6 +134,12 @@
   // https://fetch.spec.whatwg.org/#concept-response-type
   FetchResponseType response_type = FetchResponseType.kDefault;
 
+  // Pre-computed padding.  This should only be non-zero when |response_type|
+  // is set to kOpaque.  Note, this is not set by network service, but will be
+  // populated if the response was provided by a service worker FetchEvent
+  // handler.
+  int64 padding = 0;
+
   // The cache name of the CacheStorage from where the response is served via
   // the ServiceWorker. Empty if the response isn't from the CacheStorage.
   string cache_storage_cache_name;
diff -Naur a/src/3rdparty/chromium/storage/browser/BUILD.gn b/src/3rdparty/chromium/storage/browser/BUILD.gn
--- a/src/3rdparty/chromium/storage/browser/BUILD.gn	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/storage/browser/BUILD.gn	2021-06-18 16:26:16.701774671 +0100
@@ -183,8 +183,6 @@
     "file_system/watcher_manager.h",
     "quota/client_usage_tracker.cc",
     "quota/client_usage_tracker.h",
-    "quota/padding_key.cc",
-    "quota/padding_key.h",
     "quota/quota_callbacks.h",
     "quota/quota_client.h",
     "quota/quota_client_type.cc",
diff -Naur a/src/3rdparty/chromium/storage/browser/quota/padding_key.cc b/src/3rdparty/chromium/storage/browser/quota/padding_key.cc
--- a/src/3rdparty/chromium/storage/browser/quota/padding_key.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/storage/browser/quota/padding_key.cc	1970-01-01 01:00:00.000000000 +0100
@@ -1,87 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "storage/browser/quota/padding_key.h"
-
-#include <cstdint>
-#include <vector>
-
-#include "base/no_destructor.h"
-#include "crypto/hmac.h"
-#include "net/http/http_request_headers.h"
-
-using crypto::SymmetricKey;
-
-namespace storage {
-
-namespace {
-
-const SymmetricKey::Algorithm kPaddingKeyAlgorithm = SymmetricKey::AES;
-
-// The range of the padding added to response sizes for opaque resources.
-// Increment the CacheStorage padding version if changed.
-constexpr uint64_t kPaddingRange = 14431 * 1024;
-
-std::unique_ptr<SymmetricKey>* GetPaddingKeyInternal() {
-  static base::NoDestructor<std::unique_ptr<SymmetricKey>> s_padding_key([] {
-    return SymmetricKey::GenerateRandomKey(kPaddingKeyAlgorithm, 128);
-  }());
-  return s_padding_key.get();
-}
-
-}  // namespace
-
-const SymmetricKey* GetDefaultPaddingKey() {
-  return GetPaddingKeyInternal()->get();
-}
-
-std::unique_ptr<SymmetricKey> CopyDefaultPaddingKey() {
-  return SymmetricKey::Import(kPaddingKeyAlgorithm,
-                              (*GetPaddingKeyInternal())->key());
-}
-
-std::unique_ptr<SymmetricKey> DeserializePaddingKey(
-    const std::string& raw_key) {
-  return SymmetricKey::Import(kPaddingKeyAlgorithm, raw_key);
-}
-
-std::string SerializeDefaultPaddingKey() {
-  return (*GetPaddingKeyInternal())->key();
-}
-
-void ResetPaddingKeyForTesting() {
-  *GetPaddingKeyInternal() =
-      SymmetricKey::GenerateRandomKey(kPaddingKeyAlgorithm, 128);
-}
-
-int64_t ComputeResponsePadding(const std::string& response_url,
-                               const crypto::SymmetricKey* padding_key,
-                               bool has_metadata,
-                               bool loaded_with_credentials,
-                               const std::string& request_method) {
-  DCHECK(!response_url.empty());
-
-  crypto::HMAC hmac(crypto::HMAC::SHA256);
-  CHECK(hmac.Init(padding_key));
-
-  std::string key = response_url;
-  if (has_metadata)
-    key += "METADATA";
-  if (loaded_with_credentials)
-    key += "CREDENTIALED";
-
-  // It should only be possible to have a CORS safelisted method here since
-  // the spec does not permit other methods for no-cors requests.
-  DCHECK(request_method == net::HttpRequestHeaders::kGetMethod ||
-         request_method == net::HttpRequestHeaders::kHeadMethod ||
-         request_method == net::HttpRequestHeaders::kPostMethod);
-  key += request_method;
-
-  uint64_t digest_start;
-  CHECK(hmac.Sign(key, reinterpret_cast<uint8_t*>(&digest_start),
-                  sizeof(digest_start)));
-  return digest_start % kPaddingRange;
-}
-
-}  // namespace storage
diff -Naur a/src/3rdparty/chromium/storage/browser/quota/padding_key.h b/src/3rdparty/chromium/storage/browser/quota/padding_key.h
--- a/src/3rdparty/chromium/storage/browser/quota/padding_key.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/storage/browser/quota/padding_key.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,70 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef STORAGE_BROWSER_QUOTA_PADDING_KEY_H_
-#define STORAGE_BROWSER_QUOTA_PADDING_KEY_H_
-
-#include <memory>
-#include <string>
-
-#include "base/component_export.h"
-#include "crypto/symmetric_key.h"
-#include "url/gurl.h"
-
-namespace storage {
-
-COMPONENT_EXPORT(STORAGE_BROWSER)
-const crypto::SymmetricKey* GetDefaultPaddingKey();
-
-// Returns a copy of the default key used to calculate padding sizes.
-//
-// The default padding key is a singleton object whose value is randomly
-// generated the first time it is requested on every browser startup. In
-// CacheStorage, when a cache does not have a padding key, it is assigned the
-// current default key.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-std::unique_ptr<crypto::SymmetricKey> CopyDefaultPaddingKey();
-
-// Builds a key whose value is the given string.
-//
-// May return null if deserializing fails (e.g. if the raw key is the wrong
-// size).
-COMPONENT_EXPORT(STORAGE_BROWSER)
-std::unique_ptr<crypto::SymmetricKey> DeserializePaddingKey(
-    const std::string& raw_key);
-
-// Gets the raw value of the default padding key.
-//
-// Each cache stores the raw value of the key that should be used when
-// calculating its padding size.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-std::string SerializeDefaultPaddingKey();
-
-// Resets the default key to a random value.
-//
-// Simulating a key change across a browser restart lets us test that padding
-// calculations are using the appropriate key.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-void ResetPaddingKeyForTesting();
-
-// Computes the padding size for a resource.
-//
-// For AppCache, which does not support storing metadata for a resource,
-// |has_metadata| will always be false.
-//
-// For CacheStorage, the padding size of an entry depends on whether it contains
-// metadata (a.k.a. "side data") and if the response was loaded with
-// credentials. If metadata is added to the entry, the entry must be assigned a
-// new padding size. Otherwise, the growth in the entry's size would leak the
-// exact size of the added metadata.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-int64_t ComputeResponsePadding(const std::string& response_url,
-                               const crypto::SymmetricKey* padding_key,
-                               bool has_metadata,
-                               bool loaded_with_credentials,
-                               const std::string& request_method);
-
-}  // namespace storage
-
-#endif  // STORAGE_BROWSER_QUOTA_PADDING_KEY_H_
diff -Naur a/src/3rdparty/chromium/storage/common/BUILD.gn b/src/3rdparty/chromium/storage/common/BUILD.gn
--- a/src/3rdparty/chromium/storage/common/BUILD.gn	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/storage/common/BUILD.gn	2021-06-18 16:26:16.701774671 +0100
@@ -17,6 +17,8 @@
     "file_system/file_system_types.h",
     "file_system/file_system_util.cc",
     "file_system/file_system_util.h",
+    "quota/padding_key.cc",
+    "quota/padding_key.h",
   ]
 
   # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
diff -Naur a/src/3rdparty/chromium/storage/common/quota/padding_key.cc b/src/3rdparty/chromium/storage/common/quota/padding_key.cc
--- a/src/3rdparty/chromium/storage/common/quota/padding_key.cc	1970-01-01 01:00:00.000000000 +0100
+++ b/src/3rdparty/chromium/storage/common/quota/padding_key.cc	2021-06-18 16:26:16.702776403 +0100
@@ -0,0 +1,146 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/common/quota/padding_key.h"
+
+#include <inttypes.h>
+#include <cstdint>
+#include <vector>
+#include "base/no_destructor.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "crypto/hmac.h"
+#include "crypto/random.h"
+#include "crypto/symmetric_key.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
+#include "net/http/http_request_headers.h"
+#include "services/network/public/mojom/url_response_head.mojom-shared.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+#include "url/url_canon.h"
+#include "url/url_constants.h"
+#include "url/url_util.h"
+
+using crypto::SymmetricKey;
+
+namespace storage {
+
+namespace {
+
+const SymmetricKey::Algorithm kPaddingKeyAlgorithm = SymmetricKey::AES;
+
+// The range of the padding added to response sizes for opaque resources.
+// Increment the CacheStorage padding version if changed.
+constexpr uint64_t kPaddingRange = 14431 * 1024;
+
+std::unique_ptr<SymmetricKey>* GetPaddingKeyInternal() {
+  static base::NoDestructor<std::unique_ptr<SymmetricKey>> s_padding_key([] {
+    return SymmetricKey::GenerateRandomKey(kPaddingKeyAlgorithm, 128);
+  }());
+  return s_padding_key.get();
+}
+
+static bool IsStandardSchemeWithNetworkHost(base::StringPiece scheme) {
+  // file scheme is special. Windows file share origins can have network hosts.
+  if (scheme == url::kFileScheme)
+    return true;
+
+  url::SchemeType scheme_type;
+  if (!url::GetStandardSchemeType(
+          scheme.data(), url::Component(0, scheme.length()), &scheme_type)) {
+    return false;
+  }
+  return scheme_type == url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION ||
+         scheme_type == url::SCHEME_WITH_HOST_AND_PORT;
+}
+
+
+static url::Origin SchemefuleSiteReplacement(
+    const url::Origin& origin) {
+  // 1. If origin is an opaque origin, then return origin.
+  if (origin.opaque())
+    return origin;
+
+  std::string registerable_domain;
+
+  // Non-normative step.
+  // We only lookup the registerable domain for schemes with network hosts, this
+  // is non-normative. Other schemes for non-opaque origins do not
+  // meaningfully have a registerable domain for their host, so they are
+  // skipped.
+  if (IsStandardSchemeWithNetworkHost(origin.scheme())) {
+    registerable_domain = GetDomainAndRegistry(
+        origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+  }
+
+  // If origin's host's registrable domain is null, then return (origin's
+  // scheme, origin's host).
+  //
+  // `GetDomainAndRegistry()` returns an empty string for IP literals and
+  // effective TLDs.
+  //
+  // Note that `registerable_domain` could still end up empty, since the
+  // `origin` might have a scheme that permits empty hostnames, such as "file".
+  bool used_registerable_domain = !registerable_domain.empty();
+  if (!used_registerable_domain)
+    registerable_domain = origin.host();
+
+  int port = url::DefaultPortForScheme(origin.scheme().c_str(),
+                                       origin.scheme().length());
+
+  // Provide a default port of 0 for non-standard schemes.
+  if (port == url::PORT_UNSPECIFIED)
+    port = 0;
+
+  return url::Origin::CreateFromNormalizedTuple(origin.scheme(),
+                                                     registerable_domain, port);
+}
+
+}  // namespace
+
+bool ShouldPadResponseType(network::mojom::FetchResponseType type) {
+  return type == network::mojom::FetchResponseType::kOpaque ||
+         type == network::mojom::FetchResponseType::kOpaqueRedirect;
+}
+
+int64_t ComputeRandomResponsePadding() {
+  uint64_t raw_random = 0;
+  crypto::RandBytes(&raw_random, sizeof(uint64_t));
+  return raw_random % kPaddingRange;
+}
+
+int64_t ComputeStableResponsePadding(const url::Origin& origin,
+                                     const std::string& response_url,
+                                     const base::Time& response_time,
+                                     const std::string& request_method,
+                                     int64_t side_data_size) {
+  DCHECK(!response_url.empty());
+
+  url::Origin site = SchemefuleSiteReplacement(origin);
+
+  DCHECK_GT(response_time, base::Time::UnixEpoch());
+  int64_t microseconds =
+      (response_time - base::Time::UnixEpoch()).InMicroseconds();
+
+  // It should only be possible to have a CORS safelisted method here since
+  // the spec does not permit other methods for no-cors requests.
+  DCHECK(request_method == net::HttpRequestHeaders::kGetMethod ||
+         request_method == net::HttpRequestHeaders::kHeadMethod ||
+         request_method == net::HttpRequestHeaders::kPostMethod);
+
+  std::string key = base::StringPrintf(
+      "%s-%" PRId64 "-%s-%s-%" PRId64, response_url.c_str(), microseconds,
+      site.Serialize().c_str(), request_method.c_str(), side_data_size);
+
+  crypto::HMAC hmac(crypto::HMAC::SHA256);
+  CHECK(hmac.Init(GetPaddingKeyInternal()->get()));
+
+  uint64_t digest_start = 0;
+  CHECK(hmac.Sign(key, reinterpret_cast<uint8_t*>(&digest_start),
+                  sizeof(digest_start)));
+  return digest_start % kPaddingRange;
+}
+
+}  // namespace storage
diff -Naur a/src/3rdparty/chromium/storage/common/quota/padding_key.h b/src/3rdparty/chromium/storage/common/quota/padding_key.h
--- a/src/3rdparty/chromium/storage/common/quota/padding_key.h	1970-01-01 01:00:00.000000000 +0100
+++ b/src/3rdparty/chromium/storage/common/quota/padding_key.h	2021-06-18 16:26:16.702776403 +0100
@@ -0,0 +1,51 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef STORAGE_COMMON_QUOTA_PADDING_KEY_H_
+#define STORAGE_COMMON_QUOTA_PADDING_KEY_H_
+
+#include <memory>
+#include <string>
+
+#include "base/component_export.h"
+#include "services/network/public/mojom/url_response_head.mojom-shared.h"
+#include "url/gurl.h"
+
+namespace base {
+class Time;
+}  // namespace base
+
+namespace url {
+class Origin;
+}  // namespace url
+
+namespace storage {
+
+// Utility method to determine if a given type of response should be padded.
+COMPONENT_EXPORT(STORAGE_COMMON)
+bool ShouldPadResponseType(network::mojom::FetchResponseType type);
+
+// Compute a purely random padding size for a resource.  A random padding is
+// preferred except in cases where a site could rapidly trigger a large number
+// of padded values for the same resource; e.g. from http cache.
+COMPONENT_EXPORT(STORAGE_COMMON)
+int64_t ComputeRandomResponsePadding();
+
+// Compute a stable padding value for a resource.  This should be used for
+// cases where a site could trigger a large number of padding values to be
+// generated for the same resource; e.g. http cache.  The |origin| is the
+// origin of the context that loaded the resource.  Note, its important that the
+// |response_time| be the time stored in the cache and not just the current
+// time.  The |side_data_size| should only be passed if padding is being
+// computed for a side data blob.
+COMPONENT_EXPORT(STORAGE_COMMON)
+int64_t ComputeStableResponsePadding(const url::Origin& origin,
+                                     const std::string& response_url,
+                                     const base::Time& response_time,
+                                     const std::string& request_method,
+                                     int64_t side_data_size = 0);
+
+}  // namespace storage
+
+#endif  // STORAGE_COMMON_QUOTA_PADDING_KEY_H_
diff -Naur a/src/3rdparty/chromium/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc b/src/3rdparty/chromium/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc
--- a/src/3rdparty/chromium/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc	2021-06-18 16:55:44.249560701 +0100
@@ -37,6 +37,7 @@
 
 #include <algorithm>
 #include <array>
+#include <limits>
 #include "absl/base/internal/hide_ptr.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
diff -Naur a/src/3rdparty/chromium/third_party/angle/src/libANGLE/angletypes.h b/src/3rdparty/chromium/third_party/angle/src/libANGLE/angletypes.h
--- a/src/3rdparty/chromium/third_party/angle/src/libANGLE/angletypes.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/angle/src/libANGLE/angletypes.h	2021-06-18 16:26:16.702776403 +0100
@@ -74,7 +74,7 @@
 bool operator==(const Rectangle &a, const Rectangle &b);
 bool operator!=(const Rectangle &a, const Rectangle &b);
 
-bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
+ANGLE_NO_DISCARD bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
 
 struct Offset
 {
diff -Naur a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
--- a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp	2021-06-18 16:26:16.702776403 +0100
@@ -141,7 +141,10 @@
                           uint8_t *destData)
 {
     gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
-    gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea);
+    if (!gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea))
+    {
+        return;
+    }
 
     // Determine if entire rows can be copied at once instead of each individual pixel. There
     // must be no out of bounds lookups, whole rows copies, and no scale.
diff -Naur a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
--- a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp	2021-06-18 16:26:16.702776403 +0100
@@ -1117,7 +1117,10 @@
         // If pixels lying outside the read framebuffer, adjust src region
         // and dst region to appropriate in-bounds regions respectively.
         gl::Rectangle realSourceRegion;
-        ClipRectangle(bounds.sourceRegion, bounds.sourceBounds, &realSourceRegion);
+        if (!ClipRectangle(bounds.sourceRegion, bounds.sourceBounds, &realSourceRegion))
+        {
+            return angle::Result::Stop;
+        }
         GLuint xOffset = realSourceRegion.x - bounds.sourceRegion.x;
         GLuint yOffset = realSourceRegion.y - bounds.sourceRegion.y;
 
diff -Naur a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/metal/ContextMtl.mm b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/metal/ContextMtl.mm
--- a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/metal/ContextMtl.mm	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/metal/ContextMtl.mm	2021-06-18 16:26:16.702776403 +0100
@@ -1362,7 +1362,10 @@
 
     // Clip the render area to the viewport.
     gl::Rectangle viewportClippedRenderArea;
-    gl::ClipRectangle(renderArea, glState.getViewport(), &viewportClippedRenderArea);
+    if (!gl::ClipRectangle(renderArea, glState.getViewport(), &viewportClippedRenderArea))
+    {
+        viewportClippedRenderArea = gl::Rectangle();
+    }
 
     gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false);
     if (framebufferMtl->flipY())
diff -Naur a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
--- a/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp	2021-06-18 16:26:16.703778136 +0100
@@ -2824,8 +2824,11 @@
 
     // Clip the render area to the viewport.
     gl::Rectangle viewportClippedRenderArea;
-    gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()),
-                      &viewportClippedRenderArea);
+    if (!gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()),
+                           &viewportClippedRenderArea))
+    {
+        viewportClippedRenderArea = gl::Rectangle();
+    }
 
     gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false);
     gl::Rectangle rotatedScissoredArea;
diff -Naur a/src/3rdparty/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom b/src/3rdparty/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom
--- a/src/3rdparty/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom	2021-06-18 16:26:16.703778136 +0100
@@ -36,6 +36,10 @@
   network.mojom.FetchResponseType response_type =
     network.mojom.FetchResponseType.kDefault;
 
+  // Pre-computed padding for this response.  This should only be non-zero
+  // for when |response_type| is kOpaque.
+  int64 padding = 0;
+
   // The source of this response, e.g. network, CacheStorage.
   network.mojom.FetchResponseSource response_source =
     network.mojom.FetchResponseSource.kUnspecified;
@@ -89,19 +93,6 @@
   // ALPN negotiated protocol of the socket which fetched this resource.
   string alpn_negotiated_protocol = "unknown";
 
-  // True if the response was loaded with a Request where the credentials mode
-  // would potentially send cookies to the server:
-  //
-  //  https://fetch.spec.whatwg.org/#requestcredentials
-  //
-  // For example, if RequestCredentials is 'include' this field will be true.
-  // If RequestCredentials is 'same-origin', but the Response was loaded
-  // cross-origin then this field will be false.
-  //
-  // This field may be true even if there were no cookies actually available
-  // to send.
-  bool loaded_with_credentials = false;
-
   // True if the response was originally loaded via a request fetched over a
   // SPDY channel.
   bool was_fetched_via_spdy = false;
diff -Naur a/src/3rdparty/chromium/third_party/blink/public/platform/web_url_response.h b/src/3rdparty/chromium/third_party/blink/public/platform/web_url_response.h
--- a/src/3rdparty/chromium/third_party/blink/public/platform/web_url_response.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/public/platform/web_url_response.h	2021-06-18 16:26:16.703778136 +0100
@@ -264,6 +264,12 @@
   BLINK_PLATFORM_EXPORT void SetType(network::mojom::FetchResponseType);
   BLINK_PLATFORM_EXPORT network::mojom::FetchResponseType GetType() const;
 
+  // Pre-computed padding.  This should only be non-zero if the type is
+  // kOpaque.  In addition, it is only set for responses provided by a
+  // service worker FetchEvent handler.
+  BLINK_PLATFORM_EXPORT void SetPadding(int64_t);
+  BLINK_PLATFORM_EXPORT int64_t GetPadding() const;
+
   // The URL list of the Response object the ServiceWorker passed to
   // respondWith(). See
   // network::ResourceResponseInfo::url_list_via_service_worker for details.
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc b/src/3rdparty/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc	2021-06-18 16:26:16.703778136 +0100
@@ -83,28 +83,22 @@
   DEFINE_STATIC_LOCAL(ApplicableTypesMap, all_applicable_types_map, ());
   DEFINE_STATIC_LOCAL(ApplicableTypesMap, composited_applicable_types_map, ());
 
-  ApplicableTypesMap& applicable_types_map =
-      allow_all_animations_ ? all_applicable_types_map
-                            : composited_applicable_types_map;
-
-  auto entry = applicable_types_map.find(property);
-  bool found_entry = entry != applicable_types_map.end();
-
   // Custom property interpolation types may change over time so don't trust the
-  // applicableTypesMap without checking the registry.
+  // applicable_types_map without checking the registry. Also since the static
+  // map is shared between documents, the registered type may be different in
+  // the different documents.
   if (registry_ && property.IsCSSCustomProperty()) {
-    const auto* registration = GetRegistration(registry_, property);
-    if (registration) {
-      if (found_entry) {
-        applicable_types_map.erase(entry);
-      }
+    if (const auto* registration = GetRegistration(registry_, property))
       return registration->GetInterpolationTypes();
-    }
   }
 
-  if (found_entry) {
+  ApplicableTypesMap& applicable_types_map =
+      allow_all_animations_ ? all_applicable_types_map
+                            : composited_applicable_types_map;
+
+  auto entry = applicable_types_map.find(property);
+  if (entry != applicable_types_map.end())
     return *entry->value;
-  }
 
   std::unique_ptr<InterpolationTypes> applicable_types =
       std::make_unique<InterpolationTypes>();
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/BUILD.gn b/src/3rdparty/chromium/third_party/blink/renderer/core/BUILD.gn
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/BUILD.gn	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/BUILD.gn	2021-06-18 16:26:16.703778136 +0100
@@ -199,6 +199,7 @@
   ]
   deps = [
     "//components/paint_preview/common",
+    "//storage/common",
     "//third_party/blink/public/common",
     "//third_party/blink/renderer/platform",
     "//third_party/blink/renderer/platform/wtf",
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/DEPS b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/DEPS
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/DEPS	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/DEPS	2021-06-18 16:26:16.704779868 +0100
@@ -9,6 +9,7 @@
     "+net/http/http_response_info.h",
     "+services/network/public/cpp",
     "+services/network/public/mojom",
+    "+storage/common/quota/padding_key.h",
     "+url/gurl.h",
 ]
 
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc	2021-06-18 16:26:16.704779868 +0100
@@ -423,16 +423,21 @@
   FetchResponseData* response_data = FetchResponseData::CreateWithBuffer(
       BodyStreamBuffer::Create(script_state, place_holder_body_, signal_));
 
-  response_data->InitFromResourceResponse(
-      url_list_, fetch_request_data_->Method(),
-      fetch_request_data_->Credentials(), tainting, response);
-
-  FetchResponseData* tainted_response = nullptr;
-
   DCHECK(!(network_utils::IsRedirectResponseCode(response_http_status_code_) &&
            HasNonEmptyLocationHeader(response_data->HeaderList()) &&
            fetch_request_data_->Redirect() != RedirectMode::kManual));
 
+  auto response_type = response.GetType();
+  if (network_utils::IsRedirectResponseCode(response_http_status_code_) &&
+      fetch_request_data_->Redirect() == RedirectMode::kManual)
+    response_type = network::mojom::FetchResponseType::kOpaqueRedirect;
+
+  response_data->InitFromResourceResponse(
+      execution_context_, response_type, url_list_,
+      fetch_request_data_->Method(), fetch_request_data_->Credentials(),
+      tainting, response);
+
+  FetchResponseData* tainted_response = nullptr;
   if (network_utils::IsRedirectResponseCode(response_http_status_code_) &&
       fetch_request_data_->Redirect() == RedirectMode::kManual) {
     tainted_response = response_data->CreateOpaqueRedirectFilteredResponse();
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc	2021-06-18 16:26:16.704779868 +0100
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
 
+#include "storage/common/quota/padding_key.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
 #include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
@@ -188,6 +189,7 @@
                                             ExceptionState& exception_state) {
   FetchResponseData* new_response = Create();
   new_response->type_ = type_;
+  new_response->padding_ = padding_;
   new_response->response_source_ = response_source_;
   if (termination_reason_) {
     new_response->termination_reason_ = std::make_unique<TerminationReason>();
@@ -204,7 +206,6 @@
   new_response->cors_exposed_header_names_ = cors_exposed_header_names_;
   new_response->connection_info_ = connection_info_;
   new_response->alpn_negotiated_protocol_ = alpn_negotiated_protocol_;
-  new_response->loaded_with_credentials_ = loaded_with_credentials_;
   new_response->was_fetched_via_spdy_ = was_fetched_via_spdy_;
   new_response->has_range_requested_ = has_range_requested_;
 
@@ -269,6 +270,7 @@
   response->status_code = status_;
   response->status_text = status_message_;
   response->response_type = type_;
+  response->padding = padding_;
   response->response_source = response_source_;
   response->mime_type = mime_type_;
   response->request_method = request_method_;
@@ -278,7 +280,6 @@
       HeaderSetToVector(cors_exposed_header_names_);
   response->connection_info = connection_info_;
   response->alpn_negotiated_protocol = alpn_negotiated_protocol_;
-  response->loaded_with_credentials = loaded_with_credentials_;
   response->was_fetched_via_spdy = was_fetched_via_spdy_;
   response->has_range_requested = has_range_requested_;
   for (const auto& header : HeaderList()->List())
@@ -289,6 +290,8 @@
 }
 
 void FetchResponseData::InitFromResourceResponse(
+    ExecutionContext* context,
+    network::mojom::FetchResponseType response_type,
     const Vector<KURL>& request_url_list,
     const AtomicString& request_method,
     network::mojom::CredentialsMode request_credentials,
@@ -339,14 +342,23 @@
 
   SetWasFetchedViaSpdy(response.WasFetchedViaSPDY());
 
-  // TODO(wanderview): Remove |tainting| and use |response.GetType()|
-  // instead once the OOR-CORS disabled path is removed.
-  SetLoadedWithCredentials(
-      request_credentials == network::mojom::CredentialsMode::kInclude ||
-      (request_credentials == network::mojom::CredentialsMode::kSameOrigin &&
-       tainting == FetchRequestData::kBasicTainting));
-
   SetHasRangeRequested(response.HasRangeRequested());
+
+  // Use the explicit padding in the response provided by a service worker
+  // or compute a new padding if necessary.
+  if (response.GetPadding()) {
+    SetPadding(response.GetPadding());
+  } else {
+    if (storage::ShouldPadResponseType(response_type)) {
+      int64_t padding = response.WasCached()
+                            ? storage::ComputeStableResponsePadding(
+                                  context->GetSecurityOrigin()->ToUrlOrigin(),
+                                  Url()->GetString().Utf8(), ResponseTime(),
+                                  request_method.Utf8())
+                            : storage::ComputeRandomResponsePadding();
+      SetPadding(padding);
+    }
+  }
 }
 
 FetchResponseData::FetchResponseData(Type type,
@@ -354,6 +366,7 @@
                                      uint16_t status,
                                      AtomicString status_message)
     : type_(type),
+      padding_(0),
       response_source_(source),
       status_(status),
       status_message_(status_message),
@@ -361,7 +374,6 @@
       response_time_(base::Time::Now()),
       connection_info_(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
       alpn_negotiated_protocol_("unknown"),
-      loaded_with_credentials_(false),
       was_fetched_via_spdy_(false),
       has_range_requested_(false) {}
 
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h	2021-06-18 16:26:16.704779868 +0100
@@ -85,6 +85,8 @@
   }
   bool HasRangeRequested() const { return has_range_requested_; }
 
+  int64_t GetPadding() const { return padding_; }
+  void SetPadding(int64_t padding) { padding_ = padding; }
   void SetResponseSource(network::mojom::FetchResponseSource response_source) {
     response_source_ = response_source;
   }
@@ -116,9 +118,6 @@
   void SetAlpnNegotiatedProtocol(AtomicString alpn_negotiated_protocol) {
     alpn_negotiated_protocol_ = alpn_negotiated_protocol;
   }
-  void SetLoadedWithCredentials(bool loaded_with_credentials) {
-    loaded_with_credentials_ = loaded_with_credentials;
-  }
   void SetWasFetchedViaSpdy(bool was_fetched_via_spdy) {
     was_fetched_via_spdy_ = was_fetched_via_spdy;
   }
@@ -138,6 +137,8 @@
 
   // Initialize non-body data from the given |response|.
   void InitFromResourceResponse(
+      ExecutionContext* context,
+      network::mojom::FetchResponseType response_type,
       const Vector<KURL>& request_url_list,
       const AtomicString& request_method,
       network::mojom::CredentialsMode request_credentials,
@@ -148,6 +149,7 @@
 
  private:
   network::mojom::FetchResponseType type_;
+  int64_t padding_;
   network::mojom::FetchResponseSource response_source_;
   std::unique_ptr<TerminationReason> termination_reason_;
   Vector<KURL> url_list_;
@@ -163,7 +165,6 @@
   HTTPHeaderSet cors_exposed_header_names_;
   net::HttpResponseInfo::ConnectionInfo connection_info_;
   AtomicString alpn_negotiated_protocol_;
-  bool loaded_with_credentials_;
   bool was_fetched_via_spdy_;
   bool has_range_requested_;
 
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/response.cc b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/response.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/response.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/fetch/response.cc	2021-06-18 16:26:16.704779868 +0100
@@ -374,6 +374,7 @@
   else
     response = FetchResponseData::CreateNetworkErrorResponse();
 
+  response->SetPadding(fetch_api_response.padding);
   response->SetResponseSource(fetch_api_response.response_source);
   response->SetURLList(fetch_api_response.url_list);
   response->SetStatus(fetch_api_response.status_code);
@@ -386,8 +387,6 @@
   response->SetConnectionInfo(fetch_api_response.connection_info);
   response->SetAlpnNegotiatedProtocol(
       WTF::AtomicString(fetch_api_response.alpn_negotiated_protocol));
-  response->SetLoadedWithCredentials(
-      fetch_api_response.loaded_with_credentials);
   response->SetWasFetchedViaSpdy(fetch_api_response.was_fetched_via_spdy);
   response->SetHasRangeRequested(fetch_api_response.has_range_requested);
 
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc b/src/3rdparty/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc	2021-06-18 16:59:41.375635559 +0100
@@ -335,7 +335,10 @@
   loading_state_ = kLoadingStateAborted;
 
   DCHECK_NE(kDone, state_);
-  state_ = kDone;
+  // Synchronously cancel the loader before dispatching events. This way we make
+  // sure the FileReader internal state stays consistent even if another load
+  // is started from one of the event handlers, or right after abort returns.
+  Terminate();
 
   base::AutoReset<bool> firing_events(&still_firing_events_, true);
 
@@ -347,15 +350,12 @@
       ThrottlingController::RemoveReader(GetExecutionContext(), this);
 
   FireEvent(event_type_names::kAbort);
+  // TODO(https://crbug.com/1204139): Only fire loadend event if no new load was
+  // started from the abort event handler.
   FireEvent(event_type_names::kLoadend);
 
   // All possible events have fired and we're done, no more pending activity.
   ThrottlingController::FinishReader(GetExecutionContext(), this, final_step);
-
-  // Also synchronously cancel the loader, as script might initiate a new load
-  // right after this method returns, in which case an async termination would
-  // terminate the wrong loader.
-  Terminate();
 }
 
 void FileReader::result(StringOrArrayBuffer& result_attribute) const {
@@ -428,6 +428,8 @@
       ThrottlingController::RemoveReader(GetExecutionContext(), this);
 
   FireEvent(event_type_names::kLoad);
+  // TODO(https://crbug.com/1204139): Only fire loadend event if no new load was
+  // started from the abort event handler.
   FireEvent(event_type_names::kLoadend);
 
   // All possible events have fired and we're done, no more pending activity.
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc b/src/3rdparty/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc	2021-06-18 16:26:16.704779868 +0100
@@ -2766,11 +2766,14 @@
         for (PaintLayerScrollableArea* area : *animating_scrollable_areas)
           area->UpdateCompositorScrollAnimations();
       }
-      frame_view.GetLayoutView()
-          ->GetDocument()
-          .GetDocumentAnimations()
-          .UpdateAnimations(DocumentLifecycle::kPaintClean,
-                            paint_artifact_compositor_.get());
+      {
+        ScriptForbiddenScope forbid_script;
+        frame_view.GetLayoutView()
+            ->GetDocument()
+            .GetDocumentAnimations()
+            .UpdateAnimations(DocumentLifecycle::kPaintClean,
+                              paint_artifact_compositor_.get());
+      }
     });
 
     // Initialize animation properties in the newly created paint property
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc b/src/3rdparty/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc	2021-06-18 16:26:16.705781600 +0100
@@ -122,12 +122,6 @@
 
   ResourceLoaderOptions options(&modulator_->GetScriptState()->World());
 
-  // <spec step="6">If destination is "worker" or "sharedworker" and the
-  // top-level module fetch flag is set, then set request's mode to
-  // "same-origin".</spec>
-  // Cross-origin workers are not supported due to security checks in
-  // AbstractWorker::ResolveURL, so no action needs to be taken here.
-
   // <spec step="7">Set up the module script request given request and
   // options.</spec>
   //
@@ -178,6 +172,26 @@
       fetch_client_settings_object.GetSecurityOrigin(),
       options_.CredentialsMode());
 
+  // <spec step="6">If destination is "worker" or "sharedworker" and the
+  // top-level module fetch flag is set, then set request's mode to
+  // "same-origin".</spec>
+  //
+  // `kServiceWorker` is included here for consistency, while it isn't mentioned
+  // in the spec. This doesn't affect the behavior, because we already forbid
+  // redirects and cross-origin response URLs in other places.
+  if ((module_request.Destination() ==
+           network::mojom::RequestDestination::kWorker ||
+       module_request.Destination() ==
+           network::mojom::RequestDestination::kSharedWorker ||
+       module_request.Destination() ==
+           network::mojom::RequestDestination::kServiceWorker) &&
+      level == ModuleGraphLevel::kTopLevelModuleFetch) {
+    // This should be done after SetCrossOriginAccessControl() that sets the
+    // mode to kCors.
+    fetch_params.MutableResourceRequest().SetMode(
+        network::mojom::RequestMode::kSameOrigin);
+  }
+
   // <spec step="5">... referrer is referrer, ...</spec>
   fetch_params.MutableResourceRequest().SetReferrerString(
       module_request.ReferrerString());
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/core/scroll/scroll_animator_mac.mm b/src/3rdparty/chromium/third_party/blink/renderer/core/scroll/scroll_animator_mac.mm
--- a/src/3rdparty/chromium/third_party/blink/renderer/core/scroll/scroll_animator_mac.mm	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/core/scroll/scroll_animator_mac.mm	2021-06-18 16:26:16.705781600 +0100
@@ -327,6 +327,11 @@
     double fraction = delta / duration_;
     fraction = clampTo(fraction, 0.0, 1.0);
     double progress = timing_function_->Evaluate(fraction);
+    // In some scenarios, animation_ gets released during the call to
+    // setCurrentProgress. Because BlinkScrollbarPartAnimationTimer is a
+    // member variable of BlinkScrollbarPartAnimation animation_ the timer
+    // gets freed at the same time with animation_. In that case, it will
+    // not be safe to call any other code after animation_ setCurrentProgress.
     [animation_ setCurrentProgress:progress];
   }
 
@@ -401,6 +406,10 @@
 
 - (void)setCurrentProgress:(NSAnimationProgress)progress {
   DCHECK(_scrollbar);
+  // In some scenarios, BlinkScrollbarPartAnimation is released in the middle
+  // of this method by _scrollbarPainter. This is why we have to retain the self
+  // pointer when we run this method.
+  [self retain];
 
   CGFloat currentValue;
   if (_startValue > _endValue)
@@ -427,7 +436,13 @@
       break;
   }
 
-  _scrollbar->SetNeedsPaintInvalidation(invalidParts);
+  // Before BlinkScrollbarPartAnimation is released by _scrollbarPainter,
+  // invalidate is called and _scrollbar is set to nullptr. Check to see
+  // if _scrollbar is non-null before calling SetNeedsPaintInvalidation.
+  if (_scrollbar)
+    _scrollbar->SetNeedsPaintInvalidation(invalidParts);
+
+  [self release];
 }
 
 - (void)invalidate {
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc b/src/3rdparty/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc	2021-06-18 17:00:07.009966740 +0100
@@ -79,7 +79,8 @@
 // size |max_image_size|. Returns the result if it is not empty. Otherwise,
 // find the smallest image in the array and resize it proportionally to fit
 // in a box of size |max_image_size|.
-// Sets |original_image_sizes| to the sizes of |images| before resizing.
+// Sets |original_image_sizes| to the sizes of |images| before resizing. Both
+// output vectors are guaranteed to have the same size.
 void FilterAndResizeImagesForMaximalSize(
     const WTF::Vector<SkBitmap>& unfiltered,
     uint32_t max_image_size,
@@ -202,6 +203,8 @@
   FilterAndResizeImagesForMaximalSize(images, max_image_size, &result_images,
                                       &result_original_image_sizes);
 
+  DCHECK_EQ(result_images.size(), result_original_image_sizes.size());
+
   std::move(callback).Run(http_status_code, result_images,
                           result_original_image_sizes);
 }
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/src/3rdparty/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc	2021-06-18 16:26:16.705781600 +0100
@@ -158,13 +158,19 @@
   Vector<KURL> url_list(1);
   url_list[0] = preload_response_->CurrentRequestUrl();
 
+  auto response_type =
+      network_utils::IsRedirectResponseCode(preload_response_->HttpStatusCode())
+          ? network::mojom::FetchResponseType::kOpaqueRedirect
+          : network::mojom::FetchResponseType::kBasic;
+
   response_data->InitFromResourceResponse(
-      url_list, http_names::kGET, network::mojom::CredentialsMode::kInclude,
+      ExecutionContext::From(script_state), response_type, url_list,
+      http_names::kGET, network::mojom::CredentialsMode::kInclude,
       FetchRequestData::kBasicTainting,
       preload_response_->ToResourceResponse());
 
   FetchResponseData* tainted_response =
-      network_utils::IsRedirectResponseCode(preload_response_->HttpStatusCode())
+      response_type == network::mojom::FetchResponseType::kOpaqueRedirect
           ? response_data->CreateOpaqueRedirectFilteredResponse()
           : response_data->CreateBasicFilteredResponse();
   preload_response_property_->Resolve(
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/modules/webmidi/midi_dispatcher.cc b/src/3rdparty/chromium/third_party/blink/renderer/modules/webmidi/midi_dispatcher.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/modules/webmidi/midi_dispatcher.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/modules/webmidi/midi_dispatcher.cc	2021-06-18 16:26:16.705781600 +0100
@@ -101,8 +101,13 @@
 void MIDIDispatcher::SessionStarted(midi::mojom::blink::Result result) {
   TRACE_EVENT0("midi", "MIDIDispatcher::OnSessionStarted");
 
+  // We always have a valid instance in `client_` in the production code, but
+  // just in case to be robust for mojo injections and code changes in the
+  // future. Other methods protect accesses to `client_` by `initialized_` flag
+  // that is set below.
+  SECURITY_CHECK(client_);
+
   DCHECK(!initialized_);
-  DCHECK(client_);
   initialized_ = true;
 
   if (result == midi::mojom::blink::Result::OK) {
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc b/src/3rdparty/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc	2021-06-18 16:26:16.705781600 +0100
@@ -374,6 +374,13 @@
   return resource_response_->GetType();
 }
 
+void WebURLResponse::SetPadding(int64_t padding) {
+  resource_response_->SetPadding(padding);
+}
+int64_t WebURLResponse::GetPadding() const {
+  return resource_response_->GetPadding();
+}
+
 void WebURLResponse::SetUrlListViaServiceWorker(
     const WebVector<WebURL>& url_list_via_service_worker) {
   Vector<KURL> url_list(url_list_via_service_worker.size());
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
--- a/src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h	2021-06-18 16:26:16.705781600 +0100
@@ -358,6 +358,9 @@
   // https://html.spec.whatwg.org/C/#cors-cross-origin
   bool IsCorsCrossOrigin() const;
 
+  int64_t GetPadding() const { return padding_; }
+  void SetPadding(int64_t padding) { padding_ = padding; }
+
   // See network::ResourceResponseInfo::url_list_via_service_worker.
   const Vector<KURL>& UrlListViaServiceWorker() const {
     return url_list_via_service_worker_;
@@ -597,6 +600,11 @@
   network::mojom::FetchResponseType response_type_ =
       network::mojom::FetchResponseType::kDefault;
 
+  // Pre-computed padding.  This should only be non-zero if |response_type| is
+  // set to kOpaque.  In addition, it is only set if the response was provided
+  // by a service worker FetchEvent handler.
+  int64_t padding_ = 0;
+
   // HTTP version used in the response, if known.
   HTTPVersion http_version_ = kHTTPVersionUnknown;
 
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc b/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc	2021-06-18 16:26:16.705781600 +0100
@@ -395,8 +395,14 @@
 
   // If any observers were removed during the iteration they will have
   // 0 values, clean them up.
-  for (wtf_size_t i = 0; i < list->zeroed_observers.size(); ++i)
-    list->observers.EraseAt(list->zeroed_observers[i]);
+  std::sort(list->zeroed_observers.begin(), list->zeroed_observers.end());
+  int removed = 0;
+  for (wtf_size_t i = 0; i < list->zeroed_observers.size(); ++i) {
+    int index_to_remove = list->zeroed_observers[i] - removed;
+    DCHECK_EQ(nullptr, list->observers[index_to_remove]);
+    list->observers.EraseAt(index_to_remove);
+    removed += 1;
+  }
 
   list->zeroed_observers.clear();
 
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc b/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc	2021-06-18 16:26:16.706783333 +0100
@@ -528,6 +528,53 @@
       kUnknownThroughputMbps, SaveData::kOff));
 }
 
+// It should be safe to remove multiple observers in one iteration.
+TEST_F(NetworkStateNotifierTest, RemoveMultipleObserversWhileNotifying) {
+  StateObserver observer1, observer2, observer3;
+  std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle1 =
+      notifier_.AddConnectionObserver(&observer1, GetTaskRunner());
+  std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle2 =
+      notifier_.AddConnectionObserver(&observer2, GetTaskRunner());
+  std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle3 =
+      notifier_.AddConnectionObserver(&observer3, GetTaskRunner());
+  observer1.RemoveObserverOnNotification(std::move(handle1));
+  observer3.RemoveObserverOnNotification(std::move(handle3));
+
+  // Running the first time should delete observers 1 and 3.
+  SetConnection(kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+                WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt,
+                kUnknownRtt, kUnknownThroughputMbps, SaveData::kOff);
+  EXPECT_TRUE(VerifyObservations(
+      observer1, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps, SaveData::kOff));
+  EXPECT_TRUE(VerifyObservations(
+      observer2, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps, SaveData::kOff));
+  EXPECT_TRUE(VerifyObservations(
+      observer3, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps, SaveData::kOff));
+
+  // Run again and only observer 2 should have been updated.
+  SetConnection(kWebConnectionTypeEthernet, kEthernetMaxBandwidthMbps,
+                WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt,
+                kUnknownRtt, kUnknownThroughputMbps, SaveData::kOff);
+  EXPECT_TRUE(VerifyObservations(
+      observer1, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps, SaveData::kOff));
+  EXPECT_TRUE(VerifyObservations(
+      observer2, kWebConnectionTypeEthernet, kEthernetMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps, SaveData::kOff));
+  EXPECT_TRUE(VerifyObservations(
+      observer3, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+      WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+      kUnknownThroughputMbps, SaveData::kOff));
+}
+
 TEST_F(NetworkStateNotifierTest, MultipleContextsAddObserver) {
   StateObserver observer1, observer2;
   std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle1 =
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc b/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
--- a/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc	2021-06-18 16:26:16.706783333 +0100
@@ -143,7 +143,8 @@
       domain_(host_),
       port_(IsDefaultPortForProtocol(url.Port(), protocol_) ? kInvalidPort
                                                             : url.Port()),
-      effective_port_(port_ ? port_ : DefaultPortForProtocol(protocol_)) {
+      effective_port_(port_ ? port_ : DefaultPortForProtocol(protocol_)),
+      full_url_(url.Copy()) {
   DCHECK(!ShouldTreatAsOpaqueOrigin(url));
 
   // NOTE(juvaldma)(Chromium 67.0.3396.47)
@@ -193,7 +194,8 @@
       agent_cluster_id_(other->agent_cluster_id_),
       precursor_origin_(other->precursor_origin_
                             ? other->precursor_origin_->IsolatedCopy()
-                            : nullptr) {}
+                            : nullptr),
+      full_url_(other->full_url_.Copy()) {}
 
 SecurityOrigin::SecurityOrigin(const SecurityOrigin* other,
                                ConstructSameThreadCopy)
@@ -212,7 +214,8 @@
           other->is_opaque_origin_potentially_trustworthy_),
       cross_agent_cluster_access_(other->cross_agent_cluster_access_),
       agent_cluster_id_(other->agent_cluster_id_),
-      precursor_origin_(other->precursor_origin_) {}
+      precursor_origin_(other->precursor_origin_),
+      full_url_(other->full_url_.Copy()) {}
 
 scoped_refptr<SecurityOrigin> SecurityOrigin::CreateWithReferenceOrigin(
     const KURL& url,
@@ -281,6 +284,7 @@
         url::Origin::Nonce(*nonce_if_opaque), tuple_origin.get()));
   }
   CHECK(tuple_origin);
+  tuple_origin->full_url_ = KURL(origin.GetFullURL());
   return tuple_origin;
 }
 
@@ -297,6 +301,7 @@
   }
   url::Origin result = url::Origin::CreateFromNormalizedTuple(
       std::move(scheme), std::move(host), port);
+  result.SetFullURL(full_url_);
   CHECK(!result.opaque());
   return result;
 }
diff -Naur a/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h b/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
--- a/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h	2021-06-18 16:26:16.706783333 +0100
@@ -35,6 +35,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
@@ -424,6 +425,8 @@
   // origin is derived.
   const scoped_refptr<const SecurityOrigin> precursor_origin_;
 
+  KURL full_url_;
+
   DISALLOW_COPY_AND_ASSIGN(SecurityOrigin);
 };
 
diff -Naur a/src/3rdparty/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/src/3rdparty/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
--- a/src/3rdparty/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py	2021-06-18 16:26:16.706783333 +0100
@@ -1172,6 +1172,15 @@
         'allowed': ['net::RequestPriority'],
     },
     {
+        'paths':
+        ['third_party/blink/renderer/core/fetch/fetch_response_data.cc'],
+        'allowed': [
+            'storage::ComputeRandomResponsePadding',
+            'storage::ComputeStableResponsePadding',
+            'storage::ShouldPadResponseType'
+        ],
+    },
+    {
         'paths': ['third_party/blink/renderer/core/frame/local_frame_view.cc'],
         'allowed':
         ['cc::frame_viewer_instrumentation::IsTracingLayerTreeSnapshots'],
diff -Naur a/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/base_pcp_handler_test.cc.orig b/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/base_pcp_handler_test.cc.orig
--- a/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/base_pcp_handler_test.cc.orig	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/base_pcp_handler_test.cc.orig	1970-01-01 01:00:00.000000000 +0100
@@ -1,538 +0,0 @@
-#include "core_v2/internal/base_pcp_handler.h"
-
-#include <atomic>
-#include <memory>
-
-#include "core_v2/internal/base_endpoint_channel.h"
-#include "core_v2/internal/client_proxy.h"
-#include "core_v2/internal/encryption_runner.h"
-#include "core_v2/internal/offline_frames.h"
-#include "core_v2/listeners.h"
-#include "core_v2/options.h"
-#include "core_v2/params.h"
-#include "proto/connections/offline_wire_formats.pb.h"
-#include "platform_v2/base/byte_array.h"
-#include "platform_v2/public/count_down_latch.h"
-#include "platform_v2/public/pipe.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/time/time.h"
-
-namespace location {
-namespace nearby {
-namespace connections {
-namespace {
-
-using ::location::nearby::proto::connections::Medium;
-using ::testing::_;
-using ::testing::AtLeast;
-using ::testing::Invoke;
-using ::testing::MockFunction;
-using ::testing::Return;
-using ::testing::StrictMock;
-
-constexpr BooleanMediumSelector kTestCases[] = {
-    BooleanMediumSelector{},
-    BooleanMediumSelector{
-        .bluetooth = true,
-    },
-    BooleanMediumSelector{
-        .wifi_lan = true,
-    },
-    BooleanMediumSelector{
-        .bluetooth = true,
-        .wifi_lan = true,
-    },
-};
-
-class MockEndpointChannel : public BaseEndpointChannel {
- public:
-  explicit MockEndpointChannel(Pipe* reader, Pipe* writer)
-      : BaseEndpointChannel("channel", &reader->GetInputStream(),
-                            &writer->GetOutputStream()) {}
-
-  ExceptionOr<ByteArray> DoRead() { return BaseEndpointChannel::Read(); }
-  Exception DoWrite(const ByteArray& data) {
-    return BaseEndpointChannel::Write(data);
-  }
-  absl::Time DoGetLastReadTimestamp() {
-    return BaseEndpointChannel::GetLastReadTimestamp();
-  }
-
-  MOCK_METHOD(ExceptionOr<ByteArray>, Read, (), (override));
-  MOCK_METHOD(Exception, Write, (const ByteArray& data), (override));
-  MOCK_METHOD(void, CloseImpl, (), (override));
-  MOCK_METHOD(proto::connections::Medium, GetMedium, (), (const override));
-  MOCK_METHOD(std::string, GetType, (), (const override));
-  MOCK_METHOD(std::string, GetName, (), (const override));
-  MOCK_METHOD(bool, IsPaused, (), (const override));
-  MOCK_METHOD(void, Pause, (), (override));
-  MOCK_METHOD(void, Resume, (), (override));
-  MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const override));
-};
-
-class MockPcpHandler : public BasePcpHandler {
- public:
-  using DiscoveredEndpoint = BasePcpHandler::DiscoveredEndpoint;
-
-  MockPcpHandler(EndpointManager* em, EndpointChannelManager* ecm)
-      : BasePcpHandler(em, ecm, Pcp::kP2pCluster) {}
-
-  // Expose protected inner types of a base type for mocking.
-  using BasePcpHandler::ConnectImplResult;
-  using BasePcpHandler::DiscoveredEndpoint;
-  using BasePcpHandler::StartOperationResult;
-
-  MOCK_METHOD(Strategy, GetStrategy, (), (const override));
-  MOCK_METHOD(Pcp, GetPcp, (), (const override));
-
-  MOCK_METHOD(bool, HasOutgoingConnections, (ClientProxy * client),
-              (const, override));
-  MOCK_METHOD(bool, HasIncomingConnections, (ClientProxy * client),
-              (const, override));
-
-  MOCK_METHOD(bool, CanSendOutgoingConnection, (ClientProxy * client),
-              (const, override));
-  MOCK_METHOD(bool, CanReceiveIncomingConnection, (ClientProxy * client),
-              (const, override));
-
-  MOCK_METHOD(StartOperationResult, StartAdvertisingImpl,
-              (ClientProxy * client, const string& service_id,
-               const string& local_endpoint_id,
-               const string& local_endpoint_name,
-               const ConnectionOptions& options),
-              (override));
-  MOCK_METHOD(Status, StopAdvertisingImpl, (ClientProxy * client), (override));
-  MOCK_METHOD(StartOperationResult, StartDiscoveryImpl,
-              (ClientProxy * client, const string& service_id,
-               const ConnectionOptions& options),
-              (override));
-  MOCK_METHOD(Status, StopDiscoveryImpl, (ClientProxy * client), (override));
-  MOCK_METHOD(ConnectImplResult, ConnectImpl,
-              (ClientProxy * client, DiscoveredEndpoint* endpoint), (override));
-  MOCK_METHOD(proto::connections::Medium, GetDefaultUpgradeMedium, (),
-              (override));
-
-  std::vector<proto::connections::Medium> GetConnectionMediumsByPriority()
-      override {
-    return GetDiscoveryMediums();
-  }
-
-  // Mock adapters for protected non-virtual methods of a base class.
-  void OnEndpointFound(ClientProxy* client,
-                       std::shared_ptr<DiscoveredEndpoint> endpoint) {
-    BasePcpHandler::OnEndpointFound(client, std::move(endpoint));
-  }
-  void OnEndpointLost(ClientProxy* client, const DiscoveredEndpoint& endpoint) {
-    BasePcpHandler::OnEndpointLost(client, endpoint);
-  }
-
-  std::vector<proto::connections::Medium> GetDiscoveryMediums() {
-    std::vector<proto::connections::Medium> mediums;
-    auto allowed =
-        BasePcpHandler::GetDiscoveryOptions().CompatibleOptions().allowed;
-    // Mediums are sorted in order of decreasing preference.
-    if (allowed.wifi_lan)
-      mediums.push_back(proto::connections::Medium::WIFI_LAN);
-    if (allowed.web_rtc) mediums.push_back(proto::connections::Medium::WEB_RTC);
-    if (allowed.bluetooth)
-      mediums.push_back(proto::connections::Medium::BLUETOOTH);
-    return mediums;
-  }
-
-  std::vector<BasePcpHandler::DiscoveredEndpoint*> GetDiscoveredEndpoints(
-      const std::string& endpoint_id) {
-    return BasePcpHandler::GetDiscoveredEndpoints(endpoint_id);
-  }
-};
-
-class MockContext {
- public:
-  explicit MockContext(std::atomic_int* destroyed = nullptr) {
-    destroyed_ = destroyed;
-  }
-  MockContext(MockContext&&) = default;
-  MockContext& operator=(MockContext&&) = default;
-
-  ~MockContext() {
-    if (destroyed_) (*destroyed_)++;
-  }
-
- private:
-  Swapper<std::atomic_int> destroyed_{nullptr};
-};
-
-struct MockDiscoveredEndpoint : public MockPcpHandler::DiscoveredEndpoint {
-  MockDiscoveredEndpoint(DiscoveredEndpoint endpoint, MockContext context)
-      : DiscoveredEndpoint(std::move(endpoint)), context(std::move(context)) {}
-
-  MockContext context;
-};
-
-class BasePcpHandlerTest
-    : public ::testing::TestWithParam<BooleanMediumSelector> {
- protected:
-  struct MockConnectionListener {
-    StrictMock<MockFunction<void(const std::string& endpoint_id,
-                                 const ConnectionResponseInfo& info)>>
-        initiated_cb;
-    StrictMock<MockFunction<void(const std::string& endpoint_id)>> accepted_cb;
-    StrictMock<MockFunction<void(const std::string& endpoint_id,
-                                 const Status& status)>>
-        rejected_cb;
-    StrictMock<MockFunction<void(const std::string& endpoint_id)>>
-        disconnected_cb;
-    StrictMock<MockFunction<void(const std::string& endpoint_id,
-                                 std::int32_t quality)>>
-        bandwidth_changed_cb;
-  };
-  struct MockDiscoveryListener {
-    StrictMock<MockFunction<void(const std::string& endpoint_id,
-                                 const std::string& endpoint_name,
-                                 const std::string& service_id)>>
-        endpoint_found_cb;
-    StrictMock<MockFunction<void(const std::string& endpoint_id)>>
-        endpoint_lost_cb;
-    StrictMock<
-        MockFunction<void(const std::string& endpoint_id, DistanceInfo info)>>
-        endpoint_distance_changed_cb;
-  };
-
-  void StartAdvertising(ClientProxy* client, MockPcpHandler* pcp_handler,
-                        BooleanMediumSelector allowed = GetParam()) {
-    std::string service_id{"service"};
-    ConnectionOptions options{
-        .strategy = Strategy::kP2pCluster,
-        .allowed = allowed,
-        .auto_upgrade_bandwidth = true,
-        .enforce_topology_constraints = true,
-    };
-    ConnectionRequestInfo info{
-        .name = "remote_endpoint_name",
-        .listener = connection_listener_,
-    };
-    EXPECT_CALL(*pcp_handler,
-                StartAdvertisingImpl(client, service_id, _, info.name, _))
-        .WillOnce(Return(MockPcpHandler::StartOperationResult{
-            .status = {Status::kSuccess},
-            .mediums = {Medium::BLE},
-        }));
-    EXPECT_EQ(pcp_handler->StartAdvertising(client, service_id, options, info),
-              Status{Status::kSuccess});
-    EXPECT_TRUE(client->IsAdvertising());
-  }
-
-  void StartDiscovery(ClientProxy* client, MockPcpHandler* pcp_handler,
-                      BooleanMediumSelector allowed = GetParam()) {
-    std::string service_id{"service"};
-    ConnectionOptions options{
-        .strategy = Strategy::kP2pCluster,
-        .allowed = allowed,
-        .auto_upgrade_bandwidth = true,
-        .enforce_topology_constraints = true,
-    };
-    EXPECT_CALL(*pcp_handler, StartDiscoveryImpl(client, service_id, _))
-        .WillOnce(Return(MockPcpHandler::StartOperationResult{
-            .status = {Status::kSuccess},
-            .mediums = {Medium::BLE},
-        }));
-    EXPECT_EQ(pcp_handler->StartDiscovery(client, service_id, options,
-                                          discovery_listener_),
-              Status{Status::kSuccess});
-    EXPECT_TRUE(client->IsDiscovering());
-  }
-
-  std::pair<std::unique_ptr<MockEndpointChannel>,
-            std::unique_ptr<MockEndpointChannel>>
-  SetupConnection(Pipe& pipe_a, Pipe& pipe_b) {  // NOLINT
-    auto channel_a = std::make_unique<MockEndpointChannel>(&pipe_b, &pipe_a);
-    auto channel_b = std::make_unique<MockEndpointChannel>(&pipe_a, &pipe_b);
-    // On initiator (A) side, we drop the first write, since this is a
-    // connection establishment packet, and we don't have the peer entity, just
-    // the peer channel. The rest of the exchange must happen for the benefit of
-    // DH key exchange.
-    EXPECT_CALL(*channel_a, Read())
-        .WillRepeatedly(Invoke(
-            [channel = channel_a.get()]() { return channel->DoRead(); }));
-    EXPECT_CALL(*channel_a, Write(_))
-        .WillOnce(Return(Exception{Exception::kSuccess}))
-        .WillRepeatedly(
-            Invoke([channel = channel_a.get()](const ByteArray& data) {
-              return channel->DoWrite(data);
-            }));
-    EXPECT_CALL(*channel_a, GetMedium).WillRepeatedly(Return(Medium::BLE));
-    EXPECT_CALL(*channel_a, GetLastReadTimestamp)
-        .WillRepeatedly(Return(absl::Now()));
-    EXPECT_CALL(*channel_a, IsPaused).WillRepeatedly(Return(false));
-    EXPECT_CALL(*channel_b, Read())
-        .WillRepeatedly(Invoke(
-            [channel = channel_b.get()]() { return channel->DoRead(); }));
-    EXPECT_CALL(*channel_b, Write(_))
-        .WillRepeatedly(
-            Invoke([channel = channel_b.get()](const ByteArray& data) {
-              return channel->DoWrite(data);
-            }));
-    EXPECT_CALL(*channel_b, GetMedium).WillRepeatedly(Return(Medium::BLE));
-    EXPECT_CALL(*channel_b, GetLastReadTimestamp)
-        .WillRepeatedly(Return(absl::Now()));
-    EXPECT_CALL(*channel_b, IsPaused).WillRepeatedly(Return(false));
-    return std::make_pair(std::move(channel_a), std::move(channel_b));
-  }
-
-  void RequestConnection(const std::string& endpoint_id,
-                         std::unique_ptr<MockEndpointChannel> channel_a,
-                         MockEndpointChannel* channel_b, ClientProxy* client,
-                         MockPcpHandler* pcp_handler,
-                         std::atomic_int* flag = nullptr) {
-    ConnectionRequestInfo info{
-        .name = "ABCD",
-        .listener = connection_listener_,
-    };
-    EXPECT_CALL(mock_discovery_listener_.endpoint_found_cb, Call);
-    EXPECT_CALL(*pcp_handler, CanSendOutgoingConnection)
-        .WillRepeatedly(Return(true));
-    EXPECT_CALL(*pcp_handler, GetStrategy)
-        .WillRepeatedly(Return(Strategy::kP2pCluster));
-    EXPECT_CALL(mock_connection_listener_.initiated_cb, Call).Times(1);
-    // Simulate successful discovery.
-    auto encryption_runner = std::make_unique<EncryptionRunner>();
-    auto allowed_mediums = pcp_handler->GetDiscoveryMediums();
-
-    EXPECT_CALL(*pcp_handler, ConnectImpl)
-        .WillOnce(Invoke([&channel_a, medium = allowed_mediums[0]](
-                             ClientProxy* client,
-                             MockPcpHandler::DiscoveredEndpoint* endpoint) {
-          return MockPcpHandler::ConnectImplResult{
-              .medium = medium,
-              .status = {Status::kSuccess},
-              .endpoint_channel = std::move(channel_a),
-          };
-        }));
-
-    for (const auto& medium : allowed_mediums) {
-      pcp_handler->OnEndpointFound(
-          client,
-          std::make_shared<MockDiscoveredEndpoint>(MockDiscoveredEndpoint{
-              {
-                  endpoint_id,
-                  info.name,
-                  "service",
-                  medium,
-              },
-              MockContext{flag},
-          }));
-    }
-    auto other_client = std::make_unique<ClientProxy>();
-
-    // Run peer crypto in advance, if channel_b is provided.
-    // Otherwise stay in not-encrypted state.
-    if (channel_b != nullptr) {
-      encryption_runner->StartServer(other_client.get(), endpoint_id, channel_b,
-                                     {});
-    }
-    EXPECT_EQ(pcp_handler->RequestConnection(client, endpoint_id, info),
-              Status{Status::kSuccess});
-    NEARBY_LOG(INFO, "Stopping Encryption Runner");
-  }
-
-  Pipe pipe_a_;
-  Pipe pipe_b_;
-  MockConnectionListener mock_connection_listener_;
-  MockDiscoveryListener mock_discovery_listener_;
-  ConnectionListener connection_listener_{
-      .initiated_cb = mock_connection_listener_.initiated_cb.AsStdFunction(),
-      .accepted_cb = mock_connection_listener_.accepted_cb.AsStdFunction(),
-      .rejected_cb = mock_connection_listener_.rejected_cb.AsStdFunction(),
-      .disconnected_cb =
-          mock_connection_listener_.disconnected_cb.AsStdFunction(),
-      .bandwidth_changed_cb =
-          mock_connection_listener_.bandwidth_changed_cb.AsStdFunction(),
-  };
-  DiscoveryListener discovery_listener_{
-      .endpoint_found_cb =
-          mock_discovery_listener_.endpoint_found_cb.AsStdFunction(),
-      .endpoint_lost_cb =
-          mock_discovery_listener_.endpoint_lost_cb.AsStdFunction(),
-      .endpoint_distance_changed_cb =
-          mock_discovery_listener_.endpoint_distance_changed_cb.AsStdFunction(),
-  };
-};
-
-TEST_P(BasePcpHandlerTest, ConstructorDestructorWorks) {
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  SUCCEED();
-}
-
-TEST_P(BasePcpHandlerTest, StartAdvertisingChangesState) {
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartAdvertising(&client, &pcp_handler);
-}
-
-TEST_P(BasePcpHandlerTest, StopAdvertisingChangesState) {
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartAdvertising(&client, &pcp_handler);
-  EXPECT_CALL(pcp_handler, StopAdvertisingImpl(&client)).Times(1);
-  EXPECT_TRUE(client.IsAdvertising());
-  pcp_handler.StopAdvertising(&client);
-  EXPECT_FALSE(client.IsAdvertising());
-}
-
-TEST_P(BasePcpHandlerTest, StartDiscoveryChangesState) {
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartDiscovery(&client, &pcp_handler);
-}
-
-TEST_P(BasePcpHandlerTest, StopDiscoveryChangesState) {
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartDiscovery(&client, &pcp_handler);
-  EXPECT_CALL(pcp_handler, StopDiscoveryImpl(&client)).Times(1);
-  EXPECT_TRUE(client.IsDiscovering());
-  pcp_handler.StopDiscovery(&client);
-  EXPECT_FALSE(client.IsDiscovering());
-}
-
-TEST_P(BasePcpHandlerTest, RequestConnectionChangesState) {
-  std::string endpoint_id{"1234"};
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartDiscovery(&client, &pcp_handler);
-  auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
-  auto& channel_a = channel_pair.first;
-  auto& channel_b = channel_pair.second;
-  EXPECT_CALL(*channel_a, CloseImpl).Times(1);
-  EXPECT_CALL(*channel_b, CloseImpl).Times(1);
-  EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
-  RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client,
-                    &pcp_handler);
-  NEARBY_LOG(INFO, "RequestConnection complete");
-  channel_b->Close();
-  pcp_handler.DisconnectFromEndpointManager();
-}
-
-TEST_P(BasePcpHandlerTest, AcceptConnectionChangesState) {
-  std::string endpoint_id{"1234"};
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartDiscovery(&client, &pcp_handler);
-  auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
-  auto& channel_a = channel_pair.first;
-  auto& channel_b = channel_pair.second;
-  EXPECT_CALL(*channel_a, CloseImpl).Times(1);
-  EXPECT_CALL(*channel_b, CloseImpl).Times(1);
-  RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client,
-                    &pcp_handler);
-  NEARBY_LOG(INFO, "Attempting to accept connection: id=%s",
-             endpoint_id.c_str());
-  EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}),
-            Status{Status::kSuccess});
-  EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
-  NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id;
-  channel_b->Close();
-  pcp_handler.DisconnectFromEndpointManager();
-}
-
-TEST_P(BasePcpHandlerTest, RejectConnectionChangesState) {
-  std::string endpoint_id{"1234"};
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartDiscovery(&client, &pcp_handler);
-  auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
-  auto& channel_b = channel_pair.second;
-  EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(1);
-  RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(),
-                    &client, &pcp_handler);
-  NEARBY_LOGS(INFO) << "Attempting to reject connection: id=" << endpoint_id;
-  EXPECT_EQ(pcp_handler.RejectConnection(&client, endpoint_id),
-            Status{Status::kSuccess});
-  NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id;
-  channel_b->Close();
-  pcp_handler.DisconnectFromEndpointManager();
-}
-
-TEST_P(BasePcpHandlerTest, OnIncomingFrameChangesState) {
-  std::string endpoint_id{"1234"};
-  ClientProxy client;
-  EndpointChannelManager ecm;
-  EndpointManager em(&ecm);
-  MockPcpHandler pcp_handler(&em, &ecm);
-  StartDiscovery(&client, &pcp_handler);
-  auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
-  auto& channel_a = channel_pair.first;
-  auto& channel_b = channel_pair.second;
-  EXPECT_CALL(*channel_a, CloseImpl).Times(1);
-  EXPECT_CALL(*channel_b, CloseImpl).Times(1);
-  RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client,
-                    &pcp_handler);
-  NEARBY_LOGS(INFO) << "Attempting to accept connection: id=" << endpoint_id;
-  EXPECT_CALL(mock_connection_listener_.accepted_cb, Call).Times(1);
-  EXPECT_CALL(mock_connection_listener_.disconnected_cb, Call)
-      .Times(AtLeast(0));
-  EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}),
-            Status{Status::kSuccess});
-  NEARBY_LOG(INFO, "Simulating remote accept: id=%s", endpoint_id.c_str());
-  auto frame =
-      parser::FromBytes(parser::ForConnectionResponse(Status::kSuccess));
-  pcp_handler.OnIncomingFrame(frame.result(), endpoint_id, &client,
-                              Medium::BLE);
-  NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id;
-  channel_b->Close();
-  pcp_handler.DisconnectFromEndpointManager();
-}
-
-TEST_P(BasePcpHandlerTest, DestructorIsCalledOnProtocolEndpoint) {
-  std::atomic_int destroyed_flag = 0;
-  int mediums_count = 0;
-  {
-    std::string endpoint_id{"1234"};
-    ClientProxy client;
-    EndpointChannelManager ecm;
-    EndpointManager em(&ecm);
-    MockPcpHandler pcp_handler(&em, &ecm);
-    StartDiscovery(&client, &pcp_handler);
-    auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
-    auto& channel_a = channel_pair.first;
-    auto& channel_b = channel_pair.second;
-    EXPECT_CALL(*channel_a, CloseImpl).Times(1);
-    EXPECT_CALL(*channel_b, CloseImpl).Times(1);
-    RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(),
-                      &client, &pcp_handler, &destroyed_flag);
-    mediums_count = pcp_handler.GetDiscoveryMediums().size();
-    NEARBY_LOG(INFO, "Attempting to accept connection: id=%s",
-               endpoint_id.c_str());
-    EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}),
-              Status{Status::kSuccess});
-    EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
-    NEARBY_LOG(INFO, "Closing connection: id=%s", endpoint_id.c_str());
-    channel_b->Close();
-    pcp_handler.DisconnectFromEndpointManager();
-  }
-  EXPECT_EQ(destroyed_flag.load(), mediums_count);
-}
-
-INSTANTIATE_TEST_SUITE_P(ParameterizedBasePcpHandlerTest, BasePcpHandlerTest,
-                         ::testing::ValuesIn(kTestCases));
-
-}  // namespace
-}  // namespace connections
-}  // namespace nearby
-}  // namespace location
diff -Naur a/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/offline_service_controller.h.orig b/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/offline_service_controller.h.orig
--- a/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/offline_service_controller.h.orig	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/nearby/src/cpp/core_v2/internal/offline_service_controller.h.orig	1970-01-01 01:00:00.000000000 +0100
@@ -1,81 +0,0 @@
-#ifndef CORE_V2_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_
-#define CORE_V2_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-#include "core_v2/internal/client_proxy.h"
-#include "core_v2/internal/endpoint_channel_manager.h"
-#include "core_v2/internal/endpoint_manager.h"
-#include "core_v2/internal/mediums/mediums.h"
-#include "core_v2/internal/payload_manager.h"
-#include "core_v2/internal/pcp_manager.h"
-#include "core_v2/internal/service_controller.h"
-#include "core_v2/listeners.h"
-#include "core_v2/options.h"
-#include "core_v2/payload.h"
-#include "core_v2/status.h"
-
-namespace location {
-namespace nearby {
-namespace connections {
-
-class OfflineServiceController : public ServiceController {
- public:
-  OfflineServiceController() = default;
-  ~OfflineServiceController() override;
-
-  Status StartAdvertising(ClientProxy* client,
-                          const std::string& service_id,
-                          const ConnectionOptions& options,
-                          const ConnectionRequestInfo& info) override;
-  void StopAdvertising(ClientProxy* client) override;
-
-  Status StartDiscovery(ClientProxy* client,
-                        const std::string& service_id,
-                        const ConnectionOptions& options,
-                        const DiscoveryListener& listener) override;
-  void StopDiscovery(ClientProxy* client) override;
-
-  Status RequestConnection(ClientProxy* client,
-                           const std::string& endpoint_id,
-                           const ConnectionRequestInfo& info,
-                           const ConnectionOptions& options) override;
-  Status AcceptConnection(ClientProxy* client,
-                          const std::string& endpoint_id,
-                          const PayloadListener& listener) override;
-  Status RejectConnection(ClientProxy* client,
-                          const std::string& endpoint_id) override;
-
-  void InitiateBandwidthUpgrade(ClientProxy* client,
-                                const std::string& endpoint_id) override;
-
-  void SendPayload(ClientProxy* client,
-                   const std::vector<std::string>& endpoint_ids,
-                   Payload payload) override;
-  Status CancelPayload(ClientProxy* client,
-                       Payload::Id payload_id) override;
-
-  void DisconnectFromEndpoint(ClientProxy* client,
-                              const std::string& endpoint_id) override;
-
-  void Stop();
-
- private:
-  // Note that the order of declaration of these is crucial, because we depend
-  // on the destructors running (strictly) in the reverse order; a deviation
-  // from that will lead to crashes at runtime.
-  AtomicBoolean stop_{false};
-  Mediums mediums_;
-  EndpointChannelManager channel_manager_;
-  EndpointManager endpoint_manager_{&channel_manager_};
-  PayloadManager payload_manager_{endpoint_manager_};
-  PcpManager pcp_manager_{mediums_, channel_manager_, endpoint_manager_};
-};
-
-}  // namespace connections
-}  // namespace nearby
-}  // namespace location
-
-#endif  // CORE_V2_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_
diff -Naur a/src/3rdparty/chromium/third_party/perfetto/include/perfetto/base/compiler.h b/src/3rdparty/chromium/third_party/perfetto/include/perfetto/base/compiler.h
--- a/src/3rdparty/chromium/third_party/perfetto/include/perfetto/base/compiler.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/perfetto/include/perfetto/base/compiler.h	2021-06-18 16:56:16.001470839 +0100
@@ -73,6 +73,7 @@
 
 #if defined(__clang__)
 #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+#include <cstddef>
 extern "C" void __asan_poison_memory_region(void const volatile*, size_t);
 extern "C" void __asan_unpoison_memory_region(void const volatile*, size_t);
 #define PERFETTO_ASAN_POISON(a, s) __asan_poison_memory_region((a), (s))
diff -Naur a/src/3rdparty/chromium/third_party/perfetto/src/trace_processor/containers/string_pool.h b/src/3rdparty/chromium/third_party/perfetto/src/trace_processor/containers/string_pool.h
--- a/src/3rdparty/chromium/third_party/perfetto/src/trace_processor/containers/string_pool.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/perfetto/src/trace_processor/containers/string_pool.h	2021-06-18 16:55:44.249560701 +0100
@@ -17,6 +17,7 @@
 #ifndef SRC_TRACE_PROCESSOR_CONTAINERS_STRING_POOL_H_
 #define SRC_TRACE_PROCESSOR_CONTAINERS_STRING_POOL_H_
 
+#include <limits>
 #include <stddef.h>
 #include <stdint.h>
 
diff -Naur a/src/3rdparty/chromium/third_party/skia/src/core/SkScalerContext.cpp b/src/3rdparty/chromium/third_party/skia/src/core/SkScalerContext.cpp
--- a/src/3rdparty/chromium/third_party/skia/src/core/SkScalerContext.cpp	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/skia/src/core/SkScalerContext.cpp	2021-06-18 16:26:16.706783333 +0100
@@ -541,41 +541,39 @@
 }
 
 void SkScalerContext::getImage(const SkGlyph& origGlyph) {
-    const SkGlyph*  glyph = &origGlyph;
+    const SkGlyph* unfilteredGlyph = &origGlyph;
     SkGlyph  tmpGlyph{origGlyph.getPackedID()};
 
     // in case we need to call generateImage on a mask-format that is different
     // (i.e. larger) than what our caller allocated by looking at origGlyph.
     SkAutoMalloc tmpGlyphImageStorage;
 
-    if (fMaskFilter) {   // restore the prefilter bounds
-
+    if (fMaskFilter) {
         // need the original bounds, sans our maskfilter
         sk_sp<SkMaskFilter> mf = std::move(fMaskFilter);
         this->getMetrics(&tmpGlyph);
         fMaskFilter = std::move(mf);
 
-        // we need the prefilter bounds to be <= filter bounds
-        SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
-        SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
-
-        if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat) {
+        // Use the origGlyph storage for the temporary unfiltered mask if it will fit.
+        if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat &&
+            tmpGlyph.imageSize() <= origGlyph.imageSize())
+        {
             tmpGlyph.fImage = origGlyph.fImage;
         } else {
             tmpGlyphImageStorage.reset(tmpGlyph.imageSize());
             tmpGlyph.fImage = tmpGlyphImageStorage.get();
         }
-        glyph = &tmpGlyph;
+        unfilteredGlyph = &tmpGlyph;
     }
 
     if (!fGenerateImageFromPath) {
-        generateImage(*glyph);
+        generateImage(*unfilteredGlyph);
     } else {
         SkPath devPath;
-        SkMask mask = glyph->mask();
+        SkMask mask = unfilteredGlyph->mask();
 
-        if (!this->internalGetPath(glyph->getPackedID(), &devPath)) {
-            generateImage(*glyph);
+        if (!this->internalGetPath(unfilteredGlyph->getPackedID(), &devPath)) {
+            generateImage(*unfilteredGlyph);
         } else {
             SkASSERT(SkMask::kARGB32_Format != origGlyph.fMaskFormat);
             SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
@@ -587,39 +585,98 @@
     }
 
     if (fMaskFilter) {
-        // the src glyph image shouldn't be 3D
-        SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
+        // k3D_Format should not be mask filtered.
+        SkASSERT(SkMask::k3D_Format != unfilteredGlyph->fMaskFormat);
+
+        SkMask filteredMask;
+        SkMask srcMask;
+        SkMatrix m;
+        fRec.getMatrixFrom2x2(&m);
+
+        if (as_MFB(fMaskFilter)->filterMask(&filteredMask, unfilteredGlyph->mask(), m, nullptr)) {
+            // Filter succeeded; filteredMask.fImage was allocated.
+            srcMask = filteredMask;
+        } else if (unfilteredGlyph->fImage == tmpGlyphImageStorage.get()) {
+            // Filter did nothing; unfiltered mask is independent of origGlyph.fImage.
+            srcMask = unfilteredGlyph->mask();
+        } else if (origGlyph.iRect() == unfilteredGlyph->iRect()) {
+            // Filter did nothing; the unfiltered mask is in origGlyph.fImage and matches.
+            return;
+        } else {
+            // Filter did nothing; the unfiltered mask is in origGlyph.fImage and conflicts.
+            srcMask = unfilteredGlyph->mask();
+            size_t imageSize = unfilteredGlyph->imageSize();
+            tmpGlyphImageStorage.reset(imageSize);
+            srcMask.fImage = static_cast<uint8_t*>(tmpGlyphImageStorage.get());
+            memcpy(srcMask.fImage, unfilteredGlyph->fImage, imageSize);
+        }
+
+        SkASSERT_RELEASE(srcMask.fFormat == origGlyph.fMaskFormat);
+        SkMask dstMask = origGlyph.mask();
+        SkIRect origBounds = dstMask.fBounds;
+
+        // Find the intersection of src and dst while updating the fImages.
+        if (srcMask.fBounds.fTop < dstMask.fBounds.fTop) {
+            int32_t topDiff = dstMask.fBounds.fTop - srcMask.fBounds.fTop;
+            srcMask.fImage += srcMask.fRowBytes * topDiff;
+            srcMask.fBounds.fTop = dstMask.fBounds.fTop;
+        }
+        if (dstMask.fBounds.fTop < srcMask.fBounds.fTop) {
+            int32_t topDiff = srcMask.fBounds.fTop - dstMask.fBounds.fTop;
+            dstMask.fImage += dstMask.fRowBytes * topDiff;
+            dstMask.fBounds.fTop = srcMask.fBounds.fTop;
+        }
+
+        if (srcMask.fBounds.fLeft < dstMask.fBounds.fLeft) {
+            int32_t leftDiff = dstMask.fBounds.fLeft - srcMask.fBounds.fLeft;
+            srcMask.fImage += leftDiff;
+            srcMask.fBounds.fLeft = dstMask.fBounds.fLeft;
+        }
+        if (dstMask.fBounds.fLeft < srcMask.fBounds.fLeft) {
+            int32_t leftDiff = srcMask.fBounds.fLeft - dstMask.fBounds.fLeft;
+            dstMask.fImage += leftDiff;
+            dstMask.fBounds.fLeft = srcMask.fBounds.fLeft;
+        }
+
+        if (srcMask.fBounds.fBottom < dstMask.fBounds.fBottom) {
+            dstMask.fBounds.fBottom = srcMask.fBounds.fBottom;
+        }
+        if (dstMask.fBounds.fBottom < srcMask.fBounds.fBottom) {
+            srcMask.fBounds.fBottom = dstMask.fBounds.fBottom;
+        }
+
+        if (srcMask.fBounds.fRight < dstMask.fBounds.fRight) {
+            dstMask.fBounds.fRight = srcMask.fBounds.fRight;
+        }
+        if (dstMask.fBounds.fRight < srcMask.fBounds.fRight) {
+            srcMask.fBounds.fRight = dstMask.fBounds.fRight;
+        }
+
+        SkASSERT(srcMask.fBounds == dstMask.fBounds);
+        int width = srcMask.fBounds.width();
+        int height = srcMask.fBounds.height();
+        int dstRB = dstMask.fRowBytes;
+        int srcRB = srcMask.fRowBytes;
+
+        const uint8_t* src = srcMask.fImage;
+        uint8_t* dst = dstMask.fImage;
+
+        if (SkMask::k3D_Format == filteredMask.fFormat) {
+            // we have to copy 3 times as much
+            height *= 3;
+        }
+
+        // If not filling the full original glyph, clear it out first.
+        if (dstMask.fBounds != origBounds) {
+            sk_bzero(origGlyph.fImage, origGlyph.fHeight * origGlyph.rowBytes());
+        }
 
-        SkMask      srcM = glyph->mask(),
-                    dstM;
-        SkMatrix    matrix;
-
-        fRec.getMatrixFrom2x2(&matrix);
-
-        if (as_MFB(fMaskFilter)->filterMask(&dstM, srcM, matrix, nullptr)) {
-            int width = std::min<int>(origGlyph.fWidth, dstM.fBounds.width());
-            int height = std::min<int>(origGlyph.fHeight, dstM.fBounds.height());
-            int dstRB = origGlyph.rowBytes();
-            int srcRB = dstM.fRowBytes;
-
-            const uint8_t* src = (const uint8_t*)dstM.fImage;
-            uint8_t* dst = (uint8_t*)origGlyph.fImage;
-
-            if (SkMask::k3D_Format == dstM.fFormat) {
-                // we have to copy 3 times as much
-                height *= 3;
-            }
-
-            // clean out our glyph, since it may be larger than dstM
-            //sk_bzero(dst, height * dstRB);
-
-            while (--height >= 0) {
-                memcpy(dst, src, width);
-                src += srcRB;
-                dst += dstRB;
-            }
-            SkMask::FreeImage(dstM.fImage);
+        while (--height >= 0) {
+            memcpy(dst, src, width);
+            src += srcRB;
+            dst += dstRB;
         }
+        SkMask::FreeImage(filteredMask.fImage);
     }
 }
 
diff -Naur a/src/3rdparty/chromium/third_party/sqlite/src/amalgamation/sqlite3.c b/src/3rdparty/chromium/third_party/sqlite/src/amalgamation/sqlite3.c
--- a/src/3rdparty/chromium/third_party/sqlite/src/amalgamation/sqlite3.c	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/sqlite/src/amalgamation/sqlite3.c	2021-06-18 16:26:16.725816247 +0100
@@ -50422,6 +50422,7 @@
     p->page.pExtra = &p[1];
     p->isBulkLocal = 0;
     p->isAnchor = 0;
+    p->pLruPrev = 0;           /* Initializing this saves a valgrind error */
   }
   (*pCache->pnPurgeable)++;
   return p;
@@ -72324,7 +72325,9 @@
   }
   pgno = get4byte(pRight);
   while( 1 ){
-    rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+    if( rc==SQLITE_OK ){
+      rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+    }
     if( rc ){
       memset(apOld, 0, (i+1)*sizeof(MemPage*));
       goto balance_cleanup;
@@ -72363,12 +72366,10 @@
       if( pBt->btsFlags & BTS_FAST_SECURE ){
         int iOff;
 
+        /* If the following if() condition is not true, the db is corrupted.
+        ** The call to dropCell() below will detect this.  */
         iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
-        if( (iOff+szNew[i])>(int)pBt->usableSize ){
-          rc = SQLITE_CORRUPT_BKPT;
-          memset(apOld, 0, (i+1)*sizeof(MemPage*));
-          goto balance_cleanup;
-        }else{
+        if( (iOff+szNew[i])<=(int)pBt->usableSize ){
           memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
           apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
         }
@@ -231234,7 +231235,7 @@
 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
 
 /************** End of stmt.c ************************************************/
-#if __LINE__!=231237
+#if __LINE__!=231238
 #undef SQLITE_SOURCE_ID
 #define SQLITE_SOURCE_ID      "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
 #endif
diff -Naur a/src/3rdparty/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c b/src/3rdparty/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c
--- a/src/3rdparty/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c	2021-06-18 16:26:16.745850894 +0100
@@ -50435,6 +50435,7 @@
     p->page.pExtra = &p[1];
     p->isBulkLocal = 0;
     p->isAnchor = 0;
+    p->pLruPrev = 0;           /* Initializing this saves a valgrind error */
   }
   (*pCache->pnPurgeable)++;
   return p;
@@ -72337,7 +72338,9 @@
   }
   pgno = get4byte(pRight);
   while( 1 ){
-    rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+    if( rc==SQLITE_OK ){
+      rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+    }
     if( rc ){
       memset(apOld, 0, (i+1)*sizeof(MemPage*));
       goto balance_cleanup;
@@ -72376,12 +72379,10 @@
       if( pBt->btsFlags & BTS_FAST_SECURE ){
         int iOff;
 
+        /* If the following if() condition is not true, the db is corrupted.
+        ** The call to dropCell() below will detect this.  */
         iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
-        if( (iOff+szNew[i])>(int)pBt->usableSize ){
-          rc = SQLITE_CORRUPT_BKPT;
-          memset(apOld, 0, (i+1)*sizeof(MemPage*));
-          goto balance_cleanup;
-        }else{
+        if( (iOff+szNew[i])<=(int)pBt->usableSize ){
           memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
           apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
         }
@@ -231747,7 +231748,7 @@
 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
 
 /************** End of stmt.c ************************************************/
-#if __LINE__!=231750
+#if __LINE__!=231751
 #undef SQLITE_SOURCE_ID
 #define SQLITE_SOURCE_ID      "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
 #endif
diff -Naur a/src/3rdparty/chromium/third_party/sqlite/src/src/btree.c b/src/3rdparty/chromium/third_party/sqlite/src/src/btree.c
--- a/src/3rdparty/chromium/third_party/sqlite/src/src/btree.c	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/sqlite/src/src/btree.c	2021-06-18 16:26:16.747854358 +0100
@@ -7618,7 +7618,9 @@
   }
   pgno = get4byte(pRight);
   while( 1 ){
-    rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+    if( rc==SQLITE_OK ){
+      rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+    }
     if( rc ){
       memset(apOld, 0, (i+1)*sizeof(MemPage*));
       goto balance_cleanup;
@@ -7657,12 +7659,10 @@
       if( pBt->btsFlags & BTS_FAST_SECURE ){
         int iOff;
 
+        /* If the following if() condition is not true, the db is corrupted.
+        ** The call to dropCell() below will detect this.  */
         iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
-        if( (iOff+szNew[i])>(int)pBt->usableSize ){
-          rc = SQLITE_CORRUPT_BKPT;
-          memset(apOld, 0, (i+1)*sizeof(MemPage*));
-          goto balance_cleanup;
-        }else{
+        if( (iOff+szNew[i])<=(int)pBt->usableSize ){
           memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
           apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
         }
diff -Naur a/src/3rdparty/chromium/third_party/sqlite/src/src/pcache1.c b/src/3rdparty/chromium/third_party/sqlite/src/src/pcache1.c
--- a/src/3rdparty/chromium/third_party/sqlite/src/src/pcache1.c	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/sqlite/src/src/pcache1.c	2021-06-18 16:26:16.747854358 +0100
@@ -461,6 +461,7 @@
     p->page.pExtra = &p[1];
     p->isBulkLocal = 0;
     p->isAnchor = 0;
+    p->pLruPrev = 0;           /* Initializing this saves a valgrind error */
   }
   (*pCache->pnPurgeable)++;
   return p;
diff -Naur a/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.cc b/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.cc
--- a/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.cc	2021-06-18 16:26:16.747854358 +0100
@@ -20,6 +20,7 @@
 // Successful return value from usrsctp callbacks. Is not actually used by
 // usrsctp, but all example programs for usrsctp use 1 as their return value.
 constexpr int kSctpSuccessReturn = 1;
+constexpr int kSctpErrorReturn = 0;
 
 }  // namespace
 
@@ -27,6 +28,7 @@
 #include <stdio.h>
 #include <usrsctp.h>
 
+#include <functional>
 #include <memory>
 #include <unordered_map>
 
@@ -79,59 +81,22 @@
   PPID_TEXT_LAST = 51
 };
 
-// Maps SCTP transport ID to SctpTransport object, necessary in send threshold
-// callback and outgoing packet callback.
-// TODO(crbug.com/1076703): Remove once the underlying problem is fixed or
-// workaround is provided in usrsctp.
-class SctpTransportMap {
- public:
-  SctpTransportMap() = default;
-
-  // Assigns a new unused ID to the following transport.
-  uintptr_t Register(cricket::SctpTransport* transport) {
-    webrtc::MutexLock lock(&lock_);
-    // usrsctp_connect fails with a value of 0...
-    if (next_id_ == 0) {
-      ++next_id_;
-    }
-    // In case we've wrapped around and need to find an empty spot from a
-    // removed transport. Assumes we'll never be full.
-    while (map_.find(next_id_) != map_.end()) {
-      ++next_id_;
-      if (next_id_ == 0) {
-        ++next_id_;
-      }
-    };
-    map_[next_id_] = transport;
-    return next_id_++;
-  }
-
-  // Returns true if found.
-  bool Deregister(uintptr_t id) {
-    webrtc::MutexLock lock(&lock_);
-    return map_.erase(id) > 0;
-  }
-
-  cricket::SctpTransport* Retrieve(uintptr_t id) const {
-    webrtc::MutexLock lock(&lock_);
-    auto it = map_.find(id);
-    if (it == map_.end()) {
-      return nullptr;
-    }
-    return it->second;
-  }
+// Should only be modified by UsrSctpWrapper.
+ABSL_CONST_INIT cricket::SctpTransportMap* g_transport_map_ = nullptr;
 
+// Helper that will call C's free automatically.
+// TODO(b/181900299): Figure out why unique_ptr with a custom deleter is causing
+// issues in a certain build environment.
+class AutoFreedPointer {
+ public:
+  explicit AutoFreedPointer(void* ptr) : ptr_(ptr) {}
+  AutoFreedPointer(AutoFreedPointer&& o) : ptr_(o.ptr_) { o.ptr_ = nullptr; }
+  ~AutoFreedPointer() { free(ptr_); }
+  void* get() const { return ptr_; }
  private:
-  mutable webrtc::Mutex lock_;
-
-  uintptr_t next_id_ RTC_GUARDED_BY(lock_) = 0;
-  std::unordered_map<uintptr_t, cricket::SctpTransport*> map_
-      RTC_GUARDED_BY(lock_);
+  void* ptr_;
 };
 
-// Should only be modified by UsrSctpWrapper.
-ABSL_CONST_INIT SctpTransportMap* g_transport_map_ = nullptr;
-
 // Helper for logging SCTP messages.
 #if defined(__GNUC__)
 __attribute__((__format__(__printf__, 1, 2)))
@@ -256,6 +221,71 @@
 
 namespace cricket {
 
+// Maps SCTP transport ID to SctpTransport object, necessary in send threshold
+// callback and outgoing packet callback. It also provides a facility to
+// safely post a task to an SctpTransport's network thread from another thread.
+class SctpTransportMap {
+ public:
+  SctpTransportMap() = default;
+
+  // Assigns a new unused ID to the following transport.
+  uintptr_t Register(cricket::SctpTransport* transport) {
+    webrtc::MutexLock lock(&lock_);
+    // usrsctp_connect fails with a value of 0...
+    if (next_id_ == 0) {
+      ++next_id_;
+    }
+    // In case we've wrapped around and need to find an empty spot from a
+    // removed transport. Assumes we'll never be full.
+    while (map_.find(next_id_) != map_.end()) {
+      ++next_id_;
+      if (next_id_ == 0) {
+        ++next_id_;
+      }
+    };
+    map_[next_id_] = transport;
+    return next_id_++;
+  }
+
+  // Returns true if found.
+  bool Deregister(uintptr_t id) {
+    webrtc::MutexLock lock(&lock_);
+    return map_.erase(id) > 0;
+  }
+
+  // Posts |action| to the network thread of the transport identified by |id|
+  // and returns true if found, all while holding a lock to protect against the
+  // transport being simultaneously deleted/deregistered, or returns false if
+  // not found.
+  template <typename F>
+  bool PostToTransportThread(uintptr_t id, F action) const {
+    webrtc::MutexLock lock(&lock_);
+    SctpTransport* transport = RetrieveWhileHoldingLock(id);
+    if (!transport) {
+      return false;
+    }
+    transport->invoker_.AsyncInvoke<void>(
+        RTC_FROM_HERE, transport->network_thread_,
+        [transport, action{std::move(action)}]() { action(transport); });
+    return true;
+  }
+
+ private:
+  SctpTransport* RetrieveWhileHoldingLock(uintptr_t id) const
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_) {
+    auto it = map_.find(id);
+    if (it == map_.end()) {
+      return nullptr;
+    }
+    return it->second;
+  }
+
+  mutable webrtc::Mutex lock_;
+
+  uintptr_t next_id_ RTC_GUARDED_BY(lock_) = 0;
+  std::unordered_map<uintptr_t, SctpTransport*> map_ RTC_GUARDED_BY(lock_);
+};
+
 // Handles global init/deinit, and mapping from usrsctp callbacks to
 // SctpTransport calls.
 class SctpTransport::UsrSctpWrapper {
@@ -357,14 +387,6 @@
           << "OnSctpOutboundPacket called after usrsctp uninitialized?";
       return EINVAL;
     }
-    SctpTransport* transport =
-        g_transport_map_->Retrieve(reinterpret_cast<uintptr_t>(addr));
-    if (!transport) {
-      RTC_LOG(LS_ERROR)
-          << "OnSctpOutboundPacket: Failed to get transport for socket ID "
-          << addr;
-      return EINVAL;
-    }
     RTC_LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
                            "addr: "
                         << addr << "; length: " << length
@@ -372,13 +394,23 @@
                         << "; set_df: " << rtc::ToHex(set_df);
 
     VerboseLogPacket(data, length, SCTP_DUMP_OUTBOUND);
+
     // Note: We have to copy the data; the caller will delete it.
     rtc::CopyOnWriteBuffer buf(reinterpret_cast<uint8_t*>(data), length);
-    // TODO(deadbeef): Why do we need an AsyncInvoke here? We're already on the
-    // right thread and don't need to unwind the stack.
-    transport->invoker_.AsyncInvoke<void>(
-        RTC_FROM_HERE, transport->network_thread_,
-        rtc::Bind(&SctpTransport::OnPacketFromSctpToNetwork, transport, buf));
+
+    // PostsToTransportThread protects against the transport being
+    // simultaneously deregistered/deleted, since this callback may come from
+    // the SCTP timer thread and thus race with the network thread.
+    bool found = g_transport_map_->PostToTransportThread(
+        reinterpret_cast<uintptr_t>(addr), [buf](SctpTransport* transport) {
+          transport->OnPacketFromSctpToNetwork(buf);
+        });
+    if (!found) {
+      RTC_LOG(LS_ERROR)
+          << "OnSctpOutboundPacket: Failed to get transport for socket ID "
+          << addr << "; possibly was already destroyed.";
+      return EINVAL;
+    }
     return 0;
   }
 
@@ -393,28 +425,45 @@
                                  struct sctp_rcvinfo rcv,
                                  int flags,
                                  void* ulp_info) {
-    SctpTransport* transport = GetTransportFromSocket(sock);
-    if (!transport) {
+    AutoFreedPointer owned_data(data);
+    absl::optional<uintptr_t> id = GetTransportIdFromSocket(sock);
+    if (!id) {
       RTC_LOG(LS_ERROR)
-          << "OnSctpInboundPacket: Failed to get transport for socket " << sock
-          << "; possibly was already destroyed.";
-      free(data);
-      return 0;
+          << "OnSctpInboundPacket: Failed to get transport ID from socket "
+          << sock;
+      return kSctpErrorReturn;
     }
-    // Sanity check that both methods of getting the SctpTransport pointer
-    // yield the same result.
-    RTC_CHECK_EQ(transport, static_cast<SctpTransport*>(ulp_info));
-    int result =
-        transport->OnDataOrNotificationFromSctp(data, length, rcv, flags);
-    free(data);
-    return result;
+
+    if (!g_transport_map_) {
+      RTC_LOG(LS_ERROR)
+          << "OnSctpInboundPacket called after usrsctp uninitialized?";
+      return kSctpErrorReturn;
+    }
+    // PostsToTransportThread protects against the transport being
+    // simultaneously deregistered/deleted, since this callback may come from
+    // the SCTP timer thread and thus race with the network thread.
+    bool found = g_transport_map_->PostToTransportThread(
+        *id, [owned_data{std::move(owned_data)}, length, rcv,
+              flags](SctpTransport* transport) {
+          transport->OnDataOrNotificationFromSctp(owned_data.get(), length, rcv,
+                                                  flags);
+        });
+    if (!found) {
+      RTC_LOG(LS_ERROR)
+          << "OnSctpInboundPacket: Failed to get transport for socket ID "
+          << *id << "; possibly was already destroyed.";
+      return kSctpErrorReturn;
+    }
+    return kSctpSuccessReturn;
   }
 
-  static SctpTransport* GetTransportFromSocket(struct socket* sock) {
+  static absl::optional<uintptr_t> GetTransportIdFromSocket(
+      struct socket* sock) {
+    absl::optional<uintptr_t> ret;
     struct sockaddr* addrs = nullptr;
     int naddrs = usrsctp_getladdrs(sock, 0, &addrs);
     if (naddrs <= 0 || addrs[0].sa_family != AF_CONN) {
-      return nullptr;
+      return ret;
     }
     // usrsctp_getladdrs() returns the addresses bound to this socket, which
     // contains the SctpTransport id as sconn_addr.  Read the id,
@@ -423,17 +472,10 @@
     // id of the transport that created them, so [0] is as good as any other.
     struct sockaddr_conn* sconn =
         reinterpret_cast<struct sockaddr_conn*>(&addrs[0]);
-    if (!g_transport_map_) {
-      RTC_LOG(LS_ERROR)
-          << "GetTransportFromSocket called after usrsctp uninitialized?";
-      usrsctp_freeladdrs(addrs);
-      return nullptr;
-    }
-    SctpTransport* transport = g_transport_map_->Retrieve(
-        reinterpret_cast<uintptr_t>(sconn->sconn_addr));
+    ret = reinterpret_cast<uintptr_t>(sconn->sconn_addr);
     usrsctp_freeladdrs(addrs);
 
-    return transport;
+    return ret;
   }
 
   // TODO(crbug.com/webrtc/11899): This is a legacy callback signature, remove
@@ -442,14 +484,26 @@
     // Fired on our I/O thread. SctpTransport::OnPacketReceived() gets
     // a packet containing acknowledgments, which goes into usrsctp_conninput,
     // and then back here.
-    SctpTransport* transport = GetTransportFromSocket(sock);
-    if (!transport) {
+    absl::optional<uintptr_t> id = GetTransportIdFromSocket(sock);
+    if (!id) {
+      RTC_LOG(LS_ERROR)
+          << "SendThresholdCallback: Failed to get transport ID from socket "
+          << sock;
+      return 0;
+    }
+    if (!g_transport_map_) {
       RTC_LOG(LS_ERROR)
-          << "SendThresholdCallback: Failed to get transport for socket "
-          << sock << "; possibly was already destroyed.";
+          << "SendThresholdCallback called after usrsctp uninitialized?";
       return 0;
     }
-    transport->OnSendThresholdCallback();
+    bool found = g_transport_map_->PostToTransportThread(
+        *id,
+        [](SctpTransport* transport) { transport->OnSendThresholdCallback(); });
+    if (!found) {
+      RTC_LOG(LS_ERROR)
+          << "SendThresholdCallback: Failed to get transport for socket ID "
+          << *id << "; possibly was already destroyed.";
+    }
     return 0;
   }
 
@@ -459,17 +513,26 @@
     // Fired on our I/O thread. SctpTransport::OnPacketReceived() gets
     // a packet containing acknowledgments, which goes into usrsctp_conninput,
     // and then back here.
-    SctpTransport* transport = GetTransportFromSocket(sock);
-    if (!transport) {
+    absl::optional<uintptr_t> id = GetTransportIdFromSocket(sock);
+    if (!id) {
       RTC_LOG(LS_ERROR)
-          << "SendThresholdCallback: Failed to get transport for socket "
-          << sock << "; possibly was already destroyed.";
+          << "SendThresholdCallback: Failed to get transport ID from socket "
+          << sock;
       return 0;
     }
-    // Sanity check that both methods of getting the SctpTransport pointer
-    // yield the same result.
-    RTC_CHECK_EQ(transport, static_cast<SctpTransport*>(ulp_info));
-    transport->OnSendThresholdCallback();
+    if (!g_transport_map_) {
+      RTC_LOG(LS_ERROR)
+          << "SendThresholdCallback called after usrsctp uninitialized?";
+      return 0;
+    }
+    bool found = g_transport_map_->PostToTransportThread(
+        *id,
+        [](SctpTransport* transport) { transport->OnSendThresholdCallback(); });
+    if (!found) {
+      RTC_LOG(LS_ERROR)
+          << "SendThresholdCallback: Failed to get transport for socket ID "
+          << *id << "; possibly was already destroyed.";
+    }
     return 0;
   }
 };
@@ -1120,24 +1183,25 @@
                          rtc::PacketOptions(), PF_NORMAL);
 }
 
-int SctpTransport::InjectDataOrNotificationFromSctpForTesting(
+void SctpTransport::InjectDataOrNotificationFromSctpForTesting(
     void* data,
     size_t length,
     struct sctp_rcvinfo rcv,
     int flags) {
-  return OnDataOrNotificationFromSctp(data, length, rcv, flags);
+  OnDataOrNotificationFromSctp(data, length, rcv, flags);
 }
 
-int SctpTransport::OnDataOrNotificationFromSctp(void* data,
-                                                size_t length,
-                                                struct sctp_rcvinfo rcv,
-                                                int flags) {
+void SctpTransport::OnDataOrNotificationFromSctp(void* data,
+                                                 size_t length,
+                                                 struct sctp_rcvinfo rcv,
+                                                 int flags) {
+  RTC_DCHECK_RUN_ON(network_thread_);
   // If data is NULL, the SCTP association has been closed.
   if (!data) {
     RTC_LOG(LS_INFO) << debug_name_
                      << "->OnDataOrNotificationFromSctp(...): "
                         "No data; association closed.";
-    return kSctpSuccessReturn;
+    return;
   }
 
   // Handle notifications early.
@@ -1150,13 +1214,10 @@
         << "->OnDataOrNotificationFromSctp(...): SCTP notification"
         << " length=" << length;
 
-    // Copy and dispatch asynchronously
     rtc::CopyOnWriteBuffer notification(reinterpret_cast<uint8_t*>(data),
                                         length);
-    invoker_.AsyncInvoke<void>(
-        RTC_FROM_HERE, network_thread_,
-        rtc::Bind(&SctpTransport::OnNotificationFromSctp, this, notification));
-    return kSctpSuccessReturn;
+    OnNotificationFromSctp(notification);
+    return;
   }
 
   // Log data chunk
@@ -1174,7 +1235,7 @@
     // Unexpected PPID, dropping
     RTC_LOG(LS_ERROR) << "Received an unknown PPID " << ppid
                       << " on an SCTP packet.  Dropping.";
-    return kSctpSuccessReturn;
+    return;
   }
 
   // Expect only continuation messages belonging to the same SID. The SCTP
@@ -1210,7 +1271,7 @@
     if (partial_incoming_message_.size() < kSctpSendBufferSize) {
       // We still have space in the buffer. Continue buffering chunks until
       // the message is complete before handing it out.
-      return kSctpSuccessReturn;
+      return;
     } else {
       // The sender is exceeding the maximum message size that we announced.
       // Spit out a warning but still hand out the partial message. Note that
@@ -1224,17 +1285,11 @@
     }
   }
 
-  // Dispatch the complete message.
-  // The ownership of the packet transfers to |invoker_|. Using
-  // CopyOnWriteBuffer is the most convenient way to do this.
-  invoker_.AsyncInvoke<void>(
-      RTC_FROM_HERE, network_thread_,
-      rtc::Bind(&SctpTransport::OnDataFromSctpToTransport, this, params,
-                partial_incoming_message_));
+  // Dispatch the complete message and reset the message buffer.
 
-  // Reset the message buffer
+  // Dispatch the complete message and reset the message buffer.
+  OnDataFromSctpToTransport(params, partial_incoming_message_);
   partial_incoming_message_.Clear();
-  return kSctpSuccessReturn;
 }
 
 void SctpTransport::OnDataFromSctpToTransport(
diff -Naur a/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.h b/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.h
--- a/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/third_party/webrtc/media/sctp/sctp_transport.h	2021-06-18 16:26:16.748856091 +0100
@@ -96,10 +96,10 @@
   void set_debug_name_for_testing(const char* debug_name) override {
     debug_name_ = debug_name;
   }
-  int InjectDataOrNotificationFromSctpForTesting(void* data,
-                                                 size_t length,
-                                                 struct sctp_rcvinfo rcv,
-                                                 int flags);
+  void InjectDataOrNotificationFromSctpForTesting(void* data,
+                                                  size_t length,
+                                                  struct sctp_rcvinfo rcv,
+                                                  int flags);
 
   // Exposed to allow Post call from c-callbacks.
   // TODO(deadbeef): Remove this or at least make it return a const pointer.
@@ -180,12 +180,12 @@
   // Called using |invoker_| to send packet on the network.
   void OnPacketFromSctpToNetwork(const rtc::CopyOnWriteBuffer& buffer);
 
-  // Called on the SCTP thread.
+  // Called on the network thread.
   // Flags are standard socket API flags (RFC 6458).
-  int OnDataOrNotificationFromSctp(void* data,
-                                   size_t length,
-                                   struct sctp_rcvinfo rcv,
-                                   int flags);
+  void OnDataOrNotificationFromSctp(void* data,
+                                    size_t length,
+                                    struct sctp_rcvinfo rcv,
+                                    int flags);
   // Called using |invoker_| to decide what to do with the data.
   void OnDataFromSctpToTransport(const ReceiveDataParams& params,
                                  const rtc::CopyOnWriteBuffer& buffer);
@@ -281,6 +281,8 @@
   // various callbacks.
   uintptr_t id_ = 0;
 
+  friend class SctpTransportMap;
+
   RTC_DISALLOW_COPY_AND_ASSIGN(SctpTransport);
 };
 
@@ -299,6 +301,8 @@
   rtc::Thread* network_thread_;
 };
 
+class SctpTransportMap;
+
 }  // namespace cricket
 
 #endif  // MEDIA_SCTP_SCTP_TRANSPORT_H_
diff -Naur a/src/3rdparty/chromium/tools/metrics/histograms/enums.xml b/src/3rdparty/chromium/tools/metrics/histograms/enums.xml
--- a/src/3rdparty/chromium/tools/metrics/histograms/enums.xml	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/tools/metrics/histograms/enums.xml	2021-06-18 17:00:07.015977134 +0100
@@ -6487,6 +6487,7 @@
   <int value="232" label="RFH_RECEIVED_ASSOCIATED_MESSAGE_WHILE_BFCACHED"/>
   <int value="233" label="RWH_CLOSE_PORTAL"/>
   <int value="234" label="MSDH_INVALID_STREAM_TYPE"/>
+  <int value="243" label="WCI_INVALID_DOWNLOAD_IMAGE_RESULT"/>
 </enum>
 
 <enum name="BadMessageReasonExtensions">
@@ -8777,6 +8778,8 @@
   <int value="21" label="kKeysImplBackendClosed"/>
   <int value="22" label="kCreateBackendDidCreateFailed"/>
   <int value="23" label="kStorageGetAllMatchedEntriesBackendClosed"/>
+  <int value="24" label="kStorageHandleNull"/>
+  <int value="25" label="kWriteSideDataDidWriteMetadataWrongBytes"/>
 </enum>
 
 <enum name="CacheStorageErrorType">
diff -Naur a/src/3rdparty/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/src/3rdparty/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
--- a/src/3rdparty/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc	2021-06-18 16:52:55.600908299 +0100
@@ -610,7 +610,7 @@
     {0x0259, VKEY_OEM_3},      // schwa
 };
 
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(TOOLKIT_QT)
 void LoadKeymap(const std::string& layout_name,
                 scoped_refptr<base::SingleThreadTaskRunner> reply_runner,
                 LoadKeymapCallback reply_callback) {
@@ -678,7 +678,7 @@
 
 bool XkbKeyboardLayoutEngine::SetCurrentLayoutByName(
     const std::string& layout_name) {
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(TOOLKIT_QT)
   current_layout_name_ = layout_name;
   for (const auto& entry : xkb_keymaps_) {
     if (entry.layout_name == layout_name) {
diff -Naur a/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
--- a/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc	2021-06-18 16:57:43.808319538 +0100
@@ -583,7 +583,10 @@
   if (IsFullscreen() == fullscreen)
     return;
 
+  auto weak_ptr = GetWeakPtr();
   platform_window()->ToggleFullscreen();
+  if (!weak_ptr)
+    return;
 
   // The state must change synchronously to let media react on fullscreen
   // changes.
diff -Naur a/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
--- a/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc	2021-06-18 16:57:43.809321271 +0100
@@ -463,7 +463,10 @@
 }
 
 void DesktopWindowTreeHostWin::SetFullscreen(bool fullscreen) {
+  auto weak_ptr = GetWeakPtr();
   message_handler_->SetFullscreen(fullscreen);
+  if (!weak_ptr)
+    return;
   // TODO(sky): workaround for ScopedFullscreenVisibility showing window
   // directly. Instead of this should listen for visibility changes and then
   // update window.
diff -Naur a/src/3rdparty/chromium/ui/views/widget/widget.cc b/src/3rdparty/chromium/ui/views/widget/widget.cc
--- a/src/3rdparty/chromium/ui/views/widget/widget.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/views/widget/widget.cc	2021-06-18 16:57:43.809321271 +0100
@@ -724,7 +724,10 @@
   if (IsFullscreen() == fullscreen)
     return;
 
+  auto weak_ptr = GetWeakPtr();
   native_widget_->SetFullscreen(fullscreen);
+  if (!weak_ptr)
+    return;
 
   if (non_client_view_)
     non_client_view_->InvalidateLayout();
diff -Naur a/src/3rdparty/chromium/ui/views/widget/widget_unittest.cc b/src/3rdparty/chromium/ui/views/widget/widget_unittest.cc
--- a/src/3rdparty/chromium/ui/views/widget/widget_unittest.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/views/widget/widget_unittest.cc	2021-06-18 16:57:43.809321271 +0100
@@ -3084,6 +3084,41 @@
             IsNativeWindowVisible(top_level_widget->GetNativeWindow()));
 }
 
+// Used to delete the widget when the supplied bounds changes.
+class DestroyingWidgetBoundsObserver : public WidgetObserver {
+ public:
+  explicit DestroyingWidgetBoundsObserver(std::unique_ptr<Widget> widget)
+      : widget_(std::move(widget)) {
+    widget_->AddObserver(this);
+  }
+
+  // There are no assertions here as not all platforms call
+  // OnWidgetBoundsChanged() when going fullscreen.
+  ~DestroyingWidgetBoundsObserver() override = default;
+
+  // WidgetObserver:
+  void OnWidgetBoundsChanged(Widget* widget,
+                             const gfx::Rect& new_bounds) override {
+    widget_->RemoveObserver(this);
+    widget_.reset();
+  }
+
+ private:
+  std::unique_ptr<Widget> widget_;
+};
+
+// Deletes a Widget when the bounds change as part of toggling fullscreen.
+// This is a regression test for https://crbug.com/1197436 .
+TEST_F(DesktopWidgetTest, DeleteInSetFullscreen) {
+  std::unique_ptr<Widget> widget = std::make_unique<Widget>();
+  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+  params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  widget->Init(std::move(params));
+  Widget* w = widget.get();
+  DestroyingWidgetBoundsObserver destroyer(std::move(widget));
+  w->SetFullscreen(true);
+}
+
 namespace {
 
 class FullscreenAwareFrame : public views::NonClientFrameView {
diff -Naur a/src/3rdparty/chromium/ui/views/win/fullscreen_handler.cc b/src/3rdparty/chromium/ui/views/win/fullscreen_handler.cc
--- a/src/3rdparty/chromium/ui/views/win/fullscreen_handler.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/views/win/fullscreen_handler.cc	2021-06-18 16:57:43.809321271 +0100
@@ -70,6 +70,7 @@
 
   fullscreen_ = fullscreen;
 
+  auto ref = weak_ptr_factory_.GetWeakPtr();
   if (fullscreen_) {
     // Set new window style and size.
     SetWindowLong(hwnd_, GWL_STYLE,
@@ -102,6 +103,8 @@
                  new_rect.height(),
                  SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
   }
+  if (!ref)
+    return;
 
   MarkFullscreen(fullscreen);
 }
diff -Naur a/src/3rdparty/chromium/ui/views/win/fullscreen_handler.h b/src/3rdparty/chromium/ui/views/win/fullscreen_handler.h
--- a/src/3rdparty/chromium/ui/views/win/fullscreen_handler.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/views/win/fullscreen_handler.h	2021-06-18 16:57:43.809321271 +0100
@@ -11,6 +11,7 @@
 #include <map>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 
 namespace gfx {
 class Rect;
@@ -54,6 +55,8 @@
   // Used to mark a window as fullscreen.
   Microsoft::WRL::ComPtr<ITaskbarList2> task_bar_list_;
 
+  base::WeakPtrFactory<FullscreenHandler> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(FullscreenHandler);
 };
 
diff -Naur a/src/3rdparty/chromium/ui/views/win/hwnd_message_handler.cc b/src/3rdparty/chromium/ui/views/win/hwnd_message_handler.cc
--- a/src/3rdparty/chromium/ui/views/win/hwnd_message_handler.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/ui/views/win/hwnd_message_handler.cc	2021-06-18 16:57:43.810323003 +0100
@@ -895,7 +895,10 @@
 
 void HWNDMessageHandler::SetFullscreen(bool fullscreen) {
   background_fullscreen_hack_ = false;
+  auto ref = msg_handler_weak_factory_.GetWeakPtr();
   fullscreen_handler()->SetFullscreen(fullscreen);
+  if (!ref)
+    return;
 
   // Add the fullscreen window to the fullscreen window map which is used to
   // handle window activations.
@@ -1392,8 +1395,10 @@
   // Ignore size changes due to fullscreen windows losing activation.
   if (background_fullscreen_hack_ && !sent_window_size_changing_)
     return;
-  gfx::Size s = GetClientAreaBounds().size();
-  delegate_->HandleClientSizeChanged(s);
+  auto ref = msg_handler_weak_factory_.GetWeakPtr();
+  delegate_->HandleClientSizeChanged(GetClientAreaBounds().size());
+  if (!ref)
+    return;
 
   current_window_size_message_++;
   sent_window_size_changing_ = false;
@@ -1661,7 +1666,13 @@
                                          const gfx::Size& screen_size) {
   TRACE_EVENT0("ui", "HWNDMessageHandler::OnDisplayChange");
 
+  base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
   delegate_->HandleDisplayChange();
+
+  // HandleDisplayChange() may result in |this| being deleted.
+  if (!ref)
+    return;
+
   // Force a WM_NCCALCSIZE to occur to ensure that we handle auto hide
   // taskbars correctly.
   SendFrameChanged();
@@ -2912,8 +2923,11 @@
 void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
   TRACE_EVENT0("ui", "HWNDMessageHandler::OnWindowPosChanged");
 
+  base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
   if (DidClientAreaSizeChange(window_pos))
     ClientAreaSizeChanged();
+  if (!ref)
+    return;
   if (window_pos->flags & SWP_FRAMECHANGED)
     SetDwmFrameExtension(DwmFrameState::kOn);
   if (window_pos->flags & SWP_SHOWWINDOW) {
diff -Naur a/src/3rdparty/chromium/url/origin.cc b/src/3rdparty/chromium/url/origin.cc
--- a/src/3rdparty/chromium/url/origin.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/url/origin.cc	2021-06-18 16:26:16.754866485 +0100
@@ -54,7 +54,10 @@
 
   if (!tuple.IsValid())
     return Origin();
-  return Origin(std::move(tuple));
+
+  Origin origin = Origin(std::move(tuple));
+  origin.full_url_ = url;
+  return origin;
 }
 
 Origin Origin::Resolve(const GURL& url, const Origin& base_origin) {
@@ -152,6 +155,17 @@
   return tuple_.GetURL();
 }
 
+GURL Origin::GetFullURL() const {
+  if (opaque())
+    return GURL();
+
+  return full_url_;
+}
+
+void Origin::SetFullURL(const GURL &url) {
+  full_url_ = url;
+}
+
 base::Optional<base::UnguessableToken> Origin::GetNonceForSerialization()
     const {
   // TODO(nasko): Consider not making a copy here, but return a reference to
diff -Naur a/src/3rdparty/chromium/url/origin.h b/src/3rdparty/chromium/url/origin.h
--- a/src/3rdparty/chromium/url/origin.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/url/origin.h	2021-06-18 16:26:16.754866485 +0100
@@ -20,6 +20,7 @@
 #include "base/unguessable_token.h"
 #include "build/build_config.h"
 #include "ipc/ipc_param_traits.h"
+#include "url/gurl.h"
 #include "url/scheme_host_port.h"
 #include "url/third_party/mozilla/url_parse.h"
 #include "url/url_canon.h"
@@ -260,6 +261,9 @@
   // URL (e.g. with a path component).
   GURL GetURL() const;
 
+  GURL GetFullURL() const;
+  void SetFullURL(const GURL &url);
+
   // Same as GURL::DomainIs. If |this| origin is opaque, then returns false.
   bool DomainIs(base::StringPiece canonical_domain) const;
 
@@ -414,6 +418,8 @@
   // nonce is preserved when an opaque origin is copied or moved. An Origin
   // is considered opaque if and only if |nonce_| holds a value.
   base::Optional<Nonce> nonce_;
+
+  GURL full_url_;
 };
 
 // Pretty-printers for logging. These expose the internal state of the nonce.
diff -Naur a/src/3rdparty/chromium/v8/AUTHORS b/src/3rdparty/chromium/v8/AUTHORS
--- a/src/3rdparty/chromium/v8/AUTHORS	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/AUTHORS	2021-06-18 16:26:16.754866485 +0100
@@ -69,6 +69,7 @@
 Ben Noordhuis <info@bnoordhuis.nl>
 Benjamin Tan <demoneaux@gmail.com>
 Bert Belder <bertbelder@gmail.com>
+Brendon Tiszka <btiszka@gmail.com>
 Burcu Dogan <burcujdogan@gmail.com>
 Caitlin Potter <caitpotter88@gmail.com>
 Craig Schlenter <craig.schlenter@gmail.com>
diff -Naur a/src/3rdparty/chromium/v8/include/v8-version.h b/src/3rdparty/chromium/v8/include/v8-version.h
--- a/src/3rdparty/chromium/v8/include/v8-version.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/include/v8-version.h	2021-06-18 16:55:54.031477049 +0100
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 8
 #define V8_MINOR_VERSION 7
 #define V8_BUILD_NUMBER 220
-#define V8_PATCH_LEVEL 31
+#define V8_PATCH_LEVEL 32
 
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff -Naur a/src/3rdparty/chromium/v8/src/base/platform/mutex.h b/src/3rdparty/chromium/v8/src/base/platform/mutex.h
--- a/src/3rdparty/chromium/v8/src/base/platform/mutex.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/base/platform/mutex.h	2021-06-18 17:02:27.648181878 +0100
@@ -11,6 +11,7 @@
 #include "src/base/win32-headers.h"
 #endif
 #include "src/base/logging.h"
+#include "src/base/optional.h"
 
 #if V8_OS_POSIX
 #include <pthread.h>  // NOLINT
@@ -340,6 +341,20 @@
   DISALLOW_COPY_AND_ASSIGN(SharedMutexGuard);
 };
 
+template <MutexSharedType kIsShared,
+          NullBehavior Behavior = NullBehavior::kRequireNotNull>
+class SharedMutexGuardIf final {
+ public:
+  SharedMutexGuardIf(SharedMutex* mutex, bool enable_mutex) {
+    if (enable_mutex) mutex_.emplace(mutex);
+  }
+
+ private:
+  base::Optional<SharedMutexGuard<kIsShared, Behavior>> mutex_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedMutexGuardIf);
+};
+
 }  // namespace base
 }  // namespace v8
 
diff -Naur a/src/3rdparty/chromium/v8/src/builtins/builtins-array.cc b/src/3rdparty/chromium/v8/src/builtins/builtins-array.cc
--- a/src/3rdparty/chromium/v8/src/builtins/builtins-array.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/builtins/builtins-array.cc	2021-06-18 16:26:16.755868217 +0100
@@ -649,11 +649,14 @@
         index_offset_(0u),
         bit_field_(FastElementsField::encode(fast_elements) |
                    ExceedsLimitField::encode(false) |
-                   IsFixedArrayField::encode(storage->IsFixedArray()) |
+                   IsFixedArrayField::encode(storage->IsFixedArray(isolate)) |
                    HasSimpleElementsField::encode(
-                       storage->IsFixedArray() ||
-                       !storage->map().IsCustomElementsReceiverMap())) {
-    DCHECK(!(this->fast_elements() && !is_fixed_array()));
+                       storage->IsFixedArray(isolate) ||
+                       // Don't take fast path for storages that might have
+                       // side effects when storing to them.
+                       (!storage->map(isolate).IsCustomElementsReceiverMap() &&
+                        !storage->IsJSTypedArray(isolate)))) {
+    DCHECK_IMPLIES(this->fast_elements(), is_fixed_array());
   }
 
   ~ArrayConcatVisitor() { clear_storage(); }
@@ -1063,8 +1066,8 @@
     return IterateElementsSlow(isolate, receiver, length, visitor);
   }
 
-  if (!HasOnlySimpleElements(isolate, *receiver) ||
-      !visitor->has_simple_elements()) {
+  if (!visitor->has_simple_elements() ||
+      !HasOnlySimpleElements(isolate, *receiver)) {
     return IterateElementsSlow(isolate, receiver, length, visitor);
   }
   Handle<JSObject> array = Handle<JSObject>::cast(receiver);
@@ -1080,6 +1083,9 @@
     case HOLEY_SEALED_ELEMENTS:
     case HOLEY_NONEXTENSIBLE_ELEMENTS:
     case HOLEY_ELEMENTS: {
+      // Disallow execution so the cached elements won't change mid execution.
+      DisallowJavascriptExecution no_js(isolate);
+
       // Run through the elements FixedArray and use HasElement and GetElement
       // to check the prototype for missing elements.
       Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate);
@@ -1106,6 +1112,9 @@
     }
     case HOLEY_DOUBLE_ELEMENTS:
     case PACKED_DOUBLE_ELEMENTS: {
+      // Disallow execution so the cached elements won't change mid execution.
+      DisallowJavascriptExecution no_js(isolate);
+
       // Empty array is FixedArray but not FixedDoubleArray.
       if (length == 0) break;
       // Run through the elements FixedArray and use HasElement and GetElement
@@ -1142,6 +1151,9 @@
     }
 
     case DICTIONARY_ELEMENTS: {
+      // Disallow execution so the cached dictionary won't change mid execution.
+      DisallowJavascriptExecution no_js(isolate);
+
       Handle<NumberDictionary> dict(array->element_dictionary(), isolate);
       std::vector<uint32_t> indices;
       indices.reserve(dict->Capacity() / 2);
diff -Naur a/src/3rdparty/chromium/v8/src/builtins/builtins-internal-gen.cc b/src/3rdparty/chromium/v8/src/builtins/builtins-internal-gen.cc
--- a/src/3rdparty/chromium/v8/src/builtins/builtins-internal-gen.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/builtins/builtins-internal-gen.cc	2021-06-18 17:02:27.648181878 +0100
@@ -508,8 +508,8 @@
     Label dictionary(this), dont_delete(this);
     GotoIf(IsDictionaryMap(receiver_map), &dictionary);
 
-    // Fast properties need to clear recorded slots, which can only be done
-    // in C++.
+    // Fast properties need to clear recorded slots and mark the deleted
+    // property as mutable, which can only be done in C++.
     Goto(&slow);
 
     BIND(&dictionary);
diff -Naur a/src/3rdparty/chromium/v8/src/compiler/backend/ia32/instruction-selector-ia32.cc b/src/3rdparty/chromium/v8/src/compiler/backend/ia32/instruction-selector-ia32.cc
--- a/src/3rdparty/chromium/v8/src/compiler/backend/ia32/instruction-selector-ia32.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/compiler/backend/ia32/instruction-selector-ia32.cc	2021-06-18 17:01:00.567587541 +0100
@@ -2199,7 +2199,7 @@
   IA32OperandGenerator g(this);
   InstructionOperand temps[] = {g.TempSimd128Register()};
   InstructionOperand operand0 = g.UseUniqueRegister(node->InputAt(0));
-  InstructionOperand operand1 = g.UseUnique(node->InputAt(1));
+  InstructionOperand operand1 = g.UseUniqueRegister(node->InputAt(1));
 
   if (IsSupported(AVX)) {
     Emit(kIA32F64x2Min, g.DefineAsRegister(node), operand0, operand1,
@@ -2214,7 +2214,7 @@
   IA32OperandGenerator g(this);
   InstructionOperand temps[] = {g.TempSimd128Register()};
   InstructionOperand operand0 = g.UseUniqueRegister(node->InputAt(0));
-  InstructionOperand operand1 = g.UseUnique(node->InputAt(1));
+  InstructionOperand operand1 = g.UseUniqueRegister(node->InputAt(1));
   if (IsSupported(AVX)) {
     Emit(kIA32F64x2Max, g.DefineAsRegister(node), operand0, operand1,
          arraysize(temps), temps);
diff -Naur a/src/3rdparty/chromium/v8/src/compiler/backend/x64/instruction-selector-x64.cc b/src/3rdparty/chromium/v8/src/compiler/backend/x64/instruction-selector-x64.cc
--- a/src/3rdparty/chromium/v8/src/compiler/backend/x64/instruction-selector-x64.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/compiler/backend/x64/instruction-selector-x64.cc	2021-06-18 16:26:16.755868217 +0100
@@ -1279,7 +1279,9 @@
         opcode = load_rep.IsSigned() ? kX64Movsxwq : kX64Movzxwq;
         break;
       case MachineRepresentation::kWord32:
-        opcode = load_rep.IsSigned() ? kX64Movsxlq : kX64Movl;
+        // ChangeInt32ToInt64 must interpret its input as a _signed_ 32-bit
+        // integer, so here we must sign-extend the loaded value in any case.
+        opcode = kX64Movsxlq;
         break;
       default:
         UNREACHABLE();
diff -Naur a/src/3rdparty/chromium/v8/src/compiler/js-call-reducer.cc b/src/3rdparty/chromium/v8/src/compiler/js-call-reducer.cc
--- a/src/3rdparty/chromium/v8/src/compiler/js-call-reducer.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/compiler/js-call-reducer.cc	2021-06-18 16:26:16.756869949 +0100
@@ -5251,24 +5251,31 @@
       }
 
       // Compute the new {length}.
-      length = graph()->NewNode(simplified()->NumberSubtract(), length,
-                                jsgraph()->OneConstant());
+      Node* new_length = graph()->NewNode(simplified()->NumberSubtract(),
+                                          length, jsgraph()->OneConstant());
+
+      // This extra check exists solely to break an exploitation technique
+      // that abuses typer mismatches.
+      new_length = efalse = graph()->NewNode(
+          simplified()->CheckBounds(p.feedback(),
+                                    CheckBoundsFlag::kAbortOnOutOfBounds),
+          new_length, length, efalse, if_false);
 
       // Store the new {length} to the {receiver}.
       efalse = graph()->NewNode(
           simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
-          receiver, length, efalse, if_false);
+          receiver, new_length, efalse, if_false);
 
       // Load the last entry from the {elements}.
       vfalse = efalse = graph()->NewNode(
           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
-          elements, length, efalse, if_false);
+          elements, new_length, efalse, if_false);
 
       // Store a hole to the element we just removed from the {receiver}.
       efalse = graph()->NewNode(
           simplified()->StoreElement(
               AccessBuilder::ForFixedArrayElement(GetHoleyElementsKind(kind))),
-          elements, length, jsgraph()->TheHoleConstant(), efalse, if_false);
+          elements, new_length, jsgraph()->TheHoleConstant(), efalse, if_false);
     }
 
     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
@@ -5444,19 +5451,27 @@
         }
 
         // Compute the new {length}.
-        length = graph()->NewNode(simplified()->NumberSubtract(), length,
-                                  jsgraph()->OneConstant());
+        Node* new_length = graph()->NewNode(simplified()->NumberSubtract(),
+                                            length, jsgraph()->OneConstant());
+
+        // This extra check exists solely to break an exploitation technique
+        // that abuses typer mismatches.
+        new_length = etrue1 = graph()->NewNode(
+            simplified()->CheckBounds(p.feedback(),
+                                      CheckBoundsFlag::kAbortOnOutOfBounds),
+            new_length, length, etrue1, if_true1);
 
         // Store the new {length} to the {receiver}.
         etrue1 = graph()->NewNode(
             simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
-            receiver, length, etrue1, if_true1);
+            receiver, new_length, etrue1, if_true1);
 
         // Store a hole to the element we just removed from the {receiver}.
         etrue1 = graph()->NewNode(
             simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
                 GetHoleyElementsKind(kind))),
-            elements, length, jsgraph()->TheHoleConstant(), etrue1, if_true1);
+            elements, new_length, jsgraph()->TheHoleConstant(), etrue1,
+            if_true1);
       }
 
       Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
diff -Naur a/src/3rdparty/chromium/v8/src/compiler/representation-change.cc b/src/3rdparty/chromium/v8/src/compiler/representation-change.cc
--- a/src/3rdparty/chromium/v8/src/compiler/representation-change.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/compiler/representation-change.cc	2021-06-18 16:26:16.756869949 +0100
@@ -211,7 +211,10 @@
       return GetFloat32RepresentationFor(node, output_rep, output_type,
                                          use_info.truncation());
     case MachineRepresentation::kFloat64:
-      DCHECK_NE(TypeCheckKind::kBigInt, use_info.type_check());
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
+             use_info.type_check() == TypeCheckKind::kNumber ||
+             use_info.type_check() == TypeCheckKind::kNumberOrBoolean ||
+             use_info.type_check() == TypeCheckKind::kNumberOrOddball);
       return GetFloat64RepresentationFor(node, output_rep, output_type,
                                          use_node, use_info);
     case MachineRepresentation::kBit:
@@ -727,15 +730,22 @@
     }
   } else if (IsAnyTagged(output_rep)) {
     if (output_type.Is(Type::Undefined())) {
-      if (use_info.type_check() == TypeCheckKind::kNumberOrBoolean) {
+      if (use_info.type_check() == TypeCheckKind::kNumberOrOddball ||
+          (use_info.type_check() == TypeCheckKind::kNone &&
+           use_info.truncation().TruncatesOddballAndBigIntToNumber())) {
+        return jsgraph()->Float64Constant(
+            std::numeric_limits<double>::quiet_NaN());
+      } else {
+        DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
+               use_info.type_check() == TypeCheckKind::kNumber ||
+               use_info.type_check() == TypeCheckKind::kNumberOrBoolean);
         Node* unreachable = InsertUnconditionalDeopt(
-            use_node, DeoptimizeReason::kNotANumberOrBoolean);
+            use_node, use_info.type_check() == TypeCheckKind::kNumber
+                          ? DeoptimizeReason::kNotANumber
+                          : DeoptimizeReason::kNotANumberOrBoolean);
         return jsgraph()->graph()->NewNode(
             jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
             unreachable);
-      } else {
-        return jsgraph()->Float64Constant(
-            std::numeric_limits<double>::quiet_NaN());
       }
     } else if (output_rep == MachineRepresentation::kTaggedSigned) {
       node = InsertChangeTaggedSignedToInt32(node);
@@ -747,12 +757,13 @@
                output_type.Is(Type::NumberOrHole())) {
       // JavaScript 'null' is an Oddball that results in +0 when truncated to
       // Number. In a context like -0 == null, which must evaluate to false,
-      // this truncation must not happen. For this reason we restrict this case
-      // to when either the user explicitly requested a float (and thus wants
-      // +0 if null is the input) or we know from the types that the input can
-      // only be Number | Hole. The latter is necessary to handle the operator
-      // CheckFloat64Hole. We did not put in the type (Number | Oddball \ Null)
-      // to discover more bugs related to this conversion via crashes.
+      // this truncation must not happen. For this reason we restrict this
+      // case to when either the user explicitly requested a float (and thus
+      // wants +0 if null is the input) or we know from the types that the
+      // input can only be Number | Hole. The latter is necessary to handle
+      // the operator CheckFloat64Hole. We did not put in the type (Number |
+      // Oddball \ Null) to discover more bugs related to this conversion via
+      // crashes.
       op = simplified()->TruncateTaggedToFloat64();
     } else if (use_info.type_check() == TypeCheckKind::kNumber ||
                (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
@@ -949,10 +960,10 @@
     return node;
   } else if (output_rep == MachineRepresentation::kWord64) {
     if (output_type.Is(Type::Signed32()) ||
-        output_type.Is(Type::Unsigned32())) {
-      op = machine()->TruncateInt64ToInt32();
-    } else if (output_type.Is(cache_->kSafeInteger) &&
-               use_info.truncation().IsUsedAsWord32()) {
+        (output_type.Is(Type::Unsigned32()) &&
+         use_info.type_check() == TypeCheckKind::kNone) ||
+        (output_type.Is(cache_->kSafeInteger) &&
+         use_info.truncation().IsUsedAsWord32())) {
       op = machine()->TruncateInt64ToInt32();
     } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
                use_info.type_check() == TypeCheckKind::kSigned32 ||
diff -Naur a/src/3rdparty/chromium/v8/src/compiler/simplified-lowering.cc b/src/3rdparty/chromium/v8/src/compiler/simplified-lowering.cc
--- a/src/3rdparty/chromium/v8/src/compiler/simplified-lowering.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/compiler/simplified-lowering.cc	2021-06-18 16:59:18.617277999 +0100
@@ -1398,17 +1398,32 @@
     return jsgraph_->simplified();
   }
 
-  void LowerToCheckedInt32Mul(Node* node, Truncation truncation,
-                              Type input0_type, Type input1_type) {
-    // If one of the inputs is positive and/or truncation is being applied,
-    // there is no need to return -0.
-    CheckForMinusZeroMode mz_mode =
-        truncation.IdentifiesZeroAndMinusZero() ||
-                IsSomePositiveOrderedNumber(input0_type) ||
-                IsSomePositiveOrderedNumber(input1_type)
-            ? CheckForMinusZeroMode::kDontCheckForMinusZero
-            : CheckForMinusZeroMode::kCheckForMinusZero;
-    NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
+  template <Phase T>
+  void VisitForCheckedInt32Mul(Node* node, Truncation truncation,
+                               Type input0_type, Type input1_type,
+                               UseInfo input_use) {
+    DCHECK_EQ(node->opcode(), IrOpcode::kSpeculativeNumberMultiply);
+    // A -0 input is impossible or will cause a deopt.
+    DCHECK(BothInputsAre(node, Type::Signed32()) ||
+           !input_use.truncation().IdentifiesZeroAndMinusZero());
+
+    CheckForMinusZeroMode mz_mode;
+    Type restriction;
+    if (IsSomePositiveOrderedNumber(input0_type) ||
+        IsSomePositiveOrderedNumber(input1_type)) {
+      mz_mode = CheckForMinusZeroMode::kDontCheckForMinusZero;
+      restriction = Type::Signed32();
+    } else if (truncation.IdentifiesZeroAndMinusZero()) {
+      mz_mode = CheckForMinusZeroMode::kDontCheckForMinusZero;
+      restriction = Type::Signed32OrMinusZero();
+    } else {
+      mz_mode = CheckForMinusZeroMode::kCheckForMinusZero;
+      restriction = Type::Signed32();
+    }
+
+    VisitBinop<T>(node, input_use, MachineRepresentation::kWord32, restriction);
+    if (lower<T>())
+      NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
   }
 
   void ChangeToInt32OverflowOp(Node* node) {
@@ -1453,10 +1468,15 @@
     Type right_feedback_type = TypeOf(node->InputAt(1));
 
     // Using Signed32 as restriction type amounts to promising there won't be
-    // signed overflow. This is incompatible with relying on a Word32
-    // truncation in order to skip the overflow check.
+    // signed overflow. This is incompatible with relying on a Word32 truncation
+    // in order to skip the overflow check.  Similarly, we must not drop -0 from
+    // the result type unless we deopt for -0 inputs.
     Type const restriction =
-        truncation.IsUsedAsWord32() ? Type::Any() : Type::Signed32();
+        truncation.IsUsedAsWord32()
+            ? Type::Any()
+            : (truncation.identify_zeros() == kIdentifyZeros)
+                  ? Type::Signed32OrMinusZero()
+                  : Type::Signed32();
 
     // Handle the case when no int32 checks on inputs are necessary (but
     // an overflow check is needed on the output). Note that we do not
@@ -1595,12 +1615,22 @@
         VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32);
         if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node));
       } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) {
+        Type const restriction =
+            truncation.IdentifiesZeroAndMinusZero() &&
+                    TypeOf(node->InputAt(0)).Maybe(Type::MinusZero())
+                ? Type::Unsigned32OrMinusZero()
+                : Type::Unsigned32();
         VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32,
-                      Type::Unsigned32());
+                      restriction);
         if (lower<T>()) ChangeToUint32OverflowOp(node);
       } else {
+        Type const restriction =
+            truncation.IdentifiesZeroAndMinusZero() &&
+                    TypeOf(node->InputAt(0)).Maybe(Type::MinusZero())
+                ? Type::Signed32OrMinusZero()
+                : Type::Signed32();
         VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32,
-                      Type::Signed32());
+                      restriction);
         if (lower<T>()) ChangeToInt32OverflowOp(node);
       }
       return;
@@ -2160,23 +2190,17 @@
           // If both inputs and feedback are int32, use the overflow op.
           if (hint == NumberOperationHint::kSignedSmall ||
               hint == NumberOperationHint::kSigned32) {
-            VisitBinop<T>(node, UseInfo::TruncatingWord32(),
-                          MachineRepresentation::kWord32, Type::Signed32());
-            if (lower<T>()) {
-              LowerToCheckedInt32Mul(node, truncation, input0_type,
-                                     input1_type);
-            }
+            VisitForCheckedInt32Mul<T>(node, truncation, input0_type,
+                                       input1_type,
+                                       UseInfo::TruncatingWord32());
             return;
           }
         }
 
         if (hint == NumberOperationHint::kSignedSmall ||
             hint == NumberOperationHint::kSigned32) {
-          VisitBinop<T>(node, CheckedUseInfoAsWord32FromHint(hint),
-                        MachineRepresentation::kWord32, Type::Signed32());
-          if (lower<T>()) {
-            LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type);
-          }
+          VisitForCheckedInt32Mul<T>(node, truncation, input0_type, input1_type,
+                                     CheckedUseInfoAsWord32FromHint(hint));
           return;
         }
 
@@ -3896,7 +3920,6 @@
 void RepresentationSelector::SetOutput<RETYPE>(
     Node* node, MachineRepresentation representation, Type restriction_type) {
   NodeInfo* const info = GetInfo(node);
-  DCHECK(info->restriction_type().Is(restriction_type));
   DCHECK(restriction_type.Is(info->restriction_type()));
   info->set_output(representation);
 }
@@ -3906,7 +3929,6 @@
     Node* node, MachineRepresentation representation, Type restriction_type) {
   NodeInfo* const info = GetInfo(node);
   DCHECK_EQ(info->representation(), representation);
-  DCHECK(info->restriction_type().Is(restriction_type));
   DCHECK(restriction_type.Is(info->restriction_type()));
   USE(info);
 }
diff -Naur a/src/3rdparty/chromium/v8/src/compiler/type-cache.h b/src/3rdparty/chromium/v8/src/compiler/type-cache.h
--- a/src/3rdparty/chromium/v8/src/compiler/type-cache.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/compiler/type-cache.h	2021-06-18 16:26:16.756869949 +0100
@@ -80,7 +80,7 @@
       Type::Union(kPositiveIntegerOrMinusZero, Type::NaN(), zone());
 
   Type const kAdditiveSafeInteger =
-      CreateRange(-4503599627370496.0, 4503599627370496.0);
+      CreateRange(-4503599627370495.0, 4503599627370495.0);
   Type const kSafeInteger = CreateRange(-kMaxSafeInteger, kMaxSafeInteger);
   Type const kAdditiveSafeIntegerOrMinusZero =
       Type::Union(kAdditiveSafeInteger, Type::MinusZero(), zone());
diff -Naur a/src/3rdparty/chromium/v8/src/deoptimizer/deoptimize-reason.h b/src/3rdparty/chromium/v8/src/deoptimizer/deoptimize-reason.h
--- a/src/3rdparty/chromium/v8/src/deoptimizer/deoptimize-reason.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/deoptimizer/deoptimize-reason.h	2021-06-18 16:26:16.757871682 +0100
@@ -43,6 +43,7 @@
   V(NotAJavaScriptObject, "not a JavaScript object")                           \
   V(NotAJavaScriptObjectOrNullOrUndefined,                                     \
     "not a JavaScript object, Null or Undefined")                              \
+  V(NotANumber, "not a Number")                                                \
   V(NotANumberOrBoolean, "not a Number or Boolean")                            \
   V(NotANumberOrOddball, "not a Number or Oddball")                            \
   V(NotAnArrayIndex, "not an array index")                                     \
diff -Naur a/src/3rdparty/chromium/v8/src/heap/memory-chunk-layout.cc b/src/3rdparty/chromium/v8/src/heap/memory-chunk-layout.cc
--- a/src/3rdparty/chromium/v8/src/heap/memory-chunk-layout.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/heap/memory-chunk-layout.cc	2021-06-18 16:26:16.757871682 +0100
@@ -42,7 +42,7 @@
 }
 
 intptr_t MemoryChunkLayout::ObjectStartOffsetInDataPage() {
-  return RoundUp(MemoryChunk::kHeaderSize + Bitmap::kSize, kTaggedSize);
+  return RoundUp(MemoryChunk::kHeaderSize + Bitmap::kSize, kDoubleSize);
 }
 
 size_t MemoryChunkLayout::ObjectStartOffsetInMemoryChunk(
diff -Naur a/src/3rdparty/chromium/v8/src/objects/fixed-array-inl.h b/src/3rdparty/chromium/v8/src/objects/fixed-array-inl.h
--- a/src/3rdparty/chromium/v8/src/objects/fixed-array-inl.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/fixed-array-inl.h	2021-06-18 16:26:16.757871682 +0100
@@ -336,7 +336,7 @@
 double FixedDoubleArray::get_scalar(int index) {
   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
          map() != GetReadOnlyRoots().fixed_array_map());
-  DCHECK(index >= 0 && index < this->length());
+  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
   DCHECK(!is_the_hole(index));
   return ReadField<double>(kHeaderSize + index * kDoubleSize);
 }
@@ -344,7 +344,7 @@
 uint64_t FixedDoubleArray::get_representation(int index) {
   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
          map() != GetReadOnlyRoots().fixed_array_map());
-  DCHECK(index >= 0 && index < this->length());
+  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
   int offset = kHeaderSize + index * kDoubleSize;
   // Bug(v8:8875): Doubles may be unaligned.
   return base::ReadUnalignedValue<uint64_t>(field_address(offset));
@@ -362,6 +362,7 @@
 void FixedDoubleArray::set(int index, double value) {
   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
          map() != GetReadOnlyRoots().fixed_array_map());
+  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
   int offset = kHeaderSize + index * kDoubleSize;
   if (std::isnan(value)) {
     WriteField<double>(offset, std::numeric_limits<double>::quiet_NaN());
@@ -378,6 +379,7 @@
 void FixedDoubleArray::set_the_hole(int index) {
   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
          map() != GetReadOnlyRoots().fixed_array_map());
+  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
   int offset = kHeaderSize + index * kDoubleSize;
   base::WriteUnalignedValue<uint64_t>(field_address(offset), kHoleNanInt64);
 }
diff -Naur a/src/3rdparty/chromium/v8/src/objects/internal-index.h b/src/3rdparty/chromium/v8/src/objects/internal-index.h
--- a/src/3rdparty/chromium/v8/src/objects/internal-index.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/internal-index.h	2021-06-18 17:02:27.648181878 +0100
@@ -45,11 +45,11 @@
     return static_cast<int>(entry_);
   }
 
-  bool operator==(const InternalIndex& other) { return entry_ == other.entry_; }
+  bool operator==(const InternalIndex& other) const { return entry_ == other.entry_; }
 
   // Iteration support.
   InternalIndex operator*() { return *this; }
-  bool operator!=(const InternalIndex& other) { return entry_ != other.entry_; }
+  bool operator!=(const InternalIndex& other) const { return entry_ != other.entry_; }
   InternalIndex& operator++() {
     entry_++;
     return *this;
diff -Naur a/src/3rdparty/chromium/v8/src/objects/js-list-format.cc b/src/3rdparty/chromium/v8/src/objects/js-list-format.cc
--- a/src/3rdparty/chromium/v8/src/objects/js-list-format.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/js-list-format.cc	2021-06-18 16:26:16.757871682 +0100
@@ -28,6 +28,35 @@
 namespace v8 {
 namespace internal {
 
+#if U_ICU_VERSION_MAJOR_NUM >= 67
+namespace {
+
+UListFormatterWidth GetIcuWidth(JSListFormat::Style style) {
+  switch (style) {
+    case JSListFormat::Style::LONG:
+      return ULISTFMT_WIDTH_WIDE;
+    case JSListFormat::Style::SHORT:
+      return ULISTFMT_WIDTH_SHORT;
+    case JSListFormat::Style::NARROW:
+      return ULISTFMT_WIDTH_NARROW;
+  }
+  UNREACHABLE();
+}
+
+UListFormatterType GetIcuType(JSListFormat::Type type) {
+  switch (type) {
+    case JSListFormat::Type::CONJUNCTION:
+      return ULISTFMT_TYPE_AND;
+    case JSListFormat::Type::DISJUNCTION:
+      return ULISTFMT_TYPE_OR;
+    case JSListFormat::Type::UNIT:
+      return ULISTFMT_TYPE_UNITS;
+  }
+  UNREACHABLE();
+}
+
+}  // namespace
+#else
 namespace {
 const char* kStandard = "standard";
 const char* kOr = "or";
@@ -74,7 +103,7 @@
 }
 
 }  // namespace
-
+#endif
 MaybeHandle<JSListFormat> JSListFormat::New(Isolate* isolate, Handle<Map> map,
                                             Handle<Object> locales,
                                             Handle<Object> input_options) {
@@ -143,7 +172,11 @@
   icu::Locale icu_locale = r.icu_locale;
   UErrorCode status = U_ZERO_ERROR;
   icu::ListFormatter* formatter = icu::ListFormatter::createInstance(
+#if U_ICU_VERSION_MAJOR_NUM >= 67
+      icu_locale, GetIcuType(type_enum), GetIcuWidth(style_enum), status);
+#else
       icu_locale, GetIcuStyleString(style_enum, type_enum), status);
+#endif
   if (U_FAILURE(status) || formatter == nullptr) {
     delete formatter;
     THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
diff -Naur a/src/3rdparty/chromium/v8/src/objects/map.h b/src/3rdparty/chromium/v8/src/objects/map.h
--- a/src/3rdparty/chromium/v8/src/objects/map.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/map.h	2021-06-18 17:02:27.649183610 +0100
@@ -639,6 +639,7 @@
   // chain state.
   inline bool IsPrototypeValidityCellValid() const;
 
+  inline Name GetLastDescriptorName(Isolate* isolate) const;
   inline PropertyDetails GetLastDescriptorDetails(Isolate* isolate) const;
 
   inline InternalIndex LastAdded() const;
diff -Naur a/src/3rdparty/chromium/v8/src/objects/map-inl.h b/src/3rdparty/chromium/v8/src/objects/map-inl.h
--- a/src/3rdparty/chromium/v8/src/objects/map-inl.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/map-inl.h	2021-06-18 17:02:27.648181878 +0100
@@ -185,6 +185,10 @@
   }
 }
 
+Name Map::GetLastDescriptorName(Isolate* isolate) const {
+  return instance_descriptors(isolate).GetKey(LastAdded());
+}
+
 PropertyDetails Map::GetLastDescriptorDetails(Isolate* isolate) const {
   return instance_descriptors(isolate).GetDetails(LastAdded());
 }
diff -Naur a/src/3rdparty/chromium/v8/src/objects/map-updater.cc b/src/3rdparty/chromium/v8/src/objects/map-updater.cc
--- a/src/3rdparty/chromium/v8/src/objects/map-updater.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/map-updater.cc	2021-06-18 17:02:27.648181878 +0100
@@ -121,41 +121,6 @@
   PropertyDetails old_details =
       old_descriptors_->GetDetails(modified_descriptor_);
 
-  // If the {descriptor} was "const" data field so far, we need to update the
-  // {old_map_} here, otherwise we could get the constants wrong, i.e.
-  //
-  //   o.x = 1;
-  //   change o.x's attributes to something else
-  //   delete o.x;
-  //   o.x = 2;
-  //
-  // could trick V8 into thinking that `o.x` is still 1 even after the second
-  // assignment.
-  // This situation is similar to what might happen with property deletion.
-  if (old_details.constness() == PropertyConstness::kConst &&
-      old_details.location() == kField &&
-      old_details.attributes() != new_attributes_) {
-    Handle<FieldType> field_type(
-        old_descriptors_->GetFieldType(modified_descriptor_), isolate_);
-    Map::GeneralizeField(isolate_, old_map_, descriptor,
-                         PropertyConstness::kMutable,
-                         old_details.representation(), field_type);
-    // The old_map_'s property must become mutable.
-    // Note, that the {old_map_} and {old_descriptors_} are not expected to be
-    // updated by the generalization if the map is already deprecated.
-    DCHECK_IMPLIES(
-        !old_map_->is_deprecated(),
-        PropertyConstness::kMutable ==
-            old_descriptors_->GetDetails(modified_descriptor_).constness());
-    // Although the property in the old map is marked as mutable we still
-    // treat it as constant when merging with the new path in transition tree.
-    // This is fine because up until this reconfiguration the field was
-    // known to be constant, so it's fair to proceed treating it as such
-    // during this reconfiguration session. The issue is that after the
-    // reconfiguration the original field might become mutable (see the delete
-    // example above).
-  }
-
   // If property kind is not reconfigured merge the result with
   // representation/field type from the old descriptor.
   if (old_details.kind() == new_kind_) {
diff -Naur a/src/3rdparty/chromium/v8/src/objects/property-details.h b/src/3rdparty/chromium/v8/src/objects/property-details.h
--- a/src/3rdparty/chromium/v8/src/objects/property-details.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/property-details.h	2021-06-18 17:02:27.649183610 +0100
@@ -32,6 +32,12 @@
   // a non-existent property.
 };
 
+// Number of distinct bits in PropertyAttributes.
+static const int kPropertyAttributesBitsCount = 3;
+
+static const int kPropertyAttributesCombinationsCount =
+    1 << kPropertyAttributesBitsCount;
+
 enum PropertyFilter {
   ALL_PROPERTIES = 0,
   ONLY_WRITABLE = 1,
@@ -63,6 +69,11 @@
 STATIC_ASSERT(SKIP_SYMBOLS ==
               static_cast<PropertyFilter>(v8::PropertyFilter::SKIP_SYMBOLS));
 
+// Assert that kPropertyAttributesBitsCount value matches the definition of
+// ALL_ATTRIBUTES_MASK.
+STATIC_ASSERT((ALL_ATTRIBUTES_MASK == (READ_ONLY | DONT_ENUM | DONT_DELETE)) ==
+              (kPropertyAttributesBitsCount == 3));
+
 class Smi;
 class TypeInfo;
 
diff -Naur a/src/3rdparty/chromium/v8/src/objects/transitions.cc b/src/3rdparty/chromium/v8/src/objects/transitions.cc
--- a/src/3rdparty/chromium/v8/src/objects/transitions.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/transitions.cc	2021-06-18 17:02:27.649183610 +0100
@@ -272,6 +272,34 @@
   return Handle<Map>(target, isolate_);
 }
 
+void TransitionsAccessor::ForEachTransitionTo(
+    Name name, const ForEachTransitionCallback& callback,
+    DisallowHeapAllocation* no_gc) {
+  DCHECK(name.IsUniqueName());
+  switch (encoding()) {
+    case kPrototypeInfo:
+    case kUninitialized:
+    case kMigrationTarget:
+      return;
+    case kWeakRef: {
+      Map target = Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
+      InternalIndex descriptor = target.LastAdded();
+      DescriptorArray descriptors = target.instance_descriptors();
+      Name key = descriptors.GetKey(descriptor);
+      if (key == name) {
+        callback(target);
+      }
+      return;
+    }
+    case kFullTransitionArray: {
+      v8::base::SharedMutexGuardIf<base::kShared> scope(
+          isolate_->transition_array_access(), concurrent_access_);
+      return transitions().ForEachTransitionTo(name, callback);
+    }
+  }
+  UNREACHABLE();
+}
+
 bool TransitionsAccessor::CanHaveMoreTransitions() {
   if (map_.is_dictionary_map()) return false;
   if (encoding() == kFullTransitionArray) {
@@ -613,6 +641,21 @@
   return SearchDetailsAndGetTarget(transition, kind, attributes);
 }
 
+void TransitionArray::ForEachTransitionTo(
+    Name name, const ForEachTransitionCallback& callback) {
+  int transition = SearchName(name, nullptr);
+  if (transition == kNotFound) return;
+
+  int nof_transitions = number_of_transitions();
+  DCHECK(transition < nof_transitions);
+  Name key = GetKey(transition);
+  for (; transition < nof_transitions && GetKey(transition) == key;
+       transition++) {
+    Map target = GetTarget(transition);
+    callback(target);
+  }
+}
+
 void TransitionArray::Sort() {
   DisallowHeapAllocation no_gc;
   // In-place insertion sort.
diff -Naur a/src/3rdparty/chromium/v8/src/objects/transitions.h b/src/3rdparty/chromium/v8/src/objects/transitions.h
--- a/src/3rdparty/chromium/v8/src/objects/transitions.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/objects/transitions.h	2021-06-18 17:02:27.649183610 +0100
@@ -19,6 +19,9 @@
 namespace v8 {
 namespace internal {
 
+// Find all transitions with given name and calls the callback.
+using ForEachTransitionCallback = std::function<void(Map)>;
+
 // TransitionsAccessor is a helper class to encapsulate access to the various
 // ways a Map can store transitions to other maps in its respective field at
 // Map::kTransitionsOrPrototypeInfo.
@@ -68,6 +71,14 @@
     return FindTransitionToDataProperty(name, kFieldOnly);
   }
 
+  // Find all transitions with given name and calls the callback.
+  // Neither GCs nor operations requiring Isolate::full_transition_array_access
+  // lock are allowed inside the callback.
+  // If any of the GC- or lock-requiring processing is necessary, it has to be
+  // done outside of the callback.
+  void ForEachTransitionTo(Name name, const ForEachTransitionCallback& callback,
+                           DisallowHeapAllocation* no_gc);
+
   inline Handle<String> ExpectedTransitionKey();
   inline Handle<Map> ExpectedTransitionTarget();
 
@@ -320,6 +331,10 @@
   Map SearchDetailsAndGetTarget(int transition, PropertyKind kind,
                                 PropertyAttributes attributes);
 
+  // Find all transitions with given name and calls the callback.
+  void ForEachTransitionTo(Name name,
+                           const ForEachTransitionCallback& callback);
+
   inline int number_of_transitions() const;
 
   static bool CompactPrototypeTransitionArray(Isolate* isolate,
diff -Naur a/src/3rdparty/chromium/v8/src/runtime/runtime.h b/src/3rdparty/chromium/v8/src/runtime/runtime.h
--- a/src/3rdparty/chromium/v8/src/runtime/runtime.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/runtime/runtime.h	2021-06-18 17:02:27.649183610 +0100
@@ -487,6 +487,7 @@
   F(HasElementsInALargeObjectSpace, 1, 1)     \
   F(HasFastElements, 1, 1)                    \
   F(HasFastProperties, 1, 1)                  \
+  F(HasOwnConstDataProperty, 2, 1)            \
   F(HasFixedBigInt64Elements, 1, 1)           \
   F(HasFixedBigUint64Elements, 1, 1)          \
   F(HasFixedFloat32Elements, 1, 1)            \
@@ -748,9 +749,9 @@
   // Get the runtime intrinsic function table.
   static const Function* RuntimeFunctionTable(Isolate* isolate);
 
-  V8_WARN_UNUSED_RESULT static Maybe<bool> DeleteObjectProperty(
-      Isolate* isolate, Handle<JSReceiver> receiver, Handle<Object> key,
-      LanguageMode language_mode);
+  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<bool>
+  DeleteObjectProperty(Isolate* isolate, Handle<JSReceiver> receiver,
+                       Handle<Object> key, LanguageMode language_mode);
 
   V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
   SetObjectProperty(Isolate* isolate, Handle<Object> object, Handle<Object> key,
diff -Naur a/src/3rdparty/chromium/v8/src/runtime/runtime-object.cc b/src/3rdparty/chromium/v8/src/runtime/runtime-object.cc
--- a/src/3rdparty/chromium/v8/src/runtime/runtime-object.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/runtime/runtime-object.cc	2021-06-18 17:02:27.649183610 +0100
@@ -17,6 +17,7 @@
 #include "src/objects/js-array-inl.h"
 #include "src/objects/property-descriptor-object.h"
 #include "src/objects/property-descriptor.h"
+#include "src/objects/property-details.h"
 #include "src/runtime/runtime-utils.h"
 #include "src/runtime/runtime.h"
 
@@ -93,6 +94,54 @@
 
 namespace {
 
+void GeneralizeAllTransitionsToFieldAsMutable(Isolate* isolate, Handle<Map> map,
+                                              Handle<Name> name) {
+  InternalIndex descriptor(map->NumberOfOwnDescriptors());
+
+  Handle<Map> target_maps[kPropertyAttributesCombinationsCount];
+  int target_maps_count = 0;
+
+  // Collect all outgoing field transitions.
+  {
+    DisallowHeapAllocation no_gc;
+    TransitionsAccessor transitions(isolate, *map, &no_gc);
+    transitions.ForEachTransitionTo(
+        *name,
+        [&](Map target) {
+          DCHECK_EQ(descriptor, target.LastAdded());
+          DCHECK_EQ(*name, target.GetLastDescriptorName(isolate));
+          PropertyDetails details = target.GetLastDescriptorDetails(isolate);
+          // Currently, we track constness only for fields.
+          if (details.kind() == kData &&
+              details.constness() == PropertyConstness::kConst) {
+            target_maps[target_maps_count++] = handle(target, isolate);
+          }
+          DCHECK_IMPLIES(details.kind() == kAccessor,
+                         details.constness() == PropertyConstness::kConst);
+        },
+        &no_gc);
+    CHECK_LE(target_maps_count, kPropertyAttributesCombinationsCount);
+  }
+
+  for (int i = 0; i < target_maps_count; i++) {
+    Handle<Map> target = target_maps[i];
+    PropertyDetails details =
+        target->instance_descriptors(isolate)
+            .GetDetails(descriptor);
+    Handle<FieldType> field_type(
+        target->instance_descriptors(isolate)
+            .GetFieldType(descriptor),
+        isolate);
+    Map::GeneralizeField(isolate, target, descriptor,
+                         PropertyConstness::kMutable, details.representation(),
+                         field_type);
+    DCHECK_EQ(PropertyConstness::kMutable,
+              target->instance_descriptors(isolate)
+                  .GetDetails(descriptor)
+                  .constness());
+  }
+}
+
 bool DeleteObjectPropertyFast(Isolate* isolate, Handle<JSReceiver> receiver,
                               Handle<Object> raw_key) {
   // This implements a special case for fast property deletion: when the
@@ -102,6 +151,8 @@
   // (1) The receiver must be a regular object and the key a unique name.
   Handle<Map> receiver_map(receiver->map(), isolate);
   if (receiver_map->IsSpecialReceiverMap()) return false;
+  DCHECK(receiver_map->IsJSObjectMap());
+
   if (!raw_key->IsUniqueName()) return false;
   Handle<Name> key = Handle<Name>::cast(raw_key);
   // (2) The property to be deleted must be the last property.
@@ -124,26 +175,6 @@
 
   // Preconditions successful. No more bailouts after this point.
 
-  // If the {descriptor} was "const" so far, we need to update the
-  // {receiver_map} here, otherwise we could get the constants wrong, i.e.
-  //
-  //   o.x = 1;
-  //   delete o.x;
-  //   o.x = 2;
-  //
-  // could trick V8 into thinking that `o.x` is still 1 even after the second
-  // assignment.
-  if (details.constness() == PropertyConstness::kConst &&
-      details.location() == kField) {
-    Handle<FieldType> field_type(descriptors->GetFieldType(descriptor),
-                                 isolate);
-    Map::GeneralizeField(isolate, receiver_map, descriptor,
-                         PropertyConstness::kMutable, details.representation(),
-                         field_type);
-    DCHECK_EQ(PropertyConstness::kMutable,
-              descriptors->GetDetails(descriptor).constness());
-  }
-
   // Zap the property to avoid keeping objects alive. Zapping is not necessary
   // for properties stored in the descriptor array.
   if (details.location() == kField) {
@@ -190,6 +221,30 @@
   receiver->HeapObjectVerify(isolate);
   receiver->property_array().PropertyArrayVerify(isolate);
 #endif
+
+  // If the {descriptor} was "const" so far, we need to update the
+  // {receiver_map} here, otherwise we could get the constants wrong, i.e.
+  //
+  //   o.x = 1;
+  //   [change o.x's attributes or reconfigure property kind]
+  //   delete o.x;
+  //   o.x = 2;
+  //
+  // could trick V8 into thinking that `o.x` is still 1 even after the second
+  // assignment.
+
+  // Step 1: Migrate object to an up-to-date shape.
+  if (parent_map->is_deprecated()) {
+    JSObject::MigrateInstance(isolate, Handle<JSObject>::cast(receiver));
+    parent_map = handle(receiver->map(), isolate);
+  }
+
+  // Step 2: Mark outgoing transitions from the up-to-date version of the
+  // parent_map to same property name of any kind or attributes as mutable.
+  // Also migrate object to the up-to-date map to make the object shapes
+  // converge sooner.
+  GeneralizeAllTransitionsToFieldAsMutable(isolate, parent_map, key);
+
   return true;
 }
 
@@ -357,6 +412,34 @@
   return ReadOnlyRoots(isolate).false_value();
 }
 
+RUNTIME_FUNCTION(Runtime_HasOwnConstDataProperty) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, property, 1);
+
+  bool success;
+  LookupIterator::Key key(isolate, property, &success);
+  if (!success) return ReadOnlyRoots(isolate).undefined_value();
+
+  if (object->IsJSObject()) {
+    Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
+    LookupIterator it(isolate, js_obj, key, js_obj, LookupIterator::OWN);
+
+    switch (it.state()) {
+      case LookupIterator::NOT_FOUND:
+        return isolate->heap()->ToBoolean(false);
+      case LookupIterator::DATA:
+        return isolate->heap()->ToBoolean(it.constness() ==
+                                          PropertyConstness::kConst);
+      default:
+        return ReadOnlyRoots(isolate).undefined_value();
+    }
+  }
+
+  return ReadOnlyRoots(isolate).undefined_value();
+}
+
 RUNTIME_FUNCTION(Runtime_AddDictionaryProperty) {
   HandleScope scope(isolate);
   Handle<JSObject> receiver = args.at<JSObject>(0);
diff -Naur a/src/3rdparty/chromium/v8/src/wasm/baseline/arm/liftoff-assembler-arm.h b/src/3rdparty/chromium/v8/src/wasm/baseline/arm/liftoff-assembler-arm.h
--- a/src/3rdparty/chromium/v8/src/wasm/baseline/arm/liftoff-assembler-arm.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/wasm/baseline/arm/liftoff-assembler-arm.h	2021-06-18 17:01:58.704126975 +0100
@@ -689,13 +689,8 @@
                             Register offset_reg, uint32_t offset_imm,
                             LoadType type, LiftoffRegList pinned,
                             uint32_t* protected_load_pc, bool is_load_mem) {
-  // If offset_imm cannot be converted to int32 safely, we abort as a separate
-  // check should cause this code to never be executed.
-  // TODO(7881): Support when >2GB is required.
-  if (!is_uint31(offset_imm)) {
-    TurboAssembler::Abort(AbortReason::kOffsetOutOfRange);
-    return;
-  }
+  // Offsets >=2GB are statically OOB on 32-bit systems.
+  DCHECK_LE(offset_imm, std::numeric_limits<int32_t>::max());
   liftoff::LoadInternal(this, dst, src_addr, offset_reg,
                         static_cast<int32_t>(offset_imm), type, pinned,
                         protected_load_pc, is_load_mem);
@@ -705,13 +700,8 @@
                              uint32_t offset_imm, LiftoffRegister src,
                              StoreType type, LiftoffRegList pinned,
                              uint32_t* protected_store_pc, bool is_store_mem) {
-  // If offset_imm cannot be converted to int32 safely, we abort as a separate
-  // check should cause this code to never be executed.
-  // TODO(7881): Support when >2GB is required.
-  if (!is_uint31(offset_imm)) {
-    TurboAssembler::Abort(AbortReason::kOffsetOutOfRange);
-    return;
-  }
+  // Offsets >=2GB are statically OOB on 32-bit systems.
+  DCHECK_LE(offset_imm, std::numeric_limits<int32_t>::max());
   UseScratchRegisterScope temps(this);
   if (type.value() == StoreType::kF64Store) {
     Register actual_dst_addr = liftoff::CalculateActualAddress(
diff -Naur a/src/3rdparty/chromium/v8/src/wasm/baseline/ia32/liftoff-assembler-ia32.h b/src/3rdparty/chromium/v8/src/wasm/baseline/ia32/liftoff-assembler-ia32.h
--- a/src/3rdparty/chromium/v8/src/wasm/baseline/ia32/liftoff-assembler-ia32.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/wasm/baseline/ia32/liftoff-assembler-ia32.h	2021-06-18 17:01:58.705128708 +0100
@@ -324,13 +324,8 @@
                             Register offset_reg, uint32_t offset_imm,
                             LoadType type, LiftoffRegList pinned,
                             uint32_t* protected_load_pc, bool is_load_mem) {
-  if (offset_imm > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
-    // We do not generate code here, because such an offset should never pass
-    // the bounds check. However, the spec requires us to compile code with such
-    // an offset.
-    Trap();
-    return;
-  }
+  // Offsets >=2GB are statically OOB on 32-bit systems.
+  DCHECK_LE(offset_imm, std::numeric_limits<int32_t>::max());
   DCHECK_EQ(type.value_type() == kWasmI64, dst.is_gp_pair());
   Operand src_op = offset_reg == no_reg
                        ? Operand(src_addr, offset_imm)
@@ -406,6 +401,7 @@
                              StoreType type, LiftoffRegList pinned,
                              uint32_t* protected_store_pc, bool is_store_mem) {
   DCHECK_EQ(type.value_type() == kWasmI64, src.is_gp_pair());
+  // Offsets >=2GB are statically OOB on 32-bit systems.
   DCHECK_LE(offset_imm, std::numeric_limits<int32_t>::max());
   Operand dst_op = offset_reg == no_reg
                        ? Operand(dst_addr, offset_imm)
diff -Naur a/src/3rdparty/chromium/v8/src/wasm/baseline/liftoff-compiler.cc b/src/3rdparty/chromium/v8/src/wasm/baseline/liftoff-compiler.cc
--- a/src/3rdparty/chromium/v8/src/wasm/baseline/liftoff-compiler.cc	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/wasm/baseline/liftoff-compiler.cc	2021-06-18 17:01:58.705128708 +0100
@@ -2100,10 +2100,7 @@
   bool BoundsCheckMem(FullDecoder* decoder, uint32_t access_size,
                       uint64_t offset, Register index, LiftoffRegList pinned,
                       ForceCheck force_check) {
-    // If the offset does not fit in a uintptr_t, this can never succeed on this
-    // machine.
     const bool statically_oob =
-        offset > std::numeric_limits<uintptr_t>::max() ||
         !base::IsInBounds<uintptr_t>(offset, access_size,
                                      env_->max_memory_size);
 
diff -Naur a/src/3rdparty/chromium/v8/src/wasm/compilation-environment.h b/src/3rdparty/chromium/v8/src/wasm/compilation-environment.h
--- a/src/3rdparty/chromium/v8/src/wasm/compilation-environment.h	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/src/wasm/compilation-environment.h	2021-06-18 17:01:58.705128708 +0100
@@ -63,9 +63,11 @@
 
   const LowerSimd lower_simd;
 
-  static constexpr uint32_t kMaxMemoryPagesAtRuntime =
-      std::min(kV8MaxWasmMemoryPages,
-               std::numeric_limits<uintptr_t>::max() / kWasmPageSize);
+  // We assume that memories of size >= half of the virtual address space
+  // cannot be allocated (see https://crbug.com/1201340).
+  static constexpr uint32_t kMaxMemoryPagesAtRuntime = std::min(
+      kV8MaxWasmMemoryPages,
+      (uintptr_t{1} << (kSystemPointerSize == 4 ? 31 : 63)) / kWasmPageSize);
 
   constexpr CompilationEnv(const WasmModule* module,
                            UseTrapHandler use_trap_handler,
diff -Naur a/src/3rdparty/chromium/v8/tools/v8heapconst.py b/src/3rdparty/chromium/v8/tools/v8heapconst.py
--- a/src/3rdparty/chromium/v8/tools/v8heapconst.py	2021-04-01 12:19:23.000000000 +0100
+++ b/src/3rdparty/chromium/v8/tools/v8heapconst.py	2021-06-18 16:26:16.757871682 +0100
@@ -205,266 +205,266 @@
 
 # List of known V8 maps.
 KNOWN_MAPS = {
-  ("read_only_space", 0x02115): (170, "MetaMap"),
-  ("read_only_space", 0x0213d): (67, "NullMap"),
-  ("read_only_space", 0x02165): (162, "DescriptorArrayMap"),
-  ("read_only_space", 0x0218d): (156, "WeakFixedArrayMap"),
-  ("read_only_space", 0x021cd): (96, "EnumCacheMap"),
-  ("read_only_space", 0x02201): (117, "FixedArrayMap"),
-  ("read_only_space", 0x0224d): (8, "OneByteInternalizedStringMap"),
-  ("read_only_space", 0x02299): (167, "FreeSpaceMap"),
-  ("read_only_space", 0x022c1): (166, "OnePointerFillerMap"),
-  ("read_only_space", 0x022e9): (166, "TwoPointerFillerMap"),
-  ("read_only_space", 0x02311): (67, "UninitializedMap"),
-  ("read_only_space", 0x02389): (67, "UndefinedMap"),
-  ("read_only_space", 0x023cd): (66, "HeapNumberMap"),
-  ("read_only_space", 0x02401): (67, "TheHoleMap"),
-  ("read_only_space", 0x02461): (67, "BooleanMap"),
-  ("read_only_space", 0x02505): (131, "ByteArrayMap"),
-  ("read_only_space", 0x0252d): (117, "FixedCOWArrayMap"),
-  ("read_only_space", 0x02555): (118, "HashTableMap"),
-  ("read_only_space", 0x0257d): (64, "SymbolMap"),
-  ("read_only_space", 0x025a5): (40, "OneByteStringMap"),
-  ("read_only_space", 0x025cd): (129, "ScopeInfoMap"),
-  ("read_only_space", 0x025f5): (175, "SharedFunctionInfoMap"),
-  ("read_only_space", 0x0261d): (159, "CodeMap"),
-  ("read_only_space", 0x02645): (158, "CellMap"),
-  ("read_only_space", 0x0266d): (174, "GlobalPropertyCellMap"),
-  ("read_only_space", 0x02695): (70, "ForeignMap"),
-  ("read_only_space", 0x026bd): (157, "TransitionArrayMap"),
-  ("read_only_space", 0x026e5): (45, "ThinOneByteStringMap"),
-  ("read_only_space", 0x0270d): (165, "FeedbackVectorMap"),
-  ("read_only_space", 0x0273d): (67, "ArgumentsMarkerMap"),
-  ("read_only_space", 0x0279d): (67, "ExceptionMap"),
-  ("read_only_space", 0x027f9): (67, "TerminationExceptionMap"),
-  ("read_only_space", 0x02861): (67, "OptimizedOutMap"),
-  ("read_only_space", 0x028c1): (67, "StaleRegisterMap"),
-  ("read_only_space", 0x02921): (130, "ScriptContextTableMap"),
-  ("read_only_space", 0x02949): (127, "ClosureFeedbackCellArrayMap"),
-  ("read_only_space", 0x02971): (164, "FeedbackMetadataArrayMap"),
-  ("read_only_space", 0x02999): (117, "ArrayListMap"),
-  ("read_only_space", 0x029c1): (65, "BigIntMap"),
-  ("read_only_space", 0x029e9): (128, "ObjectBoilerplateDescriptionMap"),
-  ("read_only_space", 0x02a11): (132, "BytecodeArrayMap"),
-  ("read_only_space", 0x02a39): (160, "CodeDataContainerMap"),
-  ("read_only_space", 0x02a61): (161, "CoverageInfoMap"),
-  ("read_only_space", 0x02a89): (133, "FixedDoubleArrayMap"),
-  ("read_only_space", 0x02ab1): (120, "GlobalDictionaryMap"),
-  ("read_only_space", 0x02ad9): (97, "ManyClosuresCellMap"),
-  ("read_only_space", 0x02b01): (117, "ModuleInfoMap"),
-  ("read_only_space", 0x02b29): (121, "NameDictionaryMap"),
-  ("read_only_space", 0x02b51): (97, "NoClosuresCellMap"),
-  ("read_only_space", 0x02b79): (122, "NumberDictionaryMap"),
-  ("read_only_space", 0x02ba1): (97, "OneClosureCellMap"),
-  ("read_only_space", 0x02bc9): (123, "OrderedHashMapMap"),
-  ("read_only_space", 0x02bf1): (124, "OrderedHashSetMap"),
-  ("read_only_space", 0x02c19): (125, "OrderedNameDictionaryMap"),
-  ("read_only_space", 0x02c41): (172, "PreparseDataMap"),
-  ("read_only_space", 0x02c69): (173, "PropertyArrayMap"),
-  ("read_only_space", 0x02c91): (93, "SideEffectCallHandlerInfoMap"),
-  ("read_only_space", 0x02cb9): (93, "SideEffectFreeCallHandlerInfoMap"),
-  ("read_only_space", 0x02ce1): (93, "NextCallSideEffectFreeCallHandlerInfoMap"),
-  ("read_only_space", 0x02d09): (126, "SimpleNumberDictionaryMap"),
-  ("read_only_space", 0x02d31): (149, "SmallOrderedHashMapMap"),
-  ("read_only_space", 0x02d59): (150, "SmallOrderedHashSetMap"),
-  ("read_only_space", 0x02d81): (151, "SmallOrderedNameDictionaryMap"),
-  ("read_only_space", 0x02da9): (152, "SourceTextModuleMap"),
-  ("read_only_space", 0x02dd1): (153, "SyntheticModuleMap"),
-  ("read_only_space", 0x02df9): (155, "UncompiledDataWithoutPreparseDataMap"),
-  ("read_only_space", 0x02e21): (154, "UncompiledDataWithPreparseDataMap"),
-  ("read_only_space", 0x02e49): (71, "WasmTypeInfoMap"),
-  ("read_only_space", 0x02e71): (181, "WeakArrayListMap"),
-  ("read_only_space", 0x02e99): (119, "EphemeronHashTableMap"),
-  ("read_only_space", 0x02ec1): (163, "EmbedderDataArrayMap"),
-  ("read_only_space", 0x02ee9): (182, "WeakCellMap"),
-  ("read_only_space", 0x02f11): (32, "StringMap"),
-  ("read_only_space", 0x02f39): (41, "ConsOneByteStringMap"),
-  ("read_only_space", 0x02f61): (33, "ConsStringMap"),
-  ("read_only_space", 0x02f89): (37, "ThinStringMap"),
-  ("read_only_space", 0x02fb1): (35, "SlicedStringMap"),
-  ("read_only_space", 0x02fd9): (43, "SlicedOneByteStringMap"),
-  ("read_only_space", 0x03001): (34, "ExternalStringMap"),
-  ("read_only_space", 0x03029): (42, "ExternalOneByteStringMap"),
-  ("read_only_space", 0x03051): (50, "UncachedExternalStringMap"),
-  ("read_only_space", 0x03079): (0, "InternalizedStringMap"),
-  ("read_only_space", 0x030a1): (2, "ExternalInternalizedStringMap"),
-  ("read_only_space", 0x030c9): (10, "ExternalOneByteInternalizedStringMap"),
-  ("read_only_space", 0x030f1): (18, "UncachedExternalInternalizedStringMap"),
-  ("read_only_space", 0x03119): (26, "UncachedExternalOneByteInternalizedStringMap"),
-  ("read_only_space", 0x03141): (58, "UncachedExternalOneByteStringMap"),
-  ("read_only_space", 0x03169): (67, "SelfReferenceMarkerMap"),
-  ("read_only_space", 0x03191): (67, "BasicBlockCountersMarkerMap"),
-  ("read_only_space", 0x031d5): (87, "ArrayBoilerplateDescriptionMap"),
-  ("read_only_space", 0x032a5): (99, "InterceptorInfoMap"),
-  ("read_only_space", 0x05399): (72, "PromiseFulfillReactionJobTaskMap"),
-  ("read_only_space", 0x053c1): (73, "PromiseRejectReactionJobTaskMap"),
-  ("read_only_space", 0x053e9): (74, "CallableTaskMap"),
-  ("read_only_space", 0x05411): (75, "CallbackTaskMap"),
-  ("read_only_space", 0x05439): (76, "PromiseResolveThenableJobTaskMap"),
-  ("read_only_space", 0x05461): (79, "FunctionTemplateInfoMap"),
-  ("read_only_space", 0x05489): (80, "ObjectTemplateInfoMap"),
-  ("read_only_space", 0x054b1): (81, "AccessCheckInfoMap"),
-  ("read_only_space", 0x054d9): (82, "AccessorInfoMap"),
-  ("read_only_space", 0x05501): (83, "AccessorPairMap"),
-  ("read_only_space", 0x05529): (84, "AliasedArgumentsEntryMap"),
-  ("read_only_space", 0x05551): (85, "AllocationMementoMap"),
-  ("read_only_space", 0x05579): (88, "AsmWasmDataMap"),
-  ("read_only_space", 0x055a1): (89, "AsyncGeneratorRequestMap"),
-  ("read_only_space", 0x055c9): (90, "BreakPointMap"),
-  ("read_only_space", 0x055f1): (91, "BreakPointInfoMap"),
-  ("read_only_space", 0x05619): (92, "CachedTemplateObjectMap"),
-  ("read_only_space", 0x05641): (94, "ClassPositionsMap"),
-  ("read_only_space", 0x05669): (95, "DebugInfoMap"),
-  ("read_only_space", 0x05691): (98, "FunctionTemplateRareDataMap"),
-  ("read_only_space", 0x056b9): (100, "InterpreterDataMap"),
-  ("read_only_space", 0x056e1): (101, "PromiseCapabilityMap"),
-  ("read_only_space", 0x05709): (102, "PromiseReactionMap"),
-  ("read_only_space", 0x05731): (103, "PropertyDescriptorObjectMap"),
-  ("read_only_space", 0x05759): (104, "PrototypeInfoMap"),
-  ("read_only_space", 0x05781): (105, "ScriptMap"),
-  ("read_only_space", 0x057a9): (106, "SourceTextModuleInfoEntryMap"),
-  ("read_only_space", 0x057d1): (107, "StackFrameInfoMap"),
-  ("read_only_space", 0x057f9): (108, "StackTraceFrameMap"),
-  ("read_only_space", 0x05821): (109, "TemplateObjectDescriptionMap"),
-  ("read_only_space", 0x05849): (110, "Tuple2Map"),
-  ("read_only_space", 0x05871): (111, "WasmCapiFunctionDataMap"),
-  ("read_only_space", 0x05899): (112, "WasmExceptionTagMap"),
-  ("read_only_space", 0x058c1): (113, "WasmExportedFunctionDataMap"),
-  ("read_only_space", 0x058e9): (114, "WasmIndirectFunctionTableMap"),
-  ("read_only_space", 0x05911): (115, "WasmJSFunctionDataMap"),
-  ("read_only_space", 0x05939): (116, "WasmValueMap"),
-  ("read_only_space", 0x05961): (135, "SloppyArgumentsElementsMap"),
-  ("read_only_space", 0x05989): (171, "OnHeapBasicBlockProfilerDataMap"),
-  ("read_only_space", 0x059b1): (168, "InternalClassMap"),
-  ("read_only_space", 0x059d9): (177, "SmiPairMap"),
-  ("read_only_space", 0x05a01): (176, "SmiBoxMap"),
-  ("read_only_space", 0x05a29): (146, "ExportedSubClassBaseMap"),
-  ("read_only_space", 0x05a51): (147, "ExportedSubClassMap"),
-  ("read_only_space", 0x05a79): (68, "AbstractInternalClassSubclass1Map"),
-  ("read_only_space", 0x05aa1): (69, "AbstractInternalClassSubclass2Map"),
-  ("read_only_space", 0x05ac9): (134, "InternalClassWithSmiElementsMap"),
-  ("read_only_space", 0x05af1): (169, "InternalClassWithStructElementsMap"),
-  ("read_only_space", 0x05b19): (148, "ExportedSubClass2Map"),
-  ("read_only_space", 0x05b41): (178, "SortStateMap"),
-  ("read_only_space", 0x05b69): (86, "AllocationSiteWithWeakNextMap"),
-  ("read_only_space", 0x05b91): (86, "AllocationSiteWithoutWeakNextMap"),
-  ("read_only_space", 0x05bb9): (77, "LoadHandler1Map"),
-  ("read_only_space", 0x05be1): (77, "LoadHandler2Map"),
-  ("read_only_space", 0x05c09): (77, "LoadHandler3Map"),
-  ("read_only_space", 0x05c31): (78, "StoreHandler0Map"),
-  ("read_only_space", 0x05c59): (78, "StoreHandler1Map"),
-  ("read_only_space", 0x05c81): (78, "StoreHandler2Map"),
-  ("read_only_space", 0x05ca9): (78, "StoreHandler3Map"),
-  ("map_space", 0x02115): (1057, "ExternalMap"),
-  ("map_space", 0x0213d): (1072, "JSMessageObjectMap"),
-  ("map_space", 0x02165): (180, "WasmRttEqrefMap"),
-  ("map_space", 0x0218d): (180, "WasmRttExternrefMap"),
-  ("map_space", 0x021b5): (180, "WasmRttFuncrefMap"),
-  ("map_space", 0x021dd): (180, "WasmRttI31refMap"),
+  ("read_only_space", 0x02119): (170, "MetaMap"),
+  ("read_only_space", 0x02141): (67, "NullMap"),
+  ("read_only_space", 0x02169): (162, "DescriptorArrayMap"),
+  ("read_only_space", 0x02191): (156, "WeakFixedArrayMap"),
+  ("read_only_space", 0x021d1): (96, "EnumCacheMap"),
+  ("read_only_space", 0x02205): (117, "FixedArrayMap"),
+  ("read_only_space", 0x02251): (8, "OneByteInternalizedStringMap"),
+  ("read_only_space", 0x0229d): (167, "FreeSpaceMap"),
+  ("read_only_space", 0x022c5): (166, "OnePointerFillerMap"),
+  ("read_only_space", 0x022ed): (166, "TwoPointerFillerMap"),
+  ("read_only_space", 0x02315): (67, "UninitializedMap"),
+  ("read_only_space", 0x0238d): (67, "UndefinedMap"),
+  ("read_only_space", 0x023d1): (66, "HeapNumberMap"),
+  ("read_only_space", 0x02405): (67, "TheHoleMap"),
+  ("read_only_space", 0x02465): (67, "BooleanMap"),
+  ("read_only_space", 0x02509): (131, "ByteArrayMap"),
+  ("read_only_space", 0x02531): (117, "FixedCOWArrayMap"),
+  ("read_only_space", 0x02559): (118, "HashTableMap"),
+  ("read_only_space", 0x02581): (64, "SymbolMap"),
+  ("read_only_space", 0x025a9): (40, "OneByteStringMap"),
+  ("read_only_space", 0x025d1): (129, "ScopeInfoMap"),
+  ("read_only_space", 0x025f9): (175, "SharedFunctionInfoMap"),
+  ("read_only_space", 0x02621): (159, "CodeMap"),
+  ("read_only_space", 0x02649): (158, "CellMap"),
+  ("read_only_space", 0x02671): (174, "GlobalPropertyCellMap"),
+  ("read_only_space", 0x02699): (70, "ForeignMap"),
+  ("read_only_space", 0x026c1): (157, "TransitionArrayMap"),
+  ("read_only_space", 0x026e9): (45, "ThinOneByteStringMap"),
+  ("read_only_space", 0x02711): (165, "FeedbackVectorMap"),
+  ("read_only_space", 0x02741): (67, "ArgumentsMarkerMap"),
+  ("read_only_space", 0x027a1): (67, "ExceptionMap"),
+  ("read_only_space", 0x027fd): (67, "TerminationExceptionMap"),
+  ("read_only_space", 0x02865): (67, "OptimizedOutMap"),
+  ("read_only_space", 0x028c5): (67, "StaleRegisterMap"),
+  ("read_only_space", 0x02925): (130, "ScriptContextTableMap"),
+  ("read_only_space", 0x0294d): (127, "ClosureFeedbackCellArrayMap"),
+  ("read_only_space", 0x02975): (164, "FeedbackMetadataArrayMap"),
+  ("read_only_space", 0x0299d): (117, "ArrayListMap"),
+  ("read_only_space", 0x029c5): (65, "BigIntMap"),
+  ("read_only_space", 0x029ed): (128, "ObjectBoilerplateDescriptionMap"),
+  ("read_only_space", 0x02a15): (132, "BytecodeArrayMap"),
+  ("read_only_space", 0x02a3d): (160, "CodeDataContainerMap"),
+  ("read_only_space", 0x02a65): (161, "CoverageInfoMap"),
+  ("read_only_space", 0x02a8d): (133, "FixedDoubleArrayMap"),
+  ("read_only_space", 0x02ab5): (120, "GlobalDictionaryMap"),
+  ("read_only_space", 0x02add): (97, "ManyClosuresCellMap"),
+  ("read_only_space", 0x02b05): (117, "ModuleInfoMap"),
+  ("read_only_space", 0x02b2d): (121, "NameDictionaryMap"),
+  ("read_only_space", 0x02b55): (97, "NoClosuresCellMap"),
+  ("read_only_space", 0x02b7d): (122, "NumberDictionaryMap"),
+  ("read_only_space", 0x02ba5): (97, "OneClosureCellMap"),
+  ("read_only_space", 0x02bcd): (123, "OrderedHashMapMap"),
+  ("read_only_space", 0x02bf5): (124, "OrderedHashSetMap"),
+  ("read_only_space", 0x02c1d): (125, "OrderedNameDictionaryMap"),
+  ("read_only_space", 0x02c45): (172, "PreparseDataMap"),
+  ("read_only_space", 0x02c6d): (173, "PropertyArrayMap"),
+  ("read_only_space", 0x02c95): (93, "SideEffectCallHandlerInfoMap"),
+  ("read_only_space", 0x02cbd): (93, "SideEffectFreeCallHandlerInfoMap"),
+  ("read_only_space", 0x02ce5): (93, "NextCallSideEffectFreeCallHandlerInfoMap"),
+  ("read_only_space", 0x02d0d): (126, "SimpleNumberDictionaryMap"),
+  ("read_only_space", 0x02d35): (149, "SmallOrderedHashMapMap"),
+  ("read_only_space", 0x02d5d): (150, "SmallOrderedHashSetMap"),
+  ("read_only_space", 0x02d85): (151, "SmallOrderedNameDictionaryMap"),
+  ("read_only_space", 0x02dad): (152, "SourceTextModuleMap"),
+  ("read_only_space", 0x02dd5): (153, "SyntheticModuleMap"),
+  ("read_only_space", 0x02dfd): (155, "UncompiledDataWithoutPreparseDataMap"),
+  ("read_only_space", 0x02e25): (154, "UncompiledDataWithPreparseDataMap"),
+  ("read_only_space", 0x02e4d): (71, "WasmTypeInfoMap"),
+  ("read_only_space", 0x02e75): (181, "WeakArrayListMap"),
+  ("read_only_space", 0x02e9d): (119, "EphemeronHashTableMap"),
+  ("read_only_space", 0x02ec5): (163, "EmbedderDataArrayMap"),
+  ("read_only_space", 0x02eed): (182, "WeakCellMap"),
+  ("read_only_space", 0x02f15): (32, "StringMap"),
+  ("read_only_space", 0x02f3d): (41, "ConsOneByteStringMap"),
+  ("read_only_space", 0x02f65): (33, "ConsStringMap"),
+  ("read_only_space", 0x02f8d): (37, "ThinStringMap"),
+  ("read_only_space", 0x02fb5): (35, "SlicedStringMap"),
+  ("read_only_space", 0x02fdd): (43, "SlicedOneByteStringMap"),
+  ("read_only_space", 0x03005): (34, "ExternalStringMap"),
+  ("read_only_space", 0x0302d): (42, "ExternalOneByteStringMap"),
+  ("read_only_space", 0x03055): (50, "UncachedExternalStringMap"),
+  ("read_only_space", 0x0307d): (0, "InternalizedStringMap"),
+  ("read_only_space", 0x030a5): (2, "ExternalInternalizedStringMap"),
+  ("read_only_space", 0x030cd): (10, "ExternalOneByteInternalizedStringMap"),
+  ("read_only_space", 0x030f5): (18, "UncachedExternalInternalizedStringMap"),
+  ("read_only_space", 0x0311d): (26, "UncachedExternalOneByteInternalizedStringMap"),
+  ("read_only_space", 0x03145): (58, "UncachedExternalOneByteStringMap"),
+  ("read_only_space", 0x0316d): (67, "SelfReferenceMarkerMap"),
+  ("read_only_space", 0x03195): (67, "BasicBlockCountersMarkerMap"),
+  ("read_only_space", 0x031d9): (87, "ArrayBoilerplateDescriptionMap"),
+  ("read_only_space", 0x032a9): (99, "InterceptorInfoMap"),
+  ("read_only_space", 0x0539d): (72, "PromiseFulfillReactionJobTaskMap"),
+  ("read_only_space", 0x053c5): (73, "PromiseRejectReactionJobTaskMap"),
+  ("read_only_space", 0x053ed): (74, "CallableTaskMap"),
+  ("read_only_space", 0x05415): (75, "CallbackTaskMap"),
+  ("read_only_space", 0x0543d): (76, "PromiseResolveThenableJobTaskMap"),
+  ("read_only_space", 0x05465): (79, "FunctionTemplateInfoMap"),
+  ("read_only_space", 0x0548d): (80, "ObjectTemplateInfoMap"),
+  ("read_only_space", 0x054b5): (81, "AccessCheckInfoMap"),
+  ("read_only_space", 0x054dd): (82, "AccessorInfoMap"),
+  ("read_only_space", 0x05505): (83, "AccessorPairMap"),
+  ("read_only_space", 0x0552d): (84, "AliasedArgumentsEntryMap"),
+  ("read_only_space", 0x05555): (85, "AllocationMementoMap"),
+  ("read_only_space", 0x0557d): (88, "AsmWasmDataMap"),
+  ("read_only_space", 0x055a5): (89, "AsyncGeneratorRequestMap"),
+  ("read_only_space", 0x055cd): (90, "BreakPointMap"),
+  ("read_only_space", 0x055f5): (91, "BreakPointInfoMap"),
+  ("read_only_space", 0x0561d): (92, "CachedTemplateObjectMap"),
+  ("read_only_space", 0x05645): (94, "ClassPositionsMap"),
+  ("read_only_space", 0x0566d): (95, "DebugInfoMap"),
+  ("read_only_space", 0x05695): (98, "FunctionTemplateRareDataMap"),
+  ("read_only_space", 0x056bd): (100, "InterpreterDataMap"),
+  ("read_only_space", 0x056e5): (101, "PromiseCapabilityMap"),
+  ("read_only_space", 0x0570d): (102, "PromiseReactionMap"),
+  ("read_only_space", 0x05735): (103, "PropertyDescriptorObjectMap"),
+  ("read_only_space", 0x0575d): (104, "PrototypeInfoMap"),
+  ("read_only_space", 0x05785): (105, "ScriptMap"),
+  ("read_only_space", 0x057ad): (106, "SourceTextModuleInfoEntryMap"),
+  ("read_only_space", 0x057d5): (107, "StackFrameInfoMap"),
+  ("read_only_space", 0x057fd): (108, "StackTraceFrameMap"),
+  ("read_only_space", 0x05825): (109, "TemplateObjectDescriptionMap"),
+  ("read_only_space", 0x0584d): (110, "Tuple2Map"),
+  ("read_only_space", 0x05875): (111, "WasmCapiFunctionDataMap"),
+  ("read_only_space", 0x0589d): (112, "WasmExceptionTagMap"),
+  ("read_only_space", 0x058c5): (113, "WasmExportedFunctionDataMap"),
+  ("read_only_space", 0x058ed): (114, "WasmIndirectFunctionTableMap"),
+  ("read_only_space", 0x05915): (115, "WasmJSFunctionDataMap"),
+  ("read_only_space", 0x0593d): (116, "WasmValueMap"),
+  ("read_only_space", 0x05965): (135, "SloppyArgumentsElementsMap"),
+  ("read_only_space", 0x0598d): (171, "OnHeapBasicBlockProfilerDataMap"),
+  ("read_only_space", 0x059b5): (168, "InternalClassMap"),
+  ("read_only_space", 0x059dd): (177, "SmiPairMap"),
+  ("read_only_space", 0x05a05): (176, "SmiBoxMap"),
+  ("read_only_space", 0x05a2d): (146, "ExportedSubClassBaseMap"),
+  ("read_only_space", 0x05a54): (147, "ExportedSubClassMap"),
+  ("read_only_space", 0x05a7d): (68, "AbstractInternalClassSubclass1Map"),
+  ("read_only_space", 0x05aa5): (69, "AbstractInternalClassSubclass2Map"),
+  ("read_only_space", 0x05acd): (134, "InternalClassWithSmiElementsMap"),
+  ("read_only_space", 0x05af5): (169, "InternalClassWithStructElementsMap"),
+  ("read_only_space", 0x05b1d): (148, "ExportedSubClass2Map"),
+  ("read_only_space", 0x05b45): (178, "SortStateMap"),
+  ("read_only_space", 0x05b6d): (86, "AllocationSiteWithWeakNextMap"),
+  ("read_only_space", 0x05b95): (86, "AllocationSiteWithoutWeakNextMap"),
+  ("read_only_space", 0x05bbd): (77, "LoadHandler1Map"),
+  ("read_only_space", 0x05be5): (77, "LoadHandler2Map"),
+  ("read_only_space", 0x05c0d): (77, "LoadHandler3Map"),
+  ("read_only_space", 0x05c35): (78, "StoreHandler0Map"),
+  ("read_only_space", 0x05c5d): (78, "StoreHandler1Map"),
+  ("read_only_space", 0x05c85): (78, "StoreHandler2Map"),
+  ("read_only_space", 0x05cad): (78, "StoreHandler3Map"),
+  ("map_space", 0x02119): (1057, "ExternalMap"),
+  ("map_space", 0x02141): (1072, "JSMessageObjectMap"),
+  ("map_space", 0x02169): (180, "WasmRttEqrefMap"),
+  ("map_space", 0x02191): (180, "WasmRttExternrefMap"),
+  ("map_space", 0x021b9): (180, "WasmRttFuncrefMap"),
+  ("map_space", 0x021e1): (180, "WasmRttI31refMap"),
 }
 
 # List of known V8 objects.
 KNOWN_OBJECTS = {
-  ("read_only_space", 0x021b5): "EmptyWeakFixedArray",
-  ("read_only_space", 0x021bd): "EmptyDescriptorArray",
-  ("read_only_space", 0x021f5): "EmptyEnumCache",
-  ("read_only_space", 0x02229): "EmptyFixedArray",
-  ("read_only_space", 0x02231): "NullValue",
-  ("read_only_space", 0x02339): "UninitializedValue",
-  ("read_only_space", 0x023b1): "UndefinedValue",
-  ("read_only_space", 0x023f5): "NanValue",
-  ("read_only_space", 0x02429): "TheHoleValue",
-  ("read_only_space", 0x02455): "HoleNanValue",
-  ("read_only_space", 0x02489): "TrueValue",
-  ("read_only_space", 0x024c9): "FalseValue",
-  ("read_only_space", 0x024f9): "empty_string",
-  ("read_only_space", 0x02735): "EmptyScopeInfo",
-  ("read_only_space", 0x02765): "ArgumentsMarker",
-  ("read_only_space", 0x027c5): "Exception",
-  ("read_only_space", 0x02821): "TerminationException",
-  ("read_only_space", 0x02889): "OptimizedOut",
-  ("read_only_space", 0x028e9): "StaleRegister",
-  ("read_only_space", 0x031b9): "EmptyPropertyArray",
-  ("read_only_space", 0x031c1): "EmptyByteArray",
-  ("read_only_space", 0x031c9): "EmptyObjectBoilerplateDescription",
-  ("read_only_space", 0x031fd): "EmptyArrayBoilerplateDescription",
-  ("read_only_space", 0x03209): "EmptyClosureFeedbackCellArray",
-  ("read_only_space", 0x03211): "EmptySlowElementDictionary",
-  ("read_only_space", 0x03235): "EmptyOrderedHashMap",
-  ("read_only_space", 0x03249): "EmptyOrderedHashSet",
-  ("read_only_space", 0x0325d): "EmptyFeedbackMetadata",
-  ("read_only_space", 0x03269): "EmptyPropertyCell",
-  ("read_only_space", 0x0327d): "EmptyPropertyDictionary",
-  ("read_only_space", 0x032cd): "NoOpInterceptorInfo",
-  ("read_only_space", 0x032f5): "EmptyWeakArrayList",
-  ("read_only_space", 0x03301): "InfinityValue",
-  ("read_only_space", 0x0330d): "MinusZeroValue",
-  ("read_only_space", 0x03319): "MinusInfinityValue",
-  ("read_only_space", 0x03325): "SelfReferenceMarker",
-  ("read_only_space", 0x03365): "BasicBlockCountersMarker",
-  ("read_only_space", 0x033a9): "OffHeapTrampolineRelocationInfo",
-  ("read_only_space", 0x033b5): "TrampolineTrivialCodeDataContainer",
-  ("read_only_space", 0x033c1): "TrampolinePromiseRejectionCodeDataContainer",
-  ("read_only_space", 0x033cd): "GlobalThisBindingScopeInfo",
-  ("read_only_space", 0x03405): "EmptyFunctionScopeInfo",
-  ("read_only_space", 0x0342d): "NativeScopeInfo",
-  ("read_only_space", 0x03449): "HashSeed",
-  ("old_space", 0x02115): "ArgumentsIteratorAccessor",
-  ("old_space", 0x02159): "ArrayLengthAccessor",
-  ("old_space", 0x0219d): "BoundFunctionLengthAccessor",
-  ("old_space", 0x021e1): "BoundFunctionNameAccessor",
-  ("old_space", 0x02225): "ErrorStackAccessor",
-  ("old_space", 0x02269): "FunctionArgumentsAccessor",
-  ("old_space", 0x022ad): "FunctionCallerAccessor",
-  ("old_space", 0x022f1): "FunctionNameAccessor",
-  ("old_space", 0x02335): "FunctionLengthAccessor",
-  ("old_space", 0x02379): "FunctionPrototypeAccessor",
-  ("old_space", 0x023bd): "RegExpResultIndicesAccessor",
-  ("old_space", 0x02401): "StringLengthAccessor",
-  ("old_space", 0x02445): "InvalidPrototypeValidityCell",
-  ("old_space", 0x024cd): "EmptyScript",
-  ("old_space", 0x0250d): "ManyClosuresCell",
-  ("old_space", 0x02519): "ArrayConstructorProtector",
-  ("old_space", 0x0252d): "NoElementsProtector",
-  ("old_space", 0x02541): "IsConcatSpreadableProtector",
-  ("old_space", 0x02555): "ArraySpeciesProtector",
-  ("old_space", 0x02569): "TypedArraySpeciesProtector",
-  ("old_space", 0x0257d): "PromiseSpeciesProtector",
-  ("old_space", 0x02591): "RegExpSpeciesProtector",
-  ("old_space", 0x025a5): "StringLengthProtector",
-  ("old_space", 0x025b9): "ArrayIteratorProtector",
-  ("old_space", 0x025cd): "ArrayBufferDetachingProtector",
-  ("old_space", 0x025e1): "PromiseHookProtector",
-  ("old_space", 0x025f5): "PromiseResolveProtector",
-  ("old_space", 0x02609): "MapIteratorProtector",
-  ("old_space", 0x0261d): "PromiseThenProtector",
-  ("old_space", 0x02631): "SetIteratorProtector",
-  ("old_space", 0x02645): "StringIteratorProtector",
-  ("old_space", 0x02659): "SingleCharacterStringCache",
-  ("old_space", 0x02a61): "StringSplitCache",
-  ("old_space", 0x02e69): "RegExpMultipleCache",
-  ("old_space", 0x03271): "BuiltinsConstantsTable",
-  ("old_space", 0x0364d): "AsyncFunctionAwaitRejectSharedFun",
-  ("old_space", 0x03675): "AsyncFunctionAwaitResolveSharedFun",
-  ("old_space", 0x0369d): "AsyncGeneratorAwaitRejectSharedFun",
-  ("old_space", 0x036c5): "AsyncGeneratorAwaitResolveSharedFun",
-  ("old_space", 0x036ed): "AsyncGeneratorYieldResolveSharedFun",
-  ("old_space", 0x03715): "AsyncGeneratorReturnResolveSharedFun",
-  ("old_space", 0x0373d): "AsyncGeneratorReturnClosedRejectSharedFun",
-  ("old_space", 0x03765): "AsyncGeneratorReturnClosedResolveSharedFun",
-  ("old_space", 0x0378d): "AsyncIteratorValueUnwrapSharedFun",
-  ("old_space", 0x037b5): "PromiseAllResolveElementSharedFun",
-  ("old_space", 0x037dd): "PromiseAllSettledResolveElementSharedFun",
-  ("old_space", 0x03805): "PromiseAllSettledRejectElementSharedFun",
-  ("old_space", 0x0382d): "PromiseAnyRejectElementSharedFun",
-  ("old_space", 0x03855): "PromiseCapabilityDefaultRejectSharedFun",
-  ("old_space", 0x0387d): "PromiseCapabilityDefaultResolveSharedFun",
-  ("old_space", 0x038a5): "PromiseCatchFinallySharedFun",
-  ("old_space", 0x038cd): "PromiseGetCapabilitiesExecutorSharedFun",
-  ("old_space", 0x038f5): "PromiseThenFinallySharedFun",
-  ("old_space", 0x0391d): "PromiseThrowerFinallySharedFun",
-  ("old_space", 0x03945): "PromiseValueThunkFinallySharedFun",
-  ("old_space", 0x0396d): "ProxyRevokeSharedFun",
+  ("read_only_space", 0x021b9): "EmptyWeakFixedArray",
+  ("read_only_space", 0x021c1): "EmptyDescriptorArray",
+  ("read_only_space", 0x021f9): "EmptyEnumCache",
+  ("read_only_space", 0x0222d): "EmptyFixedArray",
+  ("read_only_space", 0x02235): "NullValue",
+  ("read_only_space", 0x0233d): "UninitializedValue",
+  ("read_only_space", 0x023b5): "UndefinedValue",
+  ("read_only_space", 0x023f9): "NanValue",
+  ("read_only_space", 0x0242d): "TheHoleValue",
+  ("read_only_space", 0x02459): "HoleNanValue",
+  ("read_only_space", 0x0248d): "TrueValue",
+  ("read_only_space", 0x024cd): "FalseValue",
+  ("read_only_space", 0x024fd): "empty_string",
+  ("read_only_space", 0x02739): "EmptyScopeInfo",
+  ("read_only_space", 0x02769): "ArgumentsMarker",
+  ("read_only_space", 0x027c9): "Exception",
+  ("read_only_space", 0x02825): "TerminationException",
+  ("read_only_space", 0x0288d): "OptimizedOut",
+  ("read_only_space", 0x028ed): "StaleRegister",
+  ("read_only_space", 0x031bd): "EmptyPropertyArray",
+  ("read_only_space", 0x031c5): "EmptyByteArray",
+  ("read_only_space", 0x031cd): "EmptyObjectBoilerplateDescription",
+  ("read_only_space", 0x03201): "EmptyArrayBoilerplateDescription",
+  ("read_only_space", 0x0320d): "EmptyClosureFeedbackCellArray",
+  ("read_only_space", 0x03215): "EmptySlowElementDictionary",
+  ("read_only_space", 0x03239): "EmptyOrderedHashMap",
+  ("read_only_space", 0x0324d): "EmptyOrderedHashSet",
+  ("read_only_space", 0x03261): "EmptyFeedbackMetadata",
+  ("read_only_space", 0x0326d): "EmptyPropertyCell",
+  ("read_only_space", 0x03281): "EmptyPropertyDictionary",
+  ("read_only_space", 0x032d1): "NoOpInterceptorInfo",
+  ("read_only_space", 0x032f9): "EmptyWeakArrayList",
+  ("read_only_space", 0x03305): "InfinityValue",
+  ("read_only_space", 0x03311): "MinusZeroValue",
+  ("read_only_space", 0x0331d): "MinusInfinityValue",
+  ("read_only_space", 0x03329): "SelfReferenceMarker",
+  ("read_only_space", 0x03369): "BasicBlockCountersMarker",
+  ("read_only_space", 0x033ad): "OffHeapTrampolineRelocationInfo",
+  ("read_only_space", 0x033b9): "TrampolineTrivialCodeDataContainer",
+  ("read_only_space", 0x033c5): "TrampolinePromiseRejectionCodeDataContainer",
+  ("read_only_space", 0x033d1): "GlobalThisBindingScopeInfo",
+  ("read_only_space", 0x03409): "EmptyFunctionScopeInfo",
+  ("read_only_space", 0x03432): "NativeScopeInfo",
+  ("read_only_space", 0x0344d): "HashSeed",
+  ("old_space", 0x02119): "ArgumentsIteratorAccessor",
+  ("old_space", 0x0215d): "ArrayLengthAccessor",
+  ("old_space", 0x021a1): "BoundFunctionLengthAccessor",
+  ("old_space", 0x021e5): "BoundFunctionNameAccessor",
+  ("old_space", 0x02229): "ErrorStackAccessor",
+  ("old_space", 0x0226d): "FunctionArgumentsAccessor",
+  ("old_space", 0x022b1): "FunctionCallerAccessor",
+  ("old_space", 0x022f5): "FunctionNameAccessor",
+  ("old_space", 0x02339): "FunctionLengthAccessor",
+  ("old_space", 0x0237d): "FunctionPrototypeAccessor",
+  ("old_space", 0x023c1): "RegExpResultIndicesAccessor",
+  ("old_space", 0x02405): "StringLengthAccessor",
+  ("old_space", 0x02449): "InvalidPrototypeValidityCell",
+  ("old_space", 0x024d1): "EmptyScript",
+  ("old_space", 0x02511): "ManyClosuresCell",
+  ("old_space", 0x0251d): "ArrayConstructorProtector",
+  ("old_space", 0x02531): "NoElementsProtector",
+  ("old_space", 0x02545): "IsConcatSpreadableProtector",
+  ("old_space", 0x02559): "ArraySpeciesProtector",
+  ("old_space", 0x0256d): "TypedArraySpeciesProtector",
+  ("old_space", 0x02581): "PromiseSpeciesProtector",
+  ("old_space", 0x02595): "RegExpSpeciesProtector",
+  ("old_space", 0x025a9): "StringLengthProtector",
+  ("old_space", 0x025bd): "ArrayIteratorProtector",
+  ("old_space", 0x025d1): "ArrayBufferDetachingProtector",
+  ("old_space", 0x025e5): "PromiseHookProtector",
+  ("old_space", 0x025f9): "PromiseResolveProtector",
+  ("old_space", 0x0260d): "MapIteratorProtector",
+  ("old_space", 0x02621): "PromiseThenProtector",
+  ("old_space", 0x02635): "SetIteratorProtector",
+  ("old_space", 0x02649): "StringIteratorProtector",
+  ("old_space", 0x0265d): "SingleCharacterStringCache",
+  ("old_space", 0x02a65): "StringSplitCache",
+  ("old_space", 0x02e6d): "RegExpMultipleCache",
+  ("old_space", 0x03275): "BuiltinsConstantsTable",
+  ("old_space", 0x03651): "AsyncFunctionAwaitRejectSharedFun",
+  ("old_space", 0x03679): "AsyncFunctionAwaitResolveSharedFun",
+  ("old_space", 0x036a1): "AsyncGeneratorAwaitRejectSharedFun",
+  ("old_space", 0x036c9): "AsyncGeneratorAwaitResolveSharedFun",
+  ("old_space", 0x036f1): "AsyncGeneratorYieldResolveSharedFun",
+  ("old_space", 0x03719): "AsyncGeneratorReturnResolveSharedFun",
+  ("old_space", 0x03741): "AsyncGeneratorReturnClosedRejectSharedFun",
+  ("old_space", 0x03769): "AsyncGeneratorReturnClosedResolveSharedFun",
+  ("old_space", 0x03791): "AsyncIteratorValueUnwrapSharedFun",
+  ("old_space", 0x037b9): "PromiseAllResolveElementSharedFun",
+  ("old_space", 0x037e1): "PromiseAllSettledResolveElementSharedFun",
+  ("old_space", 0x03809): "PromiseAllSettledRejectElementSharedFun",
+  ("old_space", 0x03831): "PromiseAnyRejectElementSharedFun",
+  ("old_space", 0x03859): "PromiseCapabilityDefaultRejectSharedFun",
+  ("old_space", 0x03881): "PromiseCapabilityDefaultResolveSharedFun",
+  ("old_space", 0x038a9): "PromiseCatchFinallySharedFun",
+  ("old_space", 0x038d1): "PromiseGetCapabilitiesExecutorSharedFun",
+  ("old_space", 0x038f9): "PromiseThenFinallySharedFun",
+  ("old_space", 0x03921): "PromiseThrowerFinallySharedFun",
+  ("old_space", 0x03949): "PromiseValueThunkFinallySharedFun",
+  ("old_space", 0x03971): "ProxyRevokeSharedFun",
 }
 
 # Lower 32 bits of first page addresses for various heap spaces.
diff -Naur a/src/buildtools/configure.json b/src/buildtools/configure.json
--- a/src/buildtools/configure.json	2021-04-01 15:33:27.000000000 +0100
+++ b/src/buildtools/configure.json	2021-06-18 16:42:57.601738058 +0100
@@ -56,6 +56,12 @@
                 { "type": "pkgConfig", "args": "xtst" }
             ]
         },
+        "webengine-xkbfile": {
+            "label": "xkbfile",
+            "sources": [
+                { "type": "pkgConfig", "args": "xkbfile" }
+            ]
+        },
         "webengine-nss": {
             "label": "nss >= 3.26",
             "sources": [
@@ -490,6 +496,11 @@
             "condition": "libs.webengine-xtst",
             "output": [ "privateFeature" ]
         },
+        "webengine-system-xkbfile": {
+            "label": "xkbfile",
+            "condition": "libs.webengine-xkbfile",
+            "output": [ "privateFeature" ]
+        },
         "webengine-system-gn": {
             "label": "Use System Gn",
             "autoDetect": "false",
@@ -538,7 +549,8 @@
                           && features.webengine-system-xcursor
                           && features.webengine-system-xi
                           && features.webengine-system-xproto-gl
-                          && features.webengine-system-xtst",
+                          && features.webengine-system-xtst
+                          && features.webengine-system-xkbfile",
              "output": [ "privateFeature" ]
         },
         "webengine-jumbo-build": {
@@ -784,7 +796,8 @@
                         "webengine-system-xcursor",
                         "webengine-system-xi",
                         "webengine-system-xproto-gl",
-                        "webengine-system-xtst"
+                        "webengine-system-xtst",
+                        "webengine-system-xkbfile"
                      ]
                 },
                 {
diff -Naur a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
--- a/src/core/content_browser_client_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/content_browser_client_qt.cpp	2021-06-18 16:26:16.757871682 +0100
@@ -39,6 +39,7 @@
 
 #include "content_browser_client_qt.h"
 
+#include "base/files/file_util.h"
 #include "base/optional.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
@@ -167,6 +168,7 @@
 #include "extensions/common/manifest_handlers/mime_types_handler.h"
 #include "extensions/extension_web_contents_observer_qt.h"
 #include "extensions/extensions_browser_client_qt.h"
+#include "extensions/pdf_iframe_navigation_throttle_qt.h"
 #include "net/plugin_response_interceptor_url_loader_throttle.h"
 #endif
 
@@ -222,6 +224,13 @@
 
 namespace QtWebEngineCore {
 
+void MaybeAddThrottle(
+    std::unique_ptr<content::NavigationThrottle> maybe_throttle,
+    std::vector<std::unique_ptr<content::NavigationThrottle>>* throttles) {
+    if (maybe_throttle)
+        throttles->push_back(std::move(maybe_throttle));
+}
+
 class QtShareGLContext : public gl::GLContext {
 public:
     QtShareGLContext(QOpenGLContext *qtContext)
@@ -471,12 +480,7 @@
 
 std::string ContentBrowserClientQt::GetApplicationLocale()
 {
-    std::string bcp47Name = QLocale().bcp47Name().toStdString();
-    if (m_cachedQtLocale != bcp47Name) {
-        m_cachedQtLocale = bcp47Name;
-        m_appLocale = WebEngineLibraryInfo::getApplicationLocale();
-    }
-    return m_appLocale;
+    return WebEngineLibraryInfo::getApplicationLocale();
 }
 
 std::string ContentBrowserClientQt::GetAcceptLangs(content::BrowserContext *context)
@@ -492,7 +496,7 @@
 
     std::string processType = command_line->GetSwitchValueASCII(switches::kProcessType);
     if (processType == switches::kZygoteProcess)
-        command_line->AppendSwitchASCII(switches::kLang, GetApplicationLocale());
+        command_line->AppendSwitchASCII(switches::kLang, WebEngineLibraryInfo::getApplicationLocale());
 }
 
 void ContentBrowserClientQt::GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes)
@@ -520,9 +524,8 @@
 #if defined(Q_OS_LINUX)
 void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings)
 {
-    const std::string &locale = GetApplicationLocale();
-    const base::FilePath &locale_file_path = ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale);
-    if (locale_file_path.empty())
+    const base::FilePath &locale_file_path = ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(WebEngineLibraryInfo::getResolvedLocale());
+    if (locale_file_path.empty() || !base::PathExists(locale_file_path))
         return;
 
     // Open pak file of the current locale in the Browser process and pass its file descriptor to the sandboxed
@@ -997,7 +1000,13 @@
         WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(source)->GetView())->client();
     if (!client)
         return false;
-    client->navigationRequested(pageTransitionToNavigationType(params.transition_type()),
+
+    // Redirects might not be reflected in transition_type at this point (see also chrome/.../web_navigation_api_helpers.cc)
+    auto transition_type = params.transition_type();
+    if (params.is_redirect())
+        transition_type = ui::PageTransitionFromInt(transition_type | ui::PAGE_TRANSITION_SERVER_REDIRECT);
+
+    client->navigationRequested(pageTransitionToNavigationType(transition_type),
                                 toQt(params.url()),
                                 navigationRequestAction,
                                 params.is_main_frame());
@@ -1012,6 +1021,11 @@
                             navigation_handle,
                             base::BindRepeating(&navigationThrottleCallback),
                             navigation_interception::SynchronyMode::kSync));
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+    MaybeAddThrottle(extensions::PDFIFrameNavigationThrottleQt::MaybeCreateThrottleFor(navigation_handle), &throttles);
+#endif
+
     return throttles;
 }
 
diff -Naur a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
--- a/src/core/content_browser_client_qt.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/content_browser_client_qt.h	2021-06-18 16:26:16.758873414 +0100
@@ -269,8 +269,6 @@
 
 private:
     scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick;
-    std::string m_appLocale;
-    std::string m_cachedQtLocale;
 };
 
 } // namespace QtWebEngineCore
diff -Naur a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp
--- a/src/core/content_main_delegate_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/content_main_delegate_qt.cpp	2021-06-18 16:26:16.758873414 +0100
@@ -179,7 +179,9 @@
 #endif
 
     net::NetModule::SetResourceProvider(PlatformResourceProvider);
-    ui::ResourceBundle::InitSharedInstanceWithLocale(WebEngineLibraryInfo::getApplicationLocale(), nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
+
+    base::i18n::SetICUDefaultLocale(WebEngineLibraryInfo::getApplicationLocale());
+    ui::ResourceBundle::InitSharedInstanceWithLocale(WebEngineLibraryInfo::getResolvedLocale(), nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
 
     base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess();
     logging::LoggingSettings settings;
diff -Naur a/src/core/core_chromium.pri b/src/core/core_chromium.pri
--- a/src/core/core_chromium.pri	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/core_chromium.pri	2021-06-18 16:26:16.758873414 +0100
@@ -113,7 +113,6 @@
         renderer/web_engine_page_render_frame.cpp \
         renderer/render_configuration.cpp \
         renderer/user_resource_controller.cpp \
-        renderer/plugins/plugin_placeholder_qt.cpp \
         renderer_host/web_engine_page_host.cpp \
         renderer_host/user_resource_controller_host.cpp \
         resource_bundle_qt.cpp \
@@ -218,7 +217,6 @@
         renderer/web_engine_page_render_frame.h \
         renderer/render_configuration.h \
         renderer/user_resource_controller.h \
-        renderer/plugins/plugin_placeholder_qt.h \
         renderer_host/web_engine_page_host.h \
         renderer_host/user_resource_controller_host.h \
         request_controller.h \
@@ -326,6 +324,7 @@
         extensions/extensions_browser_client_qt.cpp \
         extensions/messaging_delegate_qt.cpp \
         extensions/mime_handler_view_guest_delegate_qt.cpp \
+        extensions/pdf_iframe_navigation_throttle_qt.cpp \
         extensions/plugin_service_filter_qt.cpp \
         net/plugin_response_interceptor_url_loader_throttle.cpp \
         renderer/extensions/extensions_dispatcher_delegate_qt.cpp \
@@ -345,6 +344,7 @@
         extensions/extensions_browser_client_qt.h \
         extensions/messaging_delegate_qt.h \
         extensions/mime_handler_view_guest_delegate_qt.h \
+        extensions/pdf_iframe_navigation_throttle_qt.h \
         extensions/plugin_service_filter_qt.h \
         net/plugin_response_interceptor_url_loader_throttle.h \
         renderer/extensions/extensions_dispatcher_delegate_qt.h \
diff -Naur a/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp
--- a/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp	1970-01-01 01:00:00.000000000 +0100
+++ b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp	2021-06-18 16:26:16.758873414 +0100
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// based on //chrome/browser/plugins/pdf_iframe_navigation_throttle.cc
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#include "extensions/pdf_iframe_navigation_throttle_qt.h"
+
+#include "chrome/grit/renderer_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/download_utils.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "content/public/common/webplugininfo.h"
+#include "net/base/escape.h"
+#include "net/http/http_response_headers.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/jstemplate_builder.h"
+#include "ui/base/webui/web_ui_util.h"
+
+namespace extensions {
+
+constexpr char kPDFMimeType[] = "application/pdf";
+
+// Used to scope the posted navigation task to the lifetime of |web_contents|.
+class PdfWebContentsLifetimeHelper : public content::WebContentsUserData<PdfWebContentsLifetimeHelper>
+{
+public:
+    explicit PdfWebContentsLifetimeHelper(content::WebContents *web_contents)
+        : web_contents_(web_contents)
+    {}
+
+    base::WeakPtr<PdfWebContentsLifetimeHelper> GetWeakPtr()
+    {
+        return weak_factory_.GetWeakPtr();
+    }
+
+    void NavigateIFrameToPlaceholder(const content::OpenURLParams &url_params)
+    {
+        web_contents_->OpenURL(url_params);
+    }
+
+private:
+    friend class content::WebContentsUserData<PdfWebContentsLifetimeHelper>;
+
+    content::WebContents* const web_contents_;
+    base::WeakPtrFactory<PdfWebContentsLifetimeHelper> weak_factory_{this};
+
+    WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(PdfWebContentsLifetimeHelper)
+
+bool IsPDFPluginEnabled(content::NavigationHandle *navigation_handle, bool *is_stale)
+{
+    content::WebContents *web_contents = navigation_handle->GetWebContents();
+    int process_id = web_contents->GetMainFrame()->GetProcess()->GetID();
+    int routing_id = web_contents->GetMainFrame()->GetRoutingID();
+    content::WebPluginInfo plugin_info;
+    // Will check WebEngineSettings by PluginServiceFilterQt
+    return content::PluginService::GetInstance()->GetPluginInfo(
+        process_id, routing_id, navigation_handle->GetURL(),
+        web_contents->GetMainFrame()->GetLastCommittedOrigin(), kPDFMimeType,
+        false /* allow_wildcard */, is_stale, &plugin_info,
+        nullptr /* actual_mime_type */);
+}
+
+std::string GetPDFPlaceholderHTML(const GURL &pdf_url)
+{
+    std::string template_html = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_PDF_PLUGIN_HTML);
+    webui::AppendWebUiCssTextDefaults(&template_html);
+
+    base::DictionaryValue values;
+    values.SetString("fileName", pdf_url.ExtractFileName());
+    values.SetString("open", l10n_util::GetStringUTF8(IDS_ACCNAME_OPEN));
+    values.SetString("pdfUrl", pdf_url.spec());
+
+    return webui::GetI18nTemplateHtml(template_html, &values);
+}
+
+// static
+std::unique_ptr<content::NavigationThrottle>
+PDFIFrameNavigationThrottleQt::MaybeCreateThrottleFor(content::NavigationHandle *handle)
+{
+    if (handle->IsInMainFrame())
+        return nullptr;
+    return std::make_unique<PDFIFrameNavigationThrottleQt>(handle);
+}
+
+PDFIFrameNavigationThrottleQt::PDFIFrameNavigationThrottleQt(content::NavigationHandle *handle)
+    : content::NavigationThrottle(handle)
+{
+}
+
+PDFIFrameNavigationThrottleQt::~PDFIFrameNavigationThrottleQt()
+{
+}
+
+content::NavigationThrottle::ThrottleCheckResult PDFIFrameNavigationThrottleQt::WillProcessResponse()
+{
+    const net::HttpResponseHeaders *response_headers = navigation_handle()->GetResponseHeaders();
+    if (!response_headers)
+        return content::NavigationThrottle::PROCEED;
+
+    std::string mime_type;
+    response_headers->GetMimeType(&mime_type);
+    if (mime_type != kPDFMimeType)
+        return content::NavigationThrottle::PROCEED;
+
+    // We MUST download responses marked as attachments rather than showing
+    // a placeholder.
+    if (content::download_utils::MustDownload(navigation_handle()->GetURL(), response_headers, mime_type))
+        return content::NavigationThrottle::PROCEED;
+
+    bool is_stale = false;
+    bool pdf_plugin_enabled = IsPDFPluginEnabled(navigation_handle(), &is_stale);
+
+    if (is_stale) {
+        // On browser start, the plugin list may not be ready yet.
+        content::PluginService::GetInstance()->GetPlugins(
+            base::BindOnce(&PDFIFrameNavigationThrottleQt::OnPluginsLoaded,
+                           weak_factory_.GetWeakPtr()));
+        return content::NavigationThrottle::DEFER;
+    }
+
+    // If the plugin was found, proceed on the navigation. Otherwise fall through
+    // to the placeholder case.
+    if (pdf_plugin_enabled)
+        return content::NavigationThrottle::PROCEED;
+
+    LoadPlaceholderHTML();
+    return content::NavigationThrottle::CANCEL_AND_IGNORE;
+}
+
+const char *PDFIFrameNavigationThrottleQt::GetNameForLogging()
+{
+    return "PDFIFrameNavigationThrottleQt";
+}
+
+void PDFIFrameNavigationThrottleQt::OnPluginsLoaded(
+                        const std::vector<content::WebPluginInfo> &plugins)
+{
+    if (IsPDFPluginEnabled(navigation_handle(), nullptr /* is_stale */)) {
+        Resume();
+    } else {
+        LoadPlaceholderHTML();
+        CancelDeferredNavigation(content::NavigationThrottle::CANCEL_AND_IGNORE);
+    }
+}
+
+void PDFIFrameNavigationThrottleQt::LoadPlaceholderHTML()
+{
+    // Prepare the params to navigate to the placeholder.
+    std::string html = GetPDFPlaceholderHTML(navigation_handle()->GetURL());
+    GURL data_url("data:text/html," + net::EscapePath(html));
+    content::OpenURLParams params = content::OpenURLParams::FromNavigationHandle(navigation_handle());
+    params.url = data_url;
+    params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
+
+    // Post a task to navigate to the placeholder HTML. We don't navigate
+    // synchronously here, as starting a navigation within a navigation is
+    // an antipattern. Use a helper object scoped to the WebContents lifetime to
+    // scope the navigation task to the WebContents lifetime.
+    content::WebContents *web_contents = navigation_handle()->GetWebContents();
+    if (!web_contents)
+        return;
+
+    PdfWebContentsLifetimeHelper::CreateForWebContents(web_contents);
+    PdfWebContentsLifetimeHelper *helper = PdfWebContentsLifetimeHelper::FromWebContents(web_contents);
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&PdfWebContentsLifetimeHelper::NavigateIFrameToPlaceholder,
+                       helper->GetWeakPtr(), std::move(params)));
+}
+
+} // namespace extensions
diff -Naur a/src/core/extensions/pdf_iframe_navigation_throttle_qt.h b/src/core/extensions/pdf_iframe_navigation_throttle_qt.h
--- a/src/core/extensions/pdf_iframe_navigation_throttle_qt.h	1970-01-01 01:00:00.000000000 +0100
+++ b/src/core/extensions/pdf_iframe_navigation_throttle_qt.h	2021-06-18 16:26:16.758873414 +0100
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// based on //chrome/browser/plugins/pdf_iframe_navigation_throttle.h
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PDF_IFRAME_NAVIGATION_THROTTLE_QT
+#define PDF_IFRAME_NAVIGATION_THROTTLE_QT
+
+#include "content/public/browser/navigation_throttle.h"
+
+#include "base/memory/weak_ptr.h"
+
+namespace content {
+class NavigationHandle;
+struct WebPluginInfo;
+}
+
+namespace extensions {
+
+// This class prevents automatical download of PDFs when they are embedded
+// in subframes and plugins are disabled in API.
+class PDFIFrameNavigationThrottleQt : public content::NavigationThrottle
+{
+public:
+    static std::unique_ptr<content::NavigationThrottle> MaybeCreateThrottleFor(content::NavigationHandle *handle);
+
+    explicit PDFIFrameNavigationThrottleQt(content::NavigationHandle *handle);
+    ~PDFIFrameNavigationThrottleQt() override;
+
+    // content::NavigationThrottle
+    content::NavigationThrottle::ThrottleCheckResult WillProcessResponse() override;
+    const char *GetNameForLogging() override;
+
+private:
+    void OnPluginsLoaded(const std::vector<content::WebPluginInfo> &plugins);
+    void LoadPlaceholderHTML();
+
+    base::WeakPtrFactory<PDFIFrameNavigationThrottleQt> weak_factory_{this};
+};
+
+} // namespace extensions
+
+#endif // PDF_IFRAME_NAVIGATION_THROTTLE_QT
diff -Naur a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp
--- a/src/core/file_picker_controller.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/file_picker_controller.cpp	2021-06-18 16:44:28.945708182 +0100
@@ -95,7 +95,7 @@
         if (urlString.startsWith("file:")) {
             base::FilePath filePath = toFilePath(urlString).NormalizePathSeparators();
             std::vector<base::FilePath::StringType> pathComponents;
-            // Splits the file URL into host name, path and file name.
+            // Splits the file URL into scheme, host name, path and file name.
             filePath.GetComponents(&pathComponents);
 
             QString absolutePath;
@@ -107,7 +107,7 @@
             if (scheme.size() > 5) {
 #if defined(OS_WIN)
                 // There is no slash at the end of the file scheme and it is valid on Windows: file:C:/
-                if (scheme.at(5).isLetter() && scheme.at(6) != ':') {
+                if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == ':') {
                     absolutePath += scheme.at(5) + ":/";
                 } else {
 #endif
@@ -194,9 +194,13 @@
 void FilePickerController::filesSelectedInChooser(const QStringList &filesList)
 {
     QStringList files(filesList);
+    base::FilePath baseDir;
     if (d_ptr->mode == UploadFolder && !filesList.isEmpty()
-            && QFileInfo(filesList.first()).isDir()) // Enumerate the directory
+            && QFileInfo(filesList.first()).isDir()) {
+        // Enumerate the directory
         files = listRecursively(QDir(filesList.first()));
+        baseDir = toFilePath(filesList.first());
+    }
 
     std::vector<blink::mojom::FileChooserFileInfoPtr> chooser_files;
     for (const auto &file : qAsConst(files)) {
@@ -208,7 +212,7 @@
         d_ptr->listener->FileSelectionCanceled();
     else
         d_ptr->listener->FileSelected(std::move(chooser_files),
-                                  /* FIXME? */ base::FilePath(),
+                                 baseDir,
                                  static_cast<blink::mojom::FileChooserParams::Mode>(d_ptr->mode));
 }
 
diff -Naur a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp
--- a/src/core/net/cookie_monster_delegate_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/net/cookie_monster_delegate_qt.cpp	2021-06-18 16:26:16.758873414 +0100
@@ -80,7 +80,7 @@
 
     void AllowedAccess(const GURL &url, const net::SiteForCookies &site_for_cookies, AllowedAccessCallback callback) override
     {
-        bool allow = m_delegate->canGetCookies(toQt(site_for_cookies.RepresentativeUrl()), toQt(url));
+        bool allow = m_delegate->canGetCookies(toQt(site_for_cookies.first_party_url()), toQt(url));
         std::move(callback).Run(allow);
     }
 
diff -Naur a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp
--- a/src/core/net/proxying_restricted_cookie_manager_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp	2021-06-18 16:26:16.758873414 +0100
@@ -197,7 +197,7 @@
 {
     if (!m_profileIoData)
         return false;
-    return m_profileIoData->canGetCookies(toQt(site_for_cookies.RepresentativeUrl()), toQt(url));
+    return m_profileIoData->canGetCookies(toQt(site_for_cookies.first_party_url()), toQt(url));
 }
 
 }  // namespace QtWebEngineCore
diff -Naur a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp
--- a/src/core/net/proxying_url_loader_factory_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/net/proxying_url_loader_factory_qt.cpp	2021-06-18 16:26:16.758873414 +0100
@@ -266,7 +266,7 @@
     if (!top_document_url.is_empty())
         firstPartyUrl = toQt(top_document_url);
     else
-        firstPartyUrl = toQt(request_.site_for_cookies.RepresentativeUrl()); // m_topDocumentUrl can be empty for the main-frame.
+        firstPartyUrl = toQt(request_.site_for_cookies.first_party_url()); // m_topDocumentUrl can be empty for the main-frame.
 
     auto info = new QWebEngineUrlRequestInfoPrivate(resourceType, navigationType, originalUrl, firstPartyUrl,
                                                     initiator, QByteArray::fromStdString(request_.method));
diff -Naur a/src/core/ozone/BUILD.gn b/src/core/ozone/BUILD.gn
--- a/src/core/ozone/BUILD.gn	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/ozone/BUILD.gn	2021-06-18 16:42:57.601738058 +0100
@@ -1,6 +1,7 @@
 # Copyright 2016 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
+import("//ui/base/ui_features.gni")
 
 source_set("qt") {
   sources = [
@@ -18,4 +19,8 @@
   ]
 
   defines = [ "OZONE_IMPLEMENTATION" ]
+
+  if (use_xkbcommon && use_x11) {
+    libs = [ "xkbfile" ]
+  }
 }
diff -Naur a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp
--- a/src/core/ozone/ozone_platform_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/ozone/ozone_platform_qt.cpp	2021-06-18 16:42:57.601738058 +0100
@@ -40,9 +40,12 @@
 #include "ozone_platform_qt.h"
 
 #if defined(USE_OZONE)
+#include "ui/base/buildflags.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/display/types/native_display_delegate.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #include "ui/ozone/common/stub_client_native_pixmap_factory.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
@@ -56,6 +59,16 @@
 #include "surface_factory_qt.h"
 #include "platform_window_qt.h"
 
+#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11)
+#include "ui/events/ozone/layout/xkb/xkb_evdev_codes.h"
+#include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h"
+
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBrules.h>
+
+extern void *GetQtXDisplay();
+#endif // BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11)
+
 namespace ui {
 
 namespace {
@@ -86,6 +99,11 @@
     std::unique_ptr<InputController> input_controller_;
     std::unique_ptr<OverlayManagerOzone> overlay_manager_;
 
+#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11)
+    XkbEvdevCodes m_xkbEvdevCodeConverter;
+#endif
+    std::unique_ptr<KeyboardLayoutEngine> m_keyboardLayoutEngine;
+
     DISALLOW_COPY_AND_ASSIGN(OzonePlatformQt);
 };
 
@@ -135,12 +153,65 @@
     return nullptr;
 }
 
+#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11)
+static std::string getCurrentKeyboardLayout()
+{
+    Display *dpy = static_cast<Display *>(GetQtXDisplay());
+    if (dpy == nullptr)
+        return std::string();
+
+    XkbStateRec state;
+    if (XkbGetState(dpy, XkbUseCoreKbd, &state) != 0)
+        return std::string();
+
+    XkbRF_VarDefsRec vdr;
+    if (XkbRF_GetNamesProp(dpy, nullptr, &vdr) == 0)
+        return std::string();
+
+    char *layout = strtok(vdr.layout, ",");
+    for (int i = 0; i < state.group; i++) {
+        layout = strtok(nullptr, ",");
+        if (layout == nullptr)
+            return std::string();
+    }
+
+    char *variant = strtok(vdr.variant, ",");
+    if (!variant)
+        return layout;
+
+    for (int i = 0; i < state.group; i++) {
+        variant = strtok(nullptr, ",");
+        if (variant == nullptr)
+            return layout;
+    }
+
+    std::string layoutWithVariant = layout;
+    layoutWithVariant = layoutWithVariant.append("-");
+    layoutWithVariant = layoutWithVariant.append(variant);
+    return layoutWithVariant;
+}
+#endif // BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11)
+
 void OzonePlatformQt::InitializeUI(const ui::OzonePlatform::InitParams &)
 {
     overlay_manager_.reset(new StubOverlayManager());
     cursor_factory_ozone_.reset(new BitmapCursorFactoryOzone());
     gpu_platform_support_host_.reset(ui::CreateStubGpuPlatformSupportHost());
     input_controller_ = CreateStubInputController();
+
+#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11)
+    std::string layout = getCurrentKeyboardLayout();
+    if (layout.empty()) {
+        m_keyboardLayoutEngine = std::make_unique<StubKeyboardLayoutEngine>();
+    } else {
+        m_keyboardLayoutEngine = std::make_unique<XkbKeyboardLayoutEngine>(m_xkbEvdevCodeConverter);
+        m_keyboardLayoutEngine->SetCurrentLayoutByName(layout);
+    }
+#else
+    m_keyboardLayoutEngine = std::make_unique<StubKeyboardLayoutEngine>();
+#endif // BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11)
+
+    KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(m_keyboardLayoutEngine.get());
 }
 
 void OzonePlatformQt::InitializeGPU(const ui::OzonePlatform::InitParams &)
diff -Naur a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
--- a/src/core/permission_manager_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/permission_manager_qt.cpp	2021-06-18 16:26:16.758873414 +0100
@@ -122,7 +122,6 @@
 
 PermissionManagerQt::PermissionManagerQt()
     : m_requestIdCount(0)
-    , m_subscriberIdCount(0)
 {
 }
 
@@ -339,19 +338,19 @@
     m_permissions.remove(key);
 }
 
-int PermissionManagerQt::SubscribePermissionStatusChange(
+content::PermissionControllerDelegate::SubscriptionId PermissionManagerQt::SubscribePermissionStatusChange(
     content::PermissionType permission,
     content::RenderFrameHost * /* render_frame_host */,
     const GURL& requesting_origin,
     base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
 {
-    int subscriber_id = ++m_subscriberIdCount;
+    auto subscriber_id = subscription_id_generator_.GenerateNextId();
     m_subscribers.insert( { subscriber_id,
                             Subscription { toQt(permission), toQt(requesting_origin), std::move(callback) } });
     return subscriber_id;
 }
 
-void PermissionManagerQt::UnsubscribePermissionStatusChange(int subscription_id)
+void PermissionManagerQt::UnsubscribePermissionStatusChange(content::PermissionControllerDelegate::SubscriptionId subscription_id)
 {
     if (!m_subscribers.erase(subscription_id))
         LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id;
diff -Naur a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h
--- a/src/core/permission_manager_qt.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/permission_manager_qt.h	2021-06-18 16:26:16.758873414 +0100
@@ -89,13 +89,13 @@
         base::OnceCallback<void(
             const std::vector<blink::mojom::PermissionStatus>&)> callback) override;
 
-    int SubscribePermissionStatusChange(
+    content::PermissionControllerDelegate::SubscriptionId SubscribePermissionStatusChange(
         content::PermissionType permission,
         content::RenderFrameHost* render_frame_host,
         const GURL& requesting_origin,
         const base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) override;
 
-    void UnsubscribePermissionStatusChange(int subscription_id) override;
+    void UnsubscribePermissionStatusChange(content::PermissionControllerDelegate::SubscriptionId subscription_id) override;
 
 private:
     QHash<QPair<QUrl, ProfileAdapter::PermissionType>, bool> m_permissions;
@@ -118,9 +118,9 @@
     };
     std::vector<Request> m_requests;
     std::vector<MultiRequest> m_multiRequests;
-    std::map<int, Subscription> m_subscribers;
+    std::map<content::PermissionControllerDelegate::SubscriptionId, Subscription> m_subscribers;
+    content::PermissionControllerDelegate::SubscriptionId::Generator subscription_id_generator_;
     int m_requestIdCount;
-    int m_subscriberIdCount;
 
 };
 
diff -Naur a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
--- a/src/core/profile_adapter.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/profile_adapter.cpp	2021-06-18 16:26:16.761878611 +0100
@@ -87,6 +87,9 @@
 
 namespace QtWebEngineCore {
 
+// static
+QPointer<ProfileAdapter> ProfileAdapter::s_profileForGlobalCertificateVerification;
+
 ProfileAdapter::ProfileAdapter(const QString &storageName):
       m_name(storageName)
     , m_offTheRecord(storageName.isEmpty())
@@ -654,26 +657,26 @@
     if (m_usedForGlobalCertificateVerification == enable)
         return;
 
-    static QPointer<ProfileAdapter> profileForglobalCertificateVerification;
-
     m_usedForGlobalCertificateVerification = enable;
     if (enable) {
-        if (profileForglobalCertificateVerification) {
-            profileForglobalCertificateVerification->m_usedForGlobalCertificateVerification = false;
-            if (!m_profile->m_profileIOData->isClearHttpCacheInProgress())
-                profileForglobalCertificateVerification->m_profile->m_profileIOData->resetNetworkContext();
-            for (auto *client : qAsConst(profileForglobalCertificateVerification->m_clients))
+        if (s_profileForGlobalCertificateVerification) {
+            s_profileForGlobalCertificateVerification->m_usedForGlobalCertificateVerification = false;
+            for (auto *client : qAsConst(s_profileForGlobalCertificateVerification->m_clients))
                 client->useForGlobalCertificateVerificationChanged();
+        } else {
+            // OCSP enabled
+            for (auto adapter : qAsConst(WebEngineContext::current()->m_profileAdapters))
+                adapter->m_profile->m_profileIOData->resetNetworkContext();
         }
-        profileForglobalCertificateVerification = this;
+        s_profileForGlobalCertificateVerification = this;
     } else {
-        Q_ASSERT(profileForglobalCertificateVerification);
-        Q_ASSERT(profileForglobalCertificateVerification == this);
-        profileForglobalCertificateVerification = nullptr;
+        Q_ASSERT(s_profileForGlobalCertificateVerification);
+        Q_ASSERT(s_profileForGlobalCertificateVerification == this);
+        s_profileForGlobalCertificateVerification = nullptr;
+        // OCSP disabled
+        for (auto adapter : qAsConst(WebEngineContext::current()->m_profileAdapters))
+            adapter->m_profile->m_profileIOData->resetNetworkContext();
     }
-
-    if (!m_profile->m_profileIOData->isClearHttpCacheInProgress())
-        m_profile->m_profileIOData->resetNetworkContext();
 }
 
 bool ProfileAdapter::isUsedForGlobalCertificateVerification() const
diff -Naur a/src/core/profile_adapter.h b/src/core/profile_adapter.h
--- a/src/core/profile_adapter.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/profile_adapter.h	2021-06-18 16:26:16.761878611 +0100
@@ -216,6 +216,7 @@
 
     QString determineDownloadPath(const QString &downloadDirectory, const QString &suggestedFilename, const time_t &startTime);
 
+    static QPointer<ProfileAdapter> s_profileForGlobalCertificateVerification;
 private:
     void updateCustomUrlSchemeHandlers();
     void resetVisitedLinksManager();
diff -Naur a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
--- a/src/core/profile_io_data_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/profile_io_data_qt.cpp	2021-06-18 16:26:16.761878611 +0100
@@ -224,6 +224,9 @@
 
     SystemNetworkContextManager::GetInstance()->ConfigureDefaultNetworkContextParams(network_context_params);
 
+    // FIXME: Faking old behavior to allow not enabling OCSP
+    network_context_params->initial_ssl_config->rev_checking_enabled = !ProfileAdapter::s_profileForGlobalCertificateVerification.isNull();
+
     network_context_params->context_name = m_storageName.toStdString();
     network_context_params->user_agent = m_httpUserAgent.toStdString();
     network_context_params->accept_language = m_httpAcceptLanguage.toStdString();
diff -Naur a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni
--- a/src/core/qtwebengine_sources.gni	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/qtwebengine_sources.gni	2021-06-18 16:47:20.282016944 +0100
@@ -53,6 +53,7 @@
     "//components/performance_manager",
     "//components/plugins/renderer/",
     "//extensions/buildflags:buildflags",
+    "//qtwebengine/common:mojo_bindings",
     "//rlz/buildflags:buildflags",
     "//third_party/blink/public/mojom:mojom_platform",
   ]
diff -Naur a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
--- a/src/core/renderer/content_renderer_client_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/renderer/content_renderer_client_qt.cpp	2021-06-18 16:26:16.761878611 +0100
@@ -97,7 +97,6 @@
 
 #if BUILDFLAG(ENABLE_PLUGINS)
 #include "plugins/loadable_plugin_placeholder_qt.h"
-#include "plugins/plugin_placeholder_qt.h"
 #include "content/common/frame_messages.h"
 #endif // ENABLE_PLUGINS
 
@@ -119,6 +118,8 @@
 #include "chrome/renderer/media/webrtc_logging_agent_impl.h"
 #endif
 
+#include "web_engine_library_info.h"
+
 namespace QtWebEngineCore {
 
 static const char kHttpErrorDomain[] = "http";
@@ -135,6 +136,7 @@
 
 void ContentRendererClientQt::RenderThreadStarted()
 {
+    base::i18n::SetICUDefaultLocale(WebEngineLibraryInfo::getApplicationLocale());
     content::RenderThread *renderThread = content::RenderThread::Get();
     m_renderConfiguration.reset(new RenderConfiguration());
     m_userResourceController.reset(new UserResourceController());
diff -Naur a/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp
--- a/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.cpp	2021-06-18 16:26:16.761878611 +0100
@@ -77,7 +77,7 @@
 LoadablePluginPlaceholderQt* LoadablePluginPlaceholderQt::CreateLoadableMissingPlugin(content::RenderFrame* render_frame,
                                                                                       const blink::WebPluginParams& params)
 {
-    const base::StringPiece template_html(ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_BLOCKED_PLUGIN_HTML));
+    std::string template_html(ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_BLOCKED_PLUGIN_HTML));
 
     base::DictionaryValue values;
     values.SetString("name", "");
diff -Naur a/src/core/renderer/plugins/plugin_placeholder_qt.cpp b/src/core/renderer/plugins/plugin_placeholder_qt.cpp
--- a/src/core/renderer/plugins/plugin_placeholder_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/renderer/plugins/plugin_placeholder_qt.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// Copyright 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 "plugin_placeholder_qt.h"
-
-#include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/v8_value_converter.h"
-#include "gin/object_template_builder.h"
-
-namespace QtWebEngineCore {
-
-// static
-gin::WrapperInfo PluginPlaceholderQt::kWrapperInfo = {gin::kEmbedderNativeGin};
-
-PluginPlaceholderQt::PluginPlaceholderQt(content::RenderFrame* render_frame,
-                                         const blink::WebPluginParams& params,
-                                         const std::string& html_data)
-    : PluginPlaceholderBase(render_frame, params, html_data)
-{}
-
-PluginPlaceholderQt::~PluginPlaceholderQt() {}
-
-v8::Local<v8::Value> PluginPlaceholderQt::GetV8Handle(v8::Isolate* isolate)
-{
-    return gin::CreateHandle(isolate, this).ToV8();
-}
-
-gin::ObjectTemplateBuilder PluginPlaceholderQt::GetObjectTemplateBuilder(v8::Isolate* isolate)
-{
-    return gin::Wrappable<PluginPlaceholderQt>::GetObjectTemplateBuilder(isolate)
-        .SetMethod<void (QtWebEngineCore::PluginPlaceholderQt::*)()>(
-            "hide", &PluginPlaceholderQt::HideCallback);
-}
-
-}  // namespace QtWebEngineCore
diff -Naur a/src/core/renderer/plugins/plugin_placeholder_qt.h b/src/core/renderer/plugins/plugin_placeholder_qt.h
--- a/src/core/renderer/plugins/plugin_placeholder_qt.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/renderer/plugins/plugin_placeholder_qt.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// Copyright 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 PLUGIN_PLACEHOLDER_QT_H
-#define PLUGIN_PLACEHOLDER_QT_H
-
-#include "base/macros.h"
-#include "components/plugins/renderer/plugin_placeholder.h"
-#include "gin/handle.h"
-#include "gin/wrappable.h"
-#include "third_party/blink/public/web/web_plugin_params.h"
-
-namespace QtWebEngineCore {
-
-// A basic placeholder that supports only hiding.
-class PluginPlaceholderQt final : public plugins::PluginPlaceholderBase
-                                , public gin::Wrappable<PluginPlaceholderQt>
-{
-public:
-    static gin::WrapperInfo kWrapperInfo;
-
-    PluginPlaceholderQt(content::RenderFrame* render_frame,
-                        const blink::WebPluginParams& params,
-                        const std::string& html_data);
-    ~PluginPlaceholderQt() override;
-
-private:
-    // WebViewPlugin::Delegate methods:
-    v8::Local<v8::Value> GetV8Handle(v8::Isolate* isolate) final;
-
-    // gin::Wrappable method:
-    gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
-        v8::Isolate* isolate) override;
-};
-
-}  // namespace QtWebEngineCore
-
-#endif  // PLUGIN_PLACEHOLDER_QT_H
diff -Naur a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
--- a/src/core/render_widget_host_view_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/render_widget_host_view_qt.cpp	2021-06-18 16:42:57.602739791 +0100
@@ -80,6 +80,7 @@
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
 #include "ui/events/gesture_detection/motion_event.h"
+#include "ui/events/keycodes/dom/dom_keyboard_layout_map.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/touch_selection/touch_selection_controller.h"
 
@@ -1968,6 +1969,11 @@
     }
 }
 
+base::flat_map<std::string, std::string> RenderWidgetHostViewQt::GetKeyboardLayoutMap()
+{
+    return ui::GenerateDomKeyboardLayoutMap();
+}
+
 void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view)
 {
     DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewChildFrame());
diff -Naur a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
--- a/src/core/render_widget_host_view_qt.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/render_widget_host_view_qt.h	2021-06-18 16:42:57.602739791 +0100
@@ -175,6 +175,7 @@
     const viz::FrameSinkId &GetFrameSinkId() const override;
     const viz::LocalSurfaceId &GetLocalSurfaceId() const override;
     void FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) override;
+    base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
 
     void TakeFallbackContentFrom(content::RenderWidgetHostView *view) override;
     void EnsureSurfaceSynchronizedForWebTest() override;
diff -Naur a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp
--- a/src/core/resource_bundle_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/resource_bundle_qt.cpp	2021-06-18 16:26:16.768890737 +0100
@@ -98,7 +98,7 @@
 {
     DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded";
 
-    std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
+    std::string app_locale = l10n_util::GetApplicationLocale(pref_locale, false /* set_icu_locale */);
 
 #if defined(OS_LINUX)
     int locale_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(kWebEngineLocale);
diff -Naur a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
--- a/src/core/web_contents_adapter_client.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_contents_adapter_client.h	2021-06-18 16:35:08.955249384 +0100
@@ -466,8 +466,7 @@
     virtual void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) = 0;
     virtual void loadCommitted() = 0;
     virtual void loadVisuallyCommitted() = 0;
-    virtual void loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode,
-                              const QString &errorDescription, bool triggersErrorPage) = 0;
+    virtual void loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription) = 0;
     virtual void focusContainer() = 0;
     virtual void unhandledKeyEvent(QKeyEvent *event) = 0;
     virtual QSharedPointer<WebContentsAdapter>
diff -Naur a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
--- a/src/core/web_contents_adapter.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_contents_adapter.cpp	2021-06-18 16:35:08.955249384 +0100
@@ -716,8 +716,7 @@
             m_adapterClient->loadFinished(false, request.url(), false,
                                           net::ERR_DISALLOWED_URL_SCHEME,
                                           QCoreApplication::translate("WebContentsAdapter",
-                                          "HTTP-POST data can only be sent over HTTP(S) protocol"),
-                                          false);
+                                          "HTTP-POST data can only be sent over HTTP(S) protocol"));
             return;
         }
         params.post_data = network::ResourceRequestBody::CreateFromBytes(
@@ -773,7 +772,7 @@
 
     GURL dataUrlToLoad(urlString);
     if (dataUrlToLoad.spec().size() > url::kMaxURLChars) {
-        m_adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED, QString(), false);
+        m_adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED, QString());
         return;
     }
     content::NavigationController::LoadURLParams params((dataUrlToLoad));
@@ -1995,6 +1994,7 @@
     if (m_webContents->IsLoading()) {
         m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(webContents()), net::Error::ERR_ABORTED,
                                            QStringLiteral("Discarded"));
+        m_webContentsDelegate->DidStopLoading();
     }
 
     content::WebContents::CreateParams createParams(m_profileAdapter->profile());
diff -Naur a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
--- a/src/core/web_contents_delegate_qt.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_contents_delegate_qt.cpp	2021-06-18 16:35:38.963145971 +0100
@@ -259,14 +259,12 @@
 
 void WebContentsDelegateQt::LoadProgressChanged(double progress)
 {
-    QUrl current_url(m_viewClient->webContentsAdapter()->getNavigationEntryOriginalUrl(m_viewClient->webContentsAdapter()->currentNavigationEntryIndex()));
-    int p = qMin(qRound(progress * 100), 100);
-
-    if (!m_loadingErrorFrameList.isEmpty() || !m_loadProgressMap.contains(current_url) || m_loadProgressMap[current_url] == 100 || p ==  100)
+    if (!m_loadingInfo.isLoading()) // suppress signals that aren't between loadStarted and loadFinished
         return;
 
-    if (p > m_loadProgressMap[current_url]) { // ensure strict monotonic increase
-        m_loadProgressMap[current_url] = p;
+    int p = qMin(qRound(progress * 100), 100);
+    if (p > m_loadingInfo.progress) { // ensure strict monotonic increase
+        m_loadingInfo.progress = p;
         m_viewClient->loadProgressChanged(p);
     }
 }
@@ -286,11 +284,6 @@
     m_frameFocusedObserver.addNode(node);
 }
 
-void WebContentsDelegateQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host)
-{
-    m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID());
-}
-
 void WebContentsDelegateQt::RenderProcessGone(base::TerminationStatus status)
 {
     // RenderProcessHost::FastShutdownIfPossible results in TERMINATION_STATUS_STILL_RUNNING
@@ -339,35 +332,21 @@
     }
 }
 
-void WebContentsDelegateQt::EmitLoadStarted(const QUrl &url, bool isErrorPage)
+void WebContentsDelegateQt::emitLoadStarted(bool isErrorPage)
 {
-    m_isDocumentEmpty = true;
-    m_viewClient->loadStarted(url, isErrorPage);
-    m_viewClient->updateNavigationActions();
-
-    if ((url.hasFragment() || m_lastLoadedUrl.hasFragment())
-        && url.adjusted(QUrl::RemoveFragment) == m_lastLoadedUrl.adjusted(QUrl::RemoveFragment)
-        && !m_isNavigationCommitted) {
-        m_loadProgressMap.insert(url, 100);
-        m_lastLoadedUrl = url;
-        m_viewClient->loadProgressChanged(100);
+    // only report first ever load start or separate one for error page only
+    if (!isErrorPage && m_loadingInfo.isLoading()) // already running
         return;
-    }
 
-    if (!m_loadProgressMap.isEmpty()) {
-        QMap<QUrl, int>::iterator it = m_loadProgressMap.begin();
-        while (it != m_loadProgressMap.end()) {
-            if (it.value() == 100) {
-                it = m_loadProgressMap.erase(it);
-                continue;
-            }
-            ++it;
-        }
+    m_isDocumentEmpty = true; // reset to default which may only be overridden on actual resource load complete
+    if (!isErrorPage) {
+        m_loadingInfo.progress = 0;
+        m_viewClient->loadStarted(m_loadingInfo.url, false);
+        m_viewClient->updateNavigationActions();
+        m_viewClient->loadProgressChanged(0);
+    } else {
+        m_viewClient->loadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true);
     }
-
-    m_lastLoadedUrl = url;
-    m_loadProgressMap.insert(url, 0);
-    m_viewClient->loadProgressChanged(0);
 }
 
 void WebContentsDelegateQt::DidStartNavigation(content::NavigationHandle *navigation_handle)
@@ -375,34 +354,39 @@
     if (!webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled))
         navigation_handle->SetSilentlyIgnoreErrors();
 
-    if (!navigation_handle->IsInMainFrame())
+    if (!navigation_handle->IsInMainFrame() || !web_contents()->IsLoadingToDifferentDocument())
         return;
 
-
-    m_loadingErrorFrameList.clear();
     m_faviconManager->resetCandidates();
-    EmitLoadStarted(toQt(navigation_handle->GetURL()));
+
+    m_loadingInfo.url = toQt(navigation_handle->GetURL());
+    // IsErrorPage is only set after navigation commit, so check it otherwise: error page shouldn't have navigation entry
+    bool isErrorPage = m_loadingInfo.triggersErrorPage && !navigation_handle->GetNavigationEntry();
+    emitLoadStarted(isErrorPage);
 }
 
-void WebContentsDelegateQt::EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription, bool triggersErrorPage)
+void WebContentsDelegateQt::emitLoadFinished(bool isErrorPage)
 {
-    Q_ASSERT(!isErrorPage || webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled));
-    Q_ASSERT((triggersErrorPage && webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled)) || !triggersErrorPage);
-
-    // When error page enabled we don't need to send the error page load finished signal
-    if (m_loadProgressMap[url] == 100)
+    if (!m_loadingInfo.isLoading()) // not currently running
         return;
 
-    m_lastLoadedUrl = url;
-    m_loadProgressMap[url] = 100;
-    m_isNavigationCommitted = false;
-    m_viewClient->loadProgressChanged(100);
+    Q_ASSERT(!isErrorPage || webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled));
+    Q_ASSERT((m_loadingInfo.triggersErrorPage && webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled)) || !m_loadingInfo.triggersErrorPage);
 
-    m_viewClient->loadFinished(success, url, isErrorPage, errorCode, errorDescription, triggersErrorPage);
-    m_viewClient->updateNavigationActions();
+    if (!isErrorPage) {
+        if (m_loadingInfo.progress < 100) {
+            m_loadingInfo.progress = 100;
+            m_viewClient->loadProgressChanged(100);
+        }
+
+        m_viewClient->loadFinished(m_loadingInfo.success, m_loadingInfo.url, false, m_loadingInfo.errorCode, m_loadingInfo.errorDescription);
+        m_viewClient->updateNavigationActions();
+    } else {
+        m_viewClient->loadFinished(false, toQt(GURL(content::kUnreachableWebDataURL)), true, 0, QString());
+    }
 }
 
-void WebContentsDelegateQt::EmitLoadCommitted()
+void WebContentsDelegateQt::emitLoadCommitted()
 {
     m_findTextHelper->handleLoadCommitted();
     m_viewClient->loadCommitted();
@@ -422,8 +406,7 @@
                 profileAdapter->visitedLinksManager()->addUrl(url);
         }
 
-        m_isNavigationCommitted = true;
-        EmitLoadCommitted();
+        emitLoadCommitted();
     }
 
     // Success is reported by DidFinishLoad, but DidFailLoad is now dead code and needs to be handled below
@@ -438,13 +421,12 @@
     // The load will succede as an error-page load later, and we reported the original error above
     if (navigation_handle->IsErrorPage()) {
         // Now report we are starting to load an error-page.
-        m_loadingErrorFrameList.append(navigation_handle->GetRenderFrameHost()->GetRoutingID());
         m_faviconManager->resetCandidates();
-        EmitLoadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true);
+        emitLoadStarted(true);
 
         // If it is already committed we will not see another DidFinishNavigation call or a DidFinishLoad call.
         if (navigation_handle->HasCommitted())
-            EmitLoadCommitted();
+            emitLoadCommitted();
     }
 }
 
@@ -486,6 +468,9 @@
 
     if (m_loadingState == LoadingState::Loading)
         setLoadingState(LoadingState::Loaded);
+
+    emitLoadFinished();
+    m_loadingInfo.clear();
 }
 
 void WebContentsDelegateQt::didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription)
@@ -495,7 +480,11 @@
     // Delay notifying failure until the error-page is done loading.
     // Error-pages are not loaded on failures due to abort.
     bool aborted = (errorCode == -3 /* ERR_ABORTED*/ );
-    EmitLoadFinished(false /* success */ , url, false /* isErrorPage */, errorCode, errorDescription, errorPageEnabled && !aborted);
+    m_loadingInfo.success = false;
+    m_loadingInfo.url = url;
+    m_loadingInfo.errorCode = errorCode;
+    m_loadingInfo.errorDescription = errorDescription;
+    m_loadingInfo.triggersErrorPage = errorPageEnabled && !aborted;
 }
 
 void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code)
@@ -509,10 +498,8 @@
     if (validated_url.spec() == content::kUnreachableWebDataURL) {
         // error-pages should only ever fail due to abort:
         Q_ASSERT(error_code == -3 /* ERR_ABORTED */);
-        m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID());
         m_viewClient->iconChanged(QUrl());
-
-        EmitLoadFinished(false /* success */, toQt(validated_url), true /* isErrorPage */);
+        emitLoadFinished(/* isErrorPage = */true);
         return;
     }
     // Qt6: Consider getting rid of the error_description (Chromium already has)
@@ -527,12 +514,10 @@
 {
     Q_ASSERT(validated_url.is_valid());
     if (validated_url.spec() == content::kUnreachableWebDataURL) {
-        m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID());
-
         // Trigger LoadFinished signal for main frame's error page only.
         if (!render_frame_host->GetParent()) {
             m_viewClient->iconChanged(QUrl());
-            EmitLoadFinished(true /* success */, toQt(validated_url), true /* isErrorPage */);
+            emitLoadFinished(/* isErrorPage = */true);
         }
 
         return;
@@ -550,7 +535,11 @@
     int http_statuscode = entry ? entry->GetHttpStatusCode() : 0;
     bool errorPageEnabled = webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled);
     bool triggersErrorPage = errorPageEnabled && (http_statuscode >= 400) && m_isDocumentEmpty;
-    EmitLoadFinished(http_statuscode < 400, toQt(validated_url), false /* isErrorPage */, http_statuscode, QString(), triggersErrorPage);
+
+    m_loadingInfo.success = http_statuscode < 400;
+    m_loadingInfo.url = toQt(validated_url);
+    m_loadingInfo.errorCode = http_statuscode;
+    m_loadingInfo.triggersErrorPage = triggersErrorPage;
 }
 
 void WebContentsDelegateQt::DidUpdateFaviconURL(content::RenderFrameHost *render_frame_host, const std::vector<blink::mojom::FaviconURLPtr> &candidates)
diff -Naur a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
--- a/src/core/web_contents_delegate_qt.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_contents_delegate_qt.h	2021-06-18 16:35:38.963145971 +0100
@@ -158,7 +158,6 @@
 
     // WebContentsObserver overrides
     void RenderFrameCreated(content::RenderFrameHost *render_frame_host) override;
-    void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) override;
     void RenderProcessGone(base::TerminationStatus status) override;
     void RenderFrameHostChanged(content::RenderFrameHost *old_host, content::RenderFrameHost *new_host) override;
     void RenderViewHostChanged(content::RenderViewHost *old_host, content::RenderViewHost *new_host) override;
@@ -216,9 +215,9 @@
                  WindowOpenDisposition disposition, const gfx::Rect &initial_pos,
                  const QUrl &url,
                  bool user_gesture);
-    void EmitLoadStarted(const QUrl &url, bool isErrorPage = false);
-    void EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage = false, int errorCode = 0, const QString &errorDescription = QString(), bool triggersErrorPage = false);
-    void EmitLoadCommitted();
+    void emitLoadStarted(bool isErrorPage = false);
+    void emitLoadFinished(bool isErrorPage = false);
+    void emitLoadCommitted();
 
     LoadingState determineLoadingState(content::WebContents *contents);
     void setLoadingState(LoadingState state);
@@ -226,7 +225,6 @@
     int &streamCount(blink::mojom::MediaStreamType type);
 
     WebContentsAdapterClient *m_viewClient;
-    QVector<int64_t> m_loadingErrorFrameList;
     QScopedPointer<FaviconManager> m_faviconManager;
     QScopedPointer<FindTextHelper> m_findTextHelper;
     SavePageInfo m_savePageInfo;
@@ -242,9 +240,17 @@
     int m_desktopStreamCount = 0;
     mutable bool m_pendingUrlUpdate = false;
 
-    QMap<QUrl, int> m_loadProgressMap;
-    QUrl m_lastLoadedUrl;
-    bool m_isNavigationCommitted = false;
+    struct LoadingInfo {
+        bool success = false;
+        int progress = -1;
+        bool isLoading() const { return progress >= 0; }
+        QUrl url;
+        int errorCode = 0;
+        QString errorDescription;
+        bool triggersErrorPage = false;
+        void clear() { *this = LoadingInfo(); }
+    } m_loadingInfo;
+
     bool m_isDocumentEmpty = true;
     base::WeakPtrFactory<WebContentsDelegateQt> m_weakPtrFactory { this };
 };
diff -Naur a/src/core/web_engine_context_threads.cpp b/src/core/web_engine_context_threads.cpp
--- a/src/core/web_engine_context_threads.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_engine_context_threads.cpp	2021-06-18 16:40:43.433706766 +0100
@@ -84,7 +84,7 @@
         if (s_gpuProcessDestroyed)
             return;
 
-        s_gpuProcess = std::make_unique<content::GpuProcess>(base::ThreadPriority::DISPLAY);
+        s_gpuProcess = std::make_unique<content::GpuProcess>(base::ThreadPriority::NORMAL);
         auto gpuInit = std::make_unique<gpu::GpuInit>();
         gpuInit->InitializeInProcess(base::CommandLine::ForCurrentProcess(), gpuPreferences);
         auto childThread = new content::GpuChildThread(params, std::move(gpuInit));
diff -Naur a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
--- a/src/core/web_engine_library_info.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_engine_library_info.cpp	2021-06-18 16:26:16.768890737 +0100
@@ -351,7 +351,7 @@
     return toString16(qApp->applicationName());
 }
 
-std::string WebEngineLibraryInfo::getApplicationLocale()
+std::string WebEngineLibraryInfo::getResolvedLocale()
 {
     base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
     if (parsedCommandLine->HasSwitch(switches::kLang)) {
@@ -365,6 +365,14 @@
     return "en-US";
 }
 
+std::string WebEngineLibraryInfo::getApplicationLocale()
+{
+    base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
+    return parsedCommandLine->HasSwitch(switches::kLang)
+        ? parsedCommandLine->GetSwitchValueASCII(switches::kLang)
+        : QLocale().bcp47Name().toStdString();
+}
+
 #if defined(OS_WIN)
 bool WebEngineLibraryInfo::isRemoteDrivePath(const QString &path)
 {
diff -Naur a/src/core/web_engine_library_info.h b/src/core/web_engine_library_info.h
--- a/src/core/web_engine_library_info.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_engine_library_info.h	2021-06-18 16:26:16.768890737 +0100
@@ -57,6 +57,7 @@
     static base::FilePath getPath(int key);
     // Called by localized_error in our custom chrome layer
     static base::string16 getApplicationName();
+    static std::string getResolvedLocale();
     static std::string getApplicationLocale();
 #if defined(OS_WIN)
     static bool isRemoteDrivePath(const QString &path);
diff -Naur a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
--- a/src/core/web_event_factory.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/core/web_event_factory.cpp	2021-06-18 16:48:36.369602704 +0100
@@ -1581,7 +1581,7 @@
 #endif
         return blink::WebMouseWheelEvent::kPhaseNone;
     case Qt::ScrollBegin:
-        return ev->angleDelta().isNull() ? blink::WebMouseWheelEvent::kPhaseMayBegin : blink::WebMouseWheelEvent::kPhaseBegan;
+        return blink::WebMouseWheelEvent::kPhaseBegan;
     case Qt::ScrollUpdate:
         return blink::WebMouseWheelEvent::kPhaseChanged;
     case Qt::ScrollEnd:
diff -Naur a/src/pdf/config/common.pri b/src/pdf/config/common.pri
--- a/src/pdf/config/common.pri	2021-04-01 15:33:27.000000000 +0100
+++ b/src/pdf/config/common.pri	2021-06-18 16:26:16.768890737 +0100
@@ -24,12 +24,21 @@
 }
 
 qtConfig(webengine-qt-zlib) {
+    win32 {
+      CONFIG(debug, debug|release) {
+          qtzlib = Qt5Cored.lib
+      } else {
+          qtzlib = Qt5Core.lib
+      }
+
+    } else { qtzlib = libQt5Core.a
+    }
     gn_args += use_qt_zlib = true
     gn_args += "qt_zlib_includes=\["\
                "\"$$system_path($$[QT_INSTALL_HEADERS])\"," \
                "\"$$system_path($$[QT_INSTALL_HEADERS]/QtCore)\"," \
                "\"$$system_path($$[QT_INSTALL_HEADERS]/QtZlib)\"\]"
-    gn_args += "qt_zlib=\"$$system_path($$[QT_INSTALL_LIBS]/libQt5Core.a)\""
+    gn_args += "qt_zlib=\"$$system_path($$[QT_INSTALL_LIBS]/$$qtzlib)\""
 }
 
 qtConfig(pdf-v8) {
diff -Naur a/src/pdf/pdfcore.pro b/src/pdf/pdfcore.pro
--- a/src/pdf/pdfcore.pro	2021-04-01 15:33:27.000000000 +0100
+++ b/src/pdf/pdfcore.pro	2021-06-18 16:26:16.768890737 +0100
@@ -78,10 +78,10 @@
     api/qpdfselection_p.h \
 
 
-qtConfig(webengine-qt-freetype): QMAKE_USE_PRIVATE+= freetype
-qtConfig(webengine-qt-png): QMAKE_USE_PRIVATE+= libpng
-qtConfig(webengine-qt-harfbuzz): QMAKE_USE_PRIVATE+= harfbuzz
-qtConfig(webengine-qt-jpeg): QMAKE_USE_PRIVATE+= libjpeg
+qtConfig(webengine-qt-freetype): QMAKE_USE += freetype
+qtConfig(webengine-qt-png): QMAKE_USE += libpng
+qtConfig(webengine-qt-harfbuzz): QMAKE_USE += harfbuzz
+qtConfig(webengine-qt-jpeg): QMAKE_USE += libjpeg
 qtConfig(webengine-qt-zlib){} #qtzlib is a part of QtCore
 
 load(qt_module)
diff -Naur a/src/pdf/quick/qquickpdfsearchmodel.cpp b/src/pdf/quick/qquickpdfsearchmodel.cpp
--- a/src/pdf/quick/qquickpdfsearchmodel.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/pdf/quick/qquickpdfsearchmodel.cpp	2021-06-18 16:26:16.768890737 +0100
@@ -39,7 +39,7 @@
 
 QT_BEGIN_NAMESPACE
 
-Q_LOGGING_CATEGORY(qLcS, "qt.pdf.search")
+Q_LOGGING_CATEGORY(qLcSearch, "qt.pdf.search")
 
 /*!
     \qmltype PdfSearchModel
@@ -282,7 +282,7 @@
             currentResult = 0;
         }
     }
-    qCDebug(qLcS) << "currentResult was" << m_currentResult
+    qCDebug(qLcSearch) << "currentResult was" << m_currentResult
                   << "requested" << currentResultWas << "on page" << currentPageWas
                   << "->" << currentResult << "on page" << m_currentPage;
 
diff -Naur a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
--- a/src/webengine/api/qquickwebengineview.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/webengine/api/qquickwebengineview.cpp	2021-06-18 16:35:08.956251116 +0100
@@ -496,11 +496,9 @@
 Q_STATIC_ASSERT(static_cast<int>(WebEngineError::CertificateErrorDomain) == static_cast<int>(QQuickWebEngineView::CertificateErrorDomain));
 Q_STATIC_ASSERT(static_cast<int>(WebEngineError::DnsErrorDomain) == static_cast<int>(QQuickWebEngineView::DnsErrorDomain));
 
-void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode,
-                                              const QString &errorDescription, bool triggersErrorPage)
+void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription)
 {
     Q_Q(QQuickWebEngineView);
-    Q_UNUSED(triggersErrorPage);
 
     if (isErrorPage) {
 #if QT_CONFIG(webengine_testsupport)
diff -Naur a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
--- a/src/webengine/api/qquickwebengineview_p_p.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/webengine/api/qquickwebengineview_p_p.h	2021-06-18 16:35:08.956251116 +0100
@@ -116,8 +116,7 @@
     void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) override;
     void loadCommitted() override;
     void loadVisuallyCommitted() override;
-    void loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode,
-                      const QString &errorDescription, bool triggersErrorPage) override;
+    void loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription) override;
     void focusContainer() override;
     void unhandledKeyEvent(QKeyEvent *event) override;
     QSharedPointer<QtWebEngineCore::WebContentsAdapter>
diff -Naur a/src/webengine/api/qtwebengineglobal.cpp b/src/webengine/api/qtwebengineglobal.cpp
--- a/src/webengine/api/qtwebengineglobal.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/webengine/api/qtwebengineglobal.cpp	2021-06-18 16:26:16.768890737 +0100
@@ -72,8 +72,7 @@
 */
 void initialize()
 {
-     QCoreApplication *app = QCoreApplication::instance();
-     if (app) {
+     if (!QCoreApplication::startingUp()) {
         qWarning("QtWebEngine::initialize() called with QCoreApplication object already created and should be call before. "\
                  "This is depreciated and may fail in the future.");
         QtWebEngineCore::initialize();
diff -Naur a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
--- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc	2021-04-01 15:33:27.000000000 +0100
+++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc	2021-06-18 16:26:16.768890737 +0100
@@ -65,7 +65,7 @@
         \li \l Python 2.7.5 or later. Python 3 is not supported.
         \li Bison, Flex
         \li GPerf
-        \li Node.js for a full featured Dev Tools.
+        \li Node.js version 8 or later (version 12 or later is recommended)
     \endlist
 
     \section2 Windows
@@ -73,7 +73,7 @@
     On Windows, the following additional tools are required:
 
     \list
-        \li Visual Studio 2017 version 15.8 or later
+        \li Visual Studio 2017 version 15.8 or later, or clang-cl version 8 or later
         \li Active Template Library (ATL), usually included in the Visual Studio
             installation
         \li Windows 10 SDK version 10.0.19041 or later
diff -Naur a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
--- a/src/webenginewidgets/api/qwebenginepage.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/src/webenginewidgets/api/qwebenginepage.cpp	2021-06-18 16:35:08.956251116 +0100
@@ -282,28 +282,20 @@
     QTimer::singleShot(0, q, &QWebEnginePage::loadStarted);
 }
 
-void QWebEnginePagePrivate::loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode,
-                                         const QString &errorDescription, bool triggersErrorPage)
+void QWebEnginePagePrivate::loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription)
 {
     Q_Q(QWebEnginePage);
     Q_UNUSED(url);
     Q_UNUSED(errorCode);
     Q_UNUSED(errorDescription);
 
-    if (isErrorPage) {
-        QTimer::singleShot(0, q, [q](){
-            emit q->loadFinished(false);
-        });
+    if (isErrorPage)
         return;
-    }
 
     isLoading = false;
-    Q_ASSERT((success && !triggersErrorPage) || !success);
-    if (!triggersErrorPage) {
-        QTimer::singleShot(0, q, [q, success](){
-            emit q->loadFinished(success);
-        });
-    }
+    QTimer::singleShot(0, q, [q, success](){
+        emit q->loadFinished(success);
+    });
 }
 
 void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool success)
@@ -2526,6 +2518,10 @@
     during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
     value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
 
+    \note This function rasterizes the result when rendering onto \a printer. Please consider raising
+    the default resolution of \a printer to at least 300 DPI or using printToPdf() to produce
+    PDF file output more effectively.
+
     \since 5.8
 */
 void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback)
diff -Naur a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
--- a/src/webenginewidgets/api/qwebenginepage_p.h	2021-04-01 15:33:27.000000000 +0100
+++ b/src/webenginewidgets/api/qwebenginepage_p.h	2021-06-18 16:35:08.956251116 +0100
@@ -107,8 +107,7 @@
     void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) override;
     void loadCommitted() override { }
     void loadVisuallyCommitted() override { }
-    void loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode,
-                      const QString &errorDescription, bool triggersErrorPage) override;
+    void loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription) override;
     void focusContainer() override;
     void unhandledKeyEvent(QKeyEvent *event) override;
     QSharedPointer<QtWebEngineCore::WebContentsAdapter>
diff -Naur a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc	2021-04-01 15:33:27.000000000 +0100
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc	2021-06-18 16:32:34.683447342 +0100
@@ -381,6 +381,12 @@
     used as part of the user interface, and not to display external data, for example, when
     displaying a list of results.
 
+    \note This function is not called for fragment navigation on the same page. Such navigation,
+    for example, happens by clicking a link to a '#fragment' within the page. It does not trigger
+    a load to a different document, even though it changes page's url and adds history entry.
+    It only serves as a shortcut to scroll within the page. Hence, no delegation of this navigation
+    type is expected to happen.
+
     \note The loading process is started and the loadStarted() signal is emitted
     \e before the request is accepted or rejected. Therefore, a loadFinished()
     signal that returns \c false is to be expected even after delegating the
diff -Naur a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp
--- a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp	2021-06-18 16:26:16.769892470 +0100
@@ -249,22 +249,27 @@
     QWebEngineCookieStore *client = m_profile->cookieStore();
 
     QAtomicInt accessTested = 0;
-    client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &) { ++accessTested; return true; });
+    QList<QPair<QUrl, QUrl>> resourceFirstParty;
+    client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &request) {
+        resourceFirstParty.append(qMakePair(request.origin, request.firstPartyUrl));
+        ++accessTested;
+        return true;
+    });
 
     HttpServer httpServer;
-
-    if (!httpServer.start())
-        QSKIP("Failed to start http server");
+    httpServer.setHostDomain(QString("sub.test.localhost"));
+    QVERIFY(httpServer.start());
 
     QByteArray cookieRequestHeader;
     connect(&httpServer, &HttpServer::newRequest, [&cookieRequestHeader](HttpReqRep *rr) {
-        if (rr->requestPath().size() <= 1) {
+        if (rr->requestMethod() == "GET" && rr->requestPath() == "/test.html") {
             cookieRequestHeader = rr->requestHeader(QByteArrayLiteral("Cookie"));
             if (cookieRequestHeader.isEmpty())
                 rr->setResponseHeader(QByteArrayLiteral("Set-Cookie"), QByteArrayLiteral("Test=test"));
+            rr->setResponseBody("<head><link rel='icon' type='image/png' href='resources/Fav.png'/>"
+                                "<title>Page with a favicon and an icon</title></head>"
+                                "<body><img src='resources/Img.ico'></body>");
             rr->sendResponse();
-        } else {
-            rr->sendResponse(404);
         }
     });
 
@@ -273,12 +278,13 @@
     QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
     QSignalSpy serverSpy(&httpServer, SIGNAL(newRequest(HttpReqRep *)));
 
-    page.load(httpServer.url());
+    QUrl firstPartyUrl = httpServer.url("/test.html");
+    page.load(firstPartyUrl);
 
     QTRY_COMPARE_WITH_TIMEOUT(loadSpy.count(), 1, 30000);
     QVERIFY(loadSpy.takeFirst().takeFirst().toBool());
     QTRY_COMPARE(cookieAddedSpy.count(), 1);
-    QTRY_COMPARE(accessTested.loadAcquire(), 3);
+    QTRY_COMPARE(accessTested.loadAcquire(), 4);
     QVERIFY(cookieRequestHeader.isEmpty());
 
     page.triggerAction(QWebEnginePage::Reload);
@@ -286,12 +292,16 @@
     QVERIFY(loadSpy.takeFirst().takeFirst().toBool());
     QVERIFY(!cookieRequestHeader.isEmpty());
     QTRY_COMPARE(cookieAddedSpy.count(), 1);
-    QTRY_COMPARE(accessTested.loadAcquire(), 5);
+    QTRY_COMPARE(accessTested.loadAcquire(), 7);
 
     client->deleteAllCookies();
     QTRY_COMPARE(cookieRemovedSpy.count(), 1);
 
-    client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &) { ++accessTested; return false; });
+    client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &request) {
+        resourceFirstParty.append(qMakePair(request.origin, request.firstPartyUrl));
+        ++accessTested;
+        return false;
+    });
     page.triggerAction(QWebEnginePage::ReloadAndBypassCache);
     QTRY_COMPARE(loadSpy.count(), 1);
     QVERIFY(loadSpy.takeFirst().takeFirst().toBool());
@@ -299,8 +309,7 @@
     // Test cookies are NOT added:
     QTest::qWait(100);
     QCOMPARE(cookieAddedSpy.count(), 1);
-    QTRY_COMPARE(accessTested.loadAcquire(), 8);
-
+    QTRY_COMPARE(accessTested.loadAcquire(), 11);
     page.triggerAction(QWebEnginePage::Reload);
     QTRY_COMPARE(loadSpy.count(), 1);
     QVERIFY(loadSpy.takeFirst().takeFirst().toBool());
@@ -308,8 +317,13 @@
     QCOMPARE(cookieAddedSpy.count(), 1);
 
     // Wait for last GET /favicon.ico
-    QTRY_COMPARE(serverSpy.count(), 8);
+    QTRY_COMPARE(serverSpy.count(), 12);
     (void) httpServer.stop();
+
+    QCOMPARE(resourceFirstParty.size(), accessTested.loadAcquire());
+    for (auto &&p : qAsConst(resourceFirstParty))
+        QVERIFY2(p.second == firstPartyUrl,
+                 qPrintable(QString("Resource [%1] has wrong firstPartyUrl: %2").arg(p.first.toString(), p.second.toString())));
 }
 
 void tst_QWebEngineCookieStore::html5featureFilter()
diff -Naur a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp	2021-06-18 16:26:16.770894202 +0100
@@ -796,7 +796,7 @@
     QTRY_COMPARE(page->messages.count(), 1);
     QCOMPARE(page->levels.at(0), QWebEnginePage::InfoMessageLevel);
 
-    QUrl firstPartyUrl = QUrl(server.url().toString(QUrl::RemovePort));
+    QUrl firstPartyUrl = QUrl(server.url().toString() + "sw.js");
     QList<RequestInfo> infos;
     // Service Worker
     QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker));
diff -Naur a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST
--- a/tests/auto/quick/qmltests/BLACKLIST	1970-01-01 01:00:00.000000000 +0100
+++ b/tests/auto/quick/qmltests/BLACKLIST	2021-06-18 16:26:16.770894202 +0100
@@ -0,0 +1,2 @@
+[NewViewRequest::test_loadNewViewRequest]
+macos
diff -Naur a/tests/auto/quick/qmltests/data/test4.html b/tests/auto/quick/qmltests/data/test4.html
--- a/tests/auto/quick/qmltests/data/test4.html	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/test4.html	2021-06-18 16:35:08.956251116 +0100
@@ -24,6 +24,7 @@
             }
         </script>
         <div id="content">
+            <p><a id='anchor' href='#anchor'>anchor</a>
             <p>bla00
             <p>bla01
             <p>bla02
diff -Naur a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
--- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml	2021-06-18 16:40:17.561963374 +0100
@@ -104,7 +104,6 @@
     }
 
     TestResult { id: testResult }
-    TestCase { id: testCase }
 
     onLoadingChanged: {
         loadStatus = loadRequest.status
diff -Naur a/tests/auto/quick/qmltests/data/tst_action.qml b/tests/auto/quick/qmltests/data/tst_action.qml
--- a/tests/auto/quick/qmltests/data/tst_action.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_action.qml	2021-06-18 16:40:17.561963374 +0100
@@ -41,7 +41,7 @@
     }
 
     TestCase {
-        id: actionTests
+        id: testCase
         name: "WebEngineAction"
         when: windowShown
 
@@ -116,8 +116,8 @@
             var stopAction = webEngineView.action(WebEngineView.Stop);
             verify(stopAction);
 
-            var triggerSpy = createTemporaryObject(signalSpy, actionTests, {target: selectAction, signalName: "triggered"});
-            var stopTriggerSpy = createTemporaryObject(signalSpy, actionTests, {target: stopAction, signalName: "triggered"});
+            var triggerSpy = createTemporaryObject(signalSpy, testCase, {target: selectAction, signalName: "triggered"});
+            var stopTriggerSpy = createTemporaryObject(signalSpy, testCase, {target: stopAction, signalName: "triggered"});
 
             verify(selectAction.enabled);
             selectAction.trigger();
@@ -148,7 +148,7 @@
             compare(enabledSpy.count, 0);
             selectAllAction.trigger();
             compare(triggerSpy.count, 0);
-            compare(getTextSelection(), "");
+            compare(webEngineView.getTextSelection(), "");
 
             // Focus content by focusing window from JavaScript. Edit actions should be enabled and functional.
             webView.runJavaScript("window.focus();");
@@ -157,6 +157,7 @@
             selectAllAction.trigger();
             compare(triggerSpy.count, 1);
             tryVerify(function() { return webView.getTextSelection() === "foo bar" });
+            webView.destroy();
         }
 
         function test_editActionsWithInitialFocus() {
@@ -180,6 +181,7 @@
             selectAllAction.trigger();
             compare(triggerSpy.count, 1);
             tryVerify(function() { return webView.getTextSelection() === "foo bar" });
+            webView.destroy();
         }
     }
 }
diff -Naur a/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml
--- a/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml	2021-06-18 16:40:17.561963374 +0100
@@ -55,6 +55,7 @@
         }
 
         TestCase {
+            id: testCase
             name: "ActiveFocusOnPress"
             when:windowShown
 
diff -Naur a/tests/auto/quick/qmltests/data/tst_audioMuted.qml b/tests/auto/quick/qmltests/data/tst_audioMuted.qml
--- a/tests/auto/quick/qmltests/data/tst_audioMuted.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_audioMuted.qml	2021-06-18 16:40:17.561963374 +0100
@@ -42,7 +42,7 @@
     }
 
     TestCase {
-        id: test
+        id: testCase
         name: "WebEngineViewAudioMuted"
 
         function test_audioMuted() {
diff -Naur a/tests/auto/quick/qmltests/data/tst_contextMenu.qml b/tests/auto/quick/qmltests/data/tst_contextMenu.qml
--- a/tests/auto/quick/qmltests/data/tst_contextMenu.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_contextMenu.qml	2021-06-18 16:40:17.562965106 +0100
@@ -65,12 +65,12 @@
     }
 
     function destroyContextMenu() {
-        contextMenuTest.keyPress(Qt.Key_Escape);
+        testCase.keyPress(Qt.Key_Escape);
         return getContextMenus().length == 0;
     }
 
     TestCase {
-        id: contextMenuTest
+        id: testCase
         name: "WebEngineViewContextMenu"
         when: windowShown
 
diff -Naur a/tests/auto/quick/qmltests/data/tst_download.qml b/tests/auto/quick/qmltests/data/tst_download.qml
--- a/tests/auto/quick/qmltests/data/tst_download.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_download.qml	2021-06-18 16:36:01.778603726 +0100
@@ -80,11 +80,21 @@
     Connections {
         id: downloadItemConnections
         ignoreUnknownSignals: true
-        onStateChanged: downloadState.push(target.state)
-        onInterruptReasonChanged: downloadInterruptReason = target.interruptReason
-        onDownloadDirectoryChanged: downloadDirectoryChanged++
-        onDownloadFileNameChanged: downloadFileNameChanged++
-        onPathChanged: downloadPathChanged++
+        function onStateChanged() {
+            downloadState.push(target.state);
+        }
+        function onInterruptReasonChanged() {
+            downloadInterruptReason = target.interruptReason;
+        }
+        function onDownloadDirectoryChanged() {
+            downloadDirectoryChanged++;
+        }
+        function onDownloadFileNameChanged() {
+            downloadFileNameChanged++;
+        }
+        function onPathChanged() {
+            downloadPathChanged++;
+        }
     }
 
     WebEngineProfile {
diff -Naur a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml
--- a/tests/auto/quick/qmltests/data/tst_findText.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_findText.qml	2021-06-18 16:40:17.562965106 +0100
@@ -56,7 +56,7 @@
         // If this starts to fail then either clear was not called before findText
         // or unexpected callback was triggered from some search.
         // On c++ side callback id can be checked to verify
-        testcase.verify(!findCallbackCalled(), 'Unexpected callback call or uncleared state before findText call!')
+        testCase.verify(!findCallbackCalled(), 'Unexpected callback call or uncleared state before findText call!')
 
         webEngineView.matchCount = matchCount
         findFailed = matchCount == 0
@@ -64,7 +64,7 @@
 
 
     TestCase {
-        id: testcase
+        id: testCase
         name: "WebViewFindText"
 
         function getBodyInnerHTML() {
diff -Naur a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml
--- a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml	2021-06-18 16:40:17.562965106 +0100
@@ -65,6 +65,7 @@
     }
 
     TestCase {
+        id: testCase
         name: "WebEngineViewFocusOnNavigation"
         when: windowShown
 
diff -Naur a/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml
--- a/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml	2021-06-18 16:40:17.562965106 +0100
@@ -36,6 +36,7 @@
     height: 480
 
     TestCase {
+        id: testCase
         name: "WebEngineViewKeyboardEvents"
         when: windowShown
 
diff -Naur a/tests/auto/quick/qmltests/data/tst_loadHtml.qml b/tests/auto/quick/qmltests/data/tst_loadHtml.qml
--- a/tests/auto/quick/qmltests/data/tst_loadHtml.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_loadHtml.qml	2021-06-18 16:40:17.562965106 +0100
@@ -42,6 +42,7 @@
     }
 
     TestCase {
+        id: testCase
         name: "WebEngineViewLoadHtml"
         when: windowShown
 
diff -Naur a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
--- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml	2021-06-18 16:40:17.562965106 +0100
@@ -52,6 +52,7 @@
     }
 
     TestCase {
+        id: testCase
         name: "WebEngineViewLoadUrl"
         when: windowShown
 
@@ -298,20 +299,19 @@
             compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus);
             compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus);
 
-            // In-page navigation.
-            webEngineView.url = Qt.resolvedUrl("test4.html#content");
-            // In-page navigation doesn't trigger load succeeded, wait for load progress instead.
-            tryCompare(loadRequestArray, "length", 3);
-            tryCompare(webEngineView, "loadProgress", 100);
-            compare(loadRequestArray[2].status, WebEngineView.LoadStartedStatus);
+            // In-page navigation shouldn't trigger load
+            let anchorUrl = Qt.resolvedUrl("test4.html#anchor");
+            let c = webEngineView.getElementCenter('anchor')
+            mouseClick(webEngineView, c.x, c.y)
+            tryCompare(webEngineView, 'url', anchorUrl)
 
             // Load after in-page navigation.
             webEngineView.url = Qt.resolvedUrl("test4.html");
             verify(webEngineView.waitForLoadSucceeded());
             compare(webEngineView.loadProgress, 100);
-            compare(loadRequestArray.length, 5);
-            compare(loadRequestArray[3].status, WebEngineView.LoadStartedStatus);
-            compare(loadRequestArray[4].status, WebEngineView.LoadSucceededStatus);
+            compare(loadRequestArray.length, 4);
+            compare(loadRequestArray[2].status, WebEngineView.LoadStartedStatus);
+            compare(loadRequestArray[3].status, WebEngineView.LoadSucceededStatus);
 
             webEngineView.clear();
         }
diff -Naur a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml
--- a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml	2021-06-18 16:26:16.770894202 +0100
@@ -78,7 +78,7 @@
         name: "WebEngineViewNavigationHistory"
 
         function test_navigationHistory() {
-            compare(webEngineView.loadProgress, 0)
+            webEngineView.navigationHistory.clear()
 
             webEngineView.url = Qt.resolvedUrl("test1.html")
             verify(webEngineView.waitForLoadSucceeded())
@@ -159,7 +159,7 @@
         }
 
         function test_navigationButtons() {
-            compare(webEngineView.loadProgress, 0)
+            webEngineView.navigationHistory.clear()
 
             webEngineView.url = Qt.resolvedUrl("test1.html")
             verify(webEngineView.waitForLoadSucceeded())
diff -Naur a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
--- a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml	2021-06-18 16:40:17.562965106 +0100
@@ -79,6 +79,7 @@
     }
 
     TestCase {
+        id: testCase
         name: "WebEngineViewNavigationRequested"
         when: windowShown
 
diff -Naur a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml
--- a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml	2021-06-18 16:40:17.562965106 +0100
@@ -77,7 +77,7 @@
     }
 
     TestCase {
-        id: test
+        id: testCase
         name: "NewViewRequest"
         when: windowShown
 
@@ -158,7 +158,7 @@
                     "   <button id='popupButton' onclick='popup()'>Pop Up!</button>" +
                     "</body></html>");
                 verify(webEngineView.waitForLoadSucceeded());
-                verifyElementHasFocus("popupButton");
+                webEngineView.verifyElementHasFocus("popupButton");
                 keyPress(Qt.Key_Enter);
                 tryCompare(newViewRequestedSpy, "count", 1);
                 compare(newViewRequest.requestedUrl, url);
@@ -176,7 +176,7 @@
             compare(loadRequestArray.length, 0);
             webEngineView.url = Qt.resolvedUrl("test2.html");
             verify(webEngineView.waitForLoadSucceeded());
-            var center = getElementCenter("link");
+            var center = webEngineView.getElementCenter("link");
             mouseClick(webEngineView, center.x, center.y, Qt.LeftButton, Qt.ControlModifier);
             tryCompare(newViewRequestedSpy, "count", 1);
             compare(newViewRequest.requestedUrl, Qt.resolvedUrl("test1.html"));
diff -Naur a/tests/auto/quick/qmltests/data/tst_settings.qml b/tests/auto/quick/qmltests/data/tst_settings.qml
--- a/tests/auto/quick/qmltests/data/tst_settings.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_settings.qml	2021-06-18 16:40:17.562965106 +0100
@@ -36,6 +36,7 @@
     height: 300
 
     TestCase {
+        id: testCase
         name: "WebEngineViewSettings"
 
         function test_javascriptEnabled() {
@@ -75,7 +76,7 @@
         }
 
         function test_settingsAffectCurrentViewOnly()  {
-            var webEngineView2 = Qt.createQmlObject('TestWebEngineView {width: 400; height: 300;}', webEngineView);
+            var webEngineView2 = Qt.createQmlObject('TestWebEngineView {width: 400; height: 300;}', testCase);
 
             webEngineView.settings.javascriptEnabled = true;
             webEngineView2.settings.javascriptEnabled = true;
diff -Naur a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml
--- a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml	2021-06-18 16:40:17.562965106 +0100
@@ -46,6 +46,7 @@
         focus: true
     }
     TestCase {
+        id: testCase
         name: "WebEngineViewUnhandledKeyEventPropagation"
 
         when: false
diff -Naur a/tests/auto/quick/qmltests2/data/tst_faviconDownload.qml b/tests/auto/quick/qmltests2/data/tst_faviconDownload.qml
--- a/tests/auto/quick/qmltests2/data/tst_faviconDownload.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests2/data/tst_faviconDownload.qml	2021-06-18 16:40:17.562965106 +0100
@@ -47,7 +47,7 @@
     }
 
     TestCase {
-        id: test
+        id: testCase
         name: "WebEngineFaviconDownload"
 
         function init() {
diff -Naur a/tests/auto/quick/qmltests2/data/tst_favicon.qml b/tests/auto/quick/qmltests2/data/tst_favicon.qml
--- a/tests/auto/quick/qmltests2/data/tst_favicon.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests2/data/tst_favicon.qml	2021-06-18 16:40:17.562965106 +0100
@@ -59,16 +59,16 @@
     function getFaviconPixel(faviconImage) {
         var grabImage = Qt.createQmlObject("
                 import QtQuick 2.5\n
-                Image { }", test)
+                Image { }", testCase)
         var faviconCanvas = Qt.createQmlObject("
                 import QtQuick 2.5\n
-                Canvas { }", test)
+                Canvas { }", testCase)
 
-        test.tryVerify(function() { return faviconImage.status == Image.Ready });
+        testCase.tryVerify(function() { return faviconImage.status == Image.Ready });
         faviconImage.grabToImage(function(result) {
                 grabImage.source = result.url
             });
-        test.tryVerify(function() { return grabImage.status == Image.Ready });
+        testCase.tryVerify(function() { return grabImage.status == Image.Ready });
 
         faviconCanvas.width = faviconImage.width;
         faviconCanvas.height = faviconImage.height;
@@ -97,7 +97,7 @@
     }
 
     TestCase {
-        id: test
+        id: testCase
         name: "WebEngineFavicon"
         when: windowShown
 
@@ -315,7 +315,7 @@
         function test_faviconProvider(row) {
             var faviconImage = Qt.createQmlObject("
                     import QtQuick 2.5\n
-                    Image { sourceSize: Qt.size(width, height) }", test)
+                    Image { sourceSize: Qt.size(width, height) }", testCase)
 
             compare(iconChangedSpy.count, 0)
 
@@ -338,7 +338,7 @@
         function test_dynamicFavicon() {
             var faviconImage = Qt.createQmlObject("
                     import QtQuick 2.5\n
-                    Image { width: 16; height: 16; sourceSize: Qt.size(width, height); }", test)
+                    Image { width: 16; height: 16; sourceSize: Qt.size(width, height); }", testCase)
             faviconImage.source = Qt.binding(function() { return webEngineView.icon; });
 
             var colors = [
diff -Naur a/tests/auto/quick/qmltests2/data/tst_filePicker.qml b/tests/auto/quick/qmltests2/data/tst_filePicker.qml
--- a/tests/auto/quick/qmltests2/data/tst_filePicker.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests2/data/tst_filePicker.qml	2021-06-18 16:44:28.945708182 +0100
@@ -58,6 +58,7 @@
     onTitleChanged: { titleChanges.push(webEngineView.title) }
 
     TestCase {
+        id: testCase
         name: "WebEngineViewSingleFileUpload"
         when: windowShown
 
@@ -156,6 +157,16 @@
             webEngineView.url = Qt.resolvedUrl("directoryupload.html")
             verify(webEngineView.waitForLoadSucceeded())
 
+            webEngineView.runJavaScript(
+                "let relativePathCount = 0;" +
+                "document.getElementById('upfile').addEventListener('change', function(event) {" +
+                "   let files = event.target.files;" +
+                "   for (let i = 0; i < files.length; i++) {" +
+                "      if (files[i].webkitRelativePath != '')" +
+                "         relativePathCount++;" +
+                "   }" +
+                "}, false);")
+
             FilePickerParams.selectFiles = true
             FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("../data"))
 
@@ -163,6 +174,11 @@
             tryCompare(FilePickerParams, "filePickerOpened", true)
             // Check that the title is a file list (eg. "test1.html,test2.html")
             tryVerify(function() { return webEngineView.title.match("^([^,]+,)+[^,]+$"); })
+
+            var relativePathCount = 0;
+            runJavaScript("relativePathCount", function(result) { relativePathCount = result; });
+            // The number of files in data directory may vary
+            tryVerify(function() { return relativePathCount > 0; });
         }
 
         function test_reject() {
@@ -226,15 +242,15 @@
                    { tag: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", input: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", expected: "test.txt"},
                    { tag: "file://applib/products/a-b/abc_1/t.est/test.txt", input: "file://applib/products/a-b/abc_1/t.est/test.txt", expected: "test.txt"},
                    { tag: "file:\\\\applib\\products\\a-b\\abc_1\\t:est\\test.txt", input: "file:\\\\applib\\products\\a-b\\abc_1\\t:est\\test.txt", expected: "test.txt"},
-                   { tag: "file:C:/test.txt", input: "file:C:/test.txt", expected: "test.tx"},
-                   { tag: "file:/C:/test.txt", input: "file:/C:/test.txt", expected: "test.tx"},
+                   { tag: "file:C:/test.txt", input: "file:C:/test.txt", expected: "test.txt"},
+                   { tag: "file:/C:/test.txt", input: "file:/C:/test.txt", expected: "test.txt"},
                    { tag: "file://C:/test.txt", input: "file://C:/test.txt", expected: "Failed to Upload"},
                    { tag: "file:///C:test.txt", input: "file:///C:test.txt", expected: "Failed to Upload"},
                    { tag: "file:///C:/test.txt", input: "file:///C:/test.txt", expected: "test.txt"},
                    { tag: "file:///C:\\test.txt", input: "file:///C:\\test.txt", expected: "test.txt"},
                    { tag: "file:\\//C:/test.txt", input: "file:\\//C:/test.txt", expected: "test.txt"},
                    { tag: "file:\\\\/C:\\test.txt", input: "file:\\\\/C:\\test.txt", expected: "test.txt"},
-                   { tag: "\\\\?\\C:/test.txt", input: "\\\\?\\C:/test.txt", expected: "test.tx"},
+                   { tag: "\\\\?\\C:/test.txt", input: "\\\\?\\C:/test.txt", expected: "test.txt"},
             ];
         }
 
diff -Naur a/tests/auto/quick/qmltests2/data/tst_inputMethod.qml b/tests/auto/quick/qmltests2/data/tst_inputMethod.qml
--- a/tests/auto/quick/qmltests2/data/tst_inputMethod.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests2/data/tst_inputMethod.qml	2021-06-18 16:40:17.562965106 +0100
@@ -40,6 +40,7 @@
     testSupport: WebEngineTestSupport { }
 
     TestCase {
+        id: testCase
         name: "WebEngineViewInputMethod"
         when: windowShown
 
diff -Naur a/tests/auto/quick/qmltests2/data/tst_loadFail.qml b/tests/auto/quick/qmltests2/data/tst_loadFail.qml
--- a/tests/auto/quick/qmltests2/data/tst_loadFail.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests2/data/tst_loadFail.qml	2021-06-18 16:35:08.956251116 +0100
@@ -119,21 +119,22 @@
             verify(!loadRequest.isErrorPage)
 
             // Loading of the unavailableUrl must fail
-            loadRequest = loadRequestArray[1]
+            loadRequest = loadRequestArray[3]
             compare(loadRequest.status, WebEngineView.LoadFailedStatus)
             compare(loadRequest.errorDomain, WebEngineView.InternalErrorDomain)
             compare(loadRequest.url, unavailableUrl)
             verify(!loadRequest.isErrorPage)
 
+            // error page load is done inside main load through test support
             // Start to load error page
-            loadRequest = loadRequestArray[2]
+            loadRequest = loadRequestArray[1]
             compare(loadRequest.status, WebEngineView.LoadStartedStatus)
             compare(loadRequest.errorDomain, WebEngineView.NoErrorDomain)
             compare(loadRequest.url, "chrome-error://chromewebdata/")
             verify(loadRequest.isErrorPage)
 
             // Loading of the error page must be successful
-            loadRequest = loadRequestArray[3]
+            loadRequest = loadRequestArray[2]
             compare(loadRequest.status, WebEngineView.LoadSucceededStatus)
             compare(loadRequest.errorDomain, WebEngineView.NoErrorDomain)
             compare(loadRequest.url, "chrome-error://chromewebdata/")
diff -Naur a/tests/auto/quick/qmltests2/data/tst_mouseClick.qml b/tests/auto/quick/qmltests2/data/tst_mouseClick.qml
--- a/tests/auto/quick/qmltests2/data/tst_mouseClick.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests2/data/tst_mouseClick.qml	2021-06-18 16:40:17.562965106 +0100
@@ -65,6 +65,7 @@
 
 
     TestCase {
+        id: testCase
         name: "WebEngineViewMouseClick"
         when: windowShown
 
diff -Naur a/tests/auto/quick/qmltests2/data/tst_viewSoure.qml b/tests/auto/quick/qmltests2/data/tst_viewSoure.qml
--- a/tests/auto/quick/qmltests2/data/tst_viewSoure.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests2/data/tst_viewSoure.qml	2021-06-18 16:40:17.562965106 +0100
@@ -44,6 +44,7 @@
         errorPage.onLoadingChanged: {
             loadRequestArray.push({
                "status": loadRequest.status,
+               "url": loadRequest.url
             })
         }
     }
@@ -51,6 +52,7 @@
     onLoadingChanged: {
         loadRequestArray.push({
             "status": loadRequest.status,
+            "url": loadRequest.url
         });
     }
 
@@ -76,7 +78,7 @@
     }
 
     TestCase {
-        id: test
+        id: testCase
         name: "WebEngineViewSource"
 
         function init() {
@@ -109,14 +111,16 @@
             WebEngine.settings.errorPageEnabled = true
             webEngineView.url = row.userInputUrl;
 
+
             if (row.loadSucceed) {
-                tryVerify(function() { return loadRequestArray.length >= 2 });
+                tryVerify(function() { return loadRequestArray.length == 2 });
                 compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus);
             } else {
-                tryVerify(function() { return loadRequestArray.length >= 2 });
-                compare(loadRequestArray[1].status, WebEngineView.LoadFailedStatus);
-                tryVerify(function() { return loadRequestArray.length == 4 });
-                compare(loadRequestArray[3].status, WebEngineView.LoadSucceededStatus);
+                tryVerify(function() { return loadRequestArray.length == 4 }, 90000);
+                // error page load is done inside main load through test support
+                compare(loadRequestArray[2].status, WebEngineView.LoadSucceededStatus);
+                compare(loadRequestArray[2].url, "chrome-error://chromewebdata/")
+                compare(loadRequestArray[3].status, WebEngineView.LoadFailedStatus);
             }
             tryVerify(function() { return titleChangedSpy.count == 1; });
 
diff -Naur a/tests/auto/quick/qmltests_ssl/BLACKLIST b/tests/auto/quick/qmltests_ssl/BLACKLIST
--- a/tests/auto/quick/qmltests_ssl/BLACKLIST	1970-01-01 01:00:00.000000000 +0100
+++ b/tests/auto/quick/qmltests_ssl/BLACKLIST	2021-06-18 16:39:44.985624846 +0100
@@ -0,0 +1,2 @@
+[CertificateError::test_error]
+macos
diff -Naur a/tests/auto/quick/qmltests_ssl/data/tst_certificateError.qml b/tests/auto/quick/qmltests_ssl/data/tst_certificateError.qml
--- a/tests/auto/quick/qmltests_ssl/data/tst_certificateError.qml	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qmltests_ssl/data/tst_certificateError.qml	2021-06-18 16:40:17.562965106 +0100
@@ -45,6 +45,7 @@
     }
 
     TestCase {
+        id: testCase
         name: 'CertificateError'
         when: windowShown
 
@@ -55,6 +56,7 @@
                 request.sendResponse()
             })
             view.settings.errorPageEnabled = false
+            view.profile.useForGlobalCertificateVerification = true
         }
 
         function init() {
diff -Naur a/tests/auto/quick/qquickwebengineprofile/qquickwebengineprofile.pro b/tests/auto/quick/qquickwebengineprofile/qquickwebengineprofile.pro
--- a/tests/auto/quick/qquickwebengineprofile/qquickwebengineprofile.pro	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qquickwebengineprofile/qquickwebengineprofile.pro	1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-include(../tests.pri)
diff -Naur a/tests/auto/quick/qquickwebengineprofile/tst_qquickwebengineprofile.cpp b/tests/auto/quick/qquickwebengineprofile/tst_qquickwebengineprofile.cpp
--- a/tests/auto/quick/qquickwebengineprofile/tst_qquickwebengineprofile.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/quick/qquickwebengineprofile/tst_qquickwebengineprofile.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtQml/QQmlEngine>
-#include <QtTest/QtTest>
-#include <QtWebEngine/QQuickWebEngineProfile>
-
-class tst_QQuickWebEngineProfile : public QObject {
-    Q_OBJECT
-public:
-    tst_QQuickWebEngineProfile();
-
-    // TODO: Many tests missings
-    void usedForGlobalCertificateVerification();
-
-private Q_SLOTS:
-    void init();
-    void cleanup();
-};
-
-tst_QQuickWebEngineProfile::tst_QQuickWebEngineProfile()
-{
-    QtWebEngine::initialize();
-    QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true);
-}
-
-
-void tst_QQuickWebEngineProfile::init()
-{
-}
-
-void tst_QQuickWebEngineProfile::cleanup()
-{
-}
-
-void tst_QQuickWebEngineProfile::usedForGlobalCertificateVerification()
-{
-    QQuickWebEngineProfile *profile1 = new QQuickWebEngineProfile();
-    QQuickWebEngineProfile *profile2 = new QQuickWebEngineProfile();
-    QVERIFY(!profile1->isUsedForGlobalVerification());
-    QVERIFY(!profile2->isUsedForGlobalVerification());
-
-
-}
-
-
-QTEST_MAIN(tst_QQuickWebEngineProfile)
-#include "tst_qquickwebengineprofile.moc"
diff -Naur a/tests/auto/shared/data/loadprogress/page1.html b/tests/auto/shared/data/loadprogress/page1.html
--- a/tests/auto/shared/data/loadprogress/page1.html	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/shared/data/loadprogress/page1.html	2021-06-18 16:31:43.874578798 +0100
@@ -3,6 +3,6 @@
     <title>page1</title>
   </head>
   <body>
-    <h1>page1</h1>
+    <div><a href="page2.html#anchor">page2</a></div>
   </body>
 </html>
diff -Naur a/tests/auto/shared/data/loadprogress/page2.html b/tests/auto/shared/data/loadprogress/page2.html
--- a/tests/auto/shared/data/loadprogress/page2.html	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/shared/data/loadprogress/page2.html	2021-06-18 16:31:43.874578798 +0100
@@ -9,6 +9,7 @@
     }
   </style>
   <body>
+    <div><a href="#anchor">page2</a></div>
     <div class="fardown" id="anchor">page2 anchor</div>
   </body>
 </html>
diff -Naur a/tests/auto/shared/data/loadprogress/page5.html b/tests/auto/shared/data/loadprogress/page5.html
--- a/tests/auto/shared/data/loadprogress/page5.html	1970-01-01 01:00:00.000000000 +0100
+++ b/tests/auto/shared/data/loadprogress/page5.html	2021-06-18 16:31:43.874578798 +0100
@@ -0,0 +1,20 @@
+<html>
+  <head>
+    <title>page5</title>
+  </head>
+  <script>
+    addEventListener('DOMContentLoaded', (event) => {
+      document.getElementById('anchorLink').click();
+    });
+  </script>
+  <style>
+    .fardown {
+      position: absolute;
+      top: 2500px;
+    }
+  </style>
+  <body>
+    <div><a id="anchorLink" href="#anchor">go to the anchor</a></div>
+    <div class="fardown" id="anchor">here is the anchor</div>
+  </body>
+</html>
diff -Naur a/tests/auto/shared/data/loadprogress/page6.html b/tests/auto/shared/data/loadprogress/page6.html
--- a/tests/auto/shared/data/loadprogress/page6.html	1970-01-01 01:00:00.000000000 +0100
+++ b/tests/auto/shared/data/loadprogress/page6.html	2021-06-18 16:31:43.874578798 +0100
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title>page6</title>
+  </head>
+  <script>
+    addEventListener('DOMContentLoaded', (event) => {
+      document.getElementById('anchorLink').click();
+    });
+  </script>
+  <body>
+    <div><a id="anchorLink" href="page2.html#anchor">go to another page</a></div>
+  </body>
+</html>
diff -Naur a/tests/auto/shared/data/loadprogress/page7.html b/tests/auto/shared/data/loadprogress/page7.html
--- a/tests/auto/shared/data/loadprogress/page7.html	1970-01-01 01:00:00.000000000 +0100
+++ b/tests/auto/shared/data/loadprogress/page7.html	2021-06-18 16:31:43.874578798 +0100
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title>page6</title>
+  </head>
+  <script>
+    setTimeout(function(){
+      document.getElementById('anchorLink').click();
+    },500);
+  </script>
+  <body>
+    <div><a id="anchorLink" href="page2.html#anchor">go to another page</a></div>
+  </body>
+</html>
diff -Naur a/tests/auto/shared/data/loadprogress/page8.html b/tests/auto/shared/data/loadprogress/page8.html
--- a/tests/auto/shared/data/loadprogress/page8.html	1970-01-01 01:00:00.000000000 +0100
+++ b/tests/auto/shared/data/loadprogress/page8.html	2021-06-18 16:31:43.874578798 +0100
@@ -0,0 +1,20 @@
+<html>
+  <head>
+    <title>Page with js navigation in the end of document to anchor within the page</title>
+  </head>
+  <style>
+    .fardown {
+      position: absolute;
+      top: 2500px;
+    }
+  </style>
+  <body>
+    <div><a id="anchorLink" href="#anchor">go to the anchor</a></div>
+    <div class="fardown" id="anchor">here is the anchor</div>
+    <script>
+      addEventListener('load', (event) => {
+        window.location.replace(document.getElementById('anchorLink').href)
+      })
+    </script>
+  </body>
+</html>
diff -Naur a/tests/auto/shared/httpserver.h b/tests/auto/shared/httpserver.h
--- a/tests/auto/shared/httpserver.h	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/shared/httpserver.h	2021-06-18 16:26:16.770894202 +0100
@@ -78,6 +78,8 @@
 
     Q_INVOKABLE void setResourceDirs(const QStringList &dirs) { m_dirs = dirs; }
 
+    Q_INVOKABLE void setHostDomain(const QString &host) { m_url.setHost(host); }
+
 Q_SIGNALS:
     // Emitted after a HTTP request has been successfully parsed.
     void newRequest(HttpReqRep *reqRep);
diff -Naur a/tests/auto/shared/resources/cert.pem b/tests/auto/shared/resources/cert.pem
--- a/tests/auto/shared/resources/cert.pem	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/shared/resources/cert.pem	2021-06-18 16:46:56.650148026 +0100
@@ -1,64 +1,41 @@
 -----BEGIN CERTIFICATE-----
-MIIEpDCCAoygAwIBAgIUO90aty9AMjvBvzfUhr1WwdBrKkMwDQYJKoZIhvcNAQEL
-BQAwfzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
-DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDEyMDAGA1UEAwwpQmFkU1NM
-IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTkwODI2MTQ0
-NDIxWhcNMTkwODI3MTQ0NDIxWjBjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs
-aWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEPMA0GA1UECgwGQmFkU1NM
-MRYwFAYDVQQDDA0qLmJhZHNzbC50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEAkybT/L4zJCqefpd+eYT6aQ0PtobQfFgP+n+z5wWoUxIAJnjb5ZW4
-7IJxka/2/ggzJOfrUBur54LkTfFQ+yX85eKYCuH0GLz+Rve50LDn0ya6qSgmEhDG
-0bend2tMZY+Nl3B+5Ane1vua8hdJjv3ZO3e5UgpQwysL54eYyhEWWlbFWF11LhEd
-MYp953UGLqoV4Mlw+Li8TmFwdKQx6icgBTuloXLzk9aUU+b6NbXdadNXkmzg09IC
-sb8pnMXiF2P9Xm5rK0IoiRkSHxVnU12nQXh65Ns/2Dj5DcbHmVdvallfr4wnLeFP
-UotysZnvFmE7FLMSr/eQfkTG+Jlb7ZhoGwIDAQABozQwMjAJBgNVHRMEAjAAMCUG
-A1UdEQQeMByCDSouYmFkc3NsLnRlc3SCC2JhZHNzbC50ZXN0MA0GCSqGSIb3DQEB
-CwUAA4ICAQA7Yc+QQzqSK15ibmaYrkqq+cumggsWLCprW8jvzhpWBt9IjToP5nsy
-sKinYPoZR8jvZ1YVotcts7uQT7DkqeWkB+l+88c7gQdgujvBo6v9/g+jrXFKgsJD
-IBmkho8hpd63Slqv2Yp4bYT20O5EvR9CQvwSkwTs+ylBNEs1Q+AbekxmBjuYUxHn
-9xL4/GZ6ufoNv676iCoXo4mnDrCD8e8MRiZoU9Lq4G41HGiLWV0tM/M6BdVJYGzl
-FcBg0ZKnQT9OCWEPRe3zyRS6a+MivPAzxS8z/kYaRN+C7H68Mib3xPDsEETz1MnO
-uzGAPHAAgtYWYJi+CaaNWkgAv4n+UIQa0oyqPn4z5hLcsO+nMBws2Sg0mkQLilBX
-N1ciCdVMi7sHKuLa7GVksq/RQrXnZcQhoYQRrZAaAHKbxyo/M2pNqmDiFJppdH7a
-6Rj2vYf6ig/FXAzDGsDvf/tsGCxgJTFzGly+GsWVe40vyjfWHxWWDU/eGjfGO05k
-Xzjm+kYGJnH2hfiIlX1Jeu/jjIodiSy31F0hvuKlJu8PfaQ7oo5neRzwRO6Wq9rR
-7DMsQN6OtXGnnA+ogC0korA+aXev6wzbwYUhzMf1YTzEjrFNIXeIHsQSzq6lPcIE
-JOly5wjyO/eNF7mpHyDX8brY6Hn+bgyDeKAmsUvhOCEXgaPpKlP4gQ==
+MIIDezCCAmOgAwIBAgIUFZEIIzeR7lEA10rb14w7MfhP87MwDQYJKoZIhvcNAQEL
+BQAwWjELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwGQmVy
+bGluMRUwEwYDVQQKDAxUaGVRdENvbXBhbnkxEjAQBgNVBAsMCXdlYmVuZ2luZTAe
+Fw0yMTA1MTAyMTM1MTJaFw0yMjA1MTAyMTM1MTJaMGAxCzAJBgNVBAYTAkRFMQ8w
+DQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEVMBMGA1UECgwMVGhlUXRD
+b21wYW55MRgwFgYDVQQDDA93ZWJlbmdpbmUucXQuaW8wggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCoDKAU8bkgstvcbnUPQ4g3gqmbm3c6HWcHJOe+LWQz
+P6wIEF0JK6C3g2cqQHqSIa0wSysSbX/GDwGR9ul63e/f6MCJ1GmO8IhKrLdn0PVy
+AIUzjqGKhv8C8tmmohOICCxTh8nhq64gqEWmUgasgoy/aAryFqgEYGhFQPVEz6Kv
+CMSvpM1dNC3YCn467Gznc0s+EA6C6al/PNFHz9SZuF6f4bkyEf5dPPOt6IKXPZXo
+Dv148mPLW5Dw0nv19445YENGLNENbDGyc13bgaOSm9xpPBp+IrpV2p65v5dO2IHl
+E9qXaicKPRNANydppx5yX/OZRawgU2Q0lYNx3f+8R3I5AgMBAAGjMzAxMBoGA1Ud
+EQQTMBGCD3dlYmVuZ2luZS5xdC5pbzATBgNVHSUEDDAKBggrBgEFBQcDATANBgkq
+hkiG9w0BAQsFAAOCAQEAjThKpP0sBv1vEmaqBc1wTu//7RHmFcoStTt3scADzb2C
+9gjOVC4NzxBneLkv01444Z1p/Iiu/ZZ+VKu7aJElJgnBWEisYwJ09t3cdZRA0UY7
+XRvTVAqV0OlsB1Jn0afE+aTLGjWo+jSYzua0O+NK74e23p9jkdSmXxH9w0FB/oyM
+FGIOFnnfP0+QR4ZVvAGk2H60tBHQKmCM6b87TiD4GQIfOghCQWH+qJYSuyGu4hkE
+uis+n1KHHhed3GIJOHpm7gt1C9qtjcp1nOpv0ycQjfc9CGvr02BcQjhMeO65hX0A
+TvCgKN9/XMFv5jwwjjPCL12GBhwnN2k9hM/tEYpe2A==
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIGeTCCBGGgAwIBAgIUbVL7tFc7sgPIYnt+REVc0wiHdBcwDQYJKoZIhvcNAQEL
-BQAwdzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
-DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDEqMCgGA1UEAwwhQmFkU1NM
-IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE5MDgyNjE0NDQyMFoXDTI5
-MDgyMzE0NDQyMFowfzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx
-FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDEyMDAGA1UE
-AwwpQmFkU1NMIEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIi
-MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgoU4q43DJEUyoAOeK31uyEgLn
-s5CCd6XFmGp6wln0yupwmYRaDiCoSJ1qpmjYt+gIHpDAFS2ZzR4TbZORFirjY0cQ
-6+IWwpBEQR0hOluWN99CqjdCxfuZwiTvTV3FQv1IJZ13g23Uh2xRbnrzC2muDHzT
-4ZNM3aayvziMGY6n33aksEc6WMZb3p/Qn2OepeC7EzZiy4tXKPf9OaOPbae5aJWZ
-bOzzydFLkV4UqZb5FfySt8toIivPeIlRCiPodWLb2y5DYUXyWBk1dpbIcVa/LusV
-vsBELeJ+BFDRH1NHtwOrhOkZHKMr3SQ1YRlNDEeHUVmQkori397j9JjpPzScQJ6r
-d/W4mGyzgRmguIy9IpKMbxX5/1A6c6l5q0HqMgPv84GWxlhav4xwsOf90iT2vLPZ
-yllVCgCsCfvLEyVFhER18HAo8mTkQqKL7ZO96xXHgugA7dFN/C3BdC9kYP/GbAwd
-J0R6qKrfSiyyk1VbjWfFdFH/G/bT9H0nrjMj5tCT4q/zDCb5HkBp3BOoyUKb9yyt
-a1Cht/Iu3f1SlQzsrDBt9iMMCjXoNNAJcV7ZZ6HCxcWwfAwxgylQgq8UG60shxhn
-CBPhcA8JM+mk2nghTU2pxwY/KpAd0H4/a79b0DE97dCOnNHzyP3tqP8RenG549B0
-gsNO60aG01k6P9jFuQIDAQABo4H0MIHxMB0GA1UdDgQWBBQgvWmDuYqQ6xX7y8xc
-cgky1FO7jzCBtAYDVR0jBIGsMIGpgBTUGo+svIaoSMF/shILSbeiQ1zAQKF7pHkw
-dzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNh
-biBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDEqMCgGA1UEAwwhQmFkU1NMIFJv
-b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5ghR1qCPxzkfCSCwMFHm98245f0pk0zAM
-BgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAnGr6
-t1+KNGZV9hmAE3SyMzHRpgwtqIG4kl94A7Pz3CbA8+q7u7DW8l1GdaNx2J2wo+R5
-rJi02V5e7TNa7ZS5S9WGYHZ2y6QOjXuT28VMAPX+3HAgxk3RMxocpLpkPp8hhD/9
-S5KxA6AQDUN6av8E3xeuuWYWmTvAXNHK5ABXDFxxTp902ozNnZaSk2DxAUqcsOD4
-ago0IhRdkFGe1Q7F8gOxtlUL5owNL4uhRP8BbwOja2Gopn2+kA9CNqdwPI4Ipjlr
-yo61oCqzy3RAXOUct8WAvybacADmJODAxDq9O5fAZuYZScjjj1ASowmbyDH/Wb9z
-+WfiKKH4BfgOIukzK3I1M9wiSDefIodCFfEVXbdNudZj8f9Gw4RrZwkUuxDLeRWG
-ReDtzAWq7G0Diw3uX40S4jaj3MeS6oHp2Nrj/VyjSRiYTeN/pnA9N0M5VuCYYvXD
-f50rrigjQfOgb4TmnyJAjXWVkXW7Fa+ooLsbvlfr8wP8f31y1cgWPHTVIv6Kmug7
-Bg88k3x5gLTXmutDjseORonhGMRdAxHgJVf5aKfzdRpwXZTDZJXhsAz9OdlOhNZd
-UrYo680QugA0V3H5D8Egbr2AUUSMDkn133COjeOIDknFxX3qDqeTzqLZCAEBIoKn
-Adpix0jvG1Ys4Ayq6K2wQFdGFjtl6LsiGC7pWWU=
+MIIDOzCCAiMCFDwWg4NZxCplj3qyBxAUTi1wmj4jMA0GCSqGSIb3DQEBCwUAMFox
+CzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEV
+MBMGA1UECgwMVGhlUXRDb21wYW55MRIwEAYDVQQLDAl3ZWJlbmdpbmUwHhcNMjEw
+NTEwMjEzMTE4WhcNMjIwNTEwMjEzMTE4WjBaMQswCQYDVQQGEwJERTEPMA0GA1UE
+CAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xFTATBgNVBAoMDFRoZVF0Q29tcGFu
+eTESMBAGA1UECwwJd2ViZW5naW5lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAuc/8xVrfSzOsI6kYul+o1QIPBh1I86eQm1PhTBDMAAPHuzyPaEMgBkn2
+XAUmvkynGpNioaJDU2ndV2fBHvsoeQCdNNmjFTe1rKYjrN6U2X5KoYSzN93TOYzK
+aR38fEFx+w4qV76nnxSjYtGNe9z74GrfWFMdDQ0NJKzvaO4gaZ+OOg0OzWy4MJQ0
+aINo3UV55Y7Nt92AxFweiuHucKu+rjf3BX7n0Af/Tcs2c84f0R3HA7euReSibVvX
+f33eHLRKwu2bvDjXiUzOdkxBn9GTo6Q09LyY6wDG0ZdWnyCKj3NBQKBVrq+bs3Q0
+ATsWhj/PvYlZhhZh4EOlqYOhCpwv4wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCC
+pLSFGJcG0zhHW+2A6ogmpn2tA8gKUZx7f0J1nwgPEoAXQqWQv/299ZtmWfMKHUkk
+ygG4u80C87wWPH42XWXo/KDrP9iYzoqAvtqbRuPG9PAxefQ/JUSnuhikA51g9+Mu
+IDKKKSI+y/JW9u0Qo77fp/5n2DaFn5B+pBYvn/xLfaEa9bRdJMTEMsElGbPBzMZd
+I/7X6B78X6Ow5TuRKSeZA7E1AZ/+e5A4Hj65bLAugoSKz3zaS0dV26LwAo18c2zP
+TqtwHyIVj4QCoI6Z694q9KH4Pkml3fz8VSkk+MvZMWapvUhHu/DneTgqGbp9POYg
+nx6oWME6idhnvN6DljxB
 -----END CERTIFICATE-----
diff -Naur a/tests/auto/shared/resources/key.pem b/tests/auto/shared/resources/key.pem
--- a/tests/auto/shared/resources/key.pem	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/shared/resources/key.pem	2021-06-18 16:46:56.650148026 +0100
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAkybT/L4zJCqefpd+eYT6aQ0PtobQfFgP+n+z5wWoUxIAJnjb
-5ZW47IJxka/2/ggzJOfrUBur54LkTfFQ+yX85eKYCuH0GLz+Rve50LDn0ya6qSgm
-EhDG0bend2tMZY+Nl3B+5Ane1vua8hdJjv3ZO3e5UgpQwysL54eYyhEWWlbFWF11
-LhEdMYp953UGLqoV4Mlw+Li8TmFwdKQx6icgBTuloXLzk9aUU+b6NbXdadNXkmzg
-09ICsb8pnMXiF2P9Xm5rK0IoiRkSHxVnU12nQXh65Ns/2Dj5DcbHmVdvallfr4wn
-LeFPUotysZnvFmE7FLMSr/eQfkTG+Jlb7ZhoGwIDAQABAoIBADRXy3BL98UVo+tD
-2ClBtBFKJBy5N9ADQyvH4SZ8TLO/423L7+xqpaz7eYppHWKfaBHorTuBnFRtquhO
-vo+Xo63iPFMirMFf+NMlq2MgilYBoMQrE9+5N//BZECGWlaGCcekrH5RRIMUXLlg
-rzm98lfE7pbQNIo39bQV97NpAJqBWPuoIvCrbRCysGoA5j7ptZ/EhSlC00eA7ybD
-CeYHmh8NrsapKOTGb5u1v3paV8X/mH6vKmsVs7n6LC0opBxzM8eAHEAQ6h8rmz9H
-y99FWDYha3lOS4SLkTnuRnNHOMLJajPq3Isu+BgzLWuRGnKZ3rmuUFwPNkCZTvsV
-dTdBE4ECgYEAw6jBEil0e8Pc9sGqnz93e8qrYE9wSPso4q3BNJgTbN48kon6mqh7
-gQVgEP/75Th5YrJUrY9Pd/8H9uoMOxbDXgOXG/xNnhC0L+7aM8nhKlxCLndY1e56
-/YymYYH4+D9ZD2u526mK/nmCg2QGOkCVYYp7NXe/mA0g34drKjefmj8CgYEAwIhq
-rZhlfAvQThSOqQA9zA7NXPDh4KzIjr8htVu5YvVcv5W2uhsni9DXFaloPnhuLdJ7
-MnPF2WqzQ9YqFrGn/9/OTqeE23f60ed04qLGM4BApb45y5Kw6sCPnWu7dMYfny9i
-XeZA2A+ODmqVkrU+ZNVzqzS1krYyUP3exd1voyUCgYEAqPRARH6np3gqhqoVvA4C
-D1OjSTdPrrWzSIriG5h2rbv6ck/Tp1l1zKPnoMZrrjRmHWQA2x61cNk4926DwUKW
-0cgn5HKqU6P49Ks8oRvi48FnJNjKTXHxoqChy/GAHF4Xecl8ZMKy06v5l5v4BLVg
-SSpb2n/dYl9z05IMaBhAKeECgYBKB2n1S6ah1q0GiLL92mDoiDyAYwKG8AjBkk40
-vIsAuNUruTYkQvKmuOsqohO6CXZb2hWSpZ9KZNN+3ucaCL9PDE/4QEM+W9iuQu/X
-gLzy6npxAD6avtGVweq2ncjbMp7QB1ksP69pJDn74xGV8miGPuiVyNOUEMgyChtR
-Oz6EnQKBgEth0w80CBg6b3NKuASoc/vC08njZQvWpe5xrzY2DL8epVKb1qf6+8SE
-eX34cIcSaonEZ2g67MAeIG6jtmPwxWk4EYAsO1u4XiyziABkoNyLKVH4hZg61BsV
-jL7R5UrUvBbhKLFOwkcB4Kwdwu7COB/UKa5XJBTMbuw1UTyxlUeI
+MIIEpQIBAAKCAQEAqAygFPG5ILLb3G51D0OIN4Kpm5t3Oh1nByTnvi1kMz+sCBBd
+CSugt4NnKkB6kiGtMEsrEm1/xg8Bkfbpet3v3+jAidRpjvCISqy3Z9D1cgCFM46h
+iob/AvLZpqITiAgsU4fJ4auuIKhFplIGrIKMv2gK8haoBGBoRUD1RM+irwjEr6TN
+XTQt2Ap+Ouxs53NLPhAOgumpfzzRR8/Umbhen+G5MhH+XTzzreiClz2V6A79ePJj
+y1uQ8NJ79feOOWBDRizRDWwxsnNd24GjkpvcaTwafiK6Vdqeub+XTtiB5RPal2on
+Cj0TQDcnaacecl/zmUWsIFNkNJWDcd3/vEdyOQIDAQABAoIBAQCW93icOCdim6tu
+FIDu7HEjxSsPUpPCToWu4lWaAHcinxGx0NlzkpD4K4DzcSdrvfszBmQ0UtBVokd7
+1IAdU+HZmePWLk+CDM2zoAPHrO3Cs3r2PS0cIHhZMsearcG0E/uWMseHB08PoXuo
+lcnPEhzVGueyYe4guGcTx+5PGeUBLf+fJcEc3rIQnT2LYulM2aqBZSQM3jRUaPYs
+F0awDpCNwajW/Bt2VB14Pr+H5MJ+WSznFCqW7SolBkqDGfKckXPSHgX6xZ0y7VCI
+MM8vwlVI4mPkaHvSQMSI8vS4Qh+SGQCSs/AuuNLjjPoz1YotV3Ih4YbLj6BjFP2g
+CrqzT6VNAoGBANOHmsqE0nRkLzonTDrMdla5b0TjTxwtNM5DjLgJa6UBBqPe+1Lv
+JFoBP9bIfYDRWZOZrxXItfMmM43nK/ST6Xqgx1IpHUCLKVr2pA9RXrP+m4oawfgn
+frW212fHibeOYiLy+DaQXQ0VRFxsc/VbwKVyVlMEcNg3N93x2E67M7vjAoGBAMtg
+7wDa+5gjwuyNr7LKkp5VDTmtKQhoDtg4sw6MSQSMF6fJT9Z4kGTZ23+G85/LsM/k
+iXbceabGJ0CQJvGn6oW4dI2Ut2c2nCNVbQCxJ6Nyn/yW7bRLShMnwXvbGAVxVUax
+5ohJPZGJ8ar2CP76A0bkvm2Nwylq2gp6Y8h7+iwzAoGBAKizwfQ6sk45iKDsrpNG
+dir8gY2DbJigRTksDpLIkJ1skAspz295YpiV3oBCLjYKwVJCg6zwAo0FrqBB+oB5
+ZwByMgWI3NeZJUZy5q2Ay/Lp4MroRELR3PC3/lu6fE90szgEZ4m84TmJ+Jdtt527
+q41H/yj+pbELePb95vIDw2LZAoGBAJBZ+MmupCzUFSI5Xp+UUIS48W4ijaE92mt1
+swF8aMcleBTLOjOL11D9oGHfs0OUG6czGq6WxnGs62dT6ZBUEo1e4rsq9xH3HNOn
+anq3Qt8sGIn7xjPVzHnUGeyDEYWrb0+CLZJGCcEnG7SwdKolYfYLnW281Oysvp35
+SKGf/W0pAoGAa2+sZmhb1mpGAf6Bi4z+uym/6qOJmG6CnrBSM9e/r8nujwFVkCYF
+3iz48qx3GbuliO6za8aM1drX2u8KWp1uP5KzwYvtW5SfpQ1eusFblHEYQQNRcKLT
+j/wZBXnU961eMKkkTe2XsPirO8rVhVmxuFLqT/aEPffcragQFFIGOEQ=
 -----END RSA PRIVATE KEY-----
diff -Naur a/tests/auto/widgets/certificateerror/tst_certificateerror.cpp b/tests/auto/widgets/certificateerror/tst_certificateerror.cpp
--- a/tests/auto/widgets/certificateerror/tst_certificateerror.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/certificateerror/tst_certificateerror.cpp	2021-06-18 16:46:56.650148026 +0100
@@ -30,6 +30,7 @@
 
 #include <QWebEngineCertificateError>
 #include <QWebEnginePage>
+#include <QWebEngineProfile>
 #include <QWebEngineSettings>
 
 #include <QtTest/QtTest>
@@ -99,8 +100,8 @@
     QVERIFY(page.error->isOverridable());
     auto chain = page.error->certificateChain();
     QCOMPARE(chain.size(), 2);
-    QCOMPARE(chain[0].serialNumber(), "3b:dd:1a:b7:2f:40:32:3b:c1:bf:37:d4:86:bd:56:c1:d0:6b:2a:43");
-    QCOMPARE(chain[1].serialNumber(), "6d:52:fb:b4:57:3b:b2:03:c8:62:7b:7e:44:45:5c:d3:08:87:74:17");
+    QCOMPARE(chain[0].serialNumber(), "15:91:08:23:37:91:ee:51:00:d7:4a:db:d7:8c:3b:31:f8:4f:f3:b3");
+    QCOMPARE(chain[1].serialNumber(), "3c:16:83:83:59:c4:2a:65:8f:7a:b2:07:10:14:4e:2d:70:9a:3e:23");
 
     if (deferError) {
         QVERIFY(page.error->deferred());
@@ -124,6 +125,7 @@
 void tst_CertificateError::fatalError()
 {
     PageWithCertificateErrorHandler page(false, false);
+    page.profile()->setUseForGlobalCertificateVerification();
     page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
     QSignalSpy loadFinishedSpy(&page, &QWebEnginePage::loadFinished);
 
diff -Naur a/tests/auto/widgets/loadsignals/BLACKLIST b/tests/auto/widgets/loadsignals/BLACKLIST
--- a/tests/auto/widgets/loadsignals/BLACKLIST	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/loadsignals/BLACKLIST	1970-01-01 01:00:00.000000000 +0100
@@ -1,17 +0,0 @@
-[secondLoadForError_WhenErrorPageEnabled:ErrorPageEnabled]
-*
-
-# QTBUG-65223
-[loadStartedAndFinishedCount:WithAnchorClickedFromJS]
-*
-
-# QTBUG-66869 (https://codereview.qt-project.org/#/c/222112/ is only a workaround)
-[loadAfterInPageNavigation_qtbug66869]
-*
-
-# QTBUG-66661
-[fileDownloadDoesNotTriggerLoadSignals_qtbug66661]
-*
-
-[numberOfStartedAndFinishedSignalsIsSame]
-b2qt
diff -Naur a/tests/auto/widgets/loadsignals/tst_loadsignals.cpp b/tests/auto/widgets/loadsignals/tst_loadsignals.cpp
--- a/tests/auto/widgets/loadsignals/tst_loadsignals.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/loadsignals/tst_loadsignals.cpp	2021-06-18 16:44:51.625931333 +0100
@@ -36,6 +36,43 @@
 #include "qwebenginesettings.h"
 #include "qwebengineview.h"
 
+enum { LoadStarted, LoadSucceeded, LoadFailed };
+static const QList<int> SignalsOrderOnce({ LoadStarted, LoadSucceeded});
+static const QList<int> SignalsOrderTwice({ LoadStarted, LoadSucceeded, LoadStarted, LoadSucceeded });
+static const QList<int> SignalsOrderOnceFailure({ LoadStarted, LoadFailed });
+static const QList<int> SignalsOrderTwiceWithFailure({ LoadStarted, LoadSucceeded, LoadStarted, LoadFailed });
+
+class TestPage : public QWebEnginePage
+{
+public:
+    QSet<QUrl> blacklist;
+    int navigationRequestCount = 0;
+    QList<int> signalsOrder;
+    QList<int> loadProgress;
+
+    explicit TestPage(QObject *parent = nullptr) : TestPage(nullptr, parent) { }
+    TestPage(QWebEngineProfile *profile, QObject *parent = nullptr) : QWebEnginePage(profile, parent) {
+        connect(this, &QWebEnginePage::loadStarted, [this] () { signalsOrder.append(LoadStarted); });
+        connect(this, &QWebEnginePage::loadProgress, [this] (int p) { loadProgress.append(p); });
+        connect(this, &QWebEnginePage::loadFinished, [this] (bool r) { signalsOrder.append(r ? LoadSucceeded : LoadFailed); });
+    }
+
+    void reset()
+    {
+        blacklist.clear();
+        navigationRequestCount = 0;
+        signalsOrder.clear();
+        loadProgress.clear();
+    }
+
+protected:
+    bool acceptNavigationRequest(const QUrl &url, NavigationType, bool) override
+    {
+        ++navigationRequestCount;
+        return !blacklist.contains(url);
+    }
+};
+
 class tst_LoadSignals : public QObject
 {
     Q_OBJECT
@@ -48,10 +85,13 @@
     void monotonicity();
     void loadStartedAndFinishedCount_data();
     void loadStartedAndFinishedCount();
-    void secondLoadForError_WhenErrorPageEnabled_data();
-    void secondLoadForError_WhenErrorPageEnabled();
+    void loadStartedAndFinishedCountClick_data();
+    void loadStartedAndFinishedCountClick();
+    void rejectNavigationRequest_data();
+    void rejectNavigationRequest();
     void loadAfterInPageNavigation_qtbug66869();
-    void fileDownloadDoesNotTriggerLoadSignals_qtbug66661();
+    void fileDownload();
+    void numberOfStartedAndFinishedSignalsIsSame_data();
     void numberOfStartedAndFinishedSignalsIsSame();
     void loadFinishedAfterNotFoundError_data();
     void loadFinishedAfterNotFoundError();
@@ -59,31 +99,45 @@
     void errorPageTriggered();
 
 private:
+    void clickLink(QPoint linkPos);
+
     QWebEngineProfile profile;
-    QWebEnginePage page{&profile};
+    TestPage page{&profile};
     QWebEngineView view;
     QSignalSpy loadStartedSpy{&page, &QWebEnginePage::loadStarted};
-    QSignalSpy loadProgressSpy{&page, &QWebEnginePage::loadProgress};
     QSignalSpy loadFinishedSpy{&page, &QWebEnginePage::loadFinished};
+    void resetSpies() {
+        loadStartedSpy.clear();
+        loadFinishedSpy.clear();
+    }
 };
 
 void tst_LoadSignals::initTestCase()
 {
     view.setPage(&page);
-    view.resize(1024,768);
+    view.resize(640, 480);
     view.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&view));
 }
 
 void tst_LoadSignals::init()
 {
     // Reset content
-    loadFinishedSpy.clear();
-    view.load(QUrl("about:blank"));
-    QTRY_COMPARE(loadFinishedSpy.count(), 1);
+    if (!view.url().isEmpty()) {
+        loadFinishedSpy.clear();
+        view.load(QUrl("about:blank"));
+        QTRY_COMPARE(loadFinishedSpy.count(), 1);
+    }
+    resetSpies();
+    page.reset();
+}
 
-    loadStartedSpy.clear();
-    loadProgressSpy.clear();
-    loadFinishedSpy.clear();
+void tst_LoadSignals::clickLink(QPoint linkPos)
+{
+    // Simulate left-clicking on link.
+    QTRY_VERIFY(view.focusProxy());
+    QWidget *renderWidget = view.focusProxy();
+    QTest::mouseClick(renderWidget, Qt::LeftButton, {}, linkPos);
 }
 
 /**
@@ -92,27 +146,124 @@
 void tst_LoadSignals::loadStartedAndFinishedCount_data()
 {
     QTest::addColumn<QUrl>("url");
-    QTest::addColumn<int>("expectedLoadCount");
-    QTest::newRow("Normal") << QUrl("qrc:///resources/page1.html") << 1;
-    QTest::newRow("WithAnchor") << QUrl("qrc:///resources/page2.html#anchor") << 1;
-
-    // In this case, we get an unexpected additional loadStarted, but no corresponding
-    // loadFinished, so expectedLoadCount=2 would also not work. See also QTBUG-65223
-    QTest::newRow("WithAnchorClickedFromJS") << QUrl("qrc:///resources/page3.html") << 1;
+    QTest::addColumn<QList<int>>("expectedSignals");
+    QTest::newRow("Simple") << QUrl("qrc:///resources/page1.html") << SignalsOrderOnce;
+    QTest::newRow("SimpleWithAnchor") << QUrl("qrc:///resources/page2.html#anchor") << SignalsOrderOnce;
+    QTest::newRow("SamePageImmediate") << QUrl("qrc:///resources/page5.html") << SignalsOrderOnce;
+    QTest::newRow("SamePageDeferred") << QUrl("qrc:///resources/page3.html") << SignalsOrderOnce;
+    QTest::newRow("OtherPageImmediate") << QUrl("qrc:///resources/page6.html") << SignalsOrderOnce;
+    QTest::newRow("OtherPageDeferred") << QUrl("qrc:///resources/page7.html") << SignalsOrderTwice;
+    QTest::newRow("SamePageImmediateJS") << QUrl("qrc:///resources/page8.html") << SignalsOrderOnce;
 }
 
 void tst_LoadSignals::loadStartedAndFinishedCount()
 {
     QFETCH(QUrl, url);
-    QFETCH(int, expectedLoadCount);
+    QFETCH(QList<int>, expectedSignals);
 
     view.load(url);
+
+    int expectedLoadCount = expectedSignals.size() / 2;
+    QTRY_COMPARE(loadStartedSpy.size(), expectedLoadCount);
     QTRY_COMPARE(loadFinishedSpy.size(), expectedLoadCount);
+
+    // verify no more signals is emitted by waiting for another loadStarted or loadFinished
+    QTRY_LOOP_IMPL(loadStartedSpy.size() != expectedLoadCount || loadFinishedSpy.size() != expectedLoadCount, 1000, 100);
+
+    // No further signals should have occurred within this time and expected number of signals is preserved
+    QCOMPARE(loadStartedSpy.size(), expectedLoadCount);
+    QCOMPARE(loadFinishedSpy.size(), expectedLoadCount);
+    QCOMPARE(page.signalsOrder, expectedSignals);
+}
+
+/**
+ * Load a URL, then simulate a click to load a different URL.
+ */
+void tst_LoadSignals::loadStartedAndFinishedCountClick_data()
+{
+    QTest::addColumn<QUrl>("url");
+    QTest::addColumn<int>("numberOfSignals");
+    QTest::newRow("SamePage") << QUrl("qrc:///resources/page2.html") << 0; // in-page navigation to anchor shouldn't emit anything
+    QTest::newRow("OtherPage") << QUrl("qrc:///resources/page1.html") << 1;
+}
+
+void tst_LoadSignals::loadStartedAndFinishedCountClick()
+{
+    QFETCH(QUrl, url);
+    QFETCH(int, numberOfSignals);
+
+    view.load(url);
+    QTRY_COMPARE(loadStartedSpy.size(), 1);
+    QTRY_COMPARE(loadFinishedSpy.size(), 1);
     QVERIFY(loadFinishedSpy[0][0].toBool());
+    resetSpies();
+
+    clickLink(QPoint(10, 10));
+    if (numberOfSignals > 0) {
+        QTRY_COMPARE(loadStartedSpy.size(), numberOfSignals);
+        QTRY_COMPARE(loadFinishedSpy.size(), numberOfSignals);
+        QVERIFY(loadFinishedSpy[0][0].toBool());
+    }
+
+    // verify no more signals is emitted by waiting for another loadStarted or loadFinished
+    QTRY_LOOP_IMPL(loadStartedSpy.size() != numberOfSignals || loadFinishedSpy.size() != numberOfSignals, 1000, 100);
+
+    // No further loadStarted should have occurred within this time
+    QCOMPARE(loadStartedSpy.size(), numberOfSignals);
+    QCOMPARE(loadFinishedSpy.size(), numberOfSignals);
+    QCOMPARE(page.signalsOrder, numberOfSignals > 0 ? SignalsOrderTwice : SignalsOrderOnce);
+}
+
+void tst_LoadSignals::rejectNavigationRequest_data()
+{
+    QTest::addColumn<QUrl>("initialUrl");
+    QTest::addColumn<QUrl>("rejectedUrl");
+    QTest::addColumn<int>("expectedNavigations");
+    QTest::addColumn<QList<int>>("expectedSignals");
+    QTest::newRow("Simple")
+            << QUrl("qrc:///resources/page1.html")
+            << QUrl("qrc:///resources/page1.html")
+            << 1 << SignalsOrderOnceFailure;
+    QTest::newRow("SamePageImmediate")
+            << QUrl("qrc:///resources/page5.html")
+            << QUrl("qrc:///resources/page5.html#anchor")
+            << 1 << SignalsOrderOnce;
+    QTest::newRow("SamePageDeferred")
+            << QUrl("qrc:///resources/page3.html")
+            << QUrl("qrc:///resources/page3.html#anchor")
+            << 1 << SignalsOrderOnce;
+    QTest::newRow("OtherPageImmediate")
+            << QUrl("qrc:///resources/page6.html")
+            << QUrl("qrc:///resources/page2.html#anchor")
+            << 2 << SignalsOrderOnceFailure;
+    QTest::newRow("OtherPageDeferred")
+            << QUrl("qrc:///resources/page7.html")
+            << QUrl("qrc:///resources/page2.html#anchor")
+            << 2 << SignalsOrderTwiceWithFailure;
+}
 
-    // Wait for 10 seconds (abort waiting if another loadStarted or loadFinished occurs)
-    QTRY_LOOP_IMPL((loadStartedSpy.size() != expectedLoadCount)
-                || (loadFinishedSpy.size() != expectedLoadCount), 10000, 100);
+/**
+ * Returning false from acceptNavigationRequest means that the load
+ * fails, not that the load never starts.
+ *
+ * See QTBUG-75185.
+ */
+void tst_LoadSignals::rejectNavigationRequest()
+{
+    QFETCH(QUrl, initialUrl);
+    QFETCH(QUrl, rejectedUrl);
+    QFETCH(int, expectedNavigations);
+    QFETCH(QList<int>, expectedSignals);
+
+    page.blacklist.insert(rejectedUrl);
+    page.load(initialUrl);
+    QTRY_COMPARE(page.navigationRequestCount, expectedNavigations);
+    int expectedLoadCount = expectedSignals.size() / 2;
+    QTRY_COMPARE(loadFinishedSpy.size(), expectedLoadCount);
+    QCOMPARE(page.signalsOrder, expectedSignals);
+
+    // verify no more signals is emitted by waiting for another loadStarted or loadFinished
+    QTRY_LOOP_IMPL(loadStartedSpy.size() != expectedLoadCount || loadFinishedSpy.size() != expectedLoadCount, 1000, 100);
 
     // No further loadStarted should have occurred within this time
     QCOMPARE(loadStartedSpy.size(), expectedLoadCount);
@@ -135,53 +286,19 @@
     QTRY_COMPARE(loadFinishedSpy.size(), 1);
     QVERIFY(loadFinishedSpy[0][0].toBool());
 
+    QVERIFY(page.loadProgress.size() >= 3);
     // first loadProgress should have 0% progress
-    QCOMPARE(loadProgressSpy.takeFirst()[0].toInt(), 0);
+    QCOMPARE(page.loadProgress.first(), 0);
 
     // every loadProgress should have more progress than the one before
-    int progress = 0;
-    for (const auto &item : loadProgressSpy) {
-        QVERIFY(progress < item[0].toInt());
-        progress = item[0].toInt();
+    int progress = -1;
+    for (int p : page.loadProgress) {
+        QVERIFY(progress < p);
+        progress = p;
     }
 
     // last loadProgress should have 100% progress
-    QCOMPARE(loadProgressSpy.last()[0].toInt(), 100);
-}
-
-/**
-  * Test that we get a second loadStarted and loadFinished signal
-  * for error-pages (unless error-pages are disabled)
-  */
-void tst_LoadSignals::secondLoadForError_WhenErrorPageEnabled_data()
-{
-    QTest::addColumn<bool>("enabled");
-    // in this case, we get no second loadStarted and loadFinished, although we had
-    // agreed on making the navigation to an error page an individual load
-    QTest::newRow("ErrorPageEnabled") << true;
-    QTest::newRow("ErrorPageDisabled") << false;
-}
-
-void tst_LoadSignals::secondLoadForError_WhenErrorPageEnabled()
-{
-    QFETCH(bool, enabled);
-    view.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, enabled);
-    int expectedLoadCount = (enabled ? 2 : 1);
-
-    // RFC 2606 guarantees that this will never become a valid domain
-    view.load(QUrl("http://nonexistent.invalid"));
-    QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpy.size(), expectedLoadCount, 10000);
-    QVERIFY(!loadFinishedSpy[0][0].toBool());
-    if (enabled)
-        QVERIFY(loadFinishedSpy[1][0].toBool());
-
-    // Wait for 10 seconds (abort waiting if another loadStarted or loadFinished occurs)
-    QTRY_LOOP_IMPL((loadStartedSpy.size() != expectedLoadCount)
-                || (loadFinishedSpy.size() != expectedLoadCount), 10000, 100);
-
-    // No further loadStarted should have occurred within this time
-    QCOMPARE(loadStartedSpy.size(), expectedLoadCount);
-    QCOMPARE(loadFinishedSpy.size(), expectedLoadCount);
+    QCOMPARE(page.loadProgress.last(), 100);
 }
 
 /**
@@ -195,27 +312,17 @@
     QVERIFY(loadFinishedSpy[0][0].toBool());
 
     // page3 does an in-page navigation after 500ms
-    QTest::qWait(2000);
-    loadFinishedSpy.clear();
-    loadProgressSpy.clear();
-    loadStartedSpy.clear();
+    QTRY_COMPARE(view.url(), QUrl("qrc:///resources/page3.html#anchor"));
 
     // second load
     view.load(QUrl("qrc:///resources/page1.html"));
-    QTRY_COMPARE(loadFinishedSpy.size(), 1);
+    QTRY_COMPARE(loadFinishedSpy.size(), 2);
     QVERIFY(loadFinishedSpy[0][0].toBool());
     // loadStarted and loadFinished should have been signalled
-    QCOMPARE(loadStartedSpy.size(), 1);
-
-    // reminder that we still need to solve the core issue
-    QFAIL("https://codereview.qt-project.org/#/c/222112/ only hides the symptom, the core issue still needs to be solved");
+    QCOMPARE(loadStartedSpy.size(), 2);
 }
 
-/**
-  * Test that file-downloads don't trigger loadStarted or loadFinished signals.
-  * See QTBUG-66661
-  */
-void tst_LoadSignals::fileDownloadDoesNotTriggerLoadSignals_qtbug66661()
+void tst_LoadSignals::fileDownload()
 {
     view.load(QUrl("qrc:///resources/page4.html"));
     QTRY_COMPARE(loadFinishedSpy.size(), 1);
@@ -237,59 +344,55 @@
                     });
 
     // trigger the download link that becomes focused on page4
-    QTest::qWait(1000);
     QTest::sendKeyEvent(QTest::Press, view.focusProxy(), Qt::Key_Return, QString("\r"), Qt::NoModifier);
     QTest::sendKeyEvent(QTest::Release, view.focusProxy(), Qt::Key_Return, QString("\r"), Qt::NoModifier);
 
-    // Wait for 10 seconds (abort waiting if another loadStarted or loadFinished occurs)
-    QTRY_LOOP_IMPL((loadStartedSpy.size() != 1)
-                || (loadFinishedSpy.size() != 1), 10000, 100);
-
     // Download must have occurred
     QTRY_COMPARE(downloadState, QWebEngineDownloadItem::DownloadCompleted);
+    QTRY_COMPARE(loadFinishedSpy.size() + loadStartedSpy.size(), 4);
 
-    // No further loadStarted should have occurred within this time
-    QCOMPARE(loadStartedSpy.size(), 1);
-    QCOMPARE(loadFinishedSpy.size(), 1);
+    // verify no more signals is emitted by waiting for another loadStarted or loadFinished
+    QTRY_LOOP_IMPL(loadStartedSpy.size() != 2 || loadFinishedSpy.size() != 2, 1000, 100);
+
+    QCOMPARE(page.signalsOrder, SignalsOrderTwiceWithFailure);
 }
 
-void tst_LoadSignals::numberOfStartedAndFinishedSignalsIsSame() {
+void tst_LoadSignals::numberOfStartedAndFinishedSignalsIsSame_data()
+{
+    QTest::addColumn<bool>("imageFromServer");
+    QTest::addColumn<QString>("imageResourceUrl");
+    // triggers these calls in delegate internally:
+    // just two ordered triples DidStartNavigation/DidFinishNavigation/DidFinishLoad
+    QTest::newRow("no_image_resource") << false << "";
+    // out of order: DidStartNavigation/DidFinishNavigation/DidStartNavigation/DidFailLoad/DidFinishNavigation/DidFinishLoad
+    QTest::newRow("with_invalid_image") << false << "https://non.existent.locahost/image.png";
+    // out of order: DidStartNavigation/DidFinishNavigation/DidStartNavigation/DidFinishLoad/DidFinishNavigation/DidFinishLoad
+    QTest::newRow("with_server_image") << true << "";
+}
+
+void tst_LoadSignals::numberOfStartedAndFinishedSignalsIsSame()
+{
+    QFETCH(bool, imageFromServer);
+    QFETCH(QString, imageResourceUrl);
 
     HttpServer server;
     server.setResourceDirs({ TESTS_SOURCE_DIR "/qwebengineprofile/resources" });
-    connect(&server, &HttpServer::newRequest, [] (HttpReqRep *) {
-         QTest::qWait(250); // just add delay to trigger some progress for every sub resource
-    });
     QVERIFY(server.start());
 
-    view.load(server.url("/hedgehog.png"));
+    QUrl serverImage = server.url("/hedgehog.png");
+    QString imageUrl(!imageFromServer && imageResourceUrl.isEmpty()
+                     ? "" : (imageFromServer ? serverImage.toEncoded() : imageResourceUrl));
+
+    auto html = "<html><head><link rel='icon' href='data:,'></head><body>"
+                "%1" "<form method='GET' name='hiddenform' action='qrc:///resources/page1.html' />"
+                "<script language='javascript'>document.forms[0].submit();</script>"
+                "</body></html>";
+    view.page()->setHtml(QString(html).arg(imageUrl.isEmpty() ? "" : "<img src='" + imageUrl + "'>"));
     QTRY_COMPARE(loadFinishedSpy.size(), 1);
-    QVERIFY(loadFinishedSpy[0][0].toBool());
-
-    loadStartedSpy.clear();
-    loadFinishedSpy.clear();
-    loadProgressSpy.clear();
 
-    view.page()->setHtml("<html><body>"
-                         "<img src=\"" + server.url("/hedgehog.png").toEncoded() + "\">"
-                         "<form method='GET' name='hiddenform' action='qrc:///resources/page1.html' />"
-                         "<script language='javascript'>document.forms[0].submit();</script>"
-                         "</body></html>");
-
-    QTRY_COMPARE(loadStartedSpy.size(), 2);
-    QTRY_COMPARE(loadFinishedSpy.size(), 2);
-
-    QTRY_VERIFY(!loadFinishedSpy[0][0].toBool());
-    QTRY_VERIFY(loadFinishedSpy[1][0].toBool());
-
-    view.page()->setHtml("<html><body>"
-                         "<form method='GET' name='hiddenform' action='qrc:///resources/page1.html' />"
-                         "<script language='javascript'>document.forms[0].submit();</script>"
-                         "</body></html>");
-    QTRY_COMPARE(loadStartedSpy.size(), 4);
-    QTRY_COMPARE(loadFinishedSpy.size(), 4);
-    QVERIFY(loadFinishedSpy[2][0].toBool());
-    QVERIFY(loadFinishedSpy[3][0].toBool());
+    resetSpies();
+    QTRY_LOOP_IMPL(loadStartedSpy.size() || loadFinishedSpy.size(), 1000, 100);
+    QCOMPARE(page.signalsOrder, SignalsOrderOnce);
 }
 
 void tst_LoadSignals::loadFinishedAfterNotFoundError_data()
@@ -311,7 +414,6 @@
         server.reset(new HttpServer);
         QVERIFY(server->start());
     }
-
     view.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
     auto url = server
         ? server->url("/not-found-page.html")
@@ -321,6 +423,9 @@
     QVERIFY(!loadFinishedSpy.at(0).at(0).toBool());
     QCOMPARE(toPlainTextSync(view.page()), QString());
     QCOMPARE(loadFinishedSpy.count(), 1);
+    QCOMPARE(loadStartedSpy.count(), 1);
+    QVERIFY(std::is_sorted(page.loadProgress.begin(), page.loadProgress.end()));
+    page.loadProgress.clear();
 
     view.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, true);
     url = server
@@ -329,9 +434,12 @@
     view.load(url);
     QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpy.count(), 2, 20000);
     QVERIFY(!loadFinishedSpy.at(1).at(0).toBool());
+    QCOMPARE(loadStartedSpy.count(), 2);
 
     QEXPECT_FAIL("", "No more loads (like separate load for error pages) are expected", Continue);
     QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpy.count(), 3, 1000);
+    QCOMPARE(loadStartedSpy.count(), 2);
+    QVERIFY(std::is_sorted(page.loadProgress.begin(), page.loadProgress.end()));
 }
 
 void tst_LoadSignals::errorPageTriggered_data()
@@ -388,6 +496,5 @@
     loadFinishedSpy.clear();
 }
 
-
 QTEST_MAIN(tst_LoadSignals)
 #include "tst_loadsignals.moc"
diff -Naur a/tests/auto/widgets/loadsignals/tst_loadsignals.qrc b/tests/auto/widgets/loadsignals/tst_loadsignals.qrc
--- a/tests/auto/widgets/loadsignals/tst_loadsignals.qrc	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/loadsignals/tst_loadsignals.qrc	2021-06-18 16:31:43.874578798 +0100
@@ -4,6 +4,10 @@
         <file alias="page2.html">../../shared/data/loadprogress/page2.html</file>
         <file alias="page3.html">../../shared/data/loadprogress/page3.html</file>
         <file alias="page4.html">../../shared/data/loadprogress/page4.html</file>
+        <file alias="page5.html">../../shared/data/loadprogress/page5.html</file>
+        <file alias="page6.html">../../shared/data/loadprogress/page6.html</file>
+        <file alias="page7.html">../../shared/data/loadprogress/page7.html</file>
+        <file alias="page8.html">../../shared/data/loadprogress/page8.html</file>
         <file alias="downloadable.tar.gz">../../shared/data/loadprogress/downloadable.tar.gz</file>
     </qresource>
 </RCC>
diff -Naur a/tests/auto/widgets/qwebenginepage/resources/redirect.html b/tests/auto/widgets/qwebenginepage/resources/redirect.html
--- a/tests/auto/widgets/qwebenginepage/resources/redirect.html	1970-01-01 01:00:00.000000000 +0100
+++ b/tests/auto/widgets/qwebenginepage/resources/redirect.html	2021-06-18 16:26:16.770894202 +0100
@@ -0,0 +1,8 @@
+<html>
+<body>
+<script>
+function doRedirect() { location.replace('qrc:///resources/content.html') }
+document.addEventListener("DOMContentLoaded", doRedirect)
+</script>
+</body>
+</html>
diff -Naur a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp	2021-06-18 16:35:08.957252848 +0100
@@ -596,6 +596,39 @@
         << QWebEnginePage::NavigationTypeReload
         << QWebEnginePage::NavigationTypeTyped
         << QWebEnginePage::NavigationTypeRedirect;
+
+    // client side redirect
+    page.load(QUrl("qrc:///resources/redirect.html"));
+    QTRY_COMPARE_WITH_TIMEOUT(loadSpy.count(), 7, 20000);
+    QTRY_COMPARE(page.navigations.count(), 8);
+    expectedList += { QWebEnginePage::NavigationTypeTyped, QWebEnginePage::NavigationTypeRedirect };
+
+    // server side redirect
+    HttpServer server;
+    server.setResourceDirs({ ":/resources" });
+    connect(&server, &HttpServer::newRequest, &server, [&] (HttpReqRep *r) {
+        if (r->requestMethod() == "GET") {
+            if (r->requestPath() == "/redirect1.html") {
+                r->setResponseHeader("Location", server.url("/redirect2.html").toEncoded());
+                r->setResponseBody("<html><body>Redirect1</body></html>");
+                r->sendResponse(307); // Internal server redirect
+            } else if (r->requestPath() == "/redirect2.html") {
+                r->setResponseHeader("Location", server.url("/content.html").toEncoded());
+                r->setResponseBody("<html><body>Redirect2</body></html>");
+                r->sendResponse(301); // Moved permanently
+            }
+        }
+    });
+    QVERIFY(server.start());
+    page.load(QUrl(server.url("/redirect1.html")));
+    QTRY_COMPARE_WITH_TIMEOUT(loadSpy.count(), 8, 20000);
+    QTRY_COMPARE(page.navigations.count(), 11);
+    expectedList += {
+        QWebEnginePage::NavigationTypeTyped,
+        QWebEnginePage::NavigationTypeRedirect,
+        QWebEnginePage::NavigationTypeRedirect
+    };
+
     QVERIFY(expectedList.count() == page.navigations.count());
     for (int i = 0; i < expectedList.count(); ++i) {
         QCOMPARE(page.navigations[i].type, expectedList[i]);
@@ -2903,11 +2936,7 @@
     URLSetter setter(m_page, signal, type, urlForSetter);
     QSignalSpy spy(&setter, &URLSetter::finished);
     m_page->load(url);
-    // every loadStarted() call should have also loadFinished()
-    if (signal == URLSetter::LoadStarted)
-        QTRY_COMPARE(spy.count(), 2);
-    else
-        QTRY_COMPARE(spy.count(), 1);
+    QTRY_COMPARE(spy.count(), 1);
     QCOMPARE(m_page->url(), urlForSetter);
 }
 
@@ -4058,8 +4087,7 @@
     devToolsPage.setLifecycleState(QWebEnginePage::LifecycleState::Discarded);
     devToolsPage.setInspectedPage(&inspectedPage);
     QCOMPARE(devToolsPage.lifecycleState(), QWebEnginePage::LifecycleState::Active);
-    QTRY_COMPARE_WITH_TIMEOUT(devToolsSpy.count(), 2, 90000);
-    QCOMPARE(devToolsSpy.takeFirst().value(0), QVariant(false));
+    QTRY_COMPARE_WITH_TIMEOUT(devToolsSpy.count(), 1, 90000);
     QCOMPARE(devToolsSpy.takeFirst().value(0), QVariant(true));
     // keep DevTools open
 
diff -Naur a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc	2021-06-18 16:26:16.771895934 +0100
@@ -14,6 +14,7 @@
     <file>resources/user.css</file>
     <file>resources/image.png</file>
     <file>resources/pasteimage.html</file>
+    <file>resources/redirect.html</file>
     <file>resources/reload.html</file>
     <file>resources/style.css</file>
     <file>resources/test1.html</file>
diff -Naur a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST
--- a/tests/auto/widgets/qwebengineview/BLACKLIST	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/qwebengineview/BLACKLIST	2021-06-18 16:26:16.771895934 +0100
@@ -6,3 +6,6 @@
 
 [horizontalScrollbarTest]
 osx
+
+[mixLangLocale:eu_ES]
+*
diff -Naur a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp	2021-04-01 15:33:27.000000000 +0100
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp	2021-06-18 16:26:16.771895934 +0100
@@ -124,6 +124,7 @@
     void doNotBreakLayout();
 
     void changeLocale();
+    void mixLangLocale_data();
     void mixLangLocale();
     void inputMethodsTextFormat_data();
     void inputMethodsTextFormat();
@@ -1213,26 +1214,46 @@
     QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar"));
 }
 
+void tst_QWebEngineView::mixLangLocale_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QByteArray>("formattedNumber");
+    QTest::newRow("en_DK") << "en-DK" << QByteArray("1.234.567.890");
+    QTest::newRow("de")    << "de"    << QByteArray("1.234.567.890");
+    QTest::newRow("de_CH") << "de-CH" << QByteArray("1’234’567’890");
+    QTest::newRow("eu_ES") << "eu-ES" << QByteArray("1.234.567.890");
+    QTest::newRow("hu_HU") << "hu-HU" << QByteArray("1\xC2\xA0""234\xC2\xA0""567\xC2\xA0""890"); // no-break spaces
+}
+
 void tst_QWebEngineView::mixLangLocale()
 {
-    for (QString locale : { "en_DK", "de_CH", "eu_ES" }) {
-        QLocale::setDefault(locale);
-        QWebEngineView view;
-        QSignalSpy loadSpy(&view, &QWebEngineView::loadFinished);
-
-        bool terminated = false;
-        auto sc = connect(view.page(), &QWebEnginePage::renderProcessTerminated, [&] () { terminated = true; });
-
-        view.load(QUrl("qrc:///resources/dummy.html"));
-        QTRY_VERIFY(terminated || loadSpy.count() == 1);
-
-        QVERIFY2(!terminated,
-            qPrintable(QString("Locale [%1] terminated: %2, loaded: %3").arg(locale).arg(terminated).arg(loadSpy.count())));
-        QVERIFY(loadSpy.first().first().toBool());
+    QFETCH(QString, locale);
+    QFETCH(QByteArray, formattedNumber);
+
+    QLocale::setDefault(locale);
+
+    QWebEngineView view;
+    QSignalSpy loadSpy(&view, &QWebEngineView::loadFinished);
+
+    bool terminated = false;
+    auto sc = connect(view.page(), &QWebEnginePage::renderProcessTerminated, [&] () { terminated = true; });
+
+    view.load(QUrl("qrc:///resources/dummy.html"));
+    QTRY_VERIFY(terminated || loadSpy.count() == 1);
+
+    QVERIFY2(!terminated,
+        qPrintable(QString("Locale [%1] terminated: %2, loaded: %3").arg(locale).arg(terminated).arg(loadSpy.count())));
+    QVERIFY(loadSpy.first().first().toBool());
+
+    QString content = toPlainTextSync(view.page());
+    QVERIFY2(!content.isEmpty() && content.contains("test content"), qPrintable(content));
+
+    QCOMPARE(evaluateJavaScriptSync(view.page(), "navigator.language").toString(), QLocale().bcp47Name());
+
+    if (locale == "eu-ES")
+        QEXPECT_FAIL("", "Basque number formatting is somehow dependent on environment", Continue);
+    QCOMPARE(evaluateJavaScriptSync(view.page(), "Number(1234567890).toLocaleString()").toByteArray(), formattedNumber);
 
-        QString content = toPlainTextSync(view.page());
-        QVERIFY2(!content.isEmpty() && content.contains("test content"), qPrintable(content));
-    }
     QLocale::setDefault(QLocale("en"));
 }
 
