[tbb-commits] [tor-browser] 49/73: Bug 1761265, don't show the downloads panel when a download was started by user action that they expect will save the file, r=mhowell, kershaw a=RyanVM
gitolite role
git at cupani.torproject.org
Wed Sep 21 20:17:42 UTC 2022
This is an automated email from the git hooks/post-receive script.
richard pushed a commit to branch geckoview-102.3.0esr-12.0-1
in repository tor-browser.
commit 2c8bd7596866106d17260f75a5a9480f52ddd207
Author: Neil Deakin <neil at mozilla.com>
AuthorDate: Mon Jun 6 22:23:58 2022 +0000
Bug 1761265, don't show the downloads panel when a download was started by user action that they expect will save the file, r=mhowell,kershaw a=RyanVM
The download panel should still appear when clicking on download links or those with content-disposition: attachment
Differential Revision: https://phabricator.services.mozilla.com/D147875
---
.../components/downloads/test/browser/browser.ini | 1 +
.../browser/browser_downloads_panel_dontshow.js | 126 +++++++++++++++++++++
dom/webbrowserpersist/nsWebBrowserPersist.cpp | 3 +
netwerk/base/LoadInfo.cpp | 14 +++
netwerk/base/LoadInfo.h | 1 +
netwerk/base/TRRLoadInfo.cpp | 10 ++
netwerk/base/nsILoadInfo.idl | 6 +
toolkit/components/downloads/DownloadCore.jsm | 9 ++
.../pdfjs/test/browser_pdfjs_download_button.js | 31 +++--
9 files changed, 190 insertions(+), 11 deletions(-)
diff --git a/browser/components/downloads/test/browser/browser.ini b/browser/components/downloads/test/browser/browser.ini
index 35d3d9a486f8b..f803f34daa988 100644
--- a/browser/components/downloads/test/browser/browser.ini
+++ b/browser/components/downloads/test/browser/browser.ini
@@ -45,6 +45,7 @@ skip-if =
support-files =
foo.txt
foo.txt^headers^
+[browser_downloads_panel_dontshow.js]
[browser_downloads_panel_height.js]
[browser_downloads_panel_opens.js]
[browser_downloads_autohide.js]
diff --git a/browser/components/downloads/test/browser/browser_downloads_panel_dontshow.js b/browser/components/downloads/test/browser/browser_downloads_panel_dontshow.js
new file mode 100644
index 0000000000000..b6de758723907
--- /dev/null
+++ b/browser/components/downloads/test/browser/browser_downloads_panel_dontshow.js
@@ -0,0 +1,126 @@
+// This test verifies that the download panel opens when a
+// download occurs but not when a user manually saves a page.
+
+let MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+async function promiseDownloadFinished(list) {
+ return new Promise(resolve => {
+ list.addView({
+ onDownloadChanged(download) {
+ download.launchWhenSucceeded = false;
+ if (download.succeeded || download.error) {
+ list.removeView(this);
+ resolve(download);
+ }
+ },
+ });
+ });
+}
+
+function openTestPage() {
+ return BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ `https://www.example.com/document-builder.sjs?html=
+ <html><body>
+ <a id='normallink' href='https://www.example.com'>Link1</a>
+ <a id='downloadlink' href='https://www.example.com' download='file.txt'>Link2</a>
+ </body</html>
+ `
+ );
+}
+
+add_task(async function download_saveas_file() {
+ let tab = await openTestPage();
+
+ for (let testname of ["save link", "save page"]) {
+ if (testname == "save link") {
+ let menu = document.getElementById("contentAreaContextMenu");
+ let popupShown = BrowserTestUtils.waitForEvent(menu, "popupshown");
+ BrowserTestUtils.synthesizeMouse(
+ "#normallink",
+ 5,
+ 5,
+ { type: "contextmenu", button: 2 },
+ gBrowser.selectedBrowser
+ );
+ await popupShown;
+ }
+
+ let list = await Downloads.getList(Downloads.PUBLIC);
+ let downloadFinishedPromise = promiseDownloadFinished(list);
+
+ let saveFile = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ saveFile.append("testsavedir");
+ if (!saveFile.exists()) {
+ saveFile.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
+ }
+
+ await new Promise(resolve => {
+ MockFilePicker.showCallback = function(fp) {
+ saveFile.append("sample");
+ MockFilePicker.setFiles([saveFile]);
+ setTimeout(() => {
+ resolve(fp.defaultString);
+ }, 0);
+ return Ci.nsIFilePicker.returnOK;
+ };
+
+ if (testname == "save link") {
+ let menu = document.getElementById("contentAreaContextMenu");
+ let menuitem = document.getElementById("context-savelink");
+ menu.activateItem(menuitem);
+ } else if (testname == "save page") {
+ document.getElementById("Browser:SavePage").doCommand();
+ }
+ });
+
+ await downloadFinishedPromise;
+ is(
+ DownloadsPanel.panel.state,
+ "closed",
+ "downloads panel closed after download link after " + testname
+ );
+ }
+
+ await task_resetState();
+
+ MockFilePicker.cleanup();
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function download_link() {
+ let tab = await openTestPage();
+
+ let list = await Downloads.getList(Downloads.PUBLIC);
+ let downloadFinishedPromise = promiseDownloadFinished(list);
+
+ let panelOpenedPromise = promisePanelOpened();
+
+ BrowserTestUtils.synthesizeMouse(
+ "#downloadlink",
+ 5,
+ 5,
+ {},
+ gBrowser.selectedBrowser
+ );
+
+ let download = await downloadFinishedPromise;
+ await panelOpenedPromise;
+
+ is(
+ DownloadsPanel.panel.state,
+ "open",
+ "downloads panel open after download link clicked"
+ );
+
+ DownloadsPanel.hidePanel();
+
+ await task_resetState();
+
+ BrowserTestUtils.removeTab(tab);
+
+ try {
+ await IOUtils.remove(download.target.path);
+ } catch (ex) {}
+});
diff --git a/dom/webbrowserpersist/nsWebBrowserPersist.cpp b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
index f2c2ebf588408..7f304a77e8489 100644
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -1377,6 +1377,9 @@ nsresult nsWebBrowserPersist::SaveURIInternal(
}
}
+ nsCOMPtr<nsILoadInfo> loadInfo = inputChannel->LoadInfo();
+ loadInfo->SetIsUserTriggeredSave(true);
+
// Set the referrer, post data and headers if any
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
if (httpChannel) {
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
index c70ae05224c37..5f5f9d0514768 100644
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -1800,6 +1800,20 @@ LoadInfo::SetAllowDeprecatedSystemRequests(
return NS_OK;
}
+NS_IMETHODIMP
+LoadInfo::GetIsUserTriggeredSave(bool* aIsUserTriggeredSave) {
+ *aIsUserTriggeredSave =
+ mIsUserTriggeredSave ||
+ mInternalContentPolicyType == nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+LoadInfo::SetIsUserTriggeredSave(bool aIsUserTriggeredSave) {
+ mIsUserTriggeredSave = aIsUserTriggeredSave;
+ return NS_OK;
+}
+
NS_IMETHODIMP
LoadInfo::GetIsInDevToolsContext(bool* aIsInDevToolsContext) {
*aIsInDevToolsContext = mIsInDevToolsContext;
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
index 6452948b199c1..a1624592d20dc 100644
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -330,6 +330,7 @@ class LoadInfo final : public nsILoadInfo {
uint32_t mHttpsOnlyStatus = nsILoadInfo::HTTPS_ONLY_UNINITIALIZED;
bool mHasValidUserGestureActivation = false;
bool mAllowDeprecatedSystemRequests = false;
+ bool mIsUserTriggeredSave = false;
bool mIsInDevToolsContext = false;
bool mParserCreatedScript = false;
nsILoadInfo::StoragePermissionState mStoragePermission =
diff --git a/netwerk/base/TRRLoadInfo.cpp b/netwerk/base/TRRLoadInfo.cpp
index 7ef044cb25171..05a8878a3f26a 100644
--- a/netwerk/base/TRRLoadInfo.cpp
+++ b/netwerk/base/TRRLoadInfo.cpp
@@ -698,6 +698,16 @@ TRRLoadInfo::SetAllowDeprecatedSystemRequests(
return NS_ERROR_NOT_IMPLEMENTED;
}
+NS_IMETHODIMP
+TRRLoadInfo::GetIsUserTriggeredSave(bool* aIsUserTriggeredSave) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+TRRLoadInfo::SetIsUserTriggeredSave(bool aIsUserTriggeredSave) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
NS_IMETHODIMP
TRRLoadInfo::GetIsInDevToolsContext(bool* aIsInDevToolsContext) {
return NS_ERROR_NOT_IMPLEMENTED;
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
index 0a7d0c66fb3e5..85ba879702980 100644
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -510,6 +510,12 @@ interface nsILoadInfo : nsISupports
*/
[infallible] attribute boolean parserCreatedScript;
+ /**
+ * True if this request is known to have been triggered by a user
+ * manually requesting the URI to be saved.
+ */
+ [infallible] attribute boolean isUserTriggeredSave;
+
/**
* True if this request is from DevTools.
*/
diff --git a/toolkit/components/downloads/DownloadCore.jsm b/toolkit/components/downloads/DownloadCore.jsm
index 5292828f593a1..20771432cd47d 100644
--- a/toolkit/components/downloads/DownloadCore.jsm
+++ b/toolkit/components/downloads/DownloadCore.jsm
@@ -2865,6 +2865,15 @@ DownloadLegacySaver.prototype = {
this.download.source.referrerInfo = aRequest.referrerInfo;
}
+ // Don't open the download panel when the user initiated to save a
+ // link or document.
+ if (
+ aRequest instanceof Ci.nsIChannel &&
+ aRequest.loadInfo.isUserTriggeredSave
+ ) {
+ this.download.openDownloadsListOnStart = false;
+ }
+
this.addToHistory();
},
diff --git a/toolkit/components/pdfjs/test/browser_pdfjs_download_button.js b/toolkit/components/pdfjs/test/browser_pdfjs_download_button.js
index 5f21b241a223a..b0040a71941f6 100644
--- a/toolkit/components/pdfjs/test/browser_pdfjs_download_button.js
+++ b/toolkit/components/pdfjs/test/browser_pdfjs_download_button.js
@@ -12,6 +12,20 @@ MockFilePicker.returnValue = MockFilePicker.returnOK;
var tempDir;
+async function promiseDownloadFinished(list) {
+ return new Promise(resolve => {
+ list.addView({
+ onDownloadChanged(download) {
+ download.launchWhenSucceeded = false;
+ if (download.succeeded || download.error) {
+ list.removeView(this);
+ resolve(download);
+ }
+ },
+ });
+ });
+}
+
function createPromiseForFilePicker() {
return new Promise(resolve => {
MockFilePicker.showCallback = fp => {
@@ -77,10 +91,7 @@ add_task(async function test_downloading_pdf_nonprivate_window() {
let filePickerShown = createPromiseForFilePicker();
- let downloadsPanelPromise = BrowserTestUtils.waitForEvent(
- DownloadsPanel.panel,
- "popupshown"
- );
+ let downloadFinishedPromise = promiseDownloadFinished(downloadList);
info("Clicking on the download button...");
await SpecialPowers.spawn(browser, [], () => {
@@ -89,14 +100,13 @@ add_task(async function test_downloading_pdf_nonprivate_window() {
info("Waiting for a filename to be picked from the file picker");
await filePickerShown;
- // check that resulted in a download being added to the list
- // and the dl panel opened
- info("Waiting for download panel to open when the download is complete");
- await downloadsPanelPromise;
+ // check that resulted in a download being added to the list. The
+ // download panel should not open.
+ await downloadFinishedPromise;
is(
DownloadsPanel.panel.state,
- "open",
- "Check the download panel state is 'open'"
+ "closed",
+ "Check the download panel state is 'closed'"
);
downloadList = await Downloads.getList(Downloads.PUBLIC);
const allDownloads = await downloadList.getAll();
@@ -120,7 +130,6 @@ add_task(async function test_downloading_pdf_nonprivate_window() {
tabCount,
"No new tab was opened to view the downloaded PDF"
);
- await closeDownloadsPanel();
}
);
});
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the tbb-commits
mailing list