Base-Commit: 58c11ad487f8a237cf0ac71cc3e818b52db150df Branch: 140-based diff --git a/chromium/chrome/browser/devtools/protocol/target_handler.cc b/chromium/chrome/browser/devtools/protocol/target_handler.cc index 222bcd4023a..938ba631014 100644 --- src/3rdparty/chromium/chrome/browser/devtools/protocol/target_handler.cc +++ src/3rdparty/chromium/chrome/browser/devtools/protocol/target_handler.cc @@ -142,12 +142,17 @@ protocol::Response TargetHandler::CreateTarget( gurl = GURL(url::kAboutBlankURL); } - if (!is_trusted_ && gurl.SchemeIs(content::kChromeUIUntrustedScheme)) { + GURL inner_url = gurl; + if (gurl.SchemeIs(content::kViewSourceScheme)) { + inner_url = GURL(gurl.GetContent()); + } + + if (!is_trusted_ && inner_url.SchemeIs(content::kChromeUIUntrustedScheme)) { return protocol::Response::ServerError( "Refusing to create a target with the specified URL"); } - if (!may_read_local_files_ && gurl.SchemeIsFile()) { + if (!may_read_local_files_ && inner_url.SchemeIsFile()) { return protocol::Response::ServerError( "Creating a target with a local URL is not allowed"); } diff --git a/chromium/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc b/chromium/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc index 5821d749be0..d2a6c657668 100644 --- src/3rdparty/chromium/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc +++ src/3rdparty/chromium/components/autofill/core/browser/form_import/addresses/address_profile_save_manager.cc @@ -23,12 +23,21 @@ namespace { // with additional optional information. // This function adds the imported profile as a candidate. This is only done // after the user decision to incorporate manual edits. -void AddMultiStepComplementCandidate(FormDataImporter* form_data_importer, - const AutofillProfile& profile, - const url::Origin& origin) { +void MaybeAddMultiStepComplementCandidate(FormDataImporter* form_data_importer, + const AutofillProfile& profile, + const url::Origin& origin) { if (!form_data_importer) { return; } + MultiStepImportMerger& import_merger = + form_data_importer->GetAddressFormDataImporter() + .multi_step_import_merger(); + // Avoid adding profiles that don't match the currently tracked origin. It is + // possible that the user has navigated away since the import prompt was shown + // and submitted an (incomplete) address on the new origin in the meantime. + if (import_merger.origin().has_value() && import_merger.origin() != origin) { + return; + } // Metrics depending on `import_process.import_metadata()` are collected // for the `confirmed_import_candidate`. E.g. whether the removal of an // invalid phone number made the import possible. Just like regular updates, @@ -36,8 +45,8 @@ void AddMultiStepComplementCandidate(FormDataImporter* form_data_importer, // The `import_metadata` is thus initialized to a neutral element. ProfileImportMetadata import_metadata; import_metadata.origin = origin; - form_data_importer->AddMultiStepImportCandidate(profile, import_metadata, - /*is_imported=*/true); + import_merger.AddMultiStepImportCandidate(profile, import_metadata, + /*is_imported=*/true); } } // namespace @@ -141,9 +150,9 @@ void AddressProfileSaveManager::FinalizeProfileImport( const std::optional& confirmed_import_candidate = import_process->confirmed_import_candidate(); DCHECK(confirmed_import_candidate); - AddMultiStepComplementCandidate(client_->GetFormDataImporter(), - *confirmed_import_candidate, - import_process->import_metadata().origin); + MaybeAddMultiStepComplementCandidate(client_->GetFormDataImporter(), + *confirmed_import_candidate, + import_process->import_metadata().origin); } ClearPendingImport(std::move(import_process)); diff --git a/chromium/components/facilitated_payments/core/browser/payment_link_manager.cc b/chromium/components/facilitated_payments/core/browser/payment_link_manager.cc index 5e3b8a848d7..e0d61796271 100644 --- src/3rdparty/chromium/components/facilitated_payments/core/browser/payment_link_manager.cc +++ src/3rdparty/chromium/components/facilitated_payments/core/browser/payment_link_manager.cc @@ -58,6 +58,9 @@ void PaymentLinkManager::TriggerPaymentLinkPushPayment( const GURL& payment_link_url, const GURL& page_url, ukm::SourceId ukm_source_id) { + if (ui_state_ != UiState::kHidden) { + return; + } payment_flow_triggered_timestamp_ = base::TimeTicks::Now(); ukm_source_id_ = ukm_source_id; LogPaymentLinkDetected(ukm_source_id_); diff --git a/chromium/components/media_router/browser/presentation/controller_presentation_service_delegate_impl.cc b/chromium/components/media_router/browser/presentation/controller_presentation_service_delegate_impl.cc index 44a05b2ac37..439d3e2bb3f 100644 --- src/3rdparty/chromium/components/media_router/browser/presentation/controller_presentation_service_delegate_impl.cc +++ src/3rdparty/chromium/components/media_router/browser/presentation/controller_presentation_service_delegate_impl.cc @@ -511,6 +511,13 @@ void ControllerPresentationServiceDelegateImpl::ReconnectPresentation( return; } + if (!std::ranges::all_of(presentation_urls, IsValidPresentationUrl)) { + std::move(error_cb).Run( + PresentationError(PresentationErrorType::NO_PRESENTATION_FOUND, + "Invalid presentation URL.")); + return; + } + auto* local_presentation_manager = LocalPresentationManagerFactory::GetOrCreateForWebContents( &GetWebContents()); diff --git a/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc b/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc index 3853370e870..3aeb0ae5e97 100644 --- src/3rdparty/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc +++ src/3rdparty/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc @@ -136,8 +136,7 @@ void HttpAuthManagerImpl::OnLoginSuccesfull() { return; } - if (form_manager_->GetFormFetcher()->GetState() == - FormFetcher::State::WAITING) { + if (!form_manager_->IsFetchCompleted()) { // We have a provisional save manager, but it didn't finish matching yet. // We just give up. return; diff --git a/chromium/components/password_manager/core/browser/password_form_manager.cc b/chromium/components/password_manager/core/browser/password_form_manager.cc index decea06040b..f568168cfea 100644 --- src/3rdparty/chromium/components/password_manager/core/browser/password_form_manager.cc +++ src/3rdparty/chromium/components/password_manager/core/browser/password_form_manager.cc @@ -444,6 +444,10 @@ bool PasswordFormManager::IsBlocklisted() const { return form_fetcher_->IsBlocklisted() || newly_blocklisted_; } +bool PasswordFormManager::IsFetchCompleted() const { + return form_fetcher_->GetState() != FormFetcher::State::WAITING; +} + bool PasswordFormManager::IsMovableToAccountStore() const { if (!client_->GetPasswordFeatureManager()->IsAccountStorageEnabled()) { return false; diff --git a/chromium/components/password_manager/core/browser/password_form_manager.h b/chromium/components/password_manager/core/browser/password_form_manager.h index dc9e1fafda0..c25ee454fbe 100644 --- src/3rdparty/chromium/components/password_manager/core/browser/password_form_manager.h +++ src/3rdparty/chromium/components/password_manager/core/browser/password_form_manager.h @@ -196,6 +196,7 @@ class PasswordFormManager : public PasswordFormManagerForUI, base::span GetInteractionsStats() const override; base::span GetInsecureCredentials() const override; bool IsBlocklisted() const override; + bool IsFetchCompleted() const override; bool IsMovableToAccountStore() const override; void Save() override; diff --git a/chromium/components/password_manager/core/browser/password_form_manager_for_ui.h b/chromium/components/password_manager/core/browser/password_form_manager_for_ui.h index 67e11d5910b..2692755df1e 100644 --- src/3rdparty/chromium/components/password_manager/core/browser/password_form_manager_for_ui.h +++ src/3rdparty/chromium/components/password_manager/core/browser/password_form_manager_for_ui.h @@ -57,6 +57,9 @@ class PasswordFormManagerForUI { // Determines if the user opted to 'never remember' passwords for this form. virtual bool IsBlocklisted() const = 0; + // Returns true if the fetch of credentials from the store is completed. + virtual bool IsFetchCompleted() const = 0; + // Determines whether the submitted credentials returned by // GetPendingCredentials() can be moved to the signed in account store. // Returns true if the submitted credentials are stored in the profile store diff --git a/chromium/components/password_manager/core/browser/password_generation_manager.cc b/chromium/components/password_manager/core/browser/password_generation_manager.cc index 8e9ca52f7d6..dad4c68000b 100644 --- src/3rdparty/chromium/components/password_manager/core/browser/password_generation_manager.cc +++ src/3rdparty/chromium/components/password_manager/core/browser/password_generation_manager.cc @@ -62,6 +62,7 @@ class PasswordDataForUI : public PasswordFormManagerForUI { base::span GetInteractionsStats() const override; base::span GetInsecureCredentials() const override; bool IsBlocklisted() const override; + bool IsFetchCompleted() const override; bool IsMovableToAccountStore() const override; void Save() override; bool IsUpdateAffectingPasswordsStoredInTheGoogleAccount() const override; @@ -148,6 +149,10 @@ bool PasswordDataForUI::IsBlocklisted() const { return false; } +bool PasswordDataForUI::IsFetchCompleted() const { + return true; +} + bool PasswordDataForUI::IsMovableToAccountStore() const { // This is irrelevant for the generation conflict resolution bubble. return false; diff --git a/chromium/components/password_manager/core/browser/password_manager.cc b/chromium/components/password_manager/core/browser/password_manager.cc index 0c71b406013..862d4c2e9bb 100644 --- src/3rdparty/chromium/components/password_manager/core/browser/password_manager.cc +++ src/3rdparty/chromium/components/password_manager/core/browser/password_manager.cc @@ -996,8 +996,7 @@ bool PasswordManager::HaveFormManagersReceivedData( } for (const auto& form_manager : password_form_cache_.GetFormManagers()) { if (form_manager->GetDriver().get() == driver && - form_manager->GetFormFetcher()->GetState() == - FormFetcher::State::WAITING) { + !form_manager->IsFetchCompleted()) { return false; } } @@ -1168,8 +1167,7 @@ PasswordFormManager* PasswordManager::ProvisionallySaveForm( } } - if (is_manual_fallback && matched_manager->GetFormFetcher()->GetState() == - FormFetcher::State::WAITING) { + if (is_manual_fallback && !matched_manager->IsFetchCompleted()) { // In case of manual fallback, the form manager has to be ready for saving. return nullptr; } @@ -1416,8 +1414,7 @@ bool PasswordManager::IsAutomaticSavePromptAvailable( return false; } - if (submitted_manager->GetFormFetcher()->GetState() == - FormFetcher::State::WAITING) { + if (!submitted_manager->IsFetchCompleted()) { // We have a provisional save manager, but it didn't finish matching yet. // We just give up. RecordProvisionalSaveFailure( @@ -1895,6 +1892,10 @@ void PasswordManager::ShowManualFallbackForSaving( return; } + if (!form_manager->IsFetchCompleted()) { + return; + } + if (!form_manager->is_submitted()) { return; } diff --git a/chromium/components/saved_tab_groups/internal/shared_tab_group_data_sync_bridge.cc b/chromium/components/saved_tab_groups/internal/shared_tab_group_data_sync_bridge.cc index 8d333aeedb6..11ef66efadd 100644 --- src/3rdparty/chromium/components/saved_tab_groups/internal/shared_tab_group_data_sync_bridge.cc +++ src/3rdparty/chromium/components/saved_tab_groups/internal/shared_tab_group_data_sync_bridge.cc @@ -1220,7 +1220,8 @@ SharedTabGroupDataSyncBridge::AddGroupToLocalStorage( CHECK(specifics.has_tab_group()); - if (!model_wrapper_->GetGroup(group_guid)) { + const SavedTabGroup* existing_group = model_wrapper_->GetGroup(group_guid); + if (!existing_group) { // This is a new remotely created group. Add the group from sync into local // storage. Note that on some platforms new remote groups may open in the // tab strip, and associate its local group ID. This is currently prevented @@ -1234,20 +1235,6 @@ SharedTabGroupDataSyncBridge::AddGroupToLocalStorage( return std::nullopt; } - // Update the existing group with remote data. - const SavedTabGroup* existing_group = - model_wrapper_->MergeRemoteGroupMetadata( - group_guid, base::UTF8ToUTF16(specifics.tab_group().title()), - SyncColorToTabGroupColor(specifics.tab_group().color()), - /*position=*/std::nullopt, - /*creator_cache_guid=*/std::nullopt, - /*last_updater_cache_guid=*/std::nullopt, - TimeFromWindowsEpochMicros( - specifics.update_time_windows_epoch_micros()), - collaboration_metadata.last_updated_by()); - CHECK(existing_group); - - // TODO(crbug.com/381540386): move this check before the merge. if (existing_group->collaboration_id() != collaboration_metadata.collaboration_id()) { // Shared tab groups should never change collaboration IDs. @@ -1256,6 +1243,17 @@ SharedTabGroupDataSyncBridge::AddGroupToLocalStorage( kSharedTabGroupUnexpectedCollaborationIdForGroup); } + // Update the existing group with remote data. + existing_group = model_wrapper_->MergeRemoteGroupMetadata( + group_guid, base::UTF8ToUTF16(specifics.tab_group().title()), + SyncColorToTabGroupColor(specifics.tab_group().color()), + /*position=*/std::nullopt, + /*creator_cache_guid=*/std::nullopt, + /*last_updater_cache_guid=*/std::nullopt, + TimeFromWindowsEpochMicros(specifics.update_time_windows_epoch_micros()), + collaboration_metadata.last_updated_by()); + CHECK(existing_group); + // Create new specifics in case some fields were merged. sync_pb::SharedTabGroupDataSpecifics updated_specifics = SharedTabGroupToSpecifics(*existing_group); diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h index 5368808c7a9..5b49139d512 100644 --- src/3rdparty/chromium/content/browser/bad_message.h +++ src/3rdparty/chromium/content/browser/bad_message.h @@ -359,6 +359,7 @@ enum BadMessageReason { RFH_CRASH_REPORT_STORAGE_ALREADY_INITIALIZED = 331, RFH_CREATE_NEW_WINDOW_FROM_SANDBOXED_FRAME = 332, DT_DUPLICATE_CHILD_TARGET_CREATED = 333, + RFH_MODAL_DIALOG_FROM_SANDBOXED_FRAME = 334, // Please add new elements here. The naming convention is abbreviated class // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the // reason. After making changes, you MUST update enums.xml by running: diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc index a6370451fc7..f23cb1ea559 100644 --- src/3rdparty/chromium/content/browser/devtools/devtools_agent_host_impl.cc +++ src/3rdparty/chromium/content/browser/devtools/devtools_agent_host_impl.cc @@ -521,7 +521,7 @@ std::string DevToolsAgentHostImpl::GetSubtype() { } void DevToolsAgentHostImpl::NotifyCreated() { - DCHECK(!base::Contains(GetDevtoolsInstances(), id_)); + CHECK(!base::Contains(GetDevtoolsInstances(), id_)); GetDevtoolsInstances()[id_] = this; for (auto& observer : GetDevtoolsObservers()) observer.DevToolsAgentHostCreated(this); diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc index 16a9ad3f28a..00900ee183c 100644 --- src/3rdparty/chromium/content/browser/devtools/protocol/page_handler.cc +++ src/3rdparty/chromium/content/browser/devtools/protocol/page_handler.cc @@ -844,7 +844,13 @@ void PageHandler::Navigate(const std::string& url, Response::ServerError("Cannot navigate to invalid URL")); return; } - if (gurl.SchemeIsFile() && !may_read_local_files_) { + + GURL inner_url = gurl; + if (gurl.SchemeIs(content::kViewSourceScheme)) { + inner_url = GURL(gurl.GetContent()); + } + + if (inner_url.SchemeIsFile() && !may_read_local_files_) { callback->sendFailure( Response::ServerError("Navigating to local URL is not allowed")); return; @@ -857,8 +863,8 @@ void PageHandler::Navigate(const std::string& url, // chrome-untrusted:// WebUIs might perform high-priviledged actions on // navigation, disallow navigation to them unless the client is trusted. - if ((gurl.SchemeIs(kChromeUIUntrustedScheme) || - gurl.SchemeIs(kChromeDevToolsScheme)) && + if ((inner_url.SchemeIs(kChromeUIUntrustedScheme) || + inner_url.SchemeIs(kChromeDevToolsScheme)) && !is_trusted_) { callback->sendFailure(Response::ServerError( "Navigating to a URL with a privileged scheme is not allowed")); diff --git a/chromium/content/browser/devtools/protocol/storage_handler.cc b/chromium/content/browser/devtools/protocol/storage_handler.cc index 039f2918bc4..6b077cd5cff 100644 --- src/3rdparty/chromium/content/browser/devtools/protocol/storage_handler.cc +++ src/3rdparty/chromium/content/browser/devtools/protocol/storage_handler.cc @@ -1076,87 +1076,26 @@ void StorageHandler::OnInterestGroupAccessed( bid, bid_currency.CopyAsOptional(), auction_id.CopyAsOptional()); } -namespace { -void SendGetInterestGroup( - std::unique_ptr callback, - std::optional storage_group) { - if (!storage_group) { - callback->sendFailure(Response::ServerError("Interest group not found")); - return; - } - - base::Value::Dict ig_serialization = - SerializeInterestGroupForDevtools(storage_group.value()->interest_group); - - // "joiningOrigin" is in StorageInterestGroup, not InterestGroup, so it needs - // to be added in separately. - ig_serialization.Set("joiningOrigin", - storage_group.value()->joining_origin.Serialize()); - callback->sendSuccess( - std::make_unique(std::move(ig_serialization))); -} - -} // namespace - void StorageHandler::GetInterestGroupDetails( const std::string& owner_origin_string, const std::string& name, std::unique_ptr callback) { - if (!storage_partition_) { - callback->sendFailure(Response::InternalError()); - return; - } - - InterestGroupManagerImpl* manager = static_cast( - storage_partition_->GetInterestGroupManager()); - if (!manager) { - callback->sendFailure( - Response::ServerError("Interest group storage is disabled")); - return; - } - - GURL owner_origin_url(owner_origin_string); - if (!owner_origin_url.is_valid()) { - callback->sendFailure(Response::ServerError("Invalid Owner Origin")); - return; - } - url::Origin owner_origin = url::Origin::Create(GURL(owner_origin_string)); - DCHECK(!owner_origin.opaque()); - - manager->GetInterestGroup( - owner_origin, name, - base::BindOnce(&SendGetInterestGroup, std::move(callback))); + // TODO(crbug.com/496189510): Remove this completely once the DevTools + // frontend usage is gone. + callback->sendSuccess(std::make_unique()); } Response StorageHandler::SetInterestGroupTracking(bool enable) { - interest_group_tracking_enabled_ = enable; - return SetInterestGroupTrackingInternal(storage_partition_, enable); + // TODO(crbug.com/496189510): Remove this completely once the DevTools + // frontend usage is gone. + return Response::Success(); } Response StorageHandler::SetInterestGroupTrackingInternal( StoragePartition* storage_partition, bool enable) { - if (!storage_partition) { - return Response::InternalError(); - } - - InterestGroupManagerImpl* manager = static_cast( - storage_partition->GetInterestGroupManager()); - if (!manager) { - return Response::ServerError("Interest group storage is disabled."); - } - - if (enable) { - // Only add if we are not already registered as an observer. We only - // observe the interest group manager, so if we're observing anything then - // we are already registered. - if (!InterestGroupManagerImpl::InterestGroupObserver::IsInObserverList()) { - manager->AddInterestGroupObserver(this); - } - } else { - // Removal doesn't care if we are not registered. - manager->RemoveInterestGroupObserver(this); - } + // TODO(crbug.com/496189510): Remove this completely once the DevTools + // frontend usage is gone. return Response::Success(); } diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc index 66f4589d0f0..7cd54e41c1d 100644 --- src/3rdparty/chromium/content/browser/devtools/protocol/target_handler.cc +++ src/3rdparty/chromium/content/browser/devtools/protocol/target_handler.cc @@ -952,7 +952,7 @@ void TargetHandler::TargetInfoChanged(DevToolsAgentHost* host) { void TargetHandler::AutoAttacherDestroyed(TargetAutoAttacher* auto_attacher) { auto throttles = throttles_; - for (Throttle* throttle : throttles_) { + for (Throttle* throttle : throttles) { if (throttle->auto_attacher() == auto_attacher) { throttle->Clear(); } diff --git a/chromium/content/browser/file_system/file_system_manager_impl.cc b/chromium/content/browser/file_system/file_system_manager_impl.cc index 89859d72f6b..823c65779ed 100644 --- src/3rdparty/chromium/content/browser/file_system/file_system_manager_impl.cc +++ src/3rdparty/chromium/content/browser/file_system/file_system_manager_impl.cc @@ -19,6 +19,7 @@ #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/file_system/browser_file_system_helper.h" +#include "content/common/features.h" #include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver_set.h" @@ -211,20 +212,25 @@ void FileSystemManagerImpl::Open(const url::Origin& origin, OpenCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + url::Origin origin_to_check = origin; + if (base::FeatureList::IsEnabled( + features::kEnforceFileSystemManagerOpenOrigin)) { + origin_to_check = receivers_.current_context().origin(); + } + GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce( &ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin, base::Unretained(ChildProcessSecurityPolicyImpl::GetInstance()), - process_id_, origin), + process_id_, origin_to_check), base::BindOnce(&FileSystemManagerImpl::ContinueOpen, - weak_factory_.GetWeakPtr(), origin, file_system_type, + weak_factory_.GetWeakPtr(), file_system_type, receivers_.GetBadMessageCallback(), std::move(callback), receivers_.current_context())); } void FileSystemManagerImpl::ContinueOpen( - const url::Origin& origin, blink::mojom::FileSystemType file_system_type, mojo::ReportBadMessageCallback bad_message_callback, OpenCallback callback, diff --git a/chromium/content/browser/file_system/file_system_manager_impl.h b/chromium/content/browser/file_system/file_system_manager_impl.h index b31b7c42171..2381fb56c97 100644 --- src/3rdparty/chromium/content/browser/file_system/file_system_manager_impl.h +++ src/3rdparty/chromium/content/browser/file_system/file_system_manager_impl.h @@ -137,8 +137,7 @@ class CONTENT_EXPORT FileSystemManagerImpl struct WriteSyncCallbackEntry; struct ReadDirectorySyncCallbackEntry; - void ContinueOpen(const url::Origin& origin, - blink::mojom::FileSystemType file_system_type, + void ContinueOpen(blink::mojom::FileSystemType file_system_type, mojo::ReportBadMessageCallback bad_message_callback, OpenCallback callback, const blink::StorageKey& storage_key, diff --git a/chromium/content/browser/interest_group/auction_url_loader_factory_proxy.cc b/chromium/content/browser/interest_group/auction_url_loader_factory_proxy.cc index fcbb9507a70..27f4b174cbc 100644 --- src/3rdparty/chromium/content/browser/interest_group/auction_url_loader_factory_proxy.cc +++ src/3rdparty/chromium/content/browser/interest_group/auction_url_loader_factory_proxy.cc @@ -38,7 +38,9 @@ #include "net/cookies/site_for_cookies.h" #include "net/http/http_request_headers.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/data_element.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/resource_request_body.h" #include "services/network/public/mojom/cookie_manager.mojom-shared.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "third_party/blink/public/common/features.h" @@ -181,6 +183,26 @@ void AuctionURLLoaderFactoryProxy::CreateLoaderAndStart( } } + if (url_request.method != net::HttpRequestHeaders::kGetMethod) { + // If the request is not a GET and not a trusted signals POST, disallow the + // request. + if (url_request.method != net::HttpRequestHeaders::kPostMethod || + !is_trusted_signals_request) { + is_request_allowed = false; + } else { + // For trusted signals POSTs only allow request bodies that contain a + // single byte element, since that's all the auction worklet code should + // produce. The most important thing here is to disallow attempts to + // upload files. + if (url_request.request_body && + (url_request.request_body->elements()->size() != 1u || + url_request.request_body->elements()->front().type() != + network::DataElement::Tag::kBytes)) { + is_request_allowed = false; + } + } + } + if (!is_request_allowed) { // Debugging for https://crbug.com/1448458 SCOPED_CRASH_KEY_STRING32("fledge", "req-accept", accept_header); diff --git a/chromium/content/browser/loader/content_security_notifier.cc b/chromium/content/browser/loader/content_security_notifier.cc index 1c30ab73a0a..938174ec625 100644 --- src/3rdparty/chromium/content/browser/loader/content_security_notifier.cc +++ src/3rdparty/chromium/content/browser/loader/content_security_notifier.cc @@ -27,11 +27,11 @@ void ContentSecurityNotifier::NotifyContentWithCertificateErrorsDisplayed() { } void ContentSecurityNotifier::NotifyInsecureContentRan( - const GURL& origin, - const GURL& insecure_url) { + const GURL& insecure_url, + blink::mojom::ContentSecurityNotifier::InsecureContentOrigin origin_type) { auto* render_frame_host = RenderFrameHostImpl::FromID(render_frame_host_id_); if (render_frame_host) { - render_frame_host->OnDidRunInsecureContent(origin, insecure_url); + render_frame_host->OnDidRunInsecureContent(insecure_url, origin_type); } } diff --git a/chromium/content/browser/loader/content_security_notifier.h b/chromium/content/browser/loader/content_security_notifier.h index 0417eecd0a1..a41ea0c5c5b 100644 --- src/3rdparty/chromium/content/browser/loader/content_security_notifier.h +++ src/3rdparty/chromium/content/browser/loader/content_security_notifier.h @@ -26,8 +26,10 @@ class ContentSecurityNotifier final // blink::mojom::ContentSecurityNotifier implementation. void NotifyContentWithCertificateErrorsRan() override; void NotifyContentWithCertificateErrorsDisplayed() override; - void NotifyInsecureContentRan(const GURL& origin, - const GURL& insecure_url) override; + void NotifyInsecureContentRan( + const GURL& insecure_url, + blink::mojom::ContentSecurityNotifier::InsecureContentOrigin origin_type) + override; private: const GlobalRenderFrameHostId render_frame_host_id_; diff --git a/chromium/content/browser/loader/subresource_proxying_url_loader.cc b/chromium/content/browser/loader/subresource_proxying_url_loader.cc index 4de4b610db2..d2a87af03d0 100644 --- src/3rdparty/chromium/content/browser/loader/subresource_proxying_url_loader.cc +++ src/3rdparty/chromium/content/browser/loader/subresource_proxying_url_loader.cc @@ -6,6 +6,7 @@ #include "content/browser/browsing_topics/browsing_topics_url_loader_interceptor.h" #include "content/browser/interest_group/ad_auction_url_loader_interceptor.h" +#include "mojo/public/cpp/bindings/message.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/early_hints.mojom.h" @@ -61,6 +62,12 @@ void SubresourceProxyingURLLoader::FollowRedirect( const net::HttpRequestHeaders& modified_headers, const net::HttpRequestHeaders& modified_cors_exempt_headers, const std::optional& new_url) { + if (!redirect_pending_) { + mojo::ReportBadMessage("Unexpected FollowRedirect"); + return; + } + redirect_pending_ = false; + std::vector new_removed_headers = removed_headers; net::HttpRequestHeaders new_modified_headers = modified_headers; @@ -87,6 +94,11 @@ void SubresourceProxyingURLLoader::OnReceiveResponse( network::mojom::URLResponseHeadPtr head, mojo::ScopedDataPipeConsumerHandle body, std::optional cached_metadata) { + // Reset the redirect state. While it's unclear if a redirect can genuinely + // be pending at this point, we clear it to be robust against variations + // in URLLoader behavior (e.g., notifications of failures during redirects). + redirect_pending_ = false; + for (auto& interceptor : interceptors_) { interceptor->OnReceiveResponse(head); } @@ -98,6 +110,8 @@ void SubresourceProxyingURLLoader::OnReceiveResponse( void SubresourceProxyingURLLoader::OnReceiveRedirect( const net::RedirectInfo& redirect_info, network::mojom::URLResponseHeadPtr head) { + redirect_pending_ = true; + for (auto& interceptor : interceptors_) { interceptor->OnReceiveRedirect(redirect_info, head); } @@ -120,6 +134,11 @@ void SubresourceProxyingURLLoader::OnTransferSizeUpdated( void SubresourceProxyingURLLoader::OnComplete( const network::URLLoaderCompletionStatus& status) { + // Reset the redirect state. While it's unclear if a redirect can genuinely + // be pending at this point, we clear it to be robust against variations + // in URLLoader behavior (e.g., notifications of failures during redirects). + redirect_pending_ = false; + forwarding_client_->OnComplete(status); } diff --git a/chromium/content/browser/loader/subresource_proxying_url_loader.h b/chromium/content/browser/loader/subresource_proxying_url_loader.h index 820e65c9715..6636a5cf658 100644 --- src/3rdparty/chromium/content/browser/loader/subresource_proxying_url_loader.h +++ src/3rdparty/chromium/content/browser/loader/subresource_proxying_url_loader.h @@ -114,6 +114,10 @@ class CONTENT_EXPORT SubresourceProxyingURLLoader std::vector> interceptors_; mojo::Receiver client_receiver_{this}; + + // Whether a redirect is currently pending. If true, the next call from the + // renderer should be FollowRedirect(). + bool redirect_pending_ = false; }; } // namespace content diff --git a/chromium/content/browser/renderer_host/code_cache_host_impl.cc b/chromium/content/browser/renderer_host/code_cache_host_impl.cc index d95cba73aac..a2221118f04 100644 --- src/3rdparty/chromium/content/browser/renderer_host/code_cache_host_impl.cc +++ src/3rdparty/chromium/content/browser/renderer_host/code_cache_host_impl.cc @@ -420,7 +420,15 @@ std::optional CodeCacheHostImpl::GetSecondaryKeyForCodeCache( return std::nullopt; } - // Case 3: process_lock_url is used to enfore site-isolation in code caches. + // Case 3: PDF processes and origin-restricted sandboxed iframes should not + // have access to the code cache of their hosting origins. PDF processes are + // less trusted, and sandboxed iframes should be treated as having opaque + // origins. + if (process_lock.is_pdf() || process_lock.is_sandboxed()) { + return std::nullopt; + } + + // Case 4: process_lock_url is used to enfore site-isolation in code caches. // Http/https/chrome schemes are safe to be used as a secondary key. Other // schemes could be enabled if they are known to be safe and if it is // required to cache code from those origins. diff --git a/chromium/content/browser/renderer_host/mixed_content_checker.cc b/chromium/content/browser/renderer_host/mixed_content_checker.cc index 583ad87e6a5..34fc7e811ef 100644 --- src/3rdparty/chromium/content/browser/renderer_host/mixed_content_checker.cc +++ src/3rdparty/chromium/content/browser/renderer_host/mixed_content_checker.cc @@ -60,11 +60,6 @@ bool DoesOriginSchemeRestrictMixedContent(const url::Origin& origin) { url::kHttpsScheme; } -// This mirrors `blink::MixedContentChecker::IsMixedContent()`. -bool IsMixedContent(const url::Origin& origin, const GURL& url) { - return !IsUrlPotentiallySecure(url) && - DoesOriginSchemeRestrictMixedContent(origin); -} // This mirrors `blink::MixedContentChecker::InWhichFrameIsContentMixed()` but // without reporting to renderer. @@ -87,11 +82,13 @@ RenderFrameHostImpl* InWhichFrameIsContentMixedForFetchKeepAlive( // Check the main frame first. RenderFrameHostImpl* main_frame = initiator_frame->GetOutermostMainFrame(); - if (IsMixedContent(main_frame->GetLastCommittedOrigin(), url)) { + if (MixedContentChecker::IsMixedContent(main_frame->GetLastCommittedOrigin(), + url)) { return main_frame; } - if (IsMixedContent(initiator_frame->GetLastCommittedOrigin(), url)) { + if (MixedContentChecker::IsMixedContent( + initiator_frame->GetLastCommittedOrigin(), url)) { return initiator_frame; } @@ -180,6 +177,13 @@ void ReportBasicMixedContentFeatures( } // namespace +// static +bool MixedContentChecker::IsMixedContent(const url::Origin& security_origin, + const GURL& target_url) { + return !IsUrlPotentiallySecure(target_url) && + DoesOriginSchemeRestrictMixedContent(security_origin); +} + MixedContentChecker::MixedContentChecker() = default; MixedContentChecker::~MixedContentChecker() = default; @@ -301,9 +305,9 @@ bool MixedContentChecker::ShouldBlockInternal( prefs.allow_running_insecure_content, mixed_content_frame->GetLastCommittedOrigin(), url); if (allowed) { - const GURL& origin_url = - mixed_content_frame->GetLastCommittedOrigin().GetURL(); - mixed_content_frame->OnDidRunInsecureContent(origin_url, url); + mixed_content_frame->OnDidRunInsecureContent( + url, blink::mojom::ContentSecurityNotifier::InsecureContentOrigin:: + kCurrentFrame); if (mixed_content_features) { mixed_content_features->insert( blink::mojom::WebFeature::kMixedContentBlockableAllowed); @@ -398,7 +402,7 @@ RenderFrameHostImpl* MixedContentChecker::InWhichFrameIsContentMixed( } // Note: The code below should behave the same way as the two calls to - // `MeasureStricterVersionOfIsMixedContent()` from inside + // `MeasureStricterVersionOfMixedContentChecker::IsMixedContent()` from inside // `blink::MixedContentChecker::InWhichFrameIsContentMixed()`. if (mixed_content_frame) { // We're currently only checking for mixed content in `https://*` contexts. @@ -453,7 +457,7 @@ bool MixedContentChecker::ShouldBlockFetchKeepAlive( bool MixedContentChecker::IsMixedContentForTesting(const GURL& origin_url, const GURL& url) { const url::Origin origin = url::Origin::Create(origin_url); - return IsMixedContent(origin, url); + return MixedContentChecker::IsMixedContent(origin, url); } } // namespace content diff --git a/chromium/content/browser/renderer_host/mixed_content_checker.h b/chromium/content/browser/renderer_host/mixed_content_checker.h index bc15ef750c9..3d9a17839e2 100644 --- src/3rdparty/chromium/content/browser/renderer_host/mixed_content_checker.h +++ src/3rdparty/chromium/content/browser/renderer_host/mixed_content_checker.h @@ -43,6 +43,9 @@ class CONTENT_EXPORT MixedContentChecker { bool ShouldBlockNavigation(NavigationHandle& navigation_handle, bool for_redirect); + // Returns whether `url` is mixed content with respect to `origin`. + static bool IsMixedContent(const url::Origin& origin, const GURL& url); + // Checks if a fetch keepalive request that loads `url` should be blocked or // not due to mixed content, without reporting back to renderer. // diff --git a/chromium/content/browser/renderer_host/navigation_controller_impl.cc b/chromium/content/browser/renderer_host/navigation_controller_impl.cc index 31b9626ffae..4f4c22b0f84 100644 --- src/3rdparty/chromium/content/browser/renderer_host/navigation_controller_impl.cc +++ src/3rdparty/chromium/content/browser/renderer_host/navigation_controller_impl.cc @@ -4966,9 +4966,9 @@ blink::mojom::NavigationApiHistoryEntryArraysPtr NavigationControllerImpl::GetNavigationApiHistoryEntryVectors( FrameTreeNode* node, NavigationRequest* request) { - url::Origin pending_origin = request - ? request->GetOriginToCommit().value() - : url::Origin::Create(node->current_url()); + url::Origin pending_origin = + request ? request->GetOriginToCommit().value() + : node->current_frame_host()->GetLastCommittedOrigin(); scoped_refptr site_instance = node->current_frame_host()->GetSiteInstance(); diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.cc b/chromium/content/browser/renderer_host/render_frame_host_impl.cc index 54d943324b4..40cb0852a1c 100644 --- src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_impl.cc +++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_impl.cc @@ -133,6 +133,7 @@ #include "content/browser/renderer_host/input/input_injector_impl.h" #include "content/browser/renderer_host/ipc_utils.h" #include "content/browser/renderer_host/media/peer_connection_tracker_host.h" +#include "content/browser/renderer_host/mixed_content_checker.h" #include "content/browser/renderer_host/navigation_controller_impl.h" #include "content/browser/renderer_host/navigation_entry_impl.h" #include "content/browser/renderer_host/navigation_metrics_utils.h" @@ -193,6 +194,7 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/context_menu_params.h" #include "content/public/browser/cookie_access_details.h" +#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/disallow_activation_reason.h" #include "content/public/browser/document_ref.h" #include "content/public/browser/document_service_internal.h" @@ -6821,10 +6823,19 @@ void RenderFrameHostImpl::OnUnloadACK() { // it makes its renderer send this message. `owner_` is non null since this // attachment can only happen for subframes and pending deletion is the only // case where subframes may have a null `owner_`. + // + // Note that for MimeHandlerView specifically, the unload ACK can only be + // legitimately received after the inner delegate has already been attached by + // `RFH::SwapOuterDelegateFrame()`, and should be ignored if it's received + // during an earlier MimeHandlerView-specific preparation phase invoked via + // `RFH::PrepareForInnerContentsAttach()` (because not ignoring it would later + // disrupt the attachment, e.g. by causing the Unload IPC not to be sent). + // Hence, it's important to check for `is_inner_delegate_attached()` rather + // than `is_attaching_inner_delegate()`. RenderFrameHostOwner* owner = IsPendingDeletion() ? GetFrameTreeNodeForUnload() : owner_; if (!is_main_frame() && - owner->GetRenderFrameHostManager().is_attaching_inner_delegate()) { + owner->GetRenderFrameHostManager().is_inner_delegate_attached()) { // This RFH was unloaded while attaching an inner delegate. The RFH // will stay around but it will no longer be associated with a RenderFrame. RenderFrameDeleted(); @@ -7016,6 +7027,16 @@ void RenderFrameHostImpl::RunJavaScriptDialog( JavaScriptDialogType dialog_type, bool disable_third_party_subframe_suppresion, JavaScriptDialogCallback ipc_response_callback) { + // Sandboxed frames should only be allowed to show modal dialogs when they + // have the "allow-modals" attribute. This should have already been checked + // by the renderer process (see LocalDOMWindow::alert/confirm/prompt), and + // this browser-side check defends against compromised renderers. + if (IsSandboxed(network::mojom::WebSandboxFlags::kModals)) { + bad_message::ReceivedBadMessage( + GetProcess(), bad_message::RFH_MODAL_DIALOG_FROM_SANDBOXED_FRAME); + return; + } + // Don't show the dialog if it's triggered on a non-active RenderFrameHost // or is contained in a Fenced Frame. if (!IsActive() || IsNestedWithinFencedFrame()) { @@ -9360,6 +9381,8 @@ void RenderFrameHostImpl::DidChangeOpener( if (!owner_) return; + // Note that this call internally protects against `opener_frame_token` + // referring to an inactive frame. owner_->GetRenderFrameHostManager().DidChangeOpener( opener_frame_token, GetSiteInstance()->group()); } @@ -10218,17 +10241,12 @@ void RenderFrameHostImpl::CreateFencedFrame( return; } - // Ensure the devtools frame token doesn't exist in the FrameTree for - // this tab. - for (FrameTreeNode* node : - GetOutermostMainFrame()->frame_tree()->NodesIncludingInnerTreeNodes()) { - if (node->current_frame_host()->devtools_frame_token() == - devtools_frame_token) { - bad_message::ReceivedBadMessage( - GetProcess(), - bad_message::RFHI_CREATE_FENCED_FRAME_BAD_DEVTOOLS_FRAME_TOKEN); - return; - } + // Ensure the devtools frame token doesn't exist globally. + if (DevToolsAgentHost::GetForId(devtools_frame_token.ToString())) { + bad_message::ReceivedBadMessage( + GetProcess(), + bad_message::RFHI_CREATE_FENCED_FRAME_BAD_DEVTOOLS_FRAME_TOKEN); + return; } // Inactive pages cannot create fenced frames. If the page is in the BFCache, @@ -11240,7 +11258,9 @@ void RenderFrameHostImpl::BeginNavigation( } } + // TODO(crbug.com/40066983): Consider converting these into renderer kills. GetProcess()->FilterURL(true, &begin_params->searchable_form_url); + GetProcess()->FilterURL(true, &begin_params->client_side_redirect_url); // If the request was for a blob URL, but the validated URL is no longer a // blob URL, reset the blob_url_token to prevent hitting the ReportBadMessage @@ -18646,18 +18666,33 @@ void RenderFrameHostImpl::SetPolicyContainerForEarlyCommitAfterCrash( SetPolicyContainerHost(std::move(policy_container_host)); } -void RenderFrameHostImpl::OnDidRunInsecureContent(const GURL& security_origin, - const GURL& target_url) { +void RenderFrameHostImpl::OnDidRunInsecureContent( + const GURL& target_url, + blink::mojom::ContentSecurityNotifier::InsecureContentOrigin origin_type) { + url::Origin security_origin = + (origin_type == + blink::mojom::ContentSecurityNotifier::InsecureContentOrigin::kTopFrame) + ? GetOutermostMainFrame()->GetLastCommittedOrigin() + : GetLastCommittedOrigin(); + + if (!MixedContentChecker::IsMixedContent(security_origin, target_url)) { + mojo::ReportBadMessage( + "NotifyInsecureContentRan called for non-mixed content."); + return; + } + + const GURL& security_origin_url = security_origin.GetURL(); OPTIONAL_TRACE_EVENT2("content", "RenderFrameHostImpl::DidRunInsecureContent", - "security_origin", security_origin, "target_url", + "security_origin", security_origin_url, "target_url", target_url); RecordAction(base::UserMetricsAction("SSL.RanInsecureContent")); - if (base::EndsWith(security_origin.spec(), kDotGoogleDotCom, + if (base::EndsWith(security_origin_url.spec(), kDotGoogleDotCom, base::CompareCase::INSENSITIVE_ASCII)) { RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle")); } - frame_tree_->controller().ssl_manager()->DidRunMixedContent(security_origin); + frame_tree_->controller().ssl_manager()->DidRunMixedContent( + security_origin_url); } void RenderFrameHostImpl::OnDidRunContentWithCertificateErrors() { diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.h b/chromium/content/browser/renderer_host/render_frame_host_impl.h index 92cf1c05093..826790bbbfb 100644 --- src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_impl.h +++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_impl.h @@ -156,6 +156,7 @@ #include "third_party/blink/public/mojom/image_downloader/image_downloader.mojom.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-forward.h" #include "third_party/blink/public/mojom/installedapp/installed_app_provider.mojom-forward.h" +#include "third_party/blink/public/mojom/loader/content_security_notifier.mojom.h" #include "third_party/blink/public/mojom/loader/fetch_later.mojom-forward.h" #include "third_party/blink/public/mojom/loader/local_resource_loader_config.mojom-forward.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-forward.h" @@ -2862,8 +2863,9 @@ class CONTENT_EXPORT RenderFrameHostImpl network::mojom::ClientSecurityStatePtr BuildClientSecurityStateForWorkers() const; - void OnDidRunInsecureContent(const GURL& security_origin, - const GURL& target_url); + void OnDidRunInsecureContent( + const GURL& target_url, + blink::mojom::ContentSecurityNotifier::InsecureContentOrigin origin_type); void OnDidDisplayContentWithCertificateErrors(); void OnDidRunContentWithCertificateErrors(); diff --git a/chromium/content/browser/renderer_host/render_frame_host_manager.cc b/chromium/content/browser/renderer_host/render_frame_host_manager.cc index 6d248806310..24b82620c5e 100644 --- src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc +++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.cc @@ -1035,8 +1035,20 @@ void RenderFrameHostManager::DidChangeOpener( *opener_frame_token); // If |opener_rfhi| is null, the opener RFH has already disappeared. In // this case, clear the opener rather than keeping the old opener around. - if (opener_rfhi) + if (opener_rfhi) { + // Ignore this message if |opener_rfhi| is inactive (e.g., in BFCache or + // pending deletion), or if the FrameTreeNode's current RenderFrameHost + // is in a different BrowsingInstance, as it would be incorrect to + // establish an opener relationship in those cases. + if (opener_rfhi->IsInactiveAndDisallowActivation( + DisallowActivationReasonId::kDidChangeOpener) || + !render_frame_host_->GetSiteInstance() + ->group() + ->IsRelatedSiteInstanceGroup(source_site_instance_group)) { + return; + } opener = opener_rfhi->frame_tree_node(); + } } if (frame_tree_node_->opener() == opener) diff --git a/chromium/content/browser/renderer_host/render_frame_host_manager.h b/chromium/content/browser/renderer_host/render_frame_host_manager.h index 4ca64326e00..e5eecc249d5 100644 --- src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.h +++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_host_manager.h @@ -691,6 +691,12 @@ class CONTENT_EXPORT RenderFrameHostManager { return attach_to_inner_delegate_state_ != AttachToInnerDelegateState::NONE; } + // Returns true if an inner delegate has been fully attached. + bool is_inner_delegate_attached() const { + return attach_to_inner_delegate_state_ == + AttachToInnerDelegateState::ATTACHED; + } + // Called by the delegate at the end of the attaching process. void set_attach_inner_delegate_complete() { attach_to_inner_delegate_state_ = AttachToInnerDelegateState::ATTACHED; diff --git a/chromium/content/browser/renderer_host/render_frame_proxy_host.cc b/chromium/content/browser/renderer_host/render_frame_proxy_host.cc index 413709a6d00..67312f030c7 100644 --- src/3rdparty/chromium/content/browser/renderer_host/render_frame_proxy_host.cc +++ src/3rdparty/chromium/content/browser/renderer_host/render_frame_proxy_host.cc @@ -930,6 +930,8 @@ void RenderFrameProxyHost::UpdateViewportIntersection( void RenderFrameProxyHost::DidChangeOpener( const std::optional& opener_frame_token) { + // Note that this call internally protects against `opener_frame_token` + // referring to an inactive frame. frame_tree_node_->render_manager()->DidChangeOpener(opener_frame_token, site_instance_group()); } diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc index 397dae6666d..6567cc17d3d 100644 --- src/3rdparty/chromium/content/browser/service_worker/embedded_worker_instance.cc +++ src/3rdparty/chromium/content/browser/service_worker/embedded_worker_instance.cc @@ -388,22 +388,6 @@ void EmbeddedWorkerInstance::Start( params->devtools_worker_token.ToString()); } - // To enable runtime features, the render process must be locked to the site. - // These features are highly privileged, so the renderer process with such - // features enabled shouldn't be used for other sites. - // - // WebUI schemes are process isolated already. To isolate other sites, the - // embedder can override ContentBrowserClient::ShouldLockProcessToSite(). - if (rph->GetProcessLock().is_locked_to_site()) { - GetContentClient() - ->browser() - ->UpdateEnabledBlinkRuntimeFeaturesInIsolatedWorker( - context_->wrapper()->browser_context(), params->script_url, - params->forced_enabled_runtime_features); - } - CHECK(params->forced_enabled_runtime_features.empty() || - rph->GetProcessLock().is_locked_to_site()); - // TODO(crbug.com/40584626): Support changes to blink::RendererPreferences // while the worker is running. DCHECK(context_->wrapper()->browser_context() || diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc index bb0072fac38..555b7930a24 100644 --- src/3rdparty/chromium/content/browser/service_worker/service_worker_version.cc +++ src/3rdparty/chromium/content/browser/service_worker/service_worker_version.cc @@ -849,7 +849,9 @@ bool ServiceWorkerVersion::FinishRequestWithFetchCount(int request_id, TRACE_EVENT_NESTABLE_ASYNC_END1( "ServiceWorker", "ServiceWorkerVersion::Request", TRACE_ID_LOCAL(request), "Handled", was_handled); - request_timeouts_.erase(request->timeout_iter); + if (request->timeout_iter.has_value()) { + request_timeouts_.erase(*request->timeout_iter); + } inflight_requests_.Remove(request_id); // TODO(crbug.com/40864997): remove the following DCHECK when the cause // identified. @@ -2603,6 +2605,11 @@ void ServiceWorkerVersion::OnTimeoutTimer() { break; } timed_out_infos.push_back(*it); + // Erase the entry from `request_timeouts_` and update `InflightRequest` + // accordingly. + InflightRequest* request = inflight_requests_.Lookup(it->id); + CHECK(request); + request->timeout_iter = std::nullopt; it = request_timeouts_.erase(it); } diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h index 6d6b5825319..9d106d8575c 100644 --- src/3rdparty/chromium/content/browser/service_worker/service_worker_version.h +++ src/3rdparty/chromium/content/browser/service_worker/service_worker_version.h @@ -886,8 +886,10 @@ class CONTENT_EXPORT ServiceWorkerVersion base::Time start_time; base::TimeTicks start_time_ticks; ServiceWorkerMetrics::EventType event_type; - // Points to this request's entry in |request_timeouts_|. - std::set::iterator timeout_iter; + // Points to this request's entry in |request_timeouts_|. Please invalidate + // this when the corresponding entry is removed from `request_timeouts_`. + // TODO(crbug.com/499449324): Refactor this code by simplifying ownerships. + std::optional::iterator> timeout_iter; }; // The timeout timer interval. diff --git a/chromium/content/browser/shared_storage/shared_storage_worklet_host.cc b/chromium/content/browser/shared_storage/shared_storage_worklet_host.cc index 10002284f38..36aaa7d10e3 100644 --- src/3rdparty/chromium/content/browser/shared_storage/shared_storage_worklet_host.cc +++ src/3rdparty/chromium/content/browser/shared_storage/shared_storage_worklet_host.cc @@ -1795,6 +1795,17 @@ SharedStorageWorkletHost::MaybeConstructPrivateAggregationOperationDetails( bool SharedStorageWorkletHost::IsSharedStorageAllowed( std::string* out_debug_message, bool* out_block_is_site_setting_specific) { + if (needs_data_origin_opt_in_ && + (!data_origin_opt_in_state_ || !data_origin_opt_in_state_->first)) { + if (out_debug_message) { + *out_debug_message = + data_origin_opt_in_state_ + ? data_origin_opt_in_state_->second + : "SharedStorage cross-origin data opt-in check failed."; + } + return false; + } + RenderFrameHost* rfh = document_service_ ? &(document_service_->render_frame_host()) : nullptr; return GetContentClient()->browser()->IsSharedStorageAllowed( diff --git a/chromium/content/browser/speech/tts_controller_impl.cc b/chromium/content/browser/speech/tts_controller_impl.cc index 23ddd9c64ba..9ba77880acc 100644 --- src/3rdparty/chromium/content/browser/speech/tts_controller_impl.cc +++ src/3rdparty/chromium/content/browser/speech/tts_controller_impl.cc @@ -1011,6 +1011,10 @@ void TtsControllerImpl::WebContentsDestroyed() { StopCurrentUtteranceAndRemoveUtterancesMatching(web_contents()); } +void TtsControllerImpl::PrimaryPageChanged(Page& page) { + StopCurrentUtteranceAndRemoveUtterancesMatching(web_contents()); +} + void TtsControllerImpl::OnVisibilityChanged(Visibility visibility) { if (visibility == Visibility::HIDDEN && stop_speaking_when_hidden_) StopCurrentUtteranceAndRemoveUtterancesMatching(web_contents()); diff --git a/chromium/content/browser/speech/tts_controller_impl.h b/chromium/content/browser/speech/tts_controller_impl.h index efb52a977e7..a018fa3ea7d 100644 --- src/3rdparty/chromium/content/browser/speech/tts_controller_impl.h +++ src/3rdparty/chromium/content/browser/speech/tts_controller_impl.h @@ -196,6 +196,7 @@ class CONTENT_EXPORT TtsControllerImpl // WebContentsObserver methods void WebContentsDestroyed() override; + void PrimaryPageChanged(Page& page) override; void OnVisibilityChanged(Visibility visibility) override; // net::NetworkChangeNotifier::NetworkChangeObserver diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc index 15cdacd93da..9cacc6a0022 100644 --- src/3rdparty/chromium/content/browser/storage_partition_impl.cc +++ src/3rdparty/chromium/content/browser/storage_partition_impl.cc @@ -3637,6 +3637,7 @@ void StoragePartitionImpl::InitNetworkContext() { context_params->cors_exempt_header_list.push_back(blink::kPurposeHeaderName); context_params->cors_exempt_header_list.push_back( GetCorsExemptRequestedWithHeaderName()); + context_params->cors_exempt_header_list.push_back("Last-Event-ID"); variations::UpdateCorsExemptHeaderForVariations(context_params.get()); cors_exempt_header_list_ = context_params->cors_exempt_header_list; diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.cc b/chromium/content/browser/web_contents/web_contents_view_aura.cc index 184fc0eded3..ff20716835c 100644 --- src/3rdparty/chromium/content/browser/web_contents/web_contents_view_aura.cc +++ src/3rdparty/chromium/content/browser/web_contents/web_contents_view_aura.cc @@ -1115,6 +1115,10 @@ void WebContentsViewAura::StartDragging( const blink::mojom::DragEventSourceInfo& event_info, RenderWidgetHostImpl* source_rwh) { aura::Window* root_window = GetNativeView()->GetRootWindow(); + // Disallow reentrant drag which could be an attempt to exploit drag state. + if (drag_security_info_.did_initiate()) { + return; + } if (!aura::client::GetDragDropClient(root_window)) { web_contents_->SystemDragEnded(source_rwh); return; diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.mm b/chromium/content/browser/web_contents/web_contents_view_mac.mm index 24d11d20844..7aab80c5c05 100644 --- src/3rdparty/chromium/content/browser/web_contents/web_contents_view_mac.mm +++ src/3rdparty/chromium/content/browser/web_contents/web_contents_view_mac.mm @@ -206,6 +206,10 @@ void WebContentsViewMac::StartDragging( const gfx::Rect& drag_obj_rect, const blink::mojom::DragEventSourceInfo& event_info, RenderWidgetHostImpl* source_rwh) { + // Disallow reentrant drag which could be an attempt to exploit drag state. + if (drag_source_start_rwh_) { + return; + } // By allowing nested tasks, the code below also allows Close(), // which would deallocate |this|. The same problem can occur while // processing -sendEvent:, so Close() is deferred in that case. @@ -644,6 +648,8 @@ void WebContentsViewMac::PerformEndDrag(uint32_t drag_operation, transformed_screen_point.x(), transformed_screen_point.y(), static_cast(drag_operation), drag_source_start_rwh_.get()); + + drag_source_start_rwh_.reset(); } void WebContentsViewMac::DraggingEntered(DraggingInfoPtr dragging_info, diff --git a/chromium/content/common/features.cc b/chromium/content/common/features.cc index 5698452ff6a..9720d82f22d 100644 --- src/3rdparty/chromium/content/common/features.cc +++ src/3rdparty/chromium/content/common/features.cc @@ -184,6 +184,14 @@ BASE_FEATURE(kEnableDevToolsJsErrorReporting, base::FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +// Enforces the use of the browser-authoritative origin from the Mojo receiver +// context instead of the renderer-supplied origin in FileSystemManager::Open. +// TODO(crbug.com/497254383): Remove this flag and the origin parameter from +// the Mojo interface. +BASE_FEATURE(kEnforceFileSystemManagerOpenOrigin, + "EnforceFileSystemManagerOpenOrigin", + base::FEATURE_ENABLED_BY_DEFAULT); + // When enabled, enforces that same-document navigations must not change // the committed origin, insecure request policy, or insecure navigations set. // Any mismatch will result in a renderer kill via bad_message handling. diff --git a/chromium/content/common/features.h b/chromium/content/common/features.h index 9dda6123dfa..b8fc49dc0c7 100644 --- src/3rdparty/chromium/content/common/features.h +++ src/3rdparty/chromium/content/common/features.h @@ -65,6 +65,7 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kDocumentPolicyNegotiation); CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnableDevToolsJsErrorReporting); #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnforceSameDocumentOriginInvariants); +CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnforceFileSystemManagerOpenOrigin); CONTENT_EXPORT BASE_DECLARE_FEATURE(kEmbeddingRequiresOptIn); CONTENT_EXPORT BASE_DECLARE_FEATURE(kExperimentalContentSecurityPolicyFeatures); CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmUseOtherAccountAndLabelsNewSyntax); diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc index f340de9f145..afbc85749b1 100644 --- src/3rdparty/chromium/content/public/browser/content_browser_client.cc +++ src/3rdparty/chromium/content/public/browser/content_browser_client.cc @@ -484,11 +484,6 @@ bool ContentBrowserClient::ShouldTryToUpdateServiceWorkerRegistration( return true; } -void ContentBrowserClient::UpdateEnabledBlinkRuntimeFeaturesInIsolatedWorker( - BrowserContext* context, - const GURL& script_url, - std::vector& out_forced_enabled_runtime_features) {} - bool ContentBrowserClient::AllowSharedWorker( const GURL& worker_url, const net::SiteForCookies& site_for_cookies, diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h index ec9fb8c683c..cce4bd258b1 100644 --- src/3rdparty/chromium/content/public/browser/content_browser_client.h +++ src/3rdparty/chromium/content/public/browser/content_browser_client.h @@ -880,20 +880,6 @@ class CONTENT_EXPORT ContentBrowserClient { const GURL& scope, BrowserContext* browser_context); - // Allows the embedder to enable process-wide blink features before starting a - // service worker. This is similar to - // `blink.mojom.CommitNavigationParams.force_enabled_origin_trials` but for - // RuntimeFeatures instead of Origin Trials. - // - // This method is only called when the process that will run the Service - // Worker is isolated. These features can be highly privileged, so the - // renderer process with such features enabled shouldn't be used for other - // sites. - virtual void UpdateEnabledBlinkRuntimeFeaturesInIsolatedWorker( - BrowserContext* context, - const GURL& script_url, - std::vector& out_forced_enabled_runtime_features); - // Allow the embedder to control if a Shared Worker can be connected from a // given tab. // This is called on the UI thread. diff --git a/chromium/content/public/browser/disallow_activation_reason.h b/chromium/content/public/browser/disallow_activation_reason.h index 27d10cf7128..1ff1f7ed2b2 100644 --- src/3rdparty/chromium/content/public/browser/disallow_activation_reason.h +++ src/3rdparty/chromium/content/public/browser/disallow_activation_reason.h @@ -64,6 +64,7 @@ enum DisallowActivationReasonId : uint64_t { kIndexedDBTransactionIsStartingWhileBlockingOthers = 40, kIndexedDBTransactionIsOngoingAndBlockingOthers = 41, kBrowserInitiatedErrorPage = 42, + kDidChangeOpener = 43, // New entries go above here. New entries should be added to // tools/metrics/histograms/enums.xml . kMinEmbedderDisallowActivationReason = 2 << 16, diff --git a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc index 43d7f8a138f..26da62b4808 100644 --- src/3rdparty/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc +++ src/3rdparty/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc @@ -95,10 +95,6 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker( start_data->policy_container = ToWebPolicyContainer(std::move(params->policy_container)); - for (const auto& feature : params->forced_enabled_runtime_features) { - blink::WebRuntimeFeatures::EnableFeatureFromString(feature, true); - } - // `cache_storage` may be null if COEP is not enabled, we cannot bind // eagerly in that case. mojo::PendingRemote cache_storage = diff --git a/chromium/device/base/BUILD.gn b/chromium/device/base/BUILD.gn index be467c91bb6..1d4928f7aee 100644 --- src/3rdparty/chromium/device/base/BUILD.gn +++ src/3rdparty/chromium/device/base/BUILD.gn @@ -4,6 +4,7 @@ import("//build/config/features.gni") import("//device/vr/buildflags/buildflags.gni") +import("//device/device.gni") component("base") { output_name = "device_base" @@ -32,4 +33,7 @@ component("base") { public_deps += [ "//third_party/abseil-cpp:absl" ] libs = [ "setupapi.lib" ] } + + configs -= device_remove_configs + configs += device_add_configs } diff --git a/chromium/device/base/synchronization/BUILD.gn b/chromium/device/base/synchronization/BUILD.gn index b74e55d5e72..81dfc8f5b50 100644 --- src/3rdparty/chromium/device/base/synchronization/BUILD.gn +++ src/3rdparty/chromium/device/base/synchronization/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//device/device.gni") + source_set("synchronization") { sources = [ "one_writer_seqlock.cc", @@ -10,4 +12,7 @@ source_set("synchronization") { ] deps = [ "//base" ] + + configs -= device_remove_configs + configs += device_add_configs } diff --git a/chromium/device/bluetooth/BUILD.gn b/chromium/device/bluetooth/BUILD.gn index 70882e695ad..c52098fa1f0 100644 --- src/3rdparty/chromium/device/bluetooth/BUILD.gn +++ src/3rdparty/chromium/device/bluetooth/BUILD.gn @@ -6,6 +6,7 @@ import("//build/buildflag_header.gni") import("//build/config/features.gni") import("//device/bluetooth/cast_bluetooth.gni") import("//device/bluetooth/emulation/buildflags.gni") +import("//device/device.gni") if (is_android) { import("//build/config/android/rules.gni") @@ -644,6 +645,9 @@ component("bluetooth") { # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and # enable the diagnostic by removing this line. configs += [ "//build/config/compiler:no_exit_time_destructors" ] + + configs -= device_remove_configs + configs += device_add_configs } static_library("mocks") { diff --git a/chromium/device/bluetooth/public/cpp/BUILD.gn b/chromium/device/bluetooth/public/cpp/BUILD.gn index fbde5457ec6..8aad44956fd 100644 --- src/3rdparty/chromium/device/bluetooth/public/cpp/BUILD.gn +++ src/3rdparty/chromium/device/bluetooth/public/cpp/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//device/device.gni") + source_set("cpp") { sources = [ "bluetooth_address.cc", @@ -11,6 +13,9 @@ source_set("cpp") { ] deps = [ "//base" ] public_deps = [ ":features" ] + + configs -= device_remove_configs + configs += device_add_configs } component("features") { @@ -21,4 +26,7 @@ component("features") { ] deps = [ "//base" ] defines = [ "BLUETOOTH_FEATURES_IMPLEMENTATION" ] + + configs -= device_remove_configs + configs += device_add_configs } diff --git a/chromium/device/bluetooth/public/mojom/BUILD.gn b/chromium/device/bluetooth/public/mojom/BUILD.gn index 43adc4d6a39..496a6f60f55 100644 --- src/3rdparty/chromium/device/bluetooth/public/mojom/BUILD.gn +++ src/3rdparty/chromium/device/bluetooth/public/mojom/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//device/device.gni") import("//mojo/public/tools/bindings/mojom.gni") mojom("mojom") { @@ -66,6 +67,11 @@ mojom("mojom") { traits_public_deps = [ "//device/bluetooth" ] }, ] + + removed_cpp_configs = device_remove_configs + cpp_configs = device_add_configs + blink_removed_cpp_configs = device_remove_configs + blink_cpp_configs = device_add_configs } mojom("fake_bluetooth_interfaces") { diff --git a/chromium/device/device.gni b/chromium/device/device.gni new file mode 100644 index 00000000000..ef6f0c36210 --- /dev/null +++ src/3rdparty/chromium/device/device.gni @@ -0,0 +1,24 @@ +# Copyright (C) 2026 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +import("//build/config/compiler/compiler.gni") + +declare_args() { + device_symbol_level = symbol_level +} + +device_remove_configs = [] +device_add_configs = [] + +if (device_symbol_level != symbol_level) { + device_remove_configs += [ "//build/config/compiler:default_symbols" ] + if (device_symbol_level == 0) { + device_add_configs += [ "//build/config/compiler:no_symbols" ] + } else if (device_symbol_level == 1) { + device_add_configs += [ "//build/config/compiler:minimal_symbols" ] + } else if (device_symbol_level == 2) { + device_add_configs += [ "//build/config/compiler:symbols" ] + } else { + assert(false) + } +} diff --git a/chromium/device/fido/BUILD.gn b/chromium/device/fido/BUILD.gn index 68d4723275b..8cf874c983b 100644 --- src/3rdparty/chromium/device/fido/BUILD.gn +++ src/3rdparty/chromium/device/fido/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/features.gni") +import("//device/device.gni") import("//testing/libfuzzer/fuzzer_test.gni") component("fido") { @@ -344,6 +345,9 @@ component("fido") { ] } } + + configs -= device_remove_configs + configs += device_add_configs } if (use_blink) { diff --git a/chromium/device/fido/enclave/proto/BUILD.gn b/chromium/device/fido/enclave/proto/BUILD.gn index d08545c62e8..b28b644473e 100644 --- src/3rdparty/chromium/device/fido/enclave/proto/BUILD.gn +++ src/3rdparty/chromium/device/fido/enclave/proto/BUILD.gn @@ -2,8 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//device/device.gni") import("//third_party/protobuf/proto_library.gni") proto_library("proto") { sources = [ "evidence.proto" ] + remove_configs = device_remove_configs + extra_configs = device_add_configs } diff --git a/chromium/device/gamepad/BUILD.gn b/chromium/device/gamepad/BUILD.gn index 83e5418b978..24c4e80d441 100644 --- src/3rdparty/chromium/device/gamepad/BUILD.gn +++ src/3rdparty/chromium/device/gamepad/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/features.gni") +import("//device/device.gni") if (is_android) { import("//build/config/android/config.gni") @@ -169,6 +170,9 @@ component("gamepad") { # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and # enable the diagnostic by removing this line. configs += [ "//build/config/compiler:no_exit_time_destructors" ] + + configs -= device_remove_configs + configs += device_add_configs } static_library("test_helpers") { diff --git a/chromium/device/gamepad/public/cpp/BUILD.gn b/chromium/device/gamepad/public/cpp/BUILD.gn index 4a809ae2d4b..641cc460807 100644 --- src/3rdparty/chromium/device/gamepad/public/cpp/BUILD.gn +++ src/3rdparty/chromium/device/gamepad/public/cpp/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//device/device.gni") + # This target contains only those files that are shared by the Device Gamepad # implementation and all Device Gamepad clients, including Blink. Add a file # here only if it meets the following constraints: @@ -24,6 +26,9 @@ component("shared_with_blink") { # Do not add deps here per the above comment. defines = [ "IS_GAMEPAD_PUBLIC_IMPL" ] public_deps = [ "//base" ] + + configs -= device_remove_configs + configs += device_add_configs } # Normally typemap traits sources should be build directly into mojom targets @@ -44,6 +49,9 @@ component("shared_typemap_traits") { "//base", "//device/gamepad/public/mojom:mojom_shared", ] + + configs -= device_remove_configs + configs += device_add_configs } component("switches") { @@ -58,4 +66,7 @@ component("switches") { ] public_deps = [ "//base" ] defines = [ "GAMEPAD_FEATURES_IMPLEMENTATION" ] + + configs -= device_remove_configs + configs += device_add_configs } diff --git a/chromium/device/gamepad/public/mojom/BUILD.gn b/chromium/device/gamepad/public/mojom/BUILD.gn index d0f63243217..37be1acb691 100644 --- src/3rdparty/chromium/device/gamepad/public/mojom/BUILD.gn +++ src/3rdparty/chromium/device/gamepad/public/mojom/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//device/device.gni") import("//mojo/public/tools/bindings/mojom.gni") mojom_component("mojom") { @@ -69,4 +70,9 @@ mojom_component("mojom") { cpp_typemaps = [ shared_cpp_typemap ] blink_cpp_typemaps = [ shared_cpp_typemap ] + + removed_cpp_configs = device_remove_configs + cpp_configs = device_add_configs + blink_removed_cpp_configs = device_remove_configs + blink_cpp_configs = device_add_configs } diff --git a/chromium/device/vr/BUILD.gn b/chromium/device/vr/BUILD.gn index 8962518a9d9..f393e5b3572 100644 --- src/3rdparty/chromium/device/vr/BUILD.gn +++ src/3rdparty/chromium/device/vr/BUILD.gn @@ -298,6 +298,9 @@ if (enable_vr) { "//ui/gl/init", ] } + + configs -= device_remove_configs + configs += device_add_configs } component("vr_test_hook") { diff --git a/chromium/device/vr/public/mojom/BUILD.gn b/chromium/device/vr/public/mojom/BUILD.gn index 6086d4817ce..6f6f4970ae4 100644 --- src/3rdparty/chromium/device/vr/public/mojom/BUILD.gn +++ src/3rdparty/chromium/device/vr/public/mojom/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//device/device.gni") import("//device/vr/buildflags/buildflags.gni") import("//mojo/public/tools/bindings/mojom.gni") @@ -42,6 +43,11 @@ mojom_component("vr_service") { cpp_typemaps = [ shared_cpp_typemap ] blink_cpp_typemaps = [ shared_cpp_typemap ] + + removed_cpp_configs = device_remove_configs + cpp_configs = device_add_configs + blink_removed_cpp_configs = device_remove_configs + blink_cpp_configs = device_add_configs } # Separating the public mojom interface into vr_service and isolated_xr_service @@ -67,6 +73,9 @@ mojom_component("isolated_xr_service") { ] deps = [ "//services/viz/public/mojom" ] + + removed_cpp_configs = device_remove_configs + cpp_configs = device_add_configs } mojom_component("test_mojom") { @@ -81,6 +90,9 @@ mojom_component("test_mojom") { "//ui/gfx/geometry/mojom", "//ui/gfx/mojom", ] + + removed_cpp_configs = device_remove_configs + cpp_configs = device_add_configs } component("vr_public_typemaps") { @@ -101,6 +113,9 @@ component("vr_public_typemaps") { ] configs += [ "//build/config/compiler:wexit_time_destructors" ] + + configs -= device_remove_configs + configs += device_add_configs } mojom_component("xr_common") { @@ -134,4 +149,9 @@ mojom_component("xr_common") { webui_module_path = "/" generate_legacy_js_bindings = true + + blink_removed_cpp_configs = device_remove_configs + blink_cpp_configs = device_add_configs + removed_cpp_configs = device_remove_configs + cpp_configs = device_add_configs } diff --git a/chromium/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/chromium/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index 2b15c3c9086..fc1f0086668 100644 --- src/3rdparty/chromium/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ src/3rdparty/chromium/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc @@ -11,6 +11,7 @@ #include #include "base/check_deref.h" +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -39,6 +40,7 @@ #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/user_script.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "url/origin.h" using content::WebContents; using extensions::ExtensionResource; @@ -53,6 +55,9 @@ namespace errors = extensions::manifest_errors; namespace web_view_internal = extensions::api::web_view_internal; namespace { +// Kill switch for the fix for https://crbug.com/496016840 +// TODO(crbug.com/496016840): Remove in M151 or later. +BASE_FEATURE(kWebviewScriptFileOriginCheck, "WebviewScriptFileOriginCheck", base::FEATURE_ENABLED_BY_DEFAULT); constexpr std::string_view kCacheKey = "cache"; constexpr std::string_view kCookiesKey = "cookies"; @@ -132,6 +137,10 @@ void ParseScriptFiles(const GURL& owner_base_url, if (items.files) { for (const std::string& relative : *items.files) { GURL url = owner_base_url.Resolve(relative); + if (!url::IsSameOriginWith(owner_base_url, url) && + base::FeatureList::IsEnabled(kWebviewScriptFileOriginCheck)) { + continue; + } if (extension) { ExtensionResource resource = extension->GetResource(relative); contents->push_back(UserScript::Content::CreateFile( @@ -543,6 +552,11 @@ bool WebViewInternalExecuteCodeFunction::LoadFileForEmbedder( GURL owner_base_url(guest->GetOwnerSiteURL().GetWithEmptyPath()); GURL file_url(owner_base_url.Resolve(file_src)); + if (!url::IsSameOriginWith(owner_base_url, file_url) && + base::FeatureList::IsEnabled(kWebviewScriptFileOriginCheck)) { + return false; + } + switch (host_id().type) { case mojom::HostID::HostType::kExtensions: NOTREACHED(); diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index 031c17894be..9205423d9f1 100644 --- src/3rdparty/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ src/3rdparty/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc @@ -480,13 +480,16 @@ void PassthroughResources::SharedImageData::EnsureClear( api->glDisableFn(GL_SCISSOR_TEST); api->glClearFn(GL_COLOR_BUFFER_BIT); + if (api->glCheckFramebufferStatusEXTFn(GL_FRAMEBUFFER) == + GL_FRAMEBUFFER_COMPLETE) { + // Mark the shared image as cleared. + representation_->SetCleared(); + } + // Delete the generated framebuffer. api->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture->target(), 0, 0); api->glDeleteFramebuffersEXTFn(1, &fbo); - - // Mark the shared image as cleared. - representation_->SetCleared(); } } diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index 724b51764e1..6a152ceb436 100644 --- src/3rdparty/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ src/3rdparty/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc @@ -670,17 +670,21 @@ error::Error GLES2DecoderPassthroughImpl::DoBufferData(GLenum target, GLenum usage) { CheckErrorCallbackState(); api()->glBufferDataFn(target, size, data, usage); - if (CheckErrorCallbackState()) { - return error::kNoError; - } + // Calling glBufferData on a mapped buffer implicitly unmaps it. ANGLE's + // gl::Buffer::bufferDataImpl performs this unmap unconditionally BEFORE + // attempting the new allocation, so the driver pointer stored in + // mapped_buffer_map is invalidated even when glBufferDataFn raises an + // error (e.g. GL_OUT_OF_MEMORY). Erase the stale entry before any early + // return; otherwise a subsequent DoUnmapBuffer would memcpy renderer- + // controlled data into the freed driver mapping. if (target == GL_ELEMENT_ARRAY_BUFFER) { LazilyUpdateCurrentlyBoundElementArrayBuffer(); } - // Calling buffer data on a mapped buffer will implicitly unmap it resources_->mapped_buffer_map.erase(bound_buffers_[target]); + CheckErrorCallbackState(); return error::kNoError; } diff --git a/chromium/gpu/command_buffer/service/raster_decoder.cc b/chromium/gpu/command_buffer/service/raster_decoder.cc index 1d0bc85c648..9aa03bb6224 100644 --- src/3rdparty/chromium/gpu/command_buffer/service/raster_decoder.cc +++ src/3rdparty/chromium/gpu/command_buffer/service/raster_decoder.cc @@ -2110,6 +2110,7 @@ void RasterDecoderImpl::DoWritePixelsINTERNAL(GLint x_offset, if (!written) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glWritePixels", "Failed to write pixels to SkCanvas"); + return; } shared_context_state_->FlushWriteAccess(dest_scoped_access.get()); diff --git a/chromium/media/audio/mac/catap_audio_input_stream.h b/chromium/media/audio/mac/catap_audio_input_stream.h index b3f480c5a5f..802380e1264 100644 --- src/3rdparty/chromium/media/audio/mac/catap_audio_input_stream.h +++ src/3rdparty/chromium/media/audio/mac/catap_audio_input_stream.h @@ -21,6 +21,7 @@ namespace media { class CatapApi; +class CatapIoProcProxy; // Implementation of AudioInputStream using the CoreAudio API for macOS 14.2 // and later. The current implementation supports mono and stereo capture system @@ -181,6 +182,12 @@ class MEDIA_EXPORT API_AVAILABLE(macos(14.2)) CatapAudioInputStream kAudioObjectUnknown; CATapDescription* __strong tap_description_ GUARDED_BY_CONTEXT(sequence_checker_) = nil; + // Tracks if the synchronous fences failed during teardown. + bool stop_failed_ = false; + + // The proxy passed to CoreAudio. + std::unique_ptr io_proc_proxy_ + GUARDED_BY_CONTEXT(sequence_checker_); bool is_device_open_ GUARDED_BY_CONTEXT(sequence_checker_) = false; SEQUENCE_CHECKER(sequence_checker_); diff --git a/chromium/media/audio/mac/catap_audio_input_stream.mm b/chromium/media/audio/mac/catap_audio_input_stream.mm index d2dea46a8db..c21e51552c7 100644 --- src/3rdparty/chromium/media/audio/mac/catap_audio_input_stream.mm +++ src/3rdparty/chromium/media/audio/mac/catap_audio_input_stream.mm @@ -13,14 +13,17 @@ #include +#include "base/debug/leak_annotations.h" #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/logging.h" +#include "base/memory/raw_ptr_exclusion.h" #include "base/metrics/histogram_functions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" +#include "base/synchronization/lock.h" #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "media/audio/mac/audio_loopback_input_mac.h" @@ -29,6 +32,36 @@ #include "media/base/audio_timestamp_helper.h" namespace media { +// Acts as a thread-safe bridge between the CoreAudio IOProc and the +// CatapAudioInputStreamSource. If teardown fails, this object is intentionally +// leaked to give the orphaned OS thread a valid memory address to read. +class API_AVAILABLE(macos(14.2)) CatapIoProcProxy { + public: + CatapIoProcProxy(raw_ptr source) + : source_(source) {} + + // Called from the main sequence during teardown. + void Detach() { + base::AutoLock auto_lock(lock_); + source_ = nullptr; + } + + // Called by the CoreAudio high-priority thread. + void ForwardSample(const AudioBuffer* input_buffer, + const AudioTimeStamp* input_time) { + base::AutoLock auto_lock(lock_); + if (source_) { + source_->OnCatapSample(input_buffer, input_time); + } + } + + private: + // Lock to protect access to source_ and to ensure that ForwardSample() + // finishes before Detach() returns. + base::Lock lock_; + raw_ptr source_ GUARDED_BY(lock_); +}; + namespace { const char kCatapAudioInputStreamUmaBaseName[] = "Media.Audio.Mac.CatapAudioInputStream"; @@ -75,15 +108,14 @@ OSStatus DeviceIoProc(AudioDeviceID, AudioBufferList* output_data, const AudioTimeStamp* output_time, void* client_data) { - CatapAudioInputStream* catap_input_stream = - (CatapAudioInputStream*)client_data; - CHECK(catap_input_stream != nullptr); + CatapIoProcProxy* proxy = reinterpret_cast(client_data); + CHECK(proxy != nullptr); // SAFETY: The type of inputData cannot be changed since it's received from // the OS. Wrap it immediately using its specified size. base::span UNSAFE_BUFFERS( input_buffers(input_data->mBuffers, input_data->mNumberBuffers)); - catap_input_stream->OnCatapSample(input_buffers, input_time); + proxy->ForwardSample(input_data->mBuffers, input_time); return noErr; } @@ -362,8 +394,9 @@ AudioInputStream::OpenOutcome CatapAudioInputStream::Open() { // Initialization: Step 3. // Attach callback to the aggregate device. + io_proc_proxy_ = std::make_unique(this); status = catap_api_->AudioDeviceCreateIOProcID( - aggregate_device_id_, DeviceIoProc, this, &tap_io_proc_id_); + aggregate_device_id_, DeviceIoProc, io_proc_proxy_.get(), &tap_io_proc_id_); if (status != noErr) { ReportOpenStatus(OpenStatus::kErrorCreatingIOProcID, timer.Elapsed()); SendLogMessage("%s => Error calling AudioDeviceCreateIOProcID.", __func__); @@ -411,6 +444,14 @@ void CatapAudioInputStream::Stop() { TRACE_EVENT0("audio", "CatapAudioInputStream::Stop"); SendLogMessage("%s()", __func__); base::ElapsedTimer timer; + + // Instantly fence off the CoreAudio thread. + // If the OS thread is currently in the callback, this blocks until it + // finishes. + if (io_proc_proxy_) { + io_proc_proxy_->Detach(); + } + if (!sink_) { return; } @@ -419,12 +460,15 @@ void CatapAudioInputStream::Stop() { CHECK_NE(tap_io_proc_id_, nullptr); // Reversing Step 4. - // The call to AudioDeviceStop is synchronous. It will not return until any - // current callbacks have finished executing. The call to AudioDeviceStop() - // succeeds even though AudioDeviceStart() has not been called. + // AudioDeviceStop is synchronous when it succeeds, but may not be if it + // fails. The lock above mitigates the failure case by acting as a synchronous + // fence, ensuring that no callbacks are actively executing before we proceed. + // Note: The call to AudioDeviceStop() will succeed even if AudioDeviceStart() + // has not been called. OSStatus status = catap_api_->AudioDeviceStop(aggregate_device_id_, tap_io_proc_id_); if (status != noErr) { + stop_failed_ = true; ReportStopStatus(false, timer.Elapsed()); SendLogMessage("%s => Error stopping the device.", __func__); } @@ -444,6 +488,7 @@ void CatapAudioInputStream::Close() { Stop(); is_device_open_ = false; + bool destroy_failed = false; if (aggregate_device_id_ != kAudioObjectUnknown && tap_io_proc_id_ != nullptr) { @@ -451,6 +496,7 @@ void CatapAudioInputStream::Close() { OSStatus status = catap_api_->AudioDeviceDestroyIOProcID( aggregate_device_id_, tap_io_proc_id_); if (status != noErr) { + destroy_failed = true; ReportCloseStatus(CloseStatus::kErrorDestroyingIOProcID, timer.Elapsed()); SendLogMessage("%s => Error destroying device IO process ID.", __func__); } @@ -484,6 +530,20 @@ void CatapAudioInputStream::Close() { tap_description_ = nil; } + if (io_proc_proxy_) { + if (stop_failed_ || destroy_failed) { + // INTENTIONAL LEAK + // The OS failed to release the IOProc. The CoreAudio thread might still + // fire. We leak the proxy so the OS thread reads valid memory instead of + // triggering a Use-After-Free. + ANNOTATE_LEAKING_OBJECT_PTR(io_proc_proxy_.get()); + io_proc_proxy_.release(); + } else { + // Safe to delete, the OS has definitively relinquished the pointer. + io_proc_proxy_.reset(); + } + } + ReportCloseStatus(CloseStatus::kOk, timer.Elapsed()); // Notify the owner that the stream can be deleted. diff --git a/chromium/media/base/mac/channel_layout_util_mac.cc b/chromium/media/base/mac/channel_layout_util_mac.cc index 63f55bffea2..8ed496c6a04 100644 --- src/3rdparty/chromium/media/base/mac/channel_layout_util_mac.cc +++ src/3rdparty/chromium/media/base/mac/channel_layout_util_mac.cc @@ -127,7 +127,9 @@ std::unique_ptr ChannelLayoutToAudioChannelLayout( } else { for (int ch = 0; ch <= CHANNELS_MAX; ++ch) { const int order = ChannelOrder(input_layout, static_cast(ch)); - if (order == -1) { + // We only allocate up to `input_channels`, skip if past what was + // allocated for. + if (order == -1 || order >= input_channels) { continue; } descriptions[order].mChannelLabel = diff --git a/chromium/media/gpu/gpu_video_encode_accelerator_factory.cc b/chromium/media/gpu/gpu_video_encode_accelerator_factory.cc index f6706af1c7e..cb364a68ce8 100644 --- src/3rdparty/chromium/media/gpu/gpu_video_encode_accelerator_factory.cc +++ src/3rdparty/chromium/media/gpu/gpu_video_encode_accelerator_factory.cc @@ -148,63 +148,67 @@ std::unique_ptr CreateFuchsiaVEA() { using VEAFactoryFunction = base::RepeatingCallback()>; -std::vector GetVEAFactoryFunctions( + +std::vector CreateVEAFactoryFunctions( const gpu::GpuPreferences& gpu_preferences, const gpu::GpuDriverBugWorkarounds& gpu_workarounds, const gpu::GPUInfo::GPUDevice& gpu_device) { - // Array of VEAFactoryFunctions potentially usable on the current platform. - // This list is ordered by priority, from most to least preferred, if - // applicable. This list is composed once and then reused. - static base::NoDestructor> - vea_factory_functions; - if (gpu_preferences.disable_accelerated_video_encode) - return *vea_factory_functions; - if (!vea_factory_functions->empty()) { - return *vea_factory_functions; - } - + std::vector funcs; #if BUILDFLAG(USE_VAAPI) #if BUILDFLAG(IS_LINUX) if (base::FeatureList::IsEnabled(kAcceleratedVideoEncodeLinux)) { - vea_factory_functions->push_back(base::BindRepeating(&CreateVaapiVEA)); + funcs.push_back(base::BindRepeating(&CreateVaapiVEA)); } #else - vea_factory_functions->push_back(base::BindRepeating(&CreateVaapiVEA)); + funcs.push_back(base::BindRepeating(&CreateVaapiVEA)); #endif #elif BUILDFLAG(USE_V4L2_CODEC) #if BUILDFLAG(IS_LINUX) if (base::FeatureList::IsEnabled(kAcceleratedVideoEncodeLinux)) { - vea_factory_functions->push_back(base::BindRepeating(&CreateV4L2VEA)); + funcs.push_back(base::BindRepeating(&CreateV4L2VEA)); } #else - vea_factory_functions->push_back(base::BindRepeating(&CreateV4L2VEA)); + funcs.push_back(base::BindRepeating(&CreateV4L2VEA)); #endif #endif #if BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_WEBRTC) - vea_factory_functions->push_back(base::BindRepeating(&CreateAndroidVEA)); + funcs.push_back(base::BindRepeating(&CreateAndroidVEA)); #endif #if BUILDFLAG(IS_MAC) - vea_factory_functions->push_back(base::BindRepeating(&CreateVTVEA)); + funcs.push_back(base::BindRepeating(&CreateVTVEA)); #endif #if BUILDFLAG(IS_WIN) #if BUILDFLAG(USE_DAWN) if (base::FeatureList::IsEnabled(kD3D12VideoEncodeAccelerator)) { - vea_factory_functions->push_back( + funcs.push_back( base::BindRepeating(&CreateD3D12VEA, gpu_workarounds, gpu_device)); } else #endif { - vea_factory_functions->push_back( + funcs.push_back( base::BindRepeating(&CreateMediaFoundationVEA, gpu_preferences, gpu_workarounds, gpu_device)); } #endif #if BUILDFLAG(IS_FUCHSIA) if (base::FeatureList::IsEnabled(kFuchsiaMediacodecVideoEncoder)) { - vea_factory_functions->push_back(base::BindRepeating(&CreateFuchsiaVEA)); + funcs.push_back(base::BindRepeating(&CreateFuchsiaVEA)); } #endif + return funcs; +} + +std::vector GetVEAFactoryFunctions( + const gpu::GpuPreferences& gpu_preferences, + const gpu::GpuDriverBugWorkarounds& gpu_workarounds, + const gpu::GPUInfo::GPUDevice& gpu_device) { + // Array of VEAFactoryFunctions potentially usable on the current platform. + // This list is ordered by priority, from most to least preferred, if + // applicable. This list is composed once and then reused. + static base::NoDestructor> + vea_factory_functions(CreateVEAFactoryFunctions( + gpu_preferences, gpu_workarounds, gpu_device)); return *vea_factory_functions; } @@ -225,6 +229,34 @@ VideoEncodeAccelerator::SupportedProfiles GetSupportedProfilesInternal( GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles, &profiles); } + + if (gpu_workarounds.disable_accelerated_av1_encode) { + std::erase_if(profiles, [](const auto& vea_profile) { + return vea_profile.profile >= AV1PROFILE_PROFILE_MAIN && + vea_profile.profile <= AV1PROFILE_PROFILE_PRO; + }); + } + + if (gpu_workarounds.disable_accelerated_vp8_encode) { + std::erase_if(profiles, [](const auto& vea_profile) { + return vea_profile.profile == VP8PROFILE_ANY; + }); + } + + if (gpu_workarounds.disable_accelerated_vp9_encode) { + std::erase_if(profiles, [](const auto& vea_profile) { + return vea_profile.profile >= VP9PROFILE_PROFILE0 && + vea_profile.profile <= VP9PROFILE_PROFILE3; + }); + } + + if (gpu_workarounds.disable_accelerated_h264_encode) { + std::erase_if(profiles, [](const auto& vea_profile) { + return vea_profile.profile >= H264PROFILE_MIN && + vea_profile.profile <= H264PROFILE_MAX; + }); + } + return profiles; } @@ -247,8 +279,9 @@ GpuVideoEncodeAcceleratorFactory::CreateVEA( EncoderStatus initialization_err{ EncoderStatus::Codes::kEncoderInitializationError}; - for (const auto& create_vea : - GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device)) { + const std::vector& create_vea_functions = + GetVEAFactoryFunctions(gpu_preferences, gpu_workarounds, gpu_device); + for (const auto& create_vea : create_vea_functions) { std::unique_ptr vea = create_vea.Run(); if (!vea) continue; @@ -289,37 +322,17 @@ GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles( // (e.g. via udev) has happened instead. if (profiles->empty()) { VLOGF(1) << "Supported profiles empty, querying again..."; - *profiles = GetSupportedProfilesInternal(gpu_preferences, gpu_workarounds, - gpu_device); + static base::NoDestructor + second_try_profiles(GetSupportedProfilesInternal( + gpu_preferences, gpu_workarounds, gpu_device)); + if (second_try_profiles->empty()) { + return GetSupportedProfilesInternal(gpu_preferences, gpu_workarounds, + gpu_device); + } + return *second_try_profiles; } #endif - if (gpu_workarounds.disable_accelerated_av1_encode) { - std::erase_if(*profiles, [](const auto& vea_profile) { - return vea_profile.profile >= AV1PROFILE_PROFILE_MAIN && - vea_profile.profile <= AV1PROFILE_PROFILE_PRO; - }); - } - - if (gpu_workarounds.disable_accelerated_vp8_encode) { - std::erase_if(*profiles, [](const auto& vea_profile) { - return vea_profile.profile == VP8PROFILE_ANY; - }); - } - - if (gpu_workarounds.disable_accelerated_vp9_encode) { - std::erase_if(*profiles, [](const auto& vea_profile) { - return vea_profile.profile >= VP9PROFILE_PROFILE0 && - vea_profile.profile <= VP9PROFILE_PROFILE3; - }); - } - - if (gpu_workarounds.disable_accelerated_h264_encode) { - std::erase_if(*profiles, [](const auto& vea_profile) { - return vea_profile.profile >= H264PROFILE_MIN && - vea_profile.profile <= H264PROFILE_MAX; - }); - } return *profiles; } diff --git a/chromium/media/video/openh264_video_encoder.cc b/chromium/media/video/openh264_video_encoder.cc index e1afcd88426..14473cbfcd9 100644 --- src/3rdparty/chromium/media/video/openh264_video_encoder.cc +++ src/3rdparty/chromium/media/video/openh264_video_encoder.cc @@ -148,6 +148,18 @@ void SetUpOpenH264Params(VideoCodecProfile profile, } } +// OpenH264 silently fails during preprocessing when a frame's area +// exceeds its internal macroblock limit (MAX_MBS_PER_FRAME in +// third_party/openh264). We must manually resize such frames. +// MAX_MBS_PER_FRAME is 36864. +constexpr int kOpenH264MaxMBs = 36864; + +bool IsFrameSizeTooLarge(const gfx::Size& frame_size) { + int mb_width = (frame_size.width() + 15) / 16; + int mb_height = (frame_size.height() + 15) / 16; + return mb_width * mb_height > kOpenH264MaxMBs; +} + // OpenH264 can resize frames automatically as long as // - the input and output aspect ratios are the same and // - the input is larger than the output in both dimensions. @@ -156,6 +168,10 @@ bool NeedsManualResizing(const gfx::Size& src, const gfx::Size& dst) { return true; } + if (IsFrameSizeTooLarge(src)) { + return true; + } + if (dst.width() > src.width() || dst.height() > src.height()) { return true; } @@ -249,6 +265,14 @@ void OpenH264VideoEncoder::Initialize(VideoCodecProfile profile, "Unsupported frame size which is less than 16")); return; } + + if (IsFrameSizeTooLarge(options.frame_size)) { + std::move(done_cb).Run(EncoderStatus( + EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Configured frame size exceeds OpenH264 max macroblocks")); + return; + } + SetUpOpenH264Params( profile_, options, VideoColorSpace::FromGfxColorSpace(last_frame_color_space_), ¶ms); @@ -514,6 +538,20 @@ void OpenH264VideoEncoder::ChangeOptions(const Options& options, return; } + if (options.frame_size.width() < 16 || options.frame_size.height() < 16) { + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Unsupported frame size which is less than 16")); + return; + } + + if (IsFrameSizeTooLarge(options.frame_size)) { + std::move(done_cb).Run(EncoderStatus( + EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Configured frame size exceeds OpenH264 max macroblocks")); + return; + } + SEncParamExt params = {}; if (int err = codec_->GetDefaultParams(¶ms)) { std::move(done_cb).Run( diff --git a/chromium/net/base/elements_upload_data_stream.cc b/chromium/net/base/elements_upload_data_stream.cc index 16589b8e2bc..2bb983dd1d3 100644 --- src/3rdparty/chromium/net/base/elements_upload_data_stream.cc +++ src/3rdparty/chromium/net/base/elements_upload_data_stream.cc @@ -8,6 +8,7 @@ #include "base/check_op.h" #include "base/functional/bind.h" +#include "base/numerics/checked_math.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/upload_bytes_element_reader.h" @@ -76,11 +77,16 @@ int ElementsUploadDataStream::InitElements(size_t start_index) { return result; } - uint64_t total_size = 0; + base::CheckedNumeric total_size = 0; for (const std::unique_ptr& it : element_readers_) { total_size += it->GetContentLength(); } - SetSize(total_size); + + if (!total_size.IsValid()) { + return ERR_FILE_TOO_BIG; + } + + SetSize(total_size.ValueOrDie()); return OK; } diff --git a/chromium/net/base/upload_data_stream.cc b/chromium/net/base/upload_data_stream.cc index 8b4c183659a..de5ae7bd32a 100644 --- src/3rdparty/chromium/net/base/upload_data_stream.cc +++ src/3rdparty/chromium/net/base/upload_data_stream.cc @@ -173,9 +173,10 @@ void UploadDataStream::OnReadCompleted(int result) { if (result > 0) { current_position_ += result; if (!is_chunked_) { - DCHECK_LE(current_position_, total_size_); - if (current_position_ == total_size_) + CHECK_LE(current_position_, total_size_); + if (current_position_ == total_size_) { is_eof_ = true; + } } } diff --git a/chromium/services/network/cors/cors_url_loader.cc b/chromium/services/network/cors/cors_url_loader.cc index ccb1c8fd2ed..d35555a90b5 100644 --- src/3rdparty/chromium/services/network/cors/cors_url_loader.cc +++ src/3rdparty/chromium/services/network/cors/cors_url_loader.cc @@ -97,8 +97,9 @@ std::optional NeedsCorsPreflight( return PreflightRequiredReason::kCorsWithForcedPreflightMode; } - if (request.cors_preflight_policy == - mojom::CorsPreflightPolicy::kPreventPreflight) { + if (!base::FeatureList::IsEnabled(features::kIgnoreCorsPreflightPolicy) && + request.cors_preflight_policy == + mojom::CorsPreflightPolicy::kPreventPreflight) { return std::nullopt; } diff --git a/chromium/services/network/orb/orb_sniffers.cc b/chromium/services/network/orb/orb_sniffers.cc index f05c97cdfd7..954b4f1c2fe 100644 --- src/3rdparty/chromium/services/network/orb/orb_sniffers.cc +++ src/3rdparty/chromium/services/network/orb/orb_sniffers.cc @@ -27,6 +27,15 @@ namespace network::orb { namespace { +void AdvancePastUtf8Bom(std::string_view* data) { + // https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 + const std::string_view kUtf8Bom("\xEF\xBB\xBF"); + + if (data->starts_with(kUtf8Bom)) { + data->remove_prefix(kUtf8Bom.size()); + } +} + void AdvancePastWhitespace(std::string_view* data) { size_t offset = data->find_first_not_of(" \t\r\n"); if (offset == std::string_view::npos) { @@ -171,6 +180,7 @@ SniffingResult SniffForHTML(std::string_view data) { std::string_view(" 0) { AdvancePastWhitespace(&data); @@ -194,6 +204,7 @@ SniffingResult SniffForXML(std::string_view data) { // TODO(dsjang): Once CrossOriginReadBlocking is moved into the browser // process, we should do single-thread checking here for the static // initializer. + AdvancePastUtf8Bom(&data); AdvancePastWhitespace(&data); static constexpr std::string_view kXmlSignatures[] = { std::string_view(" checkedBufferSize = angle::base::CheckMul( + angle::base::CheckMul(sourceArea.width, sourceArea.height), pixelBytes); + ANGLE_CHECK_GL_MATH(contextGL, checkedBufferSize.IsValid()); angle::MemoryBuffer *zero; - ANGLE_CHECK_GL_ALLOC( - contextGL, - context->getZeroFilledBuffer(sourceArea.width * sourceArea.height * pixelBytes, &zero)); + ANGLE_CHECK_GL_ALLOC(contextGL, + context->getZeroFilledBuffer(checkedBufferSize.ValueOrDie(), &zero)); gl::PixelUnpackState unpack; unpack.alignment = 1; diff --git a/chromium/third_party/blink/public/mojom/loader/content_security_notifier.mojom b/chromium/third_party/blink/public/mojom/loader/content_security_notifier.mojom index bc1e5c2d07b..6fa18851c36 100644 --- src/3rdparty/chromium/third_party/blink/public/mojom/loader/content_security_notifier.mojom +++ src/3rdparty/chromium/third_party/blink/public/mojom/loader/content_security_notifier.mojom @@ -21,10 +21,24 @@ interface ContentSecurityNotifier { // connection with certificate errors was displayed. NotifyContentWithCertificateErrorsDisplayed(); - // Notifies that an embedded execution context with |origin| ran active + // Indicates which execution context's security rules triggered the mixed + // content violation. Note that in both cases, this IPC is emitted by the + // document or worker that actually loaded the insecure resource. This enum + // tells the browser which context's strictness caused the load to be flagged: + // + // - kTopFrame: The violation occurred because the top-level document is + // secure, protecting the user's expectation of security (the URL bar + // padlock). + // - kCurrentFrame: The violation occurred because the current document + // (or worker) itself is a secure context protecting its own integrity, + // even if it is embedded within an insecure top-level page. + enum InsecureContentOrigin { + kTopFrame, + kCurrentFrame, + }; + + // Notifies that an embedded execution context ran active // content (such as a script) from an insecure source. - // TODO(nhiroki): Stop passing the origin, and instead take it from the - // execution context host. - NotifyInsecureContentRan(url.mojom.Url origin, - url.mojom.Url insecure_url); + NotifyInsecureContentRan(url.mojom.Url insecure_url, + InsecureContentOrigin origin_type); }; diff --git a/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom b/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom index 67b1b5b521c..c7a01b60ec5 100644 --- src/3rdparty/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom +++ src/3rdparty/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom @@ -91,15 +91,6 @@ struct EmbeddedWorkerStartParams { // Used to set up fetch requests. RendererPreferences renderer_preferences; - // List of blink runtime features (based on their names) to enable for this - // renderer process. To avoid exposing dangerous features to other sites, this - // is only populated if the renderer process is isolated. - // - // Ideally this would be part of content.mojom.Renderer, but - // EmbedderWorkerInstanceClient and content.mojom.Renderer use separate pipes - // so a ServiceWorker could be started before the features are enabled. - array forced_enabled_runtime_features; - // Used to talk to the service worker from the browser process. pending_receiver service_worker_receiver; diff --git a/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc b/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc index 479188eb484..b2eea73448f 100644 --- src/3rdparty/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc +++ src/3rdparty/chromium/third_party/blink/renderer/core/css/element_rule_collector.cc @@ -917,18 +917,20 @@ DISABLE_CFI_PERF bool ElementRuleCollector::CollectMatchingRulesInternal( // we cannot use range-based iterators over the attributes here // if we don't synchronize before the loop; we need to use // simple indexes and then refresh the span after every call. + // We also need to not hold references into the Attribute, + // as they would be similarly invalidated. base::span attributes = GetAttributes(element, match_request.NeedStyleSynchronized()); for (unsigned attr_idx = 0; attr_idx < attributes.size(); ++attr_idx) { - const AtomicString& attribute_name = attributes[attr_idx].LocalName(); // NOTE: Attributes in non-default namespaces are case-sensitive. // There is a bug where you can set mixed-cased attributes (in // non-default namespaces) with setAttributeNS(), but they never match // anything. (The relevant code is in AnyAttributeMatches(), in // selector_checker.cc.) What we're doing here doesn't influence that // bug. - const AtomicString& lower_name = + const AtomicString& attribute_name = attributes[attr_idx].LocalName(); + const AtomicString lower_name = (lower_attrs_in_default_ns && attributes[attr_idx].NamespaceURI() == g_null_atom) ? attribute_name.LowerASCII() @@ -943,16 +945,18 @@ DISABLE_CFI_PERF bool ElementRuleCollector::CollectMatchingRulesInternal( continue; } if (CollectMatchingRulesForList( - bundle.rule_set->AttrRules(lower_name), match_request, - bundle.rule_set, bundle.style_sheet_index, checker, - context.context) && + list, match_request, bundle.rule_set, bundle.style_sheet_index, + checker, context.context) && stop_at_first_match) { return true; } - } - const AttributeCollection collection = element.AttributesWithoutUpdate(); - attributes = base::span(collection); + // Refresh the attribute span, in case CollectMatchingRulesForList() + // reallocated it. + const AttributeCollection collection = + element.AttributesWithoutUpdate(); + attributes = base::span(collection); + } } } diff --git a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc index 65e6f729e90..6f0883c5002 100644 --- src/3rdparty/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc +++ src/3rdparty/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc @@ -490,8 +490,6 @@ bool MixedContentChecker::ShouldBlockFetch( auto& local_frame_host = frame->GetLocalFrameHostRemote(); WebContentSettingsClient* content_settings_client = frame->GetContentSettingsClient(); - const SecurityOrigin* security_origin = - mixed_frame->GetSecurityContext()->GetSecurityOrigin(); bool allowed = false; // If we're in strict mode, we'll automagically fail everything, and @@ -566,8 +564,13 @@ bool MixedContentChecker::ShouldBlockFetch( // Only notify embedder about loads that would create CSP reports (i.e. // filter out preloads). if (reporting_disposition == ReportingDisposition::kReport) { - notifier.NotifyInsecureContentRan(KURL(security_origin->ToString()), - url); + auto origin_type = (mixed_frame == &frame->Tree().Top()) + ? mojom::blink::ContentSecurityNotifier:: + InsecureContentOrigin::kTopFrame + : mojom::blink::ContentSecurityNotifier:: + InsecureContentOrigin::kCurrentFrame; + + notifier.NotifyInsecureContentRan(url, origin_type); } UseCounter::Count(frame->GetDocument(), WebFeature::kMixedContentBlockableAllowed); @@ -685,10 +688,9 @@ bool MixedContentChecker::ShouldBlockFetchOnWorker( settings->GetAllowRunningOfInsecureContent(), url); if (allowed) { worker_fetch_context.GetContentSecurityNotifier() - .NotifyInsecureContentRan( - KURL( - fetch_client_settings_object.GetSecurityOrigin()->ToString()), - url); + .NotifyInsecureContentRan(url, + mojom::blink::ContentSecurityNotifier:: + InsecureContentOrigin::kCurrentFrame); worker_fetch_context.CountUsage( WebFeature::kMixedContentBlockableAllowed); } @@ -739,7 +741,6 @@ bool MixedContentChecker::IsWebSocketAllowed( WebContentSettingsClient* content_settings_client = frame->GetContentSettingsClient(); const SecurityContext* security_context = mixed_frame->GetSecurityContext(); - const SecurityOrigin* security_origin = security_context->GetSecurityOrigin(); if (ContentSecurityPolicy* policy = frame->DomWindow()->GetContentSecurityPolicy()) { @@ -755,7 +756,11 @@ bool MixedContentChecker::IsWebSocketAllowed( if (allowed) { frame_fetch_context.GetContentSecurityNotifier().NotifyInsecureContentRan( - KURL(security_origin->ToString()), url); + url, (mixed_frame == &frame->Tree().Top()) + ? mojom::blink::ContentSecurityNotifier:: + InsecureContentOrigin::kTopFrame + : mojom::blink::ContentSecurityNotifier:: + InsecureContentOrigin::kCurrentFrame); } frame->GetDocument()->AddConsoleMessage(CreateConsoleMessageAboutWebSocket( @@ -782,8 +787,6 @@ bool MixedContentChecker::IsWebSocketAllowed( } WorkerSettings* settings = worker_fetch_context.GetWorkerSettings(); - const SecurityOrigin* security_origin = - fetch_client_settings_object.GetSecurityOrigin(); bool allowed = IsWebSocketAllowedInWorker(worker_fetch_context, settings, url); @@ -791,7 +794,8 @@ bool MixedContentChecker::IsWebSocketAllowed( if (allowed) { worker_fetch_context.GetContentSecurityNotifier().NotifyInsecureContentRan( - KURL(security_origin->ToString()), url); + url, mojom::blink::ContentSecurityNotifier::InsecureContentOrigin:: + kCurrentFrame); } worker_fetch_context.GetDetachableConsoleLogger().AddConsoleMessage( diff --git a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc index 2d75fb305e5..c1c75307856 100644 --- src/3rdparty/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc +++ src/3rdparty/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc @@ -182,7 +182,9 @@ void OffscreenCanvas::SetSize(gfx::Size size) { } else if (context_->IsRenderingContext2D() || context_->IsImageBitmapRenderingContext()) { context_->Reset(); - origin_clean_ = true; + if (context_->IsRenderingContext2D()) { + origin_clean_ = true; + } } context_->DidDraw(CanvasPerformanceMonitor::DrawType::kOther); } diff --git a/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc b/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc index 9a0b1ea78c0..f461fac889f 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc @@ -150,8 +150,6 @@ void EventSource::Connect() { request.SetHttpMethod(http_names::kGET); request.SetHttpHeaderField(http_names::kAccept, AtomicString("text/event-stream")); - request.SetHttpHeaderField(http_names::kCacheControl, - AtomicString("no-cache")); request.SetRequestContext(mojom::blink::RequestContextType::EVENT_SOURCE); request.SetFetchLikeAPI(true); request.SetMode(network::mojom::RequestMode::kCors); @@ -163,14 +161,7 @@ void EventSource::Connect() { request.SetCorsPreflightPolicy( network::mojom::CorsPreflightPolicy::kPreventPreflight); if (parser_ && !parser_->LastEventId().empty()) { - // HTTP headers are Latin-1 byte strings, but the Last-Event-ID header is - // encoded as UTF-8. - // TODO(davidben): This should be captured in the type of - // setHTTPHeaderField's arguments. - std::string last_event_id_utf8 = parser_->LastEventId().Utf8(); - request.SetHttpHeaderField( - http_names::kLastEventID, - AtomicString(base::as_byte_span(last_event_id_utf8))); + request.SetEventSourceLastEventId(parser_->LastEventId()); } ResourceLoaderOptions resource_loader_options(world_); diff --git a/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc b/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc index 7f9b294990e..4508d27ad32 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc @@ -313,11 +313,17 @@ void ImageDownloaderImpl::Trace(Visitor* visitor) const { } void ImageDownloaderImpl::ContextDestroyed() { - for (const auto& fetcher : image_fetchers_) { + // Calling `Dispose()` will end up calling back synchronously into + // DidFetchImage(). To avoid `image_fetchers_` being mutated while it's being + // iterated over, move its contents to a temporary var before doing the + // iteration. + auto fetchers = std::move(image_fetchers_); + image_fetchers_.clear(); + + for (const auto& fetcher : fetchers) { // Will run callbacks with an empty image vector. fetcher->Dispose(); } - image_fetchers_.clear(); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc index 317743a0e79..fff0761080c 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc @@ -875,6 +875,7 @@ ScriptPromise RTCRtpSender::setParameters( resolver->RejectWithDOMException( DOMExceptionCode::kInvalidModificationError, "encodingOptions size must match number of encodings."); + return promise; } for (wtf_size_t i = 0; i < encoding_options.size(); i++) { encodings[i].request_key_frame = encoding_options[i]->keyFrame(); diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h index a9d38379de5..7a1913f40e9 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h +++ src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h @@ -15,6 +15,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_set_parameter_options.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/modules/mediastream/media_stream.h" +#include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_script_transform.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_send_stream.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" @@ -55,8 +56,9 @@ RTCRtpCodecParameters* ToRtpCodecParameters( const webrtc::RtpCodecParameters& codecs); // https://w3c.github.io/webrtc-pc/#rtcrtpsender-interface -class RTCRtpSender final : public ScriptWrappable, - public ExecutionContextLifecycleObserver { +class MODULES_EXPORT RTCRtpSender final + : public ScriptWrappable, + public ExecutionContextLifecycleObserver { DEFINE_WRAPPERTYPEINFO(); public: diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc index 8880892c1f5..9d223f9e0bb 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc @@ -226,7 +226,7 @@ class RTCRtpSenderImpl::RTCRtpSenderInternal } void ReplaceTrack(MediaStreamComponent* with_track, - base::OnceCallback callback) { + CrossThreadOnceFunction callback) { DCHECK(main_task_runner_->BelongsToCurrentThread()); std::unique_ptr track_ref; @@ -241,7 +241,7 @@ class RTCRtpSenderImpl::RTCRtpSenderInternal ReplaceTrackOnSignalingThread, WrapRefCounted(this), std::move(track_ref), CrossThreadUnretained(webrtc_track), - CrossThreadBindOnce(std::move(callback)))); + std::move(callback))); } std::unique_ptr GetDtmfSender() const { @@ -263,7 +263,7 @@ class RTCRtpSenderImpl::RTCRtpSenderInternal void SetParameters( Vector encodings, std::optional degradation_preference, - base::OnceCallback callback) { + CrossThreadOnceFunction callback) { DCHECK(main_task_runner_->BelongsToCurrentThread()); webrtc::RtpParameters new_parameters = parameters_; @@ -298,7 +298,7 @@ class RTCRtpSenderImpl::RTCRtpSenderInternal CrossThreadBindOnce(&RTCRtpSenderImpl::RTCRtpSenderInternal:: SetParametersOnSignalingThread, WrapRefCounted(this), std::move(new_parameters), - CrossThreadBindOnce(std::move(callback)))); + std::move(callback))); } void GetStats(RTCStatsReportCallback callback) { @@ -509,8 +509,9 @@ Vector RTCRtpSenderImpl::StreamIds() const { void RTCRtpSenderImpl::ReplaceTrack(MediaStreamComponent* with_track, RTCVoidRequest* request) { - internal_->ReplaceTrack(with_track, WTF::BindOnce(&OnReplaceTrackCompleted, - WrapPersistent(request))); + internal_->ReplaceTrack( + with_track, CrossThreadBindOnce(&OnReplaceTrackCompleted, + WrapCrossThreadPersistent(request))); } std::unique_ptr RTCRtpSenderImpl::GetDtmfSender() @@ -528,7 +529,8 @@ void RTCRtpSenderImpl::SetParameters( blink::RTCVoidRequest* request) { internal_->SetParameters( std::move(encodings), degradation_preference, - WTF::BindOnce(&OnSetParametersCompleted, WrapPersistent(request))); + CrossThreadBindOnce(&OnSetParametersCompleted, + WrapCrossThreadPersistent(request))); } void RTCRtpSenderImpl::GetStats(RTCStatsReportCallback callback) { @@ -539,8 +541,9 @@ void RTCRtpSenderImpl::SetStreams(const Vector& stream_ids) { internal_->SetStreams(stream_ids); } -void RTCRtpSenderImpl::ReplaceTrack(MediaStreamComponent* with_track, - base::OnceCallback callback) { +void RTCRtpSenderImpl::ReplaceTrack( + MediaStreamComponent* with_track, + CrossThreadOnceFunction callback) { internal_->ReplaceTrack(with_track, std::move(callback)); } diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h index 3343cb309a7..cb0b4ee07d6 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h +++ src/3rdparty/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h @@ -17,6 +17,7 @@ #include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h" #include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h" #include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/webrtc/api/peer_connection_interface.h" #include "third_party/webrtc/api/rtp_sender_interface.h" #include "third_party/webrtc/api/scoped_refptr.h" @@ -161,7 +162,7 @@ class MODULES_EXPORT RTCRtpSenderImpl : public blink::RTCRtpSenderPlatform { // ReplaceTrack() without having a blink::RTCVoidRequest, which can only be // constructed inside of blink. void ReplaceTrack(MediaStreamComponent* with_track, - base::OnceCallback callback); + CrossThreadOnceFunction callback); // Removes this sender's track from its PeerConnection. Only used in Plan B. bool RemoveFromPeerConnection(webrtc::PeerConnectionInterface* pc); diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability.cc index 87bc2526181..dd475d500a2 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/presentation/presentation_availability.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/presentation/presentation_availability.cc @@ -129,18 +129,20 @@ void PresentationAvailability::AddResolver( } void PresentationAvailability::RejectPendingPromises() { - for (auto& resolver : availability_resolvers_) { + HeapVector>> resolvers; + resolvers.swap(availability_resolvers_); + for (auto& resolver : resolvers) { resolver->RejectWithDOMException(DOMExceptionCode::kNotSupportedError, kNotSupportedErrorInfo); } - availability_resolvers_.clear(); } void PresentationAvailability::ResolvePendingPromises() { - for (auto& resolver : availability_resolvers_) { + HeapVector>> resolvers; + resolvers.swap(availability_resolvers_); + for (auto& resolver : resolvers) { resolver->Resolve(this); } - availability_resolvers_.clear(); } void PresentationAvailability::Trace(Visitor* visitor) const { diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc index eadd9ea791f..9786f71ce7e 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc @@ -103,16 +103,23 @@ void PresentationAvailabilityState::UpdateAvailability( observer->AvailabilityChanged(screen_availability); } + HeapVector> availabilities; + for (auto& availability_ptr : listener->availabilities) { + if (availability_ptr) { + availabilities.push_back(availability_ptr); + } + } + listener->availabilities.clear(); + if (screen_availability == mojom::blink::ScreenAvailability::DISABLED) { - for (auto& availability_ptr : listener->availabilities) { + for (auto& availability_ptr : availabilities) { availability_ptr->RejectPendingPromises(); } } else { - for (auto& availability_ptr : listener->availabilities) { + for (auto& availability_ptr : availabilities) { availability_ptr->ResolvePendingPromises(); } } - listener->availabilities.clear(); for (const auto& availability_url : listener->urls) { MaybeStopListeningToURL(availability_url); diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc index 3c39edae1d3..bb7b87312ee 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc @@ -78,7 +78,8 @@ void AudioNode::Dispose() { // the handler still needs to be added in case the context is resumed. DCHECK(context()); if (context()->IsPullingAudioGraph() || - context()->ContextState() == V8AudioContextState::Enum::kSuspended) { + context()->ContextState() == V8AudioContextState::Enum::kSuspended || + context()->ContextState() == V8AudioContextState::Enum::kInterrupted) { context()->GetDeferredTaskHandler().AddRenderingOrphanHandler( std::move(handler_)); } diff --git a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc index 0e257a1c9d0..d6c91349872 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc +++ src/3rdparty/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc @@ -88,7 +88,6 @@ void WebRtcAudioDeviceImpl::RenderData( audio_bus->Zero(); return; } - DCHECK(audio_transport_callback_); // Store the reported audio delay locally. output_delay_ = audio_delay; } @@ -109,9 +108,14 @@ void WebRtcAudioDeviceImpl::RenderData( TRACE_EVENT_BEGIN1("audio", "VoE::PullRenderData", "frames", frames_per_10_ms); - audio_transport_callback_->PullRenderData( - kBytesPerSample * 8, sample_rate, audio_bus->channels(), frames_per_10_ms, - audio_data, &elapsed_time_ms, &ntp_time_ms); + { + base::AutoLock callback_lock(audio_transport_callback_lock_); + if (audio_transport_callback_) { + audio_transport_callback_->PullRenderData( + kBytesPerSample * 8, sample_rate, audio_bus->channels(), + frames_per_10_ms, audio_data, &elapsed_time_ms, &ntp_time_ms); + } + } TRACE_EVENT_END2("audio", "VoE::PullRenderData", "elapsed_time_ms", elapsed_time_ms, "ntp_time_ms", ntp_time_ms); if (elapsed_time_ms >= 0) @@ -173,6 +177,7 @@ int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback( DCHECK_CALLED_ON_VALID_THREAD(signaling_thread_checker_); SendLogMessage(base::StringPrintf("%s()", __func__)); base::AutoLock lock(lock_); + base::AutoLock callback_lock(audio_transport_callback_lock_); DCHECK_EQ(!audio_transport_callback_, !!audio_callback); audio_transport_callback_ = audio_callback; return 0; @@ -246,6 +251,7 @@ int32_t WebRtcAudioDeviceImpl::StartPlayout() { DVLOG(1) << "WebRtcAudioDeviceImpl::StartPlayout()"; DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); base::AutoLock auto_lock(lock_); + base::AutoLock callback_lock(audio_transport_callback_lock_); if (!audio_transport_callback_) { LOG(ERROR) << "Audio transport is missing"; return 0; @@ -285,6 +291,7 @@ int32_t WebRtcAudioDeviceImpl::StartRecording() { DCHECK(initialized_); SendLogMessage(base::StringPrintf("%s()", __func__)); base::AutoLock auto_lock(lock_); + base::AutoLock callback_lock(audio_transport_callback_lock_); if (!audio_transport_callback_) { LOG(ERROR) << "Audio transport is missing"; return -1; diff --git a/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h b/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h index 30d437f99fe..3a34e2c6f70 100644 --- src/3rdparty/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h +++ src/3rdparty/chromium/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h @@ -169,10 +169,15 @@ class MODULES_EXPORT WebRtcAudioDeviceImpl // before it goes away. PlayoutDataSinkList playout_sinks_ GUARDED_BY(lock_); + // Protects |audio_transport_callback_| from being modified while it is in use + // by the audio render thread. + mutable base::Lock audio_transport_callback_lock_; + // Weak reference to the audio callback. // The webrtc client defines |audio_transport_callback_| by calling // RegisterAudioCallback(). - raw_ptr audio_transport_callback_; + raw_ptr audio_transport_callback_ + GUARDED_BY(audio_transport_callback_lock_); // Cached value of the current audio delay on the output/renderer side. base::TimeDelta output_delay_ GUARDED_BY(lock_); diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc index 82a5b6f2147..f5c47e3df70 100644 --- src/3rdparty/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc +++ src/3rdparty/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc @@ -434,7 +434,7 @@ int WebURLRequest::GetLoadFlagsForWebUrlRequest() const { switch (resource_request_->GetCacheMode()) { case FetchCacheMode::kNoStore: - load_flags |= net::LOAD_DISABLE_CACHE; + load_flags |= net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_CACHE; break; case FetchCacheMode::kValidateCache: load_flags |= net::LOAD_VALIDATE_CACHE; diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h index c608157b853..fe0fa7949f7 100644 --- src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h +++ src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h @@ -499,6 +499,13 @@ class PLATFORM_EXPORT ResourceRequestHead { void SetPurposeHeader(const String& value) { purpose_header_ = value; } const String& GetPurposeHeader() const { return purpose_header_; } + void SetEventSourceLastEventId(const String& value) { + event_source_last_event_id_ = value; + } + const String& GetEventSourceLastEventId() const { + return event_source_last_event_id_; + } + // A V8 stack id string describing where the request was initiated. DevTools // can use this to display the initiator call stack when debugging a process // that later intercepts the request, e.g., in a service worker fetch event @@ -784,6 +791,7 @@ class PLATFORM_EXPORT ResourceRequestHead { String requested_with_header_; String client_data_header_; String purpose_header_; + String event_source_last_event_id_; std::optional devtools_stack_id_; diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc index 7a8038f6edb..5ce53891045 100644 --- src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc +++ src/3rdparty/chromium/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc @@ -312,6 +312,15 @@ void PopulateResourceRequest(const ResourceRequestHead& src, dest->cors_exempt_headers.SetHeader(kPurposeHeaderName, src.GetPurposeHeader().Utf8()); } + // Set Last-Event-ID header to cors_exempt_headers for EventSource. + // HTTP headers are Latin-1 byte strings, but the Last-Event-ID header is + // encoded as UTF-8. + // TODO(davidben): This should be captured in the type of + // setHTTPHeaderField's arguments. + if (!src.GetEventSourceLastEventId().empty()) { + dest->cors_exempt_headers.SetHeader("Last-Event-ID", + src.GetEventSourceLastEventId().Utf8()); + } // TODO(yhirano): Remove this WrappedResourceRequest. dest->load_flags = WrappedResourceRequest(ResourceRequest(src)) diff --git a/chromium/third_party/dawn/src/dawn/native/CommandBuffer.cpp b/chromium/third_party/dawn/src/dawn/native/CommandBuffer.cpp index 0093c4dc898..981accb39bd 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/CommandBuffer.cpp +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/CommandBuffer.cpp @@ -155,7 +155,13 @@ SubresourceRange GetSubresourcesAffectedByCopy(const TextureCopy& copy, const Ex DAWN_UNREACHABLE(); } -void LazyClearRenderPassAttachments(BeginRenderPassCmd* renderPass) { +MaybeError LazyClearRenderPassAttachments(DeviceBase* device, + BeginRenderPassCmd* renderPass, + LazyClearTexture3DHelper clearTexture3D) { + if (!device->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) { + return {}; + } + for (auto i : renderPass->attachmentState->GetColorAttachmentsMask()) { auto& attachmentInfo = renderPass->colorAttachments[i]; TextureViewBase* view = attachmentInfo.view.Get(); @@ -164,14 +170,24 @@ void LazyClearRenderPassAttachments(BeginRenderPassCmd* renderPass) { DAWN_ASSERT(view->GetLayerCount() == 1); DAWN_ASSERT(view->GetLevelCount() == 1); SubresourceRange range = view->GetSubresourceRange(); + TextureBase* texture = view->GetTexture(); // If the loadOp is Load, but the subresource is not initialized, use Clear instead. if (attachmentInfo.loadOp == wgpu::LoadOp::Load && - !view->GetTexture()->IsSubresourceContentInitialized(range)) { + !texture->IsSubresourceContentInitialized(range)) { attachmentInfo.loadOp = wgpu::LoadOp::Clear; attachmentInfo.clearColor = {0.f, 0.f, 0.f, 0.f}; } + // For 3D textures, rendering to a single depthSlice marks the entire mip level as + // initialized. If it wasn't already initialized, we must clear the other slices + // before the render pass starts. + // TODO(500975625): Optimize this. + if (texture->GetDimension() == wgpu::TextureDimension::e3D && + !texture->IsSubresourceContentInitialized(range)) { + DAWN_TRY(clearTexture3D(texture, range)); + } + if (hasResolveTarget) { // We need to set the resolve target to initialized so that it does not get // cleared later in the pipeline. The texture will be resolved from the @@ -266,6 +282,7 @@ void LazyClearRenderPassAttachments(BeginRenderPassCmd* renderPass) { } } } + return {}; } bool IsFullBufferOverwrittenInTextureToBufferCopy(const CopyTextureToBufferCmd* copy) { diff --git a/chromium/third_party/dawn/src/dawn/native/CommandBuffer.h b/chromium/third_party/dawn/src/dawn/native/CommandBuffer.h index 578ea87007c..796f50db8f8 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/CommandBuffer.h +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/CommandBuffer.h @@ -91,7 +91,10 @@ bool IsCompleteSubresourceCopiedTo(const TextureBase* texture, wgpu::TextureAspect textureAspect); SubresourceRange GetSubresourcesAffectedByCopy(const TextureCopy& copy, const Extent3D& copySize); -void LazyClearRenderPassAttachments(BeginRenderPassCmd* renderPass); +using LazyClearTexture3DHelper = std::function; +MaybeError LazyClearRenderPassAttachments(DeviceBase* device, + BeginRenderPassCmd* renderPass, + LazyClearTexture3DHelper clearTexture); bool IsFullBufferOverwrittenInTextureToBufferCopy(const CopyTextureToBufferCmd* copy); bool IsFullBufferOverwrittenInTextureToBufferCopy(const TextureCopy& source, diff --git a/chromium/third_party/dawn/src/dawn/native/d3d11/CommandBufferD3D11.cpp b/chromium/third_party/dawn/src/dawn/native/d3d11/CommandBufferD3D11.cpp index 20b58ed8728..63f5f3ba527 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/d3d11/CommandBufferD3D11.cpp +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/d3d11/CommandBufferD3D11.cpp @@ -643,10 +643,19 @@ MaybeError CommandBuffer::ExecuteRenderPass( // Skip the clear as it will be handled by the workaround. colorAttachment.loadOp = wgpu::LoadOp::Load; // Mark the resource as initialized to avoid the lazy clear. - SubresourceRange range = colorAttachment.view->GetSubresourceRange(); - colorAttachment.view->GetTexture()->SetIsSubresourceContentInitialized(true, range); + // For 3D textures, the view range covers the entire mip level (all depth slices), but + // the workaround only clears a single slice. So we must not mark it as initialized + // here, and let LazyClearRenderPassAttachments handle the initialization of the + // other slices. + if (colorAttachment.view->GetTexture()->GetDimension() != wgpu::TextureDimension::e3D) { + SubresourceRange range = colorAttachment.view->GetSubresourceRange(); + colorAttachment.view->GetTexture()->SetIsSubresourceContentInitialized(true, range); + } } - LazyClearRenderPassAttachments(renderPass); + DAWN_TRY(LazyClearRenderPassAttachments( + GetDevice(), renderPass, [&](TextureBase* texture, const SubresourceRange& range) { + return ToBackend(texture)->EnsureSubresourceContentInitialized(commandContext, range); + })); auto* d3d11DeviceContext = commandContext->GetD3D11DeviceContext3(); // Hold ID3D11RenderTargetView ComPtr to make attachments alive. diff --git a/chromium/third_party/dawn/src/dawn/native/d3d12/CommandBufferD3D12.cpp b/chromium/third_party/dawn/src/dawn/native/d3d12/CommandBufferD3D12.cpp index 87a3123fa65..f4caf44d4be 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/d3d12/CommandBufferD3D12.cpp +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/d3d12/CommandBufferD3D12.cpp @@ -921,7 +921,12 @@ MaybeError CommandBuffer::RecordCommands(CommandRecordingContext* commandContext commandContext, GetResourceUsages().renderPasses[nextRenderPassNumber], &passHasUAV)); - LazyClearRenderPassAttachments(beginRenderPassCmd); + DAWN_TRY(LazyClearRenderPassAttachments( + device, beginRenderPassCmd, + [&](TextureBase* texture, const SubresourceRange& range) { + return ToBackend(texture)->EnsureSubresourceContentInitialized( + commandContext, range); + })); DAWN_TRY(RecordRenderPass(commandContext, descriptorHeapState.GetGraphicsBindingTracker(), beginRenderPassCmd, passHasUAV)); diff --git a/chromium/third_party/dawn/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp b/chromium/third_party/dawn/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp index 71b5b0acfc0..67265e6029e 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp @@ -190,7 +190,7 @@ uint32_t GetColumnPitch(uint32_t baseHeight, uint32_t mipLevelCount) { return Align(columnPitch, 4); } -uint32_t ComputeExtraArraySizeForIntelGen12(uint32_t width, +uint64_t ComputeExtraArraySizeForIntelGen12(uint32_t width, uint32_t height, uint32_t arrayLayerCount, uint32_t mipLevelCount, @@ -354,10 +354,18 @@ ResultOrError ResourceAllocatorManager::AllocateMemory( // Multisample textures have one layer at most. Only non-multisample textures need the // workaround. DAWN_ASSERT(revisedDescriptor.SampleDesc.Count <= 1); - revisedDescriptor.DepthOrArraySize += ComputeExtraArraySizeForIntelGen12( - resourceDescriptor.Width, resourceDescriptor.Height, - resourceDescriptor.DepthOrArraySize, resourceDescriptor.MipLevels, - resourceDescriptor.SampleDesc.Count, colorFormatBytesPerBlock); + // Make sure the result fits in DepthOrArraySize which is a UINT16 + uint64_t depthOrArraySize = + revisedDescriptor.DepthOrArraySize + + ComputeExtraArraySizeForIntelGen12( + resourceDescriptor.Width, resourceDescriptor.Height, + resourceDescriptor.DepthOrArraySize, resourceDescriptor.MipLevels, + resourceDescriptor.SampleDesc.Count, colorFormatBytesPerBlock); + if (depthOrArraySize >= std::numeric_limits::max()) { + return DAWN_OUT_OF_MEMORY_ERROR( + "Texture array size with Intel Gen12 workaround exceeds UINT16"); + } + revisedDescriptor.DepthOrArraySize = depthOrArraySize; } // TODO(crbug.com/dawn/849): Conditionally disable sub-allocation. diff --git a/chromium/third_party/dawn/src/dawn/native/metal/CommandBufferMTL.mm b/chromium/third_party/dawn/src/dawn/native/metal/CommandBufferMTL.mm index 4656633a8d5..6f1378c195f 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/metal/CommandBufferMTL.mm +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/metal/CommandBufferMTL.mm @@ -1042,7 +1042,13 @@ MaybeError CommandBuffer::FillCommands(CommandRecordingContext* commandContext) commandContext->EndCompute(); } - LazyClearRenderPassAttachments(cmd); + Device* device = ToBackend(GetDevice()); + DAWN_TRY(LazyClearRenderPassAttachments( + device, cmd, [&](TextureBase* texture, const SubresourceRange& range) { + return ToBackend(texture)->EnsureSubresourceContentInitialized( + commandContext, range); + })); + if (cmd->attachmentState->HasDepthStencilAttachment() && ToBackend(cmd->depthStencilAttachment.view->GetTexture()) ->ShouldKeepInitialized()) { diff --git a/chromium/third_party/dawn/src/dawn/native/opengl/CommandBufferGL.cpp b/chromium/third_party/dawn/src/dawn/native/opengl/CommandBufferGL.cpp index 03b29c0c2e8..ca10b1d9bc8 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/opengl/CommandBufferGL.cpp +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/opengl/CommandBufferGL.cpp @@ -772,7 +772,10 @@ MaybeError CommandBuffer::Execute() { } DAWN_TRY( LazyClearSyncScope(GetResourceUsages().renderPasses[nextRenderPassNumber])); - LazyClearRenderPassAttachments(cmd); + DAWN_TRY(LazyClearRenderPassAttachments( + GetDevice(), cmd, [&](TextureBase* texture, const SubresourceRange& range) { + return ToBackend(texture)->EnsureSubresourceContentInitialized(gl, range); + })); DAWN_TRY(ExecuteRenderPass(cmd)); nextRenderPassNumber++; diff --git a/chromium/third_party/dawn/src/dawn/native/vulkan/CommandBufferVk.cpp b/chromium/third_party/dawn/src/dawn/native/vulkan/CommandBufferVk.cpp index 99a420beb05..5c99db5696c 100644 --- src/3rdparty/chromium/third_party/dawn/src/dawn/native/vulkan/CommandBufferVk.cpp +++ src/3rdparty/chromium/third_party/dawn/src/dawn/native/vulkan/CommandBufferVk.cpp @@ -866,7 +866,11 @@ MaybeError CommandBuffer::RecordCommands(CommandRecordingContext* recordingConte device, recordingContext, GetResourceUsages().renderPasses[nextRenderPassNumber])); - LazyClearRenderPassAttachments(cmd); + DAWN_TRY(LazyClearRenderPassAttachments( + device, cmd, [&](TextureBase* texture, const SubresourceRange& range) { + return ToBackend(texture)->EnsureSubresourceContentInitialized( + recordingContext, range); + })); DAWN_TRY(RecordRenderPass(recordingContext, cmd)); recordingContext->hasRecordedRenderPass = true; diff --git a/chromium/third_party/dawn/src/tint/lang/core/ir/transform/robustness.cc b/chromium/third_party/dawn/src/tint/lang/core/ir/transform/robustness.cc index e0bafd4b105..cc8f1a497ae 100644 --- src/3rdparty/chromium/third_party/dawn/src/tint/lang/core/ir/transform/robustness.cc +++ src/3rdparty/chromium/third_party/dawn/src/tint/lang/core/ir/transform/robustness.cc @@ -369,6 +369,14 @@ struct State { b.Call(ty.u32(), core::BuiltinFn::kMin, CastToU32(args[idx]), limit)->Result()); }; + // Helper for clamping the sample index. + auto clamp_sample_index = [&](uint32_t idx) { + auto* num_samples = b.Call(ty.u32(), core::BuiltinFn::kTextureNumSamples, args[0]); + auto* limit = b.Subtract(num_samples, 1_u); + call->SetOperand(CoreBuiltinCall::kArgsOperandOffset + idx, + b.Min(CastToU32(args[idx]), limit)->Result()); + }; + // Select which arguments to clamp based on the function overload. switch (call->Func()) { case core::BuiltinFn::kTextureDimensions: { @@ -385,6 +393,9 @@ struct State { if (texture->IsAnyOf()) { clamp_level(next_arg++); } + if (texture->IsAnyOf()) { + clamp_sample_index(next_arg++); + } clamp_coords(1u); // Must run after clamp_level break; } diff --git a/chromium/third_party/dawn/src/tint/lang/wgsl/inspector/inspector.cc b/chromium/third_party/dawn/src/tint/lang/wgsl/inspector/inspector.cc index c94745df46c..138444c2f2b 100644 --- src/3rdparty/chromium/third_party/dawn/src/tint/lang/wgsl/inspector/inspector.cc +++ src/3rdparty/chromium/third_party/dawn/src/tint/lang/wgsl/inspector/inspector.cc @@ -570,6 +570,7 @@ const Inspector::EntryPointTextureMetadata& Inspector::ComputeTextureMetadata( } bool uses_num_levels = false; + bool uses_num_samples = false; switch (builtin->Fn()) { case wgsl::BuiltinFn::kTextureNumLevels: uses_num_levels = true; @@ -587,6 +588,8 @@ const Inspector::EntryPointTextureMetadata& Inspector::ComputeTextureMetadata( uses_num_levels = !texture_type->IsAnyOf(); + uses_num_samples = texture_type->IsAnyOf(); metadata.has_texture_load_with_depth_texture |= texture_type ->IsAnyOf(); @@ -601,10 +604,7 @@ const Inspector::EntryPointTextureMetadata& Inspector::ComputeTextureMetadata( break; case wgsl::BuiltinFn::kTextureNumSamples: - for (const auto* texture : textures) { - auto texture_binding_point = texture->Attributes().binding_point.value(); - metadata.textures_with_num_samples.insert(texture_binding_point); - } + uses_num_samples = true; break; default: @@ -617,6 +617,12 @@ const Inspector::EntryPointTextureMetadata& Inspector::ComputeTextureMetadata( metadata.textures_with_num_levels.insert(texture_binding_point); } } + if (uses_num_samples) { + for (const auto* texture : textures) { + auto texture_binding_point = texture->Attributes().binding_point.value(); + metadata.textures_with_num_samples.insert(texture_binding_point); + } + } }; // Iterate the call graph in reverse topological order such that function callers come before diff --git a/chromium/third_party/libaom/source/libaom/third_party/libwebm/mkvmuxer/mkvmuxer.cc b/chromium/third_party/libaom/source/libaom/third_party/libwebm/mkvmuxer/mkvmuxer.cc index 21e51be474e..6811c6c8430 100644 --- src/3rdparty/chromium/third_party/libaom/source/libaom/third_party/libwebm/mkvmuxer/mkvmuxer.cc +++ src/3rdparty/chromium/third_party/libaom/source/libaom/third_party/libwebm/mkvmuxer/mkvmuxer.cc @@ -4134,12 +4134,14 @@ bool Segment::WriteFramesLessThan(uint64_t timestamp) { doc_type_version_ = 4; if (!cluster->AddFrame(frame_prev)) { delete frame_prev; + ++shift_left; continue; } if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) { if (!AddCuePoint(frame_prev->timestamp(), cues_track_)) { delete frame_prev; + ++shift_left; continue; } } diff --git a/chromium/third_party/libvpx/source/libvpx/third_party/libwebm/mkvmuxer/mkvmuxer.cc b/chromium/third_party/libvpx/source/libvpx/third_party/libwebm/mkvmuxer/mkvmuxer.cc index 21e51be474e..6811c6c8430 100644 --- src/3rdparty/chromium/third_party/libvpx/source/libvpx/third_party/libwebm/mkvmuxer/mkvmuxer.cc +++ src/3rdparty/chromium/third_party/libvpx/source/libvpx/third_party/libwebm/mkvmuxer/mkvmuxer.cc @@ -4134,12 +4134,14 @@ bool Segment::WriteFramesLessThan(uint64_t timestamp) { doc_type_version_ = 4; if (!cluster->AddFrame(frame_prev)) { delete frame_prev; + ++shift_left; continue; } if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) { if (!AddCuePoint(frame_prev->timestamp(), cues_track_)) { delete frame_prev; + ++shift_left; continue; } } diff --git a/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c b/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c index d83d8f01f62..24787593a12 100644 --- src/3rdparty/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c +++ src/3rdparty/chromium/third_party/libvpx/source/libvpx/vp9/vp9_cx_iface.c @@ -72,6 +72,7 @@ typedef struct vp9_extracfg { unsigned int row_mt; unsigned int motion_vector_unit_test; int delta_q_uv; + unsigned int validate_input_hbd; } vp9_extracfg; static struct vp9_extracfg default_extra_cfg = { @@ -112,6 +113,7 @@ static struct vp9_extracfg default_extra_cfg = { 0, // row_mt 0, // motion_vector_unit_test 0, // delta_q_uv + 1, // validate_input_hbd }; struct vpx_codec_alg_priv { @@ -984,6 +986,12 @@ static vpx_codec_err_t ctrl_set_keyframe_filtering(vpx_codec_alg_priv_t *ctx, return update_extra_cfg(ctx, &extra_cfg); } +static vpx_codec_err_t ctrl_set_validate_input_hbd(vpx_codec_alg_priv_t *ctx, + va_list args) { + struct vp9_extracfg extra_cfg = ctx->extra_cfg; + extra_cfg.validate_input_hbd = CAST(VP9E_SET_VALIDATE_INPUT_HBD, args); + return update_extra_cfg(ctx, &extra_cfg); +} static vpx_codec_err_t ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t *ctx, va_list args) { struct vp9_extracfg extra_cfg = ctx->extra_cfg; @@ -1452,6 +1460,36 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, if (img != NULL) { YV12_BUFFER_CONFIG sd; +#if CONFIG_VP9_HIGHBITDEPTH + if (ctx->extra_cfg.validate_input_hbd && + (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) && + ctx->oxcf.input_bit_depth > 8) { + const unsigned int h = img->d_h; + const unsigned int w = img->d_w; + const unsigned int bit_depth = ctx->oxcf.input_bit_depth; + const int max_val = 1 << bit_depth; + for (int plane = 0; plane < 3; ++plane) { + const unsigned short *src = + (const unsigned short *)img->planes[plane]; + const unsigned int stride = img->stride[plane] / 2; + const unsigned int ph = + (plane == 0) ? h + : (h + img->y_chroma_shift) >> img->y_chroma_shift; + const unsigned int pw = + (plane == 0) ? w + : (w + img->x_chroma_shift) >> img->x_chroma_shift; + for (unsigned int i = 0; i < ph; ++i) { + for (unsigned int j = 0; j < pw; ++j) { + if (src[j] >= max_val) { + return VPX_CODEC_INVALID_PARAM; + } + } + src += stride; + } + } + } +#endif // CONFIG_VP9_HIGHBITDEPTH + if (!ctx->pts_offset_initialized) { ctx->pts_offset = pts; ctx->pts_offset_initialized = 1; @@ -2154,6 +2192,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { { VP9E_SET_TILE_ROWS, ctrl_set_tile_rows }, { VP9E_SET_TPL, ctrl_set_tpl_model }, { VP9E_SET_KEY_FRAME_FILTERING, ctrl_set_keyframe_filtering }, + { VP9E_SET_VALIDATE_INPUT_HBD, ctrl_set_validate_input_hbd }, { VP8E_SET_ARNR_MAXFRAMES, ctrl_set_arnr_max_frames }, { VP8E_SET_ARNR_STRENGTH, ctrl_set_arnr_strength }, { VP8E_SET_ARNR_TYPE, ctrl_set_arnr_type }, diff --git a/chromium/third_party/libvpx/source/libvpx/vpx/vp8cx.h b/chromium/third_party/libvpx/source/libvpx/vpx/vp8cx.h index 3a432cc12f9..459c30c6aa3 100644 --- src/3rdparty/chromium/third_party/libvpx/source/libvpx/vpx/vp8cx.h +++ src/3rdparty/chromium/third_party/libvpx/source/libvpx/vpx/vp8cx.h @@ -776,6 +776,16 @@ enum vp8e_enc_control_id { * 1. The default value is set to be 0. */ VP9E_SET_KEY_FRAME_FILTERING, + + /*!\brief Codec control function to validate HBD input. + * + * VP9 allows the encoder to validate the high bitdepth (HBD) input and + * ensure that every pixel is within the valid range. To disable/enable, + * set this parameter to 0/1. The default value is set to be 1. + * + * Supported in codecs: VP9 + */ + VP9E_SET_VALIDATE_INPUT_HBD, }; /*!\brief vpx 1-D scaling mode @@ -1108,6 +1118,8 @@ VPX_CTRL_USE_TYPE(VP9E_SET_QUANTIZER_ONE_PASS, int) #define VPX_CTRL_VP9E_SET_QUANTIZER_ONE_PASS VPX_CTRL_USE_TYPE(VP9E_SET_KEY_FRAME_FILTERING, int) #define VPX_CTRL_VP9E_SET_KEY_FRAME_FILTERING +VPX_CTRL_USE_TYPE(VP9E_SET_VALIDATE_INPUT_HBD, int) +#define VPX_CTRL_VP9E_SET_VALIDATE_INPUT_HBD /*!\endcond */ /*! @} - end defgroup vp8_encoder */ diff --git a/chromium/third_party/libwebm/source/mkvmuxer/mkvmuxer.cc b/chromium/third_party/libwebm/source/mkvmuxer/mkvmuxer.cc index 77520b70415..9ac09cbf434 100644 --- src/3rdparty/chromium/third_party/libwebm/source/mkvmuxer/mkvmuxer.cc +++ src/3rdparty/chromium/third_party/libwebm/source/mkvmuxer/mkvmuxer.cc @@ -4152,12 +4152,14 @@ bool Segment::WriteFramesLessThan(uint64_t timestamp) { doc_type_version_ = 4; if (!cluster->AddFrame(frame_prev)) { delete frame_prev; + ++shift_left; continue; } if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) { if (!AddCuePoint(frame_prev->timestamp(), cues_track_)) { delete frame_prev; + ++shift_left; continue; } } diff --git a/chromium/third_party/libxml/src/parser.c b/chromium/third_party/libxml/src/parser.c index d8d590ffd89..bf1734bac0e 100644 --- src/3rdparty/chromium/third_party/libxml/src/parser.c +++ src/3rdparty/chromium/third_party/libxml/src/parser.c @@ -7488,10 +7488,10 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { if ((cur->type == XML_TEXT_NODE) || (ctxt->options & XML_PARSE_NOCDATA)) { if (ctxt->sax->characters != NULL) - ctxt->sax->characters(ctxt, cur->content, len); + ctxt->sax->characters(ctxt->userData, cur->content, len); } else { if (ctxt->sax->cdataBlock != NULL) - ctxt->sax->cdataBlock(ctxt, cur->content, len); + ctxt->sax->cdataBlock(ctxt->userData, cur->content, len); } cur = cur->next; @@ -7511,10 +7511,10 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { if ((cur->type == XML_TEXT_NODE) || (ctxt->options & XML_PARSE_NOCDATA)) { if (ctxt->sax->characters != NULL) - ctxt->sax->characters(ctxt, cur->content, len); + ctxt->sax->characters(ctxt->userData, cur->content, len); } else { if (ctxt->sax->cdataBlock != NULL) - ctxt->sax->cdataBlock(ctxt, cur->content, len); + ctxt->sax->cdataBlock(ctxt->userData, cur->content, len); } break; diff --git a/chromium/third_party/pdfium/third_party/libopenjpeg/pi.c b/chromium/third_party/pdfium/third_party/libopenjpeg/pi.c index ad96f47eb50..b199a7b2a1d 100644 --- src/3rdparty/chromium/third_party/pdfium/third_party/libopenjpeg/pi.c +++ src/3rdparty/chromium/third_party/pdfium/third_party/libopenjpeg/pi.c @@ -1703,9 +1703,12 @@ opj_pi_iterator_t *opj_pi_initialise_encode(const opj_image_t *p_image, l_current_pi = l_pi; /* memory allocation for include*/ - l_current_pi->include_size = l_tcp->numlayers * l_step_l; - l_current_pi->include = (OPJ_INT16*) opj_calloc(l_current_pi->include_size, - sizeof(OPJ_INT16)); + l_current_pi->include = NULL; + if (l_step_l <= UINT_MAX / l_tcp->numlayers) { + l_current_pi->include_size = l_tcp->numlayers * l_step_l; + l_current_pi->include = (OPJ_INT16*) opj_calloc(l_current_pi->include_size, + sizeof(OPJ_INT16)); + } if (!l_current_pi->include) { opj_free(l_tmp_data); opj_free(l_tmp_ptr); diff --git a/chromium/third_party/pdfium/third_party/libtiff/tif_getimage.c b/chromium/third_party/pdfium/third_party/libtiff/tif_getimage.c index 3ee06262ab8..aab6b860a8c 100644 --- src/3rdparty/chromium/third_party/pdfium/third_party/libtiff/tif_getimage.c +++ src/3rdparty/chromium/third_party/pdfium/third_party/libtiff/tif_getimage.c @@ -2117,7 +2117,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) uint32_t *cp1 = cp + w + toskew; uint32_t *cp2 = cp1 + w + toskew; uint32_t *cp3 = cp2 + w + toskew; - int32_t incr = 3 * w + 4 * toskew; + const tmsize_t incr = 3 * (tmsize_t)w + 4 * (tmsize_t)toskew; (void)y; /* adjust fromskew */ @@ -2257,7 +2257,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) DECLAREContigPutFunc(putcontig8bitYCbCr42tile) { uint32_t *cp1 = cp + w + toskew; - int32_t incr = 2 * toskew + w; + const tmsize_t incr = 2 * (tmsize_t)toskew + w; (void)y; fromskew = (fromskew / 4) * (4 * 2 + 2); @@ -2413,7 +2413,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile) DECLAREContigPutFunc(putcontig8bitYCbCr22tile) { uint32_t *cp2; - int32_t incr = 2 * toskew + w; + const tmsize_t incr = 2 * (tmsize_t)toskew + w; (void)y; fromskew = (fromskew / 2) * (2 * 2 + 2); cp2 = cp + w + toskew; @@ -2516,7 +2516,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile) DECLAREContigPutFunc(putcontig8bitYCbCr12tile) { uint32_t *cp2; - int32_t incr = 2 * toskew + w; + const tmsize_t incr = 2 * (tmsize_t)toskew + w; (void)y; fromskew = (fromskew / 1) * (1 * 2 + 2); cp2 = cp + w + toskew; diff --git a/chromium/third_party/skia/include/effects/SkRuntimeEffect.h b/chromium/third_party/skia/include/effects/SkRuntimeEffect.h index 8e932cd4c93..b371d00cd85 100644 --- src/3rdparty/chromium/third_party/skia/include/effects/SkRuntimeEffect.h +++ src/3rdparty/chromium/third_party/skia/include/effects/SkRuntimeEffect.h @@ -323,8 +323,8 @@ private: uint32_t fStableKey = 0; SkString fName; - std::unique_ptr fBaseProgram; - std::unique_ptr fRPProgram; + std::unique_ptr fBaseProgram; + std::unique_ptr fRPProgram; mutable SkOnce fCompileRPProgramOnce; const SkSL::FunctionDefinition& fMain; std::vector fUniforms; diff --git a/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp b/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp index 7ba0ebe71ca..e0a441377c5 100644 --- src/3rdparty/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp +++ src/3rdparty/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp @@ -222,30 +222,48 @@ const SkSL::RP::Program* SkRuntimeEffect::getRPProgram(SkSL::DebugTracePriv* deb fCompileRPProgramOnce([&] { // We generally do not run the inliner when an SkRuntimeEffect program is initially created, // because the final compile to native shader code will do this. However, in SkRP, there's - // no additional compilation occurring, so we need to manually inline here if we want the - // performance boost of inlining. - if (!(fFlags & kDisableOptimization_Flag)) { + // no additional compilation occurring, so we need to optimize/inline here if we want the + // performance boost of inlining. Since fBaseProgram is a shared (const) object, we can't + // mutate it in-place (e.g. calling compiler.runInliner). If optimization is neccesary, + // we re-compile the program from source with inlining and optimization enabled to get a + // freshly optimized copy (it's pretty cheap to re-compile and there's no easy way to copy + // an SkSL::Program). + const SkSL::Program* programToUse = fBaseProgram.get(); + const SkSL::FunctionDefinition* mainToUse = &fMain; + + std::unique_ptr optimizedCopy; + bool shouldOptimize = !(fFlags & kDisableOptimization_Flag); + SkSL::ProgramSettings settings = fBaseProgram->fConfig->fSettings; + bool needsOptimization = !settings.fOptimize || + settings.fInlineThreshold < SkSL::kDefaultInlineThreshold; + if (shouldOptimize && needsOptimization) { SkSL::Compiler compiler; - fBaseProgram->fConfig->fSettings.fInlineThreshold = SkSL::kDefaultInlineThreshold; - compiler.runInliner(*fBaseProgram); - - // After inlining, the program is likely to have dead functions left behind. - while (SkSL::Transform::EliminateDeadFunctions(*fBaseProgram)) { - // Removing dead functions may cause more functions to become unreferenced. + settings.fOptimize = true; + settings.fInlineThreshold = SkSL::kDefaultInlineThreshold; + optimizedCopy = compiler.convertProgram( + fBaseProgram->fConfig->fKind, *fBaseProgram->fSource, settings); + SkASSERT(optimizedCopy); + if (optimizedCopy) { + const auto* mainDecl = optimizedCopy->getFunction("main"); + SkASSERT(mainDecl); + if (mainDecl) { + programToUse = optimizedCopy.get(); + mainToUse = mainDecl->definition(); + } } } SkSL::DebugTracePriv tempDebugTrace; if (debugTrace) { const_cast(this)->fRPProgram = MakeRasterPipelineProgram( - *fBaseProgram, fMain, debugTrace, /*writeTraceOps=*/true); + *programToUse, *mainToUse, debugTrace, /*writeTraceOps=*/true); } else if (kRPEnableLiveTrace) { debugTrace = &tempDebugTrace; const_cast(this)->fRPProgram = MakeRasterPipelineProgram( - *fBaseProgram, fMain, debugTrace, /*writeTraceOps=*/false); + *programToUse, *mainToUse, debugTrace, /*writeTraceOps=*/false); } else { const_cast(this)->fRPProgram = MakeRasterPipelineProgram( - *fBaseProgram, fMain, /*debugTrace=*/nullptr, /*writeTraceOps=*/false); + *programToUse, *mainToUse, /*debugTrace=*/nullptr, /*writeTraceOps=*/false); } if (kRPEnableLiveTrace) { @@ -450,8 +468,9 @@ void SkRuntimeEffectPriv::WriteChildEffects( } SkSL::ProgramSettings SkRuntimeEffect::MakeSettings(const Options& options) { + constexpr int kDisableSKSLInlining = 0; SkSL::ProgramSettings settings; - settings.fInlineThreshold = 0; + settings.fInlineThreshold = kDisableSKSLInlining; settings.fForceNoInline = options.forceUnoptimized; settings.fOptimize = !options.forceUnoptimized; settings.fMaxVersionAllowed = options.maxVersionAllowed; diff --git a/chromium/third_party/skia/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp b/chromium/third_party/skia/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp index 5f0d4b4698b..6c86bfdb180 100644 --- src/3rdparty/chromium/third_party/skia/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp +++ src/3rdparty/chromium/third_party/skia/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp @@ -387,7 +387,7 @@ void Builder::discard_stack(int32_t count, int stackID) { case BuilderOp::copy_stack_to_slots_unmasked: { // Look for a pattern of `push, immediate-ops, pop` and simplify it down to an // immediate-op directly to the value slot. - if (count == 1) { + if (count == lastInstruction->fImmA) { if (this->simplifyImmediateUnmaskedOp()) { return; } @@ -1374,7 +1374,7 @@ Program::StackDepths Program::tempStackMaxDepths() const { current[stackID] += stack_usage(inst); largest[stackID] = std::max(current[stackID], largest[stackID]); // If we assert here, the generated program has popped off the top of the stack. - SkASSERTF(current[stackID] >= 0, "unbalanced temp stack push/pop on stack %d", stackID); + SkASSERTF_RELEASE(current[stackID] >= 0, "unbalanced temp stack push/pop on stack"); } // Ensure that when the program is complete, our stacks are fully balanced. diff --git a/chromium/third_party/skia/src/text/gpu/SkChromeRemoteGlyphCache.cpp b/chromium/third_party/skia/src/text/gpu/SkChromeRemoteGlyphCache.cpp index 4c274f6022e..18788148717 100644 --- src/3rdparty/chromium/third_party/skia/src/text/gpu/SkChromeRemoteGlyphCache.cpp +++ src/3rdparty/chromium/third_party/skia/src/text/gpu/SkChromeRemoteGlyphCache.cpp @@ -644,9 +644,12 @@ bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memo SkASSERT(memorySize != 0); SkASSERT(memory != nullptr); + // Use a local copy to defend against volatile memory TOCTOU issues during deserialization. + sk_sp safeMemory = SkData::MakeWithCopy(const_cast(memory), memorySize); + // We do not need to set any SkDeserialProcs here because SkStrikeServerImpl::writeStrikeData // did not encode any SkImages. - SkReadBuffer buffer{const_cast(memory), memorySize}; + SkReadBuffer buffer{safeMemory->data(), safeMemory->size()}; // Limit the kinds of effects that appear in a glyph's drawable (crbug.com/1442140): buffer.setAllowSkSL(false); diff --git a/chromium/tools/metrics/histograms/enums.xml b/chromium/tools/metrics/histograms/enums.xml index 16596844e34..85c93682f0b 100644 --- src/3rdparty/chromium/tools/metrics/histograms/enums.xml +++ src/3rdparty/chromium/tools/metrics/histograms/enums.xml @@ -6388,6 +6388,9 @@ shown properly on the user-facing crash UI. The browser process navigated a frame to an error page based on behavior in the currently committed page. + + A request was received to change window.opener to a frame in BFCache. + diff --git a/chromium/tools/metrics/histograms/metadata/stability/enums.xml b/chromium/tools/metrics/histograms/metadata/stability/enums.xml index cce11229408..e6157848b08 100644 --- src/3rdparty/chromium/tools/metrics/histograms/metadata/stability/enums.xml +++ src/3rdparty/chromium/tools/metrics/histograms/metadata/stability/enums.xml @@ -499,6 +499,7 @@ Called by update_bad_message_reasons.py.--> + diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc index 300809acf67..dc6d530ac88 100644 --- src/3rdparty/chromium/ui/aura/window.cc +++ src/3rdparty/chromium/ui/aura/window.cc @@ -1226,9 +1226,10 @@ void Window::NotifyRemovingFromRootWindow(Window* new_root) { UnregisterFrameSinkId(); for (WindowObserver& observer : observers_) observer.OnWindowRemovingFromRootWindow(this, new_root); - for (Window::Windows::const_iterator it = children_.begin(); - it != children_.end(); ++it) { - (*it)->NotifyRemovingFromRootWindow(new_root); + + WindowTracker tracker(children_); + while (!tracker.windows().empty()) { + tracker.Pop()->NotifyRemovingFromRootWindow(new_root); } } @@ -1237,9 +1238,10 @@ void Window::NotifyAddedToRootWindow() { RegisterFrameSinkId(); for (WindowObserver& observer : observers_) observer.OnWindowAddedToRootWindow(this); - for (Window::Windows::const_iterator it = children_.begin(); - it != children_.end(); ++it) { - (*it)->NotifyAddedToRootWindow(); + + WindowTracker tracker(children_); + while (!tracker.windows().empty()) { + tracker.Pop()->NotifyAddedToRootWindow(); } } @@ -1261,9 +1263,9 @@ void Window::NotifyWindowHierarchyChange( void Window::NotifyWindowHierarchyChangeDown( const WindowObserver::HierarchyChangeParams& params) { NotifyWindowHierarchyChangeAtReceiver(params); - for (Window::Windows::const_iterator it = children_.begin(); - it != children_.end(); ++it) { - (*it)->NotifyWindowHierarchyChangeDown(params); + WindowTracker tracker(children_); + while (!tracker.windows().empty()) { + tracker.Pop()->NotifyWindowHierarchyChangeDown(params); } } diff --git a/chromium/ui/gfx/x/connection.h b/chromium/ui/gfx/x/connection.h index 766bd3fc1c4..7f2d90476e7 100644 --- src/3rdparty/chromium/ui/gfx/x/connection.h +++ src/3rdparty/chromium/ui/gfx/x/connection.h @@ -372,11 +372,14 @@ class COMPONENT_EXPORT(X11) Connection final : public XProto, .long_length = static_cast( amount ? length : std::numeric_limits::max())}) .Sync(); - if (!response || response->format / 8u != sizeof(T)) { + if (!response || + (response->format != 8 && response->format != 16 && + response->format != 32) || + response->format / 8u != sizeof(T)) { return false; } - size_t byte_len = response->value_len * response->format / 8u; + size_t byte_len = response->value_len * sizeof(T); value->resize(response->value_len); if (byte_len > 0u) { UNSAFE_TODO(memcpy(value->data(), response->value->bytes(), byte_len)); diff --git a/chromium/ui/gfx/x/gen_xproto.py b/chromium/ui/gfx/x/gen_xproto.py index 92a433828cf..6043a8cf26c 100644 --- src/3rdparty/chromium/ui/gfx/x/gen_xproto.py +++ src/3rdparty/chromium/ui/gfx/x/gen_xproto.py @@ -613,6 +613,13 @@ class GenXproto(FileWriter): if t.is_ref_counted_memory: if self.is_read: + if name == 'value' and field.parent and field.parent[1] == ( + 'xcb', 'GetProperty'): + with Indent( + self, + 'if (format != 0 && format != 8 && format != 16 && format != 32) {', + '}'): + self.write('return nullptr;') self.write('%s = buffer->ReadAndAdvance(%s);' % (name, size)) elif t.is_sized: self.write('buf.AppendSizedBuffer(%s);' % (name)) diff --git a/chromium/ui/gfx/x/generated_protos/xproto.cc b/chromium/ui/gfx/x/generated_protos/xproto.cc index d5e2ce084b8..c2d7de4860f 100644 --- src/3rdparty/chromium/ui/gfx/x/generated_protos/xproto.cc +++ src/3rdparty/chromium/ui/gfx/x/generated_protos/xproto.cc @@ -4276,6 +4276,9 @@ std::unique_ptr detail::ReadReply( Pad(&buf, 12); // value + if (format != 0 && format != 8 && format != 16 && format != 32) { + return nullptr; + } value = buffer->ReadAndAdvance((value_len) * ((format) / (8))); Align(&buf, 4); diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc index c206a2ebcb0..91711d2ace6 100644 --- src/3rdparty/chromium/ui/views/controls/menu/menu_controller.cc +++ src/3rdparty/chromium/ui/views/controls/menu/menu_controller.cc @@ -1767,8 +1767,13 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source, SetSelection(part.menu, selection_types); } -void MenuController::StartDrag(SubmenuView* source, +void MenuController::StartDrag(SubmenuView* source_raw, const gfx::Point& location) { + // TODO(crbug.com/497736679): Intended to keep `source_raw` quarantined inside + // StartDrag(). Since `source_raw` might be destroyed while RunDrawDropLoop(), + // `source` will be sometimes dangling pointer. So detecting + // `source` is dangling is expected. + raw_ptr source(source_raw); MenuItemView* item = state_.item; DCHECK(item); // Points are in the coordinates of the submenu, need to map to that of diff --git a/chromium/ui/wm/core/transient_window_manager.cc b/chromium/ui/wm/core/transient_window_manager.cc index fac1ea66227..4f2b2931d16 100644 --- src/3rdparty/chromium/ui/wm/core/transient_window_manager.cc +++ src/3rdparty/chromium/ui/wm/core/transient_window_manager.cc @@ -10,6 +10,7 @@ #include "base/auto_reset.h" #include "base/containers/contains.h" #include "base/memory/ptr_util.h" +#include "base/memory/weak_auto_reset.h" #include "base/observer_list.h" #include "ui/aura/client/transient_window_client.h" #include "ui/aura/client/transient_window_client_observer.h" @@ -170,8 +171,9 @@ void TransientWindowManager::RestackTransientDescendants() { if (child_window != window_ && HasTransientAncestor(child_window, window_)) { TransientWindowManager* descendant_manager = GetOrCreate(child_window); - base::AutoReset> resetter( - &descendant_manager->stacking_target_, window_); + base::WeakAutoReset resetter(descendant_manager->weak_factory_.GetWeakPtr(), + &TransientWindowManager::stacking_target_, + window_); parent->StackChildAbove(child_window, window_); } } @@ -191,7 +193,9 @@ void TransientWindowManager::OnWindowHierarchyChanged( // Reparenting multiple sibling transient children will call back onto us // (the transient parent) in [2] below, to restack all our descendants. We // should pause restacking until we're done with all the reparenting. - base::AutoReset reset(&pause_transient_descendants_restacking_, true); + base::WeakAutoReset reset( + weak_factory_.GetWeakPtr(), + &TransientWindowManager::pause_transient_descendants_restacking_, true); for (aura::Window* transient_child : transient_children_) { if (transient_child->parent() == old_parent) { new_parent->AddChild(transient_child); @@ -212,7 +216,9 @@ void TransientWindowManager::OnWindowHierarchyChanged( void TransientWindowManager::UpdateTransientChildVisibility( bool parent_visible) { - base::AutoReset reset(&ignore_visibility_changed_event_, true); + base::WeakAutoReset reset( + weak_factory_.GetWeakPtr(), + &TransientWindowManager::ignore_visibility_changed_event_, true); if (!parent_visible) { show_on_parent_visible_ = window_->TargetVisibility(); window_->Hide(); @@ -247,7 +253,9 @@ void TransientWindowManager::OnWindowVisibilityChanged(Window* window, } if (!transient_parent_->TargetVisibility() && visible) { - base::AutoReset reset(&ignore_visibility_changed_event_, true); + base::WeakAutoReset reset( + weak_factory_.GetWeakPtr(), + &TransientWindowManager::ignore_visibility_changed_event_, true); show_on_parent_visible_ = true; window_->Hide(); } else if (!visible) { diff --git a/chromium/ui/wm/core/transient_window_manager.h b/chromium/ui/wm/core/transient_window_manager.h index 06dc34f9298..416eff0390b 100644 --- src/3rdparty/chromium/ui/wm/core/transient_window_manager.h +++ src/3rdparty/chromium/ui/wm/core/transient_window_manager.h @@ -9,6 +9,7 @@ #include "base/component_export.h" #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "ui/aura/window_observer.h" @@ -118,6 +119,8 @@ class COMPONENT_EXPORT(UI_WM) TransientWindowManager bool pause_transient_descendants_restacking_ = false; base::ObserverList::Unchecked observers_; + + base::WeakPtrFactory weak_factory_{this}; }; } // namespace wm diff --git a/chromium/v8/src/builtins/array-slice.tq b/chromium/v8/src/builtins/array-slice.tq index 067262a9362..0557958bfd3 100644 --- src/3rdparty/chromium/v8/src/builtins/array-slice.tq +++ src/3rdparty/chromium/v8/src/builtins/array-slice.tq @@ -3,12 +3,21 @@ // found in the LICENSE file. namespace array { + +const kJSArrayHeaderSizeSlots: + constexpr int31 generates 'JSArray::kHeaderSize / kTaggedSize'; + macro HandleSimpleArgumentsSlice( context: NativeContext, args: JSArgumentsObjectWithLength, start: Smi, count: Smi): JSArray labels Bailout { // If the resulting array doesn't fit in new space, use the slow path. - if (count >= kMaxNewSpaceFixedArrayElements) goto Bailout; + // We subtract the JSArray header size to ensure the JSArray and elements + // allocation can be safely folded together into a single object. + if (count >= kMaxNewSpaceFixedArrayElements - kJSArrayHeaderSizeSlots) { + goto Bailout; + } + const end: Smi = start + count; const sourceElements: FixedArray = @@ -32,7 +41,11 @@ macro HandleFastAliasedSloppyArgumentsSlice( count: Smi): JSArray labels Bailout { // If the resulting array doesn't fit in new space, use the slow path. - if (count >= kMaxNewSpaceFixedArrayElements) goto Bailout; + // We subtract the JSArray header size to ensure the JSArray and elements + // allocation can be safely folded together into a single object. + if (count >= kMaxNewSpaceFixedArrayElements - kJSArrayHeaderSizeSlots) { + goto Bailout; + } const sloppyElements: SloppyArgumentsElements = Cast(args.elements) otherwise Bailout; diff --git a/chromium/v8/src/compiler/turboshaft/wasm-load-elimination-reducer.h b/chromium/v8/src/compiler/turboshaft/wasm-load-elimination-reducer.h index 6331c93eb09..69d72848dd9 100644 --- src/3rdparty/chromium/v8/src/compiler/turboshaft/wasm-load-elimination-reducer.h +++ src/3rdparty/chromium/v8/src/compiler/turboshaft/wasm-load-elimination-reducer.h @@ -229,10 +229,17 @@ class WasmMemoryContentTable return all_keys_.find(mem) != all_keys_.end(); } + bool LoadLikeMutability(int offset_sentinel) { + // While strings themselves are immutable, their heap object representation + // could get rewritten into a ThinString or ExternalString, so we need + // to consider them mutable (and invalidate such values at calls). + if (offset_sentinel == kStringPrepareForGetCodeunitIndex) return true; + return false; + } + OpIndex FindLoadLike(OpIndex op_idx, int offset_sentinel) { - static constexpr bool mutability = false; return FindImpl(ResolveBase(op_idx), offset_sentinel, kLoadLikeType, - kLoadLikeSize, mutability); + kLoadLikeSize, LoadLikeMutability(offset_sentinel)); } OpIndex FindImpl(OpIndex object, int offset, wasm::ModuleTypeIndex type_index, @@ -263,9 +270,8 @@ class WasmMemoryContentTable void InsertLoadLike(OpIndex base_idx, int offset_sentinel, OpIndex value_idx) { OpIndex base = ResolveBase(base_idx); - static constexpr bool mutability = false; - Insert(base, offset_sentinel, kLoadLikeType, kLoadLikeSize, mutability, - value_idx); + Insert(base, offset_sentinel, kLoadLikeType, kLoadLikeSize, + LoadLikeMutability(offset_sentinel), value_idx); } #ifdef DEBUG diff --git a/chromium/v8/src/inspector/v8-debugger-agent-impl.cc b/chromium/v8/src/inspector/v8-debugger-agent-impl.cc index fcb68f6ae6e..1e05ab60725 100644 --- src/3rdparty/chromium/v8/src/inspector/v8-debugger-agent-impl.cc +++ src/3rdparty/chromium/v8/src/inspector/v8-debugger-agent-impl.cc @@ -445,7 +445,7 @@ void V8DebuggerAgentImpl::enableImpl() { std::vector> compiledScripts = m_debugger->getCompiledScripts(m_session->contextGroupId(), this); for (auto& script : compiledScripts) { - didParseSource(std::move(script), true); + didParseSource(std::move(script)); } m_breakpointsActive = m_state->booleanProperty( @@ -698,6 +698,10 @@ Response V8DebuggerAgentImpl::setBreakpointByUrl( std::unique_ptr location = setBreakpointImpl(breakpointId, script.first, condition, adjustedLineNumber, adjustedColumnNumber); + if (!enabled()) { + return Response::ServerError( + "Debugger domain disabled during setBreakpoint"); + } if (location && type != BreakpointType::kByUrlRegex) { hint = breakpointHint(*script.second, lineNumber, columnNumber, location->getLineNumber(), @@ -1072,6 +1076,7 @@ V8DebuggerAgentImpl::setBreakpointImpl(const String16& breakpointId, ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); if (scriptIterator == m_scripts.end()) return nullptr; V8DebuggerScript* script = scriptIterator->second.get(); + if (script->hadCompileError()) return nullptr; v8::debug::BreakpointId debuggerBreakpointId; v8::debug::Location location(lineNumber, columnNumber); @@ -1082,6 +1087,7 @@ V8DebuggerAgentImpl::setBreakpointImpl(const String16& breakpointId, { v8::Context::Scope contextScope(inspected->context()); + v8::TryCatch tryCatch(m_isolate); if (!script->setBreakpoint(condition, &location, &debuggerBreakpointId)) { return nullptr; } @@ -1947,9 +1953,9 @@ class DeferredMakeWeakScope { } // namespace void V8DebuggerAgentImpl::didParseSource( - std::unique_ptr script, bool success) { + std::unique_ptr script) { v8::HandleScope handles(m_isolate); - if (!success) { + if (script->hadCompileError()) { String16 scriptSource = script->source(0); script->setSourceURL(findSourceURL(scriptSource, false)); script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); @@ -2016,7 +2022,7 @@ void V8DebuggerAgentImpl::didParseSource( ? stack->buildInspectorObjectImpl(m_debugger, 0) : nullptr; - if (!success) { + if (scriptRef->hadCompileError()) { m_frontend.scriptFailedToParse( scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), scriptRef->endLine(), scriptRef->endColumn(), contextId, diff --git a/chromium/v8/src/inspector/v8-debugger-agent-impl.h b/chromium/v8/src/inspector/v8-debugger-agent-impl.h index 7c81ced8be6..c71e9ab7fb9 100644 --- src/3rdparty/chromium/v8/src/inspector/v8-debugger-agent-impl.h +++ src/3rdparty/chromium/v8/src/inspector/v8-debugger-agent-impl.h @@ -182,7 +182,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { v8::debug::ExceptionType exceptionType, bool isUncaught, v8::debug::BreakReasons breakReasons); void didContinue(); - void didParseSource(std::unique_ptr, bool success); + void didParseSource(std::unique_ptr); bool isFunctionBlackboxed(const String16& scriptId, const v8::debug::Location& start, diff --git a/chromium/v8/src/inspector/v8-debugger-script.cc b/chromium/v8/src/inspector/v8-debugger-script.cc index 5d65d7abbb1..05f8107e9e2 100644 --- src/3rdparty/chromium/v8/src/inspector/v8-debugger-script.cc +++ src/3rdparty/chromium/v8/src/inspector/v8-debugger-script.cc @@ -42,13 +42,15 @@ String16 calculateHash(v8::Isolate* isolate, v8::Local source) { V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, v8::Local script, - bool isLiveEdit, V8DebuggerAgentImpl* agent, + bool hadCompileError, bool isLiveEdit, + V8DebuggerAgentImpl* agent, V8InspectorClient* client) : m_id(String16::fromInteger(script->Id())), m_url(GetScriptURL(isolate, script, client)), m_isolate(isolate), m_embedderName(GetScriptName(isolate, script, client)), m_agent(agent), + m_hadCompileError(hadCompileError), m_isLiveEdit(isLiveEdit) { Initialize(script); } diff --git a/chromium/v8/src/inspector/v8-debugger-script.h b/chromium/v8/src/inspector/v8-debugger-script.h index d8f5e1db9c1..107b8704692 100644 --- src/3rdparty/chromium/v8/src/inspector/v8-debugger-script.h +++ src/3rdparty/chromium/v8/src/inspector/v8-debugger-script.h @@ -53,8 +53,8 @@ class V8DebuggerScript { enum class Language { JavaScript, WebAssembly }; V8DebuggerScript(v8::Isolate* isolate, v8::Local script, - bool isLiveEdit, V8DebuggerAgentImpl* agent, - V8InspectorClient* client); + bool hadCompileError, bool isLiveEdit, + V8DebuggerAgentImpl* agent, V8InspectorClient* client); ~V8DebuggerScript() = default; V8DebuggerScript(const V8DebuggerScript&) = delete; V8DebuggerScript& operator=(const V8DebuggerScript&) = delete; @@ -76,6 +76,7 @@ class V8DebuggerScript { int endColumn() const { return m_endColumn; } int codeOffset() const; int executionContextId() const { return m_executionContextId; } + bool hadCompileError() const { return m_hadCompileError; } bool isLiveEdit() const { return m_isLiveEdit; } bool isModule() const { return m_isModule; } int length() const; @@ -132,6 +133,7 @@ class V8DebuggerScript { String16 m_sourceMappingURL; mutable String16 m_buildId; Language m_language; + bool m_hadCompileError = false; bool m_isLiveEdit = false; bool m_isModule = false; mutable String16 m_hash; diff --git a/chromium/v8/src/inspector/v8-debugger.cc b/chromium/v8/src/inspector/v8-debugger.cc index 4924ec10979..d1d7e77c15a 100644 --- src/3rdparty/chromium/v8/src/inspector/v8-debugger.cc +++ src/3rdparty/chromium/v8/src/inspector/v8-debugger.cc @@ -177,7 +177,7 @@ std::vector> V8Debugger::getCompiledScripts( if (m_inspector->contextGroupId(contextId) != contextGroupId) continue; } result.push_back(std::make_unique( - m_isolate, script, false, agent, m_inspector->client())); + m_isolate, script, false, false, agent, m_inspector->client())); } return result; } @@ -612,10 +612,8 @@ void V8Debugger::ScriptCompiled(v8::Local script, client](V8InspectorSessionImpl* session) { auto agent = session->debuggerAgent(); if (!agent->enabled()) return; - agent->didParseSource( - std::make_unique(isolate, script, is_live_edited, - agent, client), - !has_compile_error); + agent->didParseSource(std::make_unique( + isolate, script, has_compile_error, is_live_edited, agent, client)); }); }