Submitted By: Ken Moffat 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 -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 +commit eafc7b60313d9827f976f1d4fbb5e7f5d54eea7b +Author: Allan Sandfeld Jensen +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 -Date: Tue Mar 23 18:47:22 2021 +0000 +commit eaffb82d5ee99ea1db8c0d4d359bbc72e77f065b +Author: 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 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 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 viewers_; + base::ObserverList viewers_; std::unique_ptr 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& bitmaps, const std::vector& 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& original_sizes, int desired_size_in_dip, float* score) { + DCHECK_EQ(bitmaps.size(), original_sizes.size()); const std::vector& favicon_scales = favicon_base::GetFaviconScales(); std::vector 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& bitmaps, const std::vector& 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 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& origin) override; - int SubscribePermissionStatusChange( + SubscriptionId SubscribePermissionStatusChange( content::PermissionType permission, content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, base::RepeatingCallback 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>; + using SubscriptionsMap = + base::IDMap, 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( metadata.response().cors_exposed_header_names().begin(), @@ -448,55 +466,28 @@ // Default proto value of 0 maps to CONNECTION_INFO_UNKNOWN. static_cast( 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 scheduler_task_runner, scoped_refptr quota_manager_proxy, - scoped_refptr blob_storage_context, - std::unique_ptr cache_padding_key) { + scoped_refptr 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 quota_manager_proxy, scoped_refptr blob_storage_context, int64_t cache_size, - int64_t cache_padding, - std::unique_ptr 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 quota_manager_proxy, scoped_refptr blob_storage_context, int64_t cache_size, - int64_t cache_padding, - std::unique_ptr 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 query_cache_context, + disk_cache::ScopedEntryPtr entry, + std::unique_ptr 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 self, + std::unique_ptr query_cache_context, + disk_cache::ScopedEntryPtr entry, + std::unique_ptr 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 serialized = std::make_unique(); + if (!metadata.SerializeToString(serialized.get())) { + std::move(callback).Run(0, -1); + return; + } + + scoped_refptr buffer = + base::MakeRefCounted(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 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 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 buffer = - base::MakeRefCounted(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 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 scheduler_task_runner, scoped_refptr quota_manager_proxy, - scoped_refptr blob_storage_context, - std::unique_ptr cache_padding_key); + scoped_refptr blob_storage_context); static std::unique_ptr CreatePersistentCache( const url::Origin& origin, CacheStorageOwner owner, @@ -81,12 +75,7 @@ scoped_refptr quota_manager_proxy, scoped_refptr blob_storage_context, int64_t cache_size, - int64_t cache_padding, - std::unique_ptr 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 quota_manager_proxy, scoped_refptr blob_storage_context, int64_t cache_size, - int64_t cache_padding, - std::unique_ptr 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 query_cache_context, disk_cache::ScopedEntryPtr entry, std::unique_ptr metadata); + void QueryCacheUpgradePadding( + std::unique_ptr query_cache_context, + disk_cache::ScopedEntryPtr entry, + std::unique_ptr 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 query_cache_results); + // Utility method to write metadata headers to an entry. + using WriteMetadataCallback = + base::OnceCallback; + 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 response, - int side_data_size_before_write, + std::unique_ptr 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 put_context, disk_cache::EntryResult result); void PutDidWriteHeaders(std::unique_ptr put_context, + int64_t padding, + int64_t side_data_padding, int expected_bytes, int rv); void PutWriteBlobToCache(std::unique_ptr 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 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 CreateCache( const std::string& cache_name, int64_t cache_size, - int64_t cache_padding, - std::unique_ptr 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 CreateCache( const std::string& cache_name, int64_t cache_size, - int64_t cache_padding, - std::unique_ptr 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 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 CreateCache( const std::string& cache_name, int64_t cache_size, - int64_t cache_padding, - std::unique_ptr 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 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] // [stream0 (checksum key entry)] // [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(data.data()), data.size()), + base::StringPiece(reinterpret_cast(copy.data()), copy.size()), result, base::size(result)); std::string checksum_key = base::HexEncode(result, base::size(result)); small_buffer = base::MakeRefCounted( @@ -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(0); - auto large_buffer2 = base::MakeRefCounted(std::move(data)); + auto large_buffer2 = base::MakeRefCounted(std::move(copy)); auto op2 = std::make_unique(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 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 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 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 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& callback); - void UnsubscribePermissionStatusChange(int subscription_id); + void UnsubscribePermissionStatusChange(SubscriptionId subscription_id); private: struct Subscription; - using SubscriptionsMap = base::IDMap>; + using SubscriptionsMap = + base::IDMap, SubscriptionId>; using SubscriptionsStatusMap = base::flat_map; @@ -98,7 +99,13 @@ const base::Optional& 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 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 #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 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 services_; - std::unordered_map> + std::unordered_map> 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 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(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(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 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 RenderWidgetHostInputEventRouter::GetRenderWidgetHostViewsForTests() const { std::vector 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& 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; - using TargetMap = std::map; + using FrameSinkIdOwnerMap = + std::unordered_map, + viz::FrameSinkIdHash>; + using TargetMap = std::map>; 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(), std::vector())); 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 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(), + std::vector()); + 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& result); // Called with the result of a DownloadImage() request. - void OnDidDownloadImage(ImageDownloadCallback callback, + void OnDidDownloadImage(base::WeakPtr 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; + 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 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 { + 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; + + // 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 { + 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::OnceCallbackSetWasFallbackRequiredByServiceWorker( 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 callback) { // TODO(crbug.com/1063094): Implement permission status subscription. It's // used in blink to emit PermissionStatus.onchange notifications. - NOTIMPLEMENTED() << ": " << static_cast(permission); - return content::PermissionController::kNoPendingOperation; + NOTIMPLEMENTED_LOG_ONCE() << ": " << static_cast(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 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 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 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(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(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 pending_broker_clients; std::unordered_map @@ -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 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 struct ReceiverSetTraits; @@ -361,11 +361,11 @@ Context context, scoped_refptr task_runner) { ReceiverId id = next_receiver_id_++; - DCHECK_GE(next_receiver_id_, 0u); auto entry = std::make_unique(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((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::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, ®istrable_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::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:: 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 -#include - -#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* GetPaddingKeyInternal() { - static base::NoDestructor> s_padding_key([] { - return SymmetricKey::GenerateRandomKey(kPaddingKeyAlgorithm, 128); - }()); - return s_padding_key.get(); -} - -} // namespace - -const SymmetricKey* GetDefaultPaddingKey() { - return GetPaddingKeyInternal()->get(); -} - -std::unique_ptr CopyDefaultPaddingKey() { - return SymmetricKey::Import(kPaddingKeyAlgorithm, - (*GetPaddingKeyInternal())->key()); -} - -std::unique_ptr 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(&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 -#include - -#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 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 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 +#include +#include +#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* GetPaddingKeyInternal() { + static base::NoDestructor> 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(&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 +#include + +#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 #include +#include #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 applicable_types = std::make_unique(); 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(); @@ -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& 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& 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 termination_reason_; Vector 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 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()); - // If destination is "worker" or "sharedworker" and the - // top-level module fetch flag is set, then set request's mode to - // "same-origin". - // Cross-origin workers are not supported due to security checks in - // AbstractWorker::ResolveURL, so no action needs to be taken here. - // Set up the module script request given request and // options. // @@ -178,6 +172,26 @@ fetch_client_settings_object.GetSecurityOrigin(), options_.CredentialsMode()); + // If destination is "worker" or "sharedworker" and the + // top-level module fetch flag is set, then set request's mode to + // "same-origin". + // + // `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); + } + // ... referrer is referrer, ... 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& 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 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& url_list_via_service_worker) { Vector 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& 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 handle1 = + notifier_.AddConnectionObserver(&observer1, GetTaskRunner()); + std::unique_ptr handle2 = + notifier_.AddConnectionObserver(&observer2, GetTaskRunner()); + std::unique_ptr 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 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::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 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 -#include - -#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 DoRead() { return BaseEndpointChannel::Read(); } - Exception DoWrite(const ByteArray& data) { - return BaseEndpointChannel::Write(data); - } - absl::Time DoGetLastReadTimestamp() { - return BaseEndpointChannel::GetLastReadTimestamp(); - } - - MOCK_METHOD(ExceptionOr, 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 GetConnectionMediumsByPriority() - override { - return GetDiscoveryMediums(); - } - - // Mock adapters for protected non-virtual methods of a base class. - void OnEndpointFound(ClientProxy* client, - std::shared_ptr endpoint) { - BasePcpHandler::OnEndpointFound(client, std::move(endpoint)); - } - void OnEndpointLost(ClientProxy* client, const DiscoveredEndpoint& endpoint) { - BasePcpHandler::OnEndpointLost(client, endpoint); - } - - std::vector GetDiscoveryMediums() { - std::vector 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 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 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 { - protected: - struct MockConnectionListener { - StrictMock> - initiated_cb; - StrictMock> accepted_cb; - StrictMock> - rejected_cb; - StrictMock> - disconnected_cb; - StrictMock> - bandwidth_changed_cb; - }; - struct MockDiscoveryListener { - StrictMock> - endpoint_found_cb; - StrictMock> - endpoint_lost_cb; - StrictMock< - MockFunction> - 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> - SetupConnection(Pipe& pipe_a, Pipe& pipe_b) { // NOLINT - auto channel_a = std::make_unique(&pipe_b, &pipe_a); - auto channel_b = std::make_unique(&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 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(); - 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{ - { - endpoint_id, - info.name, - "service", - medium, - }, - MockContext{flag}, - })); - } - auto other_client = std::make_unique(); - - // 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 -#include -#include - -#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& 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 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 #include #include 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 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(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(origGlyph.fWidth, dstM.fBounds.width()); - int height = std::min(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 #include +#include #include #include @@ -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 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 + bool PostToTransportThread(uintptr_t id, F action) const { + webrtc::MutexLock lock(&lock_); + SctpTransport* transport = RetrieveWhileHoldingLock(id); + if (!transport) { + return false; + } + transport->invoker_.AsyncInvoke( + 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 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(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(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( - 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(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 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(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 GetTransportIdFromSocket( + struct socket* sock) { + absl::optional 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(&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(sconn->sconn_addr)); + ret = reinterpret_cast(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 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 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(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(data), length); - invoker_.AsyncInvoke( - 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( - 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 @@ + @@ -8777,6 +8778,8 @@ + + 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 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_(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_; +}; + +// 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 = std::make_unique(); + 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 #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 task_bar_list_; + base::WeakPtrFactory 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 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 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 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_; + + 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 Benjamin Tan Bert Belder +Brendon Tiszka Burcu Dogan Caitlin Potter Craig Schlenter 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 // NOLINT @@ -340,6 +341,20 @@ DISALLOW_COPY_AND_ASSIGN(SharedMutexGuard); }; +template +class SharedMutexGuardIf final { + public: + SharedMutexGuardIf(SharedMutex* mutex, bool enable_mutex) { + if (enable_mutex) mutex_.emplace(mutex); + } + + private: + base::Optional> 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 array = Handle::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 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 dict(array->element_dictionary(), isolate); std::vector 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::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::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 + 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(node, input_use, MachineRepresentation::kWord32, restriction); + if (lower()) + 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(node, lhs_use, rhs_use, MachineRepresentation::kWord32); if (lower()) 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(node, lhs_use, rhs_use, MachineRepresentation::kWord32, - Type::Unsigned32()); + restriction); if (lower()) ChangeToUint32OverflowOp(node); } else { + Type const restriction = + truncation.IdentifiesZeroAndMinusZero() && + TypeOf(node->InputAt(0)).Maybe(Type::MinusZero()) + ? Type::Signed32OrMinusZero() + : Type::Signed32(); VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kWord32, - Type::Signed32()); + restriction); if (lower()) 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(node, UseInfo::TruncatingWord32(), - MachineRepresentation::kWord32, Type::Signed32()); - if (lower()) { - LowerToCheckedInt32Mul(node, truncation, input0_type, - input1_type); - } + VisitForCheckedInt32Mul(node, truncation, input0_type, + input1_type, + UseInfo::TruncatingWord32()); return; } } if (hint == NumberOperationHint::kSignedSmall || hint == NumberOperationHint::kSigned32) { - VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), - MachineRepresentation::kWord32, Type::Signed32()); - if (lower()) { - LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type); - } + VisitForCheckedInt32Mul(node, truncation, input0_type, input1_type, + CheckedUseInfoAsWord32FromHint(hint)); return; } @@ -3896,7 +3920,6 @@ void RepresentationSelector::SetOutput( 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(index), static_cast(length())); DCHECK(!is_the_hole(index)); return ReadField(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(index), static_cast(length())); int offset = kHeaderSize + index * kDoubleSize; // Bug(v8:8875): Doubles may be unaligned. return base::ReadUnalignedValue(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(index), static_cast(length())); int offset = kHeaderSize + index * kDoubleSize; if (std::isnan(value)) { WriteField(offset, std::numeric_limits::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(index), static_cast(length())); int offset = kHeaderSize + index * kDoubleSize; base::WriteUnalignedValue(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(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::New(Isolate* isolate, Handle map, Handle locales, Handle 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 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(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(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 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; + // 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 ExpectedTransitionKey(); inline Handle 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 DeleteObjectProperty( - Isolate* isolate, Handle receiver, Handle key, - LanguageMode language_mode); + V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe + DeleteObjectProperty(Isolate* isolate, Handle receiver, + Handle key, LanguageMode language_mode); V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle SetObjectProperty(Isolate* isolate, Handle object, Handle 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, + Handle name) { + InternalIndex descriptor(map->NumberOfOwnDescriptors()); + + Handle 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 target = target_maps[i]; + PropertyDetails details = + target->instance_descriptors(isolate) + .GetDetails(descriptor); + Handle 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 receiver, Handle 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 receiver_map(receiver->map(), isolate); if (receiver_map->IsSpecialReceiverMap()) return false; + DCHECK(receiver_map->IsJSObjectMap()); + if (!raw_key->IsUniqueName()) return false; Handle key = Handle::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 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::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 js_obj = Handle::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 receiver = args.at(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::max()); liftoff::LoadInternal(this, dst, src_addr, offset_reg, static_cast(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::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(std::numeric_limits::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::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::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::max() || !base::IsInBounds(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::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 maybe_throttle, + std::vector>* 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* 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(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 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 +{ +public: + explicit PdfWebContentsLifetimeHelper(content::WebContents *web_contents) + : web_contents_(web_contents) + {} + + base::WeakPtr GetWeakPtr() + { + return weak_factory_.GetWeakPtr(); + } + + void NavigateIFrameToPlaceholder(const content::OpenURLParams &url_params) + { + web_contents_->OpenURL(url_params); + } + +private: + friend class content::WebContentsUserData; + + content::WebContents* const web_contents_; + base::WeakPtrFactory 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 +PDFIFrameNavigationThrottleQt::MaybeCreateThrottleFor(content::NavigationHandle *handle) +{ + if (handle->IsInMainFrame()) + return nullptr; + return std::make_unique(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 &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 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 &plugins); + void LoadPlaceholderHTML(); + + base::WeakPtrFactory 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 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 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(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 +#include + +extern void *GetQtXDisplay(); +#endif // BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) + namespace ui { namespace { @@ -86,6 +99,11 @@ std::unique_ptr input_controller_; std::unique_ptr overlay_manager_; +#if BUILDFLAG(USE_XKBCOMMON) && defined(USE_X11) + XkbEvdevCodes m_xkbEvdevCodeConverter; +#endif + std::unique_ptr 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(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(); + } else { + m_keyboardLayoutEngine = std::make_unique(m_xkbEvdevCodeConverter); + m_keyboardLayoutEngine->SetCurrentLayoutByName(layout); + } +#else + m_keyboardLayoutEngine = std::make_unique(); +#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 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&)> callback) override; - int SubscribePermissionStatusChange( + content::PermissionControllerDelegate::SubscriptionId SubscribePermissionStatusChange( content::PermissionType permission, content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, const base::RepeatingCallback callback) override; - void UnsubscribePermissionStatusChange(int subscription_id) override; + void UnsubscribePermissionStatusChange(content::PermissionControllerDelegate::SubscriptionId subscription_id) override; private: QHash, bool> m_permissions; @@ -118,9 +118,9 @@ }; std::vector m_requests; std::vector m_multiRequests; - std::map m_subscribers; + std::map 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::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 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 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 PluginPlaceholderQt::GetV8Handle(v8::Isolate* isolate) -{ - return gin::CreateHandle(isolate, this).ToV8(); -} - -gin::ObjectTemplateBuilder PluginPlaceholderQt::GetObjectTemplateBuilder(v8::Isolate* isolate) -{ - return gin::Wrappable::GetObjectTemplateBuilder(isolate) - .SetMethod( - "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 -{ -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 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 RenderWidgetHostViewQt::GetKeyboardLayoutMap() +{ + return ui::GenerateDomKeyboardLayoutMap(); +} + void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view) { DCHECK(!static_cast(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 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 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::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 &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 m_loadingErrorFrameList; QScopedPointer m_faviconManager; QScopedPointer m_findTextHelper; SavePageInfo m_savePageInfo; @@ -242,9 +240,17 @@ int m_desktopStreamCount = 0; mutable bool m_pendingUrlUpdate = false; - QMap 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 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(base::ThreadPriority::DISPLAY); + s_gpuProcess = std::make_unique(base::ThreadPriority::NORMAL); auto gpuInit = std::make_unique(); 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(WebEngineError::CertificateErrorDomain) == static_cast(QQuickWebEngineView::CertificateErrorDomain)); Q_STATIC_ASSERT(static_cast(WebEngineError::DnsErrorDomain) == static_cast(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 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 &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 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> 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("" + "Page with a favicon and an icon" + ""); 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 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 @@ }
+

anchor

bla00

bla01

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 @@ " " + ""); 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 -#include -#include - -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 @@ page1 -

page1

+ 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 @@ } +
page2 anchor
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 @@ + + + page5 + + + + + +
here is the anchor
+ + 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 @@ + + + page6 + + + + + + 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 @@ + + + page6 + + + + + + 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 @@ + + + Page with js navigation in the end of document to anchor within the page + + + + +
here is the anchor
+ + + 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 #include +#include #include #include @@ -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 SignalsOrderOnce({ LoadStarted, LoadSucceeded}); +static const QList SignalsOrderTwice({ LoadStarted, LoadSucceeded, LoadStarted, LoadSucceeded }); +static const QList SignalsOrderOnceFailure({ LoadStarted, LoadFailed }); +static const QList SignalsOrderTwiceWithFailure({ LoadStarted, LoadSucceeded, LoadStarted, LoadFailed }); + +class TestPage : public QWebEnginePage +{ +public: + QSet blacklist; + int navigationRequestCount = 0; + QList signalsOrder; + QList 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("url"); - QTest::addColumn("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>("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, 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("url"); + QTest::addColumn("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("initialUrl"); + QTest::addColumn("rejectedUrl"); + QTest::addColumn("expectedNavigations"); + QTest::addColumn>("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, 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("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("imageFromServer"); + QTest::addColumn("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 = "" + "%1" "
" + "" + ""; + view.page()->setHtml(QString(html).arg(imageUrl.isEmpty() ? "" : "")); QTRY_COMPARE(loadFinishedSpy.size(), 1); - QVERIFY(loadFinishedSpy[0][0].toBool()); - - loadStartedSpy.clear(); - loadFinishedSpy.clear(); - loadProgressSpy.clear(); - view.page()->setHtml("" - "" - "" - "" - ""); - - 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("" - "" - "" - ""); - 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 @@ ../../shared/data/loadprogress/page2.html ../../shared/data/loadprogress/page3.html ../../shared/data/loadprogress/page4.html + ../../shared/data/loadprogress/page5.html + ../../shared/data/loadprogress/page6.html + ../../shared/data/loadprogress/page7.html + ../../shared/data/loadprogress/page8.html ../../shared/data/loadprogress/downloadable.tar.gz 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 @@ + + + + + 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("Redirect1"); + r->sendResponse(307); // Internal server redirect + } else if (r->requestPath() == "/redirect2.html") { + r->setResponseHeader("Location", server.url("/content.html").toEncoded()); + r->setResponseBody("Redirect2"); + 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 @@ resources/user.css resources/image.png resources/pasteimage.html + resources/redirect.html resources/reload.html resources/style.css resources/test1.html 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("locale"); + QTest::addColumn("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")); }