mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1068660 - Add confirmation dialog to unblock downloads. r=Paolo r=MattN
This commit is contained in:
parent
175343fd0f
commit
d6907bfa04
@ -67,6 +67,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
||||
"resource:///modules/RecentWindow.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsLogger",
|
||||
"resource:///modules/DownloadsLogger.jsm");
|
||||
|
||||
@ -143,6 +145,13 @@ PrefObserver.register({
|
||||
* and provides shared methods for all the instances of the user interface.
|
||||
*/
|
||||
this.DownloadsCommon = {
|
||||
/**
|
||||
* Constants with the different types of unblock messages.
|
||||
*/
|
||||
BLOCK_VERDICT_MALWARE: "Malware",
|
||||
BLOCK_VERDICT_POTENTIALLY_UNWANTED: "PotentiallyUnwanted",
|
||||
BLOCK_VERDICT_UNCOMMON: "Uncommon",
|
||||
|
||||
log: function DC_log(...aMessageArgs) {
|
||||
delete this.log;
|
||||
this.log = function DC_log(...aMessageArgs) {
|
||||
@ -511,7 +520,69 @@ this.DownloadsCommon = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays an alert message box which asks the user if they want to
|
||||
* unblock the downloaded file or not.
|
||||
*
|
||||
* @param aType
|
||||
* The type of malware the downloaded file contains.
|
||||
* @param aOwnerWindow
|
||||
* The window with which this action is associated.
|
||||
*
|
||||
* @return True to unblock the file, false to keep the user safe and
|
||||
* cancel the operation.
|
||||
*/
|
||||
confirmUnblockDownload: Task.async(function* DP_confirmUnblockDownload(aType, aOwnerWindow) {
|
||||
let s = DownloadsCommon.strings;
|
||||
let title = s.unblockHeader;
|
||||
let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
|
||||
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
|
||||
let type = "";
|
||||
let message = s.unblockTip;
|
||||
let okButton = s.unblockButtonContinue;
|
||||
let cancelButton = s.unblockButtonCancel;
|
||||
|
||||
switch (aType) {
|
||||
case this.BLOCK_VERDICT_MALWARE:
|
||||
type = s.unblockTypeMalware;
|
||||
break;
|
||||
case this.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
|
||||
type = s.unblockTypePotentiallyUnwanted;
|
||||
break;
|
||||
case this.BLOCK_VERDICT_UNCOMMON:
|
||||
type = s.unblockTypeUncommon;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
message = type + "\n\n" + message;
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(function onOpen(subj, topic) {
|
||||
if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
|
||||
// Make sure to listen for "DOMContentLoaded" because it is fired
|
||||
// before the "load" event.
|
||||
subj.addEventListener("DOMContentLoaded", function onLoad() {
|
||||
subj.removeEventListener("DOMContentLoaded", onLoad);
|
||||
if (subj.document.documentURI ==
|
||||
"chrome://global/content/commonDialog.xul") {
|
||||
Services.ww.unregisterNotification(onOpen);
|
||||
let dialog = subj.document.getElementById("commonDialog");
|
||||
if (dialog) {
|
||||
// Change the dialog to use a warning icon.
|
||||
dialog.classList.add("alert-dialog");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let rv = Services.prompt.confirmEx(aOwnerWindow, title, message, buttonFlags,
|
||||
cancelButton, okButton, null, null, {});
|
||||
return (rv == 1);
|
||||
}),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -7,3 +7,4 @@ skip-if = buildapp == "mulet" || e10s
|
||||
skip-if = os == "linux" # Bug 949434
|
||||
[browser_overflow_anchor.js]
|
||||
skip-if = os == "linux" # Bug 952422
|
||||
[browser_confirm_unblock_download.js]
|
||||
|
@ -3,12 +3,15 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
registerCleanupFunction(function*() {
|
||||
yield task_resetState();
|
||||
});
|
||||
|
||||
/**
|
||||
* Make sure the downloads panel can display items in the right order and
|
||||
* contains the expected data.
|
||||
*/
|
||||
function test_task()
|
||||
{
|
||||
add_task(function* test_basic_functionality() {
|
||||
// Display one of each download state.
|
||||
const DownloadData = [
|
||||
{ state: nsIDM.DOWNLOAD_NOTSTARTED },
|
||||
@ -18,40 +21,35 @@ function test_task()
|
||||
{ state: nsIDM.DOWNLOAD_CANCELED },
|
||||
];
|
||||
|
||||
try {
|
||||
// Wait for focus first
|
||||
yield promiseFocus();
|
||||
// Wait for focus first
|
||||
yield promiseFocus();
|
||||
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
|
||||
// For testing purposes, show all the download items at once.
|
||||
var originalCountLimit = DownloadsView.kItemCountLimit;
|
||||
DownloadsView.kItemCountLimit = DownloadData.length;
|
||||
registerCleanupFunction(function () {
|
||||
DownloadsView.kItemCountLimit = originalCountLimit;
|
||||
});
|
||||
// For testing purposes, show all the download items at once.
|
||||
var originalCountLimit = DownloadsView.kItemCountLimit;
|
||||
DownloadsView.kItemCountLimit = DownloadData.length;
|
||||
registerCleanupFunction(function () {
|
||||
DownloadsView.kItemCountLimit = originalCountLimit;
|
||||
});
|
||||
|
||||
// Populate the downloads database with the data required by this test.
|
||||
yield task_addDownloads(DownloadData);
|
||||
// Populate the downloads database with the data required by this test.
|
||||
yield task_addDownloads(DownloadData);
|
||||
|
||||
// Open the user interface and wait for data to be fully loaded.
|
||||
yield task_openPanel();
|
||||
// Open the user interface and wait for data to be fully loaded.
|
||||
yield task_openPanel();
|
||||
|
||||
// Test item data and count. This also tests the ordering of the display.
|
||||
let richlistbox = document.getElementById("downloadsListBox");
|
||||
/* disabled for failing intermittently (bug 767828)
|
||||
// Test item data and count. This also tests the ordering of the display.
|
||||
let richlistbox = document.getElementById("downloadsListBox");
|
||||
/* disabled for failing intermittently (bug 767828)
|
||||
is(richlistbox.children.length, DownloadData.length,
|
||||
"There is the correct number of richlistitems");
|
||||
*/
|
||||
let itemCount = richlistbox.children.length;
|
||||
for (let i = 0; i < itemCount; i++) {
|
||||
let element = richlistbox.children[itemCount - i - 1];
|
||||
let dataItem = new DownloadsViewItemController(element).dataItem;
|
||||
is(dataItem.state, DownloadData[i].state, "Download states match up");
|
||||
}
|
||||
} finally {
|
||||
// Clean up when the test finishes.
|
||||
yield task_resetState();
|
||||
*/
|
||||
let itemCount = richlistbox.children.length;
|
||||
for (let i = 0; i < itemCount; i++) {
|
||||
let element = richlistbox.children[itemCount - i - 1];
|
||||
let dataItem = new DownloadsViewItemController(element).dataItem;
|
||||
is(dataItem.state, DownloadData[i].state, "Download states match up");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -0,0 +1,46 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests the dialog which allows the user to unblock a downloaded file.
|
||||
|
||||
registerCleanupFunction(() => {});
|
||||
|
||||
function addDialogOpenObserver(buttonAction) {
|
||||
Services.ww.registerNotification(function onOpen(subj, topic, data) {
|
||||
if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
|
||||
// The test listens for the "load" event which guarantees that the alert
|
||||
// class has already been added (it is added when "DOMContentLoaded" is
|
||||
// fired).
|
||||
subj.addEventListener("load", function onLoad() {
|
||||
subj.removeEventListener("load", onLoad);
|
||||
if (subj.document.documentURI ==
|
||||
"chrome://global/content/commonDialog.xul") {
|
||||
Services.ww.unregisterNotification(onOpen);
|
||||
|
||||
let dialog = subj.document.getElementById("commonDialog");
|
||||
ok(dialog.classList.contains("alert-dialog"),
|
||||
"The dialog element should contain an alert class.");
|
||||
|
||||
let doc = subj.document.documentElement;
|
||||
doc.getButton(buttonAction).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* test_confirm_unblock_dialog_unblock() {
|
||||
addDialogOpenObserver("cancel");
|
||||
let result = yield DownloadsCommon.confirmUnblockDownload(DownloadsCommon.UNBLOCK_MALWARE,
|
||||
window);
|
||||
ok(result, "Should return true when the user clicks on `Unblock` button.");
|
||||
});
|
||||
|
||||
add_task(function* test_confirm_unblock_dialog_keep_safe() {
|
||||
addDialogOpenObserver("accept");
|
||||
let result = yield DownloadsCommon.confirmUnblockDownload(DownloadsCommon.UNBLOCK_MALWARE,
|
||||
window);
|
||||
ok(!result, "Should return false when the user clicks on `Keep me safe` button.");
|
||||
});
|
@ -8,58 +8,50 @@
|
||||
* download it notices. All subsequent downloads, even across sessions, should
|
||||
* not open the panel automatically.
|
||||
*/
|
||||
function test_task()
|
||||
{
|
||||
add_task(function* test_first_download_panel() {
|
||||
// Clear the download panel has shown preference first as this test is used to
|
||||
// verify this preference's behaviour.
|
||||
let oldPrefValue = true;
|
||||
try {
|
||||
oldPrefValue = Services.prefs.getBoolPref("browser.download.panel.shown");
|
||||
} catch(ex) { }
|
||||
let oldPrefValue = Services.prefs.getBoolPref("browser.download.panel.shown");
|
||||
Services.prefs.setBoolPref("browser.download.panel.shown", false);
|
||||
|
||||
try {
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
|
||||
// With this set to false, we should automatically open the panel the first
|
||||
// time a download is started.
|
||||
DownloadsCommon.getData(window).panelHasShownBefore = false;
|
||||
|
||||
let promise = promisePanelOpened();
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
yield promise;
|
||||
|
||||
// If we got here, that means the panel opened.
|
||||
DownloadsPanel.hidePanel();
|
||||
|
||||
ok(DownloadsCommon.getData(window).panelHasShownBefore,
|
||||
"Should have recorded that the panel was opened on a download.")
|
||||
|
||||
// Next, make sure that if we start another download, we don't open the
|
||||
// panel automatically.
|
||||
let originalOnPopupShown = DownloadsPanel.onPopupShown;
|
||||
DownloadsPanel.onPopupShown = function () {
|
||||
originalOnPopupShown.apply(this, arguments);
|
||||
ok(false, "Should not have opened the downloads panel.");
|
||||
};
|
||||
|
||||
try {
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
|
||||
// Wait 2 seconds to ensure that the panel does not open.
|
||||
let deferTimeout = Promise.defer();
|
||||
setTimeout(deferTimeout.resolve, 2000);
|
||||
yield deferTimeout.promise;
|
||||
} finally {
|
||||
DownloadsPanel.onPopupShown = originalOnPopupShown;
|
||||
}
|
||||
} finally {
|
||||
registerCleanupFunction(function*() {
|
||||
// Clean up when the test finishes.
|
||||
yield task_resetState();
|
||||
|
||||
// Set the preference instead of clearing it afterwards to ensure the
|
||||
// right value is used no matter what the default was. This ensures the
|
||||
// panel doesn't appear and affect other tests.
|
||||
Services.prefs.setBoolPref("browser.download.panel.shown", oldPrefValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
|
||||
// With this set to false, we should automatically open the panel the first
|
||||
// time a download is started.
|
||||
DownloadsCommon.getData(window).panelHasShownBefore = false;
|
||||
|
||||
let promise = promisePanelOpened();
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
yield promise;
|
||||
|
||||
// If we got here, that means the panel opened.
|
||||
DownloadsPanel.hidePanel();
|
||||
|
||||
ok(DownloadsCommon.getData(window).panelHasShownBefore,
|
||||
"Should have recorded that the panel was opened on a download.")
|
||||
|
||||
// Next, make sure that if we start another download, we don't open the
|
||||
// panel automatically.
|
||||
let originalOnPopupShown = DownloadsPanel.onPopupShown;
|
||||
DownloadsPanel.onPopupShown = function () {
|
||||
originalOnPopupShown.apply(this, arguments);
|
||||
ok(false, "Should not have opened the downloads panel.");
|
||||
};
|
||||
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
|
||||
// Wait 2 seconds to ensure that the panel does not open.
|
||||
yield new Promise(resolve => setTimeout(resolve, 2000));
|
||||
DownloadsPanel.onPopupShown = originalOnPopupShown;
|
||||
});
|
||||
|
@ -1,69 +1,69 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
registerCleanupFunction(function*() {
|
||||
// Clean up when the test finishes.
|
||||
yield task_resetState();
|
||||
});
|
||||
|
||||
/**
|
||||
* Make sure the downloads button and indicator overflows into the nav-bar
|
||||
* chevron properly, and then when those buttons are clicked in the overflow
|
||||
* panel that the downloads panel anchors to the chevron.
|
||||
*/
|
||||
function test_task() {
|
||||
try {
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
add_task(function* test_overflow_anchor() {
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
|
||||
// Record the original width of the window so we can put it back when
|
||||
// this test finishes.
|
||||
let oldWidth = window.outerWidth;
|
||||
// Record the original width of the window so we can put it back when
|
||||
// this test finishes.
|
||||
let oldWidth = window.outerWidth;
|
||||
|
||||
// The downloads button should not be overflowed to begin with.
|
||||
let button = CustomizableUI.getWidget("downloads-button")
|
||||
.forWindow(window);
|
||||
ok(!button.overflowed, "Downloads button should not be overflowed.");
|
||||
// The downloads button should not be overflowed to begin with.
|
||||
let button = CustomizableUI.getWidget("downloads-button")
|
||||
.forWindow(window);
|
||||
ok(!button.overflowed, "Downloads button should not be overflowed.");
|
||||
|
||||
// Hack - we lock the size of the default flex-y items in the nav-bar,
|
||||
// namely, the URL and search inputs. That way we can resize the
|
||||
// window without worrying about them flexing.
|
||||
const kFlexyItems = ["urlbar-container", "search-container"];
|
||||
registerCleanupFunction(() => unlockWidth(kFlexyItems));
|
||||
lockWidth(kFlexyItems);
|
||||
// Hack - we lock the size of the default flex-y items in the nav-bar,
|
||||
// namely, the URL and search inputs. That way we can resize the
|
||||
// window without worrying about them flexing.
|
||||
const kFlexyItems = ["urlbar-container", "search-container"];
|
||||
registerCleanupFunction(() => unlockWidth(kFlexyItems));
|
||||
lockWidth(kFlexyItems);
|
||||
|
||||
// Resize the window to half of its original size. That should
|
||||
// be enough to overflow the downloads button.
|
||||
window.resizeTo(oldWidth / 2, window.outerHeight);
|
||||
yield waitForOverflowed(button, true);
|
||||
// Resize the window to half of its original size. That should
|
||||
// be enough to overflow the downloads button.
|
||||
window.resizeTo(oldWidth / 2, window.outerHeight);
|
||||
yield waitForOverflowed(button, true);
|
||||
|
||||
let promise = promisePanelOpened();
|
||||
button.node.doCommand();
|
||||
yield promise;
|
||||
let promise = promisePanelOpened();
|
||||
button.node.doCommand();
|
||||
yield promise;
|
||||
|
||||
let panel = DownloadsPanel.panel;
|
||||
let chevron = document.getElementById("nav-bar-overflow-button");
|
||||
is(panel.anchorNode, chevron, "Panel should be anchored to the chevron.");
|
||||
let panel = DownloadsPanel.panel;
|
||||
let chevron = document.getElementById("nav-bar-overflow-button");
|
||||
is(panel.anchorNode, chevron, "Panel should be anchored to the chevron.");
|
||||
|
||||
DownloadsPanel.hidePanel();
|
||||
DownloadsPanel.hidePanel();
|
||||
|
||||
// Unlock the widths on the flex-y items.
|
||||
unlockWidth(kFlexyItems);
|
||||
// Unlock the widths on the flex-y items.
|
||||
unlockWidth(kFlexyItems);
|
||||
|
||||
// Put the window back to its original dimensions.
|
||||
window.resizeTo(oldWidth, window.outerHeight);
|
||||
// Put the window back to its original dimensions.
|
||||
window.resizeTo(oldWidth, window.outerHeight);
|
||||
|
||||
// The downloads button should eventually be un-overflowed.
|
||||
yield waitForOverflowed(button, false);
|
||||
// The downloads button should eventually be un-overflowed.
|
||||
yield waitForOverflowed(button, false);
|
||||
|
||||
// Now try opening the panel again.
|
||||
promise = promisePanelOpened();
|
||||
button.node.doCommand();
|
||||
yield promise;
|
||||
// Now try opening the panel again.
|
||||
promise = promisePanelOpened();
|
||||
button.node.doCommand();
|
||||
yield promise;
|
||||
|
||||
is(panel.anchorNode.id, "downloads-indicator-anchor");
|
||||
is(panel.anchorNode.id, "downloads-indicator-anchor");
|
||||
|
||||
DownloadsPanel.hidePanel();
|
||||
} finally {
|
||||
// Clean up when the test finishes.
|
||||
yield task_resetState();
|
||||
}
|
||||
}
|
||||
DownloadsPanel.hidePanel();
|
||||
});
|
||||
|
||||
/**
|
||||
* For some node IDs, finds the nodes and sets their min-width's to their
|
||||
|
@ -28,15 +28,6 @@ registerCleanupFunction(function () {
|
||||
gTestTargetFile.remove(false);
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Infrastructure
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
Task.spawn(test_task).then(null, ex => ok(false, ex)).then(finish);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Asynchronous support subroutines
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
<dialog id="commonDialog"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
aria-describedby="info.body"
|
||||
onload="commonDialogOnLoad();"
|
||||
onunload="commonDialogOnUnload();"
|
||||
ondialogaccept="Dialog.onButton0(); return true;"
|
||||
ondialogcancel="Dialog.onButton1(); return true;"
|
||||
@ -23,6 +22,11 @@
|
||||
|
||||
<script type="application/javascript" src="chrome://global/content/commonDialog.js"/>
|
||||
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
|
||||
<script type="application/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
commonDialogOnLoad();
|
||||
});
|
||||
</script>
|
||||
|
||||
<commandset id="selectEditMenuItems">
|
||||
<command id="cmd_copy" oncommand="goDoCommand('cmd_copy')" disabled="true"/>
|
||||
|
@ -60,6 +60,7 @@ window.dialog {
|
||||
list-style-image: url("moz-icon://stock/gtk-dialog-info?size=dialog");
|
||||
}
|
||||
|
||||
.alert-dialog #info\.icon,
|
||||
.alert-icon {
|
||||
list-style-image: url("moz-icon://stock/gtk-dialog-warning?size=dialog");
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ window.dialog {
|
||||
list-style-image: url("chrome://global/skin/icons/information-64.png");
|
||||
}
|
||||
|
||||
.alert-dialog #info\.icon,
|
||||
.alert-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/warning-64.png");
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ window.dialog {
|
||||
list-style-image: url("chrome://global/skin/icons/information-32.png");
|
||||
}
|
||||
|
||||
.alert-dialog #info\.icon,
|
||||
.alert-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/Warning.png");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user