Chrome · Chromium
CVE-2026-7931
Logic Error in Chromium
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifios/chrome/browser/download/coordinator/download_manager_mediator.mm |
modified | |
ifios/chrome/browser/download/ui/download_manager_view_controller.mm |
modified |
Files Changed
ios/chrome/browser/download/coordinator/download_manager_mediator.hios/chrome/browser/download/coordinator/download_manager_mediator.mmios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mmios/chrome/browser/download/ui/download_manager_consumer.hios/chrome/browser/download/ui/download_manager_view_controller.mmios/chrome/test/fakes/fake_download_manager_consumer.h
Patch
From 4b80a20a9e149f08efe8437ca00f3e87c113ade8 Mon Sep 17 00:00:00 2001 From: Quentin Pubert <[email protected]> Date: Wed, 18 Mar 2026 05:41:17 -0700 Subject: [PATCH] [iOS] Always show origin in download manager This CL changes the download mediator UI so that the download origin will no longer be hidden if it happens to match the content of the address bar. Instead there will either be a origin host displayed if any is available, or instead a string indicating that the origin of the download is unknown. Bug: 474338157 Change-Id: Iae9389ac3aed54b5afefc72079d277b79daeeb1a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7674638 Reviewed-by: Olivier Robin <[email protected]> Auto-Submit: Quentin Pubert <[email protected]> Reviewed-by: Ewann Pellé <[email protected]> Commit-Queue: Olivier Robin <[email protected]> Cr-Commit-Position: refs/heads/main@{#1601200} --- diff --git a/ios/chrome/browser/download/coordinator/download_manager_mediator.h b/ios/chrome/browser/download/coordinator/download_manager_mediator.h index 6b8c8769..95c6771b 100644 --- a/ios/chrome/browser/download/coordinator/download_manager_mediator.h +++ b/ios/chrome/browser/download/coordinator/download_manager_mediator.h @@ -148,7 +148,6 @@ // Observers for NSNotificationCenter notifications. __strong id<NSObject> application_foregrounding_observer_; bool is_google_drive_app_installed_ = false; - bool should_show_origin_ = false; base::WeakPtrFactory<DownloadManagerMediator> weak_ptr_factory_; }; diff --git a/ios/chrome/browser/download/coordinator/download_manager_mediator.mm b/ios/chrome/browser/download/coordinator/download_manager_mediator.mm index e6d04fb5..1f074fb 100644 --- a/ios/chrome/browser/download/coordinator/download_manager_mediator.mm +++ b/ios/chrome/browser/download/coordinator/download_manager_mediator.mm @@ -246,7 +246,6 @@ [consumer_ setFileName:base::apple::FilePathToNSString(filename)]; NSString* originating_host = nil; - bool display_originating_host = false; if (@available(iOS 18.2, *)) { // The originating host is only populated when compiled with iOS18.2 SDK // and running on iOS18.2. @@ -259,19 +258,9 @@ originating_host = base::SysUTF8ToNSString(download_task_->GetRedirectedUrl().GetHost()); } - // Only show the compute the originating host if it is not what is displayed - // in the omnibox. - display_originating_host = - download_task_->GetWebState()->GetLastCommittedURL().GetHost() != - base::SysNSStringToUTF8(originating_host); - - // If the host was already displayed, keep it displayed - display_originating_host = display_originating_host || should_show_origin_; - should_show_origin_ = display_originating_host; } - [consumer_ setOriginatingHost:originating_host - display:display_originating_host]; + [consumer_ setOriginatingHost:originating_host]; int a11y_announcement = GetDownloadManagerA11yAnnouncement(); if (a11y_announcement != -1) { diff --git a/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm b/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm index b1159d7..c0273a1 100644 --- a/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm +++ b/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm @@ -351,21 +351,18 @@ mediator->UpdateConsumer(); EXPECT_NSEQ(consumer_.originatingHost, base::SysUTF8ToNSString(GURL(kSameDomainURL).GetHost())); - EXPECT_FALSE(consumer_.originatingHostDisplayed); // WebState and task have different domains. web_state_->SetCurrentURL(GURL(kCrossDomainURL)); mediator->UpdateConsumer(); EXPECT_NSEQ(consumer_.originatingHost, base::SysUTF8ToNSString(GURL(kSameDomainURL).GetHost())); - EXPECT_TRUE(consumer_.originatingHostDisplayed); // Navigate back, origin should still be visible. web_state_->SetCurrentURL(GURL(kSameDomainURL)); mediator->UpdateConsumer(); EXPECT_NSEQ(consumer_.originatingHost, base::SysUTF8ToNSString(GURL(kSameDomainURL).GetHost())); - EXPECT_TRUE(consumer_.originatingHostDisplayed); // Reset Mediator. web_state_->SetCurrentURL(GURL(kSameDomainURL)); @@ -380,19 +377,4 @@ mediator->UpdateConsumer(); EXPECT_NSEQ(consumer_.originatingHost, base::SysUTF8ToNSString(GURL(kCrossDomainURL).GetHost())); - EXPECT_TRUE(consumer_.originatingHostDisplayed); - - // Reset Mediator. - web_state_->SetCurrentURL(GURL(kSameDomainURL)); - mediator = std::make_unique<DownloadManagerMediator>(); - mediator->SetDownloadTask(task()); - mediator->SetConsumer(consumer_); - - // Check that if no URL is available, the placeholder is displayed. - task()->SetRedirectedURL(GURL("data:")); - task()->SetOriginatingHost(@""); - web_state_->SetCurrentURL(GURL("data:")); - mediator->UpdateConsumer(); - EXPECT_NSEQ(consumer_.originatingHost, nil); - EXPECT_TRUE(consumer_.originatingHostDisplayed); } diff --git a/ios/chrome/browser/download/ui/download_manager_consumer.h b/ios/chrome/browser/download/ui/download_manager_consumer.h index fb5d489..8359d13e 100644 --- a/ios/chrome/browser/download/ui/download_manager_consumer.h +++ b/ios/chrome/browser/download/ui/download_manager_consumer.h @@ -41,11 +41,9 @@ // Sets visible state to Install Google Drive button. - (void)setInstallDriveButtonVisible:(BOOL)visible animated:(BOOL)animated; -// Sets the originating host for the consumer. -// If `display` is false, then the string is not displayed to the user. -// If `display` is true, the host is displayed in the details of the download, -// with a special string if the host is actually empty. -- (void)setOriginatingHost:(NSString*)originatingHost display:(BOOL)display; +// Sets the originating host for the consumer. If `originatingHost` is nil then +// it means that the source of the download is unknown. +- (void)setOriginatingHost:(NSString*)originatingHost; @optional diff --git a/ios/chrome/browser/download/ui/download_manager_view_controller.mm b/ios/chrome/browser/download/ui/download_manager_view_controller.mm index 86a9969..6af12ef 100644 --- a/ios/chrome/browser/download/ui/download_manager_view_controller.mm +++ b/ios/chrome/browser/download/ui/download_manager_view_controller.mm @@ -147,7 +147,6 @@ @interface DownloadManagerViewController () <FullscreenUIElement> { NSString* _fileName; NSString* _originatingHost; - BOOL _displayOriginatingHost; int64_t _countOfBytesReceived; int64_t _countOfBytesExpectedToReceive; float _progress; @@ -352,13 +351,12 @@ } } -- (void)setOriginatingHost:(NSString*)originatingHost display:(BOOL)display { - if ([_originatingHost isEqualToString:originatingHost] && - _displayOriginatingHost == display) { +- (void)setOriginatingHost:(NSString*)originatingHost { + if (_originatingHost == originatingHost || + [_originatingHost isEqualToString:originatingHost]) { return; } _originatingHost = [originatingHost copy]; - _displayOriginatingHost = display; [self updateViews]; } @@ -817,16 +815,13 @@ self.statusLabel.text = [self localizedFileNameAndSizeWithPeriod:NO]; // Update detail label text. NSMutableArray* details = [NSMutableArray array]; - if (_displayOriginatingHost) { - if ([_originatingHost length]) { - [details addObject:l10n_util::GetNSStringF( - IDS_IOS_DOWNLOAD_MANAGER_ORIGIN_HOST_LABEL, - base::SysNSStringToUTF16(_originatingHost))]; - } else { - [details - addObject:l10n_util::GetNSString( - IDS_IOS_DOWNLOAD_MANAGER_ORIGIN_HOST_UNKNOWN_LABEL)]; - } + if ([_originatingHost length]) { + [details addObject:l10n_util::GetNSStringF( + IDS_IOS_DOWNLOAD_MANAGER_ORIGIN_HOST_LABEL, + base::SysNSStringToUTF16(_originatingHost))]; + } else { + [details addObject:l10n_util::GetNSString( + IDS_IOS_DOWNLOAD_MANAGER_ORIGIN_HOST_UNKNOWN_LABEL)]; } if (self.incognito) { [details addObject:l10n_util::GetNSString( diff --git a/ios/chrome/test/fakes/fake_download_manager_consumer.h b/ios/chrome/test/fakes/fake_download_manager_consumer.h index f4b00442..32752eb6 100644 --- a/ios/chrome/test/fakes/fake_download_manager_consumer.h +++ b/ios/chrome/test/fakes/fake_download_manager_consumer.h @@ -34,9 +34,6 @@ // The host that triggered the download. @property(nonatomic) NSString* originatingHost; -// Whether the originating host is displayed. -@property(nonatomic) BOOL originatingHostDisplayed; - @end #endif // IOS_CHROME_TEST_FAKES_FAKE_DOWNLOAD_MANAGER_CONSUMER_H_ diff --git a/ios/chrome/test/fakes/fake_download_manager_consumer.mm b/ios/chrome/test/fakes/fake_download_manager_consumer.mm index cf5d544..6d46d66 100644
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm b/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm
index b1159d7..c0273a1 100644
--- a/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm
+++ b/ios/chrome/browser/download/coordinator/download_manager_mediator_unittest.mm
@@ -351,21 +351,18 @@
mediator->UpdateConsumer();
EXPECT_NSEQ(consumer_.originatingHost,
base::SysUTF8ToNSString(GURL(kSameDomainURL).GetHost()));
- EXPECT_FALSE(consumer_.originatingHostDisplayed);
// WebState and task have different domains.
web_state_->SetCurrentURL(GURL(kCrossDomainURL));
mediator->UpdateConsumer();
EXPECT_NSEQ(consumer_.originatingHost,
base::SysUTF8ToNSString(GURL(kSameDomainURL).GetHost()));
- EXPECT_TRUE(consumer_.originatingHostDisplayed);
// Navigate back, origin should still be visible.
web_state_->SetCurrentURL(GURL(kSameDomainURL));
mediator->UpdateConsumer();
EXPECT_NSEQ(consumer_.originatingHost,
base::SysUTF8ToNSString(GURL(kSameDomainURL).GetHost()));
- EXPECT_TRUE(consumer_.originatingHostDisplayed);
// Reset Mediator.
web_state_->SetCurrentURL(GURL(kSameDomainURL));
@@ -380,19 +377,4 @@
mediator->UpdateConsumer();
EXPECT_NSEQ(consumer_.originatingHost,
base::SysUTF8ToNSString(GURL(kCrossDomainURL).GetHost()));
- EXPECT_TRUE(consumer_.originatingHostDisplayed);
-
- // Reset Mediator.
- web_state_->SetCurrentURL(GURL(kSameDomainURL));
- mediator = std::make_unique<DownloadManagerMediator>();
- mediator->SetDownloadTask(task());
- mediator->SetConsumer(consumer_);
-
- // Check that if no URL is available, the placeholder is displayed.
- task()->SetRedirectedURL(GURL("data:"));
- task()->SetOriginatingHost(@"");
- web_state_->SetCurrentURL(GURL("data:"));
- mediator->UpdateConsumer();
- EXPECT_NSEQ(consumer_.originatingHost, nil);
- EXPECT_TRUE(consumer_.originatingHostDisplayed);
}
diff --git a/ios/chrome/test/fakes/fake_download_manager_consumer.h b/ios/chrome/test/fakes/fake_download_manager_consumer.h
index f4b00442..32752eb6 100644
--- a/ios/chrome/test/fakes/fake_download_manager_consumer.h
+++ b/ios/chrome/test/fakes/fake_download_manager_consumer.h
@@ -34,9 +34,6 @@
// The host that triggered the download.
@property(nonatomic) NSString* originatingHost;
-// Whether the originating host is displayed.
-@property(nonatomic) BOOL originatingHostDisplayed;
-
@end
#endif // IOS_CHROME_TEST_FAKES_FAKE_DOWNLOAD_MANAGER_CONSUMER_H_
diff --git a/ios/chrome/test/fakes/fake_download_manager_consumer.mm b/ios/chrome/test/fakes/fake_download_manager_consumer.mm
index cf5d544..6d46d66 100644
--- a/ios/chrome/test/fakes/fake_download_manager_consumer.mm
+++ b/ios/chrome/test/fakes/fake_download_manager_consumer.mm
@@ -28,9 +28,4 @@
- (void)setCanOpenFile:(BOOL)canOpenFile {
}
-- (void)setOriginatingHost:(NSString*)originatingHost display:(BOOL)display {
- _originatingHost = originatingHost;
- _originatingHostDisplayed = display;
-}
-
@end
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page