Skip to content

Commit 86d5562

Browse files
author
Rebecca King
committed
Bug 1790641 - Only delete downloaded files in private browsing if deletePrivate pref is set to true - r=mconley,fluent-reviewers,settings-reviewers,desktop-theme-reviewers,hjones,bolsson,mossop
Differential Revision: https://phabricator.services.mozilla.com/D230168
1 parent 71c854a commit 86d5562

File tree

16 files changed

+411
-15
lines changed

16 files changed

+411
-15
lines changed

browser/components/customizableui/PanelMultiView.sys.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,9 @@ export var PanelMultiView = class extends AssociatedToNode {
11001100

11011101
// Avoid transforming element if the user has prefers-reduced-motion set
11021102
if (
1103-
this.window.matchMedia("(prefers-reduced-motion: no-preference)").matches
1103+
this.window.matchMedia("(prefers-reduced-motion: no-preference)")
1104+
.matches &&
1105+
!viewNode.getAttribute("no-panelview-transition")
11041106
) {
11051107
this._viewStack.style.transform =
11061108
"translateX(" + (moveToLeft ? "" : "-") + deltaX + "px)";

browser/components/downloads/content/downloads.js

Lines changed: 110 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ ChromeUtils.defineESModuleGetters(this, {
4040
FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
4141
NetUtil: "resource://gre/modules/NetUtil.sys.mjs",
4242
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
43+
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
4344
});
4445

4546
const { Integration } = ChromeUtils.importESModule(
@@ -710,6 +711,24 @@ var DownloadsPanel = {
710711
if (!this._openedManually) {
711712
this._delayPopupItems();
712713
}
714+
715+
let isPrivate =
716+
window && PrivateBrowsingUtils.isContentWindowPrivate(window);
717+
718+
if (
719+
// If private, show message asking whether to delete files at end of session
720+
isPrivate &&
721+
Services.prefs.getBoolPref(
722+
"browser.download.enableDeletePrivate",
723+
false
724+
) &&
725+
!Services.prefs.getBoolPref(
726+
"browser.download.deletePrivate.chosen",
727+
false
728+
)
729+
) {
730+
PrivateDownloadsSubview.openWhenReady();
731+
}
713732
}, console.error);
714733
}, 0);
715734
},
@@ -1343,7 +1362,11 @@ var DownloadsViewController = {
13431362
// nsIController
13441363

13451364
supportsCommand(aCommand) {
1346-
if (aCommand === "downloadsCmd_clearList") {
1365+
if (
1366+
aCommand === "downloadsCmd_clearList" ||
1367+
aCommand === "downloadsCmd_deletePrivate" ||
1368+
aCommand === "downloadsCmd_dismissDeletePrivate"
1369+
) {
13471370
return true;
13481371
}
13491372
// Firstly, determine if this is a command that we can handle.
@@ -1379,16 +1402,22 @@ var DownloadsViewController = {
13791402

13801403
isCommandEnabled(aCommand) {
13811404
// Handle commands that are not selection-specific.
1382-
if (aCommand == "downloadsCmd_clearList") {
1383-
return DownloadsCommon.getData(window).canRemoveFinished;
1405+
switch (aCommand) {
1406+
case "downloadsCmd_clearList": {
1407+
return DownloadsCommon.getData(window).canRemoveFinished;
1408+
}
1409+
case "downloadsCmd_deletePrivate":
1410+
case "downloadsCmd_dismissDeletePrivate":
1411+
return true;
1412+
default: {
1413+
// Other commands are selection-specific.
1414+
let element = DownloadsView.richListBox.selectedItem;
1415+
return (
1416+
element &&
1417+
DownloadsView.itemForElement(element).isCommandEnabled(aCommand)
1418+
);
1419+
}
13841420
}
1385-
1386-
// Other commands are selection-specific.
1387-
let element = DownloadsView.richListBox.selectedItem;
1388-
return (
1389-
element &&
1390-
DownloadsView.itemForElement(element).isCommandEnabled(aCommand)
1391-
);
13921421
},
13931422

13941423
doCommand(aCommand) {
@@ -1427,6 +1456,14 @@ var DownloadsViewController = {
14271456
downloadsCmd_clearList() {
14281457
DownloadsCommon.getData(window).removeFinished();
14291458
},
1459+
1460+
downloadsCmd_deletePrivate() {
1461+
PrivateDownloadsSubview.choose(true /* deletePrivate */);
1462+
},
1463+
1464+
downloadsCmd_dismissDeletePrivate() {
1465+
PrivateDownloadsSubview.choose(false /* deletePrivate */);
1466+
},
14301467
};
14311468

14321469
XPCOMUtils.defineConstant(
@@ -1781,3 +1818,66 @@ XPCOMUtils.defineConstant(
17811818
"DownloadsBlockedSubview",
17821819
DownloadsBlockedSubview
17831820
);
1821+
1822+
/**
1823+
* Manages the private browsing downloads subview that appears when you download a file in private browsing mode
1824+
*/
1825+
var PrivateDownloadsSubview = {
1826+
/**
1827+
* Slides in the private downloads subview.
1828+
*
1829+
* @param element
1830+
* The download richlistitem element that was clicked.
1831+
*/
1832+
openWhenReady() {
1833+
DownloadsView.subViewOpen = true;
1834+
DownloadsViewController.updateCommands();
1835+
1836+
this.mainView.addEventListener("ViewShown", this, { once: true });
1837+
this.mainView.toggleAttribute("showing-private-browsing-choice", true);
1838+
},
1839+
1840+
handleEvent(event) {
1841+
// This is called when the main view is shown or the panel is hidden.
1842+
1843+
// Focus the proper element if we're going back to the main panel.
1844+
if (event.type == "ViewShown") {
1845+
this.panelMultiView.showSubView(this.subview);
1846+
}
1847+
},
1848+
1849+
/**
1850+
* Sets whether to delete files at the end of private download session
1851+
* Based on user response to download notification prompt
1852+
*
1853+
* @param deletePrivate
1854+
* True if the user chose to delete files at the end of the session
1855+
*/
1856+
choose(deletePrivate) {
1857+
if (deletePrivate) {
1858+
Services.prefs.setBoolPref("browser.download.deletePrivate", true);
1859+
}
1860+
Services.prefs.setBoolPref("browser.download.deletePrivate.chosen", true);
1861+
DownloadsView.subViewOpen = false;
1862+
this.mainView.toggleAttribute("showing-private-browsing-choice", false);
1863+
this.panelMultiView.goBack();
1864+
},
1865+
};
1866+
1867+
ChromeUtils.defineLazyGetter(PrivateDownloadsSubview, "panelMultiView", () =>
1868+
document.getElementById("downloadsPanel-multiView")
1869+
);
1870+
1871+
ChromeUtils.defineLazyGetter(PrivateDownloadsSubview, "mainView", () =>
1872+
document.getElementById("downloadsPanel-mainView")
1873+
);
1874+
1875+
ChromeUtils.defineLazyGetter(PrivateDownloadsSubview, "subview", () =>
1876+
document.getElementById("downloadsPanel-privateBrowsing")
1877+
);
1878+
1879+
XPCOMUtils.defineConstant(
1880+
this,
1881+
"PrivateDownloadsSubview",
1882+
PrivateDownloadsSubview
1883+
);

browser/components/downloads/content/downloadsPanel.inc.xhtml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
<command id="downloadsCmd_alwaysOpenInSystemViewer" />
2828
<command id="downloadsCmd_alwaysOpenSimilarFiles" />
2929
<command id="downloadsCmd_deleteFile" />
30+
<command id="downloadsCmd_deletePrivate"/>
31+
<command id="downloadsCmd_dismissDeletePrivate"/>
3032
</commandset>
3133

3234
<!-- For accessibility to screen readers, we use a label on the panel instead
@@ -159,6 +161,32 @@
159161
default="true"/>
160162
</html:moz-button-group>
161163
</panelview>
164+
165+
<panelview id="downloadsPanel-privateBrowsing"
166+
class="PanelUI-subview"
167+
data-l10n-id="downloads-private-browsing-details"
168+
no-panelview-transition="true"
169+
has-custom-header="true"
170+
no-back-button="true">
171+
<box class="panel-header panel-header-with-additional-element">
172+
<html:h1>
173+
<html:span/>
174+
</html:h1>
175+
</box>
176+
<vbox class="panel-view-body-unscrollable">
177+
<description data-l10n-id="downloads-private-browsing-message"/>
178+
</vbox>
179+
<html:moz-button-group
180+
class="panel-footer">
181+
<button class="footer-button secondary"
182+
command="downloadsCmd_deletePrivate"
183+
data-l10n-id="downloads-private-browsing-delete-button"/>
184+
<button class="footer-button primary"
185+
default="true"
186+
command="downloadsCmd_dismissDeletePrivate"
187+
data-l10n-id="downloads-private-browsing-accept-button"/>
188+
</html:moz-button-group>
189+
</panelview>
162190
</panelmultiview>
163191

164192
</panel>

browser/components/preferences/main.inc.xhtml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@
492492
<checkbox id="alwaysAsk"
493493
data-l10n-id="download-always-ask-where"
494494
preference="browser.download.useDownloadDir"/>
495+
<checkbox id="deletePrivate"
496+
data-l10n-id="download-private-browsing-delete"
497+
preference="browser.download.deletePrivate"/>
495498
</groupbox>
496499

497500
<groupbox id="applicationsGroup" data-category="paneGeneral" hidden="true">

browser/components/preferences/main.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Preferences.addAll([
5757

5858
// Downloads
5959
{ id: "browser.download.useDownloadDir", type: "bool", inverted: true },
60+
{ id: "browser.download.deletePrivate", type: "bool" },
6061
{ id: "browser.download.always_ask_before_handling_new_types", type: "bool" },
6162
{ id: "browser.download.folderList", type: "int" },
6263
{ id: "browser.download.dir", type: "file" },
@@ -739,6 +740,11 @@ var gMainPane = {
739740
"command",
740741
gMainPane.onMigrationButtonCommand
741742
);
743+
setEventListener(
744+
"deletePrivate",
745+
"command",
746+
gMainPane.onDeletePrivateChanged
747+
);
742748

743749
document
744750
.getElementById("migrationWizardDialog")
@@ -1032,6 +1038,11 @@ var gMainPane = {
10321038
() => this.readBrowserContainersCheckbox()
10331039
);
10341040

1041+
if (!Services.prefs.getBoolPref("browser.download.enableDeletePrivate")) {
1042+
let deletePrivateCheckbox = document.getElementById("deletePrivate");
1043+
deletePrivateCheckbox.hidden = true;
1044+
}
1045+
10351046
this.setInitialized();
10361047
},
10371048

@@ -2453,6 +2464,10 @@ var gMainPane = {
24532464
});
24542465
},
24552466

2467+
onDeletePrivateChanged() {
2468+
Services.prefs.setBoolPref("browser.download.deletePrivate.chosen", true);
2469+
},
2470+
24562471
/**
24572472
* Displays the migration wizard dialog in an HTML dialog.
24582473
*/
@@ -3667,7 +3682,12 @@ var gMainPane = {
36673682
* True - Save files directly to the folder configured via the
36683683
* browser.download.folderList preference.
36693684
* False - Always ask the user where to save a file and default to
3670-
* browser.download.lastDir when displaying a folder picker dialog.
3685+
* browser.download.lastDir when displaying a folder picker dialog.
3686+
* browser.download.deletePrivate - bool
3687+
* True - Delete files that were downloaded in a private browsing session
3688+
* on close of the session
3689+
* False - Keep files that were downloaded in a private browsing
3690+
* session
36713691
* browser.download.always_ask_before_handling_new_types - bool
36723692
* Defines the default behavior for new file handlers.
36733693
* True - When downloading a file that doesn't match any existing

browser/locales/en-US/browser/downloads.ftl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@ downloads-history =
194194
downloads-details =
195195
.title = Download details
196196
197+
## These strings are displayed in the private browsing view of the downloads panel
198+
199+
downloads-private-browsing-details =
200+
.title = Files stay on your device
201+
downloads-private-browsing-message = Anyone using this device can see downloads, even when you close all private windows.
202+
downloads-private-browsing-delete-button =
203+
.label = Delete files automatically
204+
.accesskey = D
205+
downloads-private-browsing-accept-button =
206+
.label = Got it
207+
.accesskey = G
208+
197209
## Displayed when a site attempts to automatically download many files.
198210
## Variables:
199211
## $num (number) - Number of blocked downloads.

browser/locales/en-US/browser/preferences/preferences.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ download-choose-folder =
408408
download-always-ask-where =
409409
.label = Always ask you where to save files
410410
.accesskey = A
411+
download-private-browsing-delete =
412+
.label = Delete files downloaded in private browsing when all private windows are closed
413+
.accesskey = D
411414
412415
applications-header = Applications
413416

browser/themes/shared/downloads/downloads.inc.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,20 @@
261261
#downloadsFooterButtons > toolbarseparator {
262262
margin-inline: 0;
263263
}
264+
265+
/*** Delete files in private browsing subview ***/
266+
#downloadsPanel-mainView[showing-private-browsing-choice] > .panel-view-body-unscrollable > #downloadsListBox > richlistitem {
267+
display: none;
268+
}
269+
270+
#downloadsPanel-privateBrowsing {
271+
padding-inline-start: var(--space-medium);
272+
}
273+
274+
#downloadsPanel-privateBrowsing > .panel-header {
275+
text-align: start;
276+
}
277+
278+
#downloadsPanel-privateBrowsing > toolbarseparator {
279+
display: none;
280+
}

modules/libpref/init/StaticPrefList.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,22 @@
15931593
value: false
15941594
mirror: always
15951595

1596+
# See bug 1790641
1597+
- name: browser.download.enableDeletePrivate
1598+
type: bool
1599+
value: false
1600+
mirror: always
1601+
1602+
- name: browser.download.deletePrivate
1603+
type: bool
1604+
value: false
1605+
mirror: always
1606+
1607+
- name: browser.download.deletePrivateChosen
1608+
type: bool
1609+
value: false
1610+
mirror: always
1611+
15961612
# See bug 1731668
15971613
- name: browser.download.enable_spam_prevention
15981614
type: bool

toolkit/components/downloads/DownloadCore.sys.mjs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,8 +640,6 @@ Download.prototype = {
640640
if (this.launchWhenSucceeded) {
641641
this.launch().catch(console.error);
642642

643-
// Always schedule files to be deleted at the end of the private browsing
644-
// mode, regardless of the value of the pref.
645643
if (this.source.isPrivate) {
646644
lazy.gExternalAppLauncher.deleteTemporaryPrivateFileWhenPossible(
647645
new lazy.FileUtils.File(this.target.path)
@@ -658,6 +656,19 @@ Download.prototype = {
658656
);
659657
}
660658
}
659+
660+
if (
661+
Services.prefs.getBoolPref(
662+
"browser.download.enableDeletePrivate",
663+
false
664+
) &&
665+
Services.prefs.getBoolPref("browser.download.deletePrivate", false) &&
666+
this.source.isPrivate
667+
) {
668+
lazy.gExternalAppLauncher.deletePrivateFileWhenPossible(
669+
new lazy.FileUtils.File(this.target.path)
670+
);
671+
}
661672
},
662673

663674
/**

0 commit comments

Comments
 (0)