зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c a=merge CLOSED TREE
--HG-- extra : commitid : 8cnDWzxc5CW
This commit is contained in:
Коммит
5c5db39163
|
@ -66,23 +66,36 @@ AlertsService.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// nsIAlertsService
|
// nsIAlertsService
|
||||||
|
showAlert: function(aAlert, aAlertListener) {
|
||||||
|
if (!aAlert) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cpmm.sendAsyncMessage(kMessageAlertNotificationSend, {
|
||||||
|
imageURL: aAlert.imageURL,
|
||||||
|
title: aAlert.title,
|
||||||
|
text: aAlert.text,
|
||||||
|
clickable: aAlert.textClickable,
|
||||||
|
cookie: aAlert.cookie,
|
||||||
|
listener: aAlertListener,
|
||||||
|
id: aAlert.name,
|
||||||
|
dir: aAlert.dir,
|
||||||
|
lang: aAlert.lang,
|
||||||
|
dataStr: aAlert.data,
|
||||||
|
inPrivateBrowsing: aAlert.inPrivateBrowsing
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
|
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
|
||||||
aCookie, aAlertListener, aName, aBidi,
|
aCookie, aAlertListener, aName, aBidi,
|
||||||
aLang, aDataStr, aPrincipal,
|
aLang, aDataStr, aPrincipal,
|
||||||
aInPrivateBrowsing) {
|
aInPrivateBrowsing) {
|
||||||
cpmm.sendAsyncMessage(kMessageAlertNotificationSend, {
|
let alert = Cc["@mozilla.org/alert-notification;1"].
|
||||||
imageURL: aImageUrl,
|
createInstance(Ci.nsIAlertNotification);
|
||||||
title: aTitle,
|
|
||||||
text: aText,
|
alert.init(aName, aImageUrl, aTitle, aText, aTextClickable, aCookie,
|
||||||
clickable: aTextClickable,
|
aBidi, aLang, aDataStr, aPrincipal, aInPrivateBrowsing);
|
||||||
cookie: aCookie,
|
|
||||||
listener: aAlertListener,
|
this.showAlert(alert, aAlertListener);
|
||||||
id: aName,
|
|
||||||
dir: aBidi,
|
|
||||||
lang: aLang,
|
|
||||||
dataStr: aDataStr,
|
|
||||||
inPrivateBrowsing: aInPrivateBrowsing
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
closeAlert: function(aName) {
|
closeAlert: function(aName) {
|
||||||
|
|
|
@ -739,8 +739,6 @@ HistoryMenu.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let enabled = PlacesUIUtils.shouldEnableTabsFromOtherComputersMenuitem();
|
|
||||||
menuitem.setAttribute("disabled", !enabled);
|
|
||||||
menuitem.setAttribute("hidden", false);
|
menuitem.setAttribute("hidden", false);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -803,6 +803,15 @@ BrowserGlue.prototype = {
|
||||||
this._sanitizer.onStartup();
|
this._sanitizer.onStartup();
|
||||||
// check if we're in safe mode
|
// check if we're in safe mode
|
||||||
if (Services.appinfo.inSafeMode) {
|
if (Services.appinfo.inSafeMode) {
|
||||||
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1231112#c7 . We need to
|
||||||
|
// register the observer early if we have to migrate tab groups
|
||||||
|
let currentUIVersion = 0;
|
||||||
|
try {
|
||||||
|
currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
|
||||||
|
} catch(ex) {}
|
||||||
|
if (currentUIVersion < 35) {
|
||||||
|
this._maybeMigrateTabGroups();
|
||||||
|
}
|
||||||
Services.ww.openWindow(null, "chrome://browser/content/safeMode.xul",
|
Services.ww.openWindow(null, "chrome://browser/content/safeMode.xul",
|
||||||
"_blank", "chrome,centerscreen,modal,resizable=no", null);
|
"_blank", "chrome,centerscreen,modal,resizable=no", null);
|
||||||
}
|
}
|
||||||
|
@ -2241,7 +2250,8 @@ BrowserGlue.prototype = {
|
||||||
this._notifyNotificationsUpgrade().catch(Cu.reportError);
|
this._notifyNotificationsUpgrade().catch(Cu.reportError);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUIVersion < 35) {
|
// Only do this outside of safe mode, because in safe mode we do this earlier.
|
||||||
|
if (currentUIVersion < 35 && !Services.appinfo.inSafeMode) {
|
||||||
this._maybeMigrateTabGroups();
|
this._maybeMigrateTabGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -556,7 +556,8 @@ var WindowListener = {
|
||||||
buttonNode.accessKey = paused ? this._getString("infobar_button_resume_accesskey") :
|
buttonNode.accessKey = paused ? this._getString("infobar_button_resume_accesskey") :
|
||||||
this._getString("infobar_button_pause_accesskey");
|
this._getString("infobar_button_pause_accesskey");
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
type: "pause"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: this._getString("infobar_button_stop_label"),
|
label: this._getString("infobar_button_stop_label"),
|
||||||
|
@ -565,7 +566,8 @@ var WindowListener = {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
this._hideBrowserSharingInfoBar();
|
this._hideBrowserSharingInfoBar();
|
||||||
LoopUI.MozLoopService.hangupAllChatWindows();
|
LoopUI.MozLoopService.hangupAllChatWindows();
|
||||||
}
|
},
|
||||||
|
type: "stop"
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,11 @@
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hide Pause/Resume button until the functionality is complete */
|
||||||
|
notification[value="loop-sharing-notification"] .notification-button[type="pause"] {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
notification[value="loop-sharing-notification"].paused .notification-button {
|
notification[value="loop-sharing-notification"].paused .notification-button {
|
||||||
background: #57bd35;
|
background: #57bd35;
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,6 +192,11 @@
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hide Pause/Resume button until the functionality is complete */
|
||||||
|
notification[value="loop-sharing-notification"] .notification-button[type="pause"] {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
notification[value="loop-sharing-notification"].paused .notification-button {
|
notification[value="loop-sharing-notification"].paused .notification-button {
|
||||||
background-color: #57bd35;
|
background-color: #57bd35;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
|
@ -1440,6 +1440,10 @@ richlistitem[type~="action"][actiontype$="tab"] > .ac-url-box > .ac-action-icon
|
||||||
background-color: Window;
|
background-color: Window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sidebar-header > .close-icon:not(:hover):-moz-lwtheme-brighttext {
|
||||||
|
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
|
||||||
|
}
|
||||||
|
|
||||||
.browserContainer > findbar {
|
.browserContainer > findbar {
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
color: -moz-DialogText;
|
color: -moz-DialogText;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
%include ../shared/devedition.inc.css
|
%include ../shared/devedition.inc.css
|
||||||
|
|
||||||
|
:root[devtoolstheme="dark"] .findbar-closebutton:not(:hover),
|
||||||
|
:root[devtoolstheme="dark"] #sidebar-header > .close-icon:not(:hover),
|
||||||
.tab-close-button[visuallyselected]:not(:hover) {
|
.tab-close-button[visuallyselected]:not(:hover) {
|
||||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
|
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
|
||||||
}
|
}
|
||||||
|
@ -76,8 +78,9 @@
|
||||||
border-top-width: 0 !important;
|
border-top-width: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent devedition foreground color from seeping into the sidebar-box (since
|
/* Fix the bad-looking text-shadow in the sidebar header: */
|
||||||
* its background colors aren't affected by the devedition theme) */
|
.sidebar-header,
|
||||||
#sidebar-box {
|
#sidebar-header {
|
||||||
color: initial;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,8 @@
|
||||||
|
|
||||||
@media (-moz-os-version: windows-vista),
|
@media (-moz-os-version: windows-vista),
|
||||||
(-moz-os-version: windows-win7) {
|
(-moz-os-version: windows-win7) {
|
||||||
.sidebar-header,
|
.sidebar-header:not(:-moz-lwtheme),
|
||||||
#sidebar-header {
|
#sidebar-header:not(:-moz-lwtheme) {
|
||||||
background-color: #EEF3FA;
|
background-color: #EEF3FA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1872,6 +1872,18 @@ richlistitem[type~="action"][actiontype$="tab"] > .ac-url-box > .ac-action-icon
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media not all and (min-resolution: 1.1dppx) {
|
||||||
|
#sidebar-header > .close-icon:-moz-lwtheme-brighttext {
|
||||||
|
list-style-image: url("chrome://global/skin/icons/close-inverted.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-resolution: 1.1dppx) {
|
||||||
|
#sidebar-header > .close-icon:-moz-lwtheme-brighttext {
|
||||||
|
list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (-moz-os-version: windows-xp),
|
@media (-moz-os-version: windows-xp),
|
||||||
(-moz-os-version: windows-vista),
|
(-moz-os-version: windows-vista),
|
||||||
(-moz-os-version: windows-win7) {
|
(-moz-os-version: windows-win7) {
|
||||||
|
|
|
@ -107,6 +107,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[devtoolstheme="dark"] .findbar-closebutton,
|
:root[devtoolstheme="dark"] .findbar-closebutton,
|
||||||
|
:root[devtoolstheme="dark"] #sidebar-header > .close-icon,
|
||||||
/* Tab styling - make sure to use an inverted icon for the selected tab
|
/* Tab styling - make sure to use an inverted icon for the selected tab
|
||||||
(brighttext only covers the unselected tabs) */
|
(brighttext only covers the unselected tabs) */
|
||||||
.tab-close-button[visuallyselected=true] {
|
.tab-close-button[visuallyselected=true] {
|
||||||
|
@ -115,6 +116,7 @@
|
||||||
|
|
||||||
@media (min-resolution: 1.1dppx) {
|
@media (min-resolution: 1.1dppx) {
|
||||||
:root[devtoolstheme="dark"] .findbar-closebutton,
|
:root[devtoolstheme="dark"] .findbar-closebutton,
|
||||||
|
:root[devtoolstheme="dark"] #sidebar-header > .close-icon,
|
||||||
.tab-close-button[visuallyselected=true] {
|
.tab-close-button[visuallyselected=true] {
|
||||||
list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
|
list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
|
||||||
}
|
}
|
||||||
|
@ -254,6 +256,14 @@
|
||||||
border-right: none !important;
|
border-right: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The sidebar header has no background now that the background of the #browser-panel
|
||||||
|
* has no image and is transparent. Fix: */
|
||||||
|
.sidebar-header:-moz-lwtheme,
|
||||||
|
#sidebar-header {
|
||||||
|
background-color: var(--chrome-background-color);
|
||||||
|
color: var(--chrome-color);
|
||||||
|
}
|
||||||
|
|
||||||
@media (-moz-os-version: windows-vista),
|
@media (-moz-os-version: windows-vista),
|
||||||
(-moz-os-version: windows-win7),
|
(-moz-os-version: windows-win7),
|
||||||
(-moz-os-version: windows-win8) {
|
(-moz-os-version: windows-win8) {
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Cu = Components.utils;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||||
|
|
||||||
|
// Helper to listen to a key on all windows
|
||||||
|
function MultiWindowKeyListener({ keyCode, ctrlKey, altKey, callback }) {
|
||||||
|
let keyListener = function (event) {
|
||||||
|
if (event.ctrlKey == !!ctrlKey &&
|
||||||
|
event.altKey == !!altKey &&
|
||||||
|
event.keyCode === keyCode) {
|
||||||
|
callback(event);
|
||||||
|
|
||||||
|
// Call preventDefault to avoid duplicated events when
|
||||||
|
// doing the key stroke within a tab.
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let observer = function (window, topic, data) {
|
||||||
|
// Listen on keyup to call keyListener only once per stroke
|
||||||
|
if (topic === "domwindowopened") {
|
||||||
|
window.addEventListener("keyup", keyListener);
|
||||||
|
} else {
|
||||||
|
window.removeEventListener("keyup", keyListener);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: function () {
|
||||||
|
// Automatically process already opened windows
|
||||||
|
let e = Services.ww.getWindowEnumerator();
|
||||||
|
while (e.hasMoreElements()) {
|
||||||
|
let window = e.getNext();
|
||||||
|
observer(window, "domwindowopened", null);
|
||||||
|
}
|
||||||
|
// And listen for new ones to come
|
||||||
|
Services.ww.registerNotification(observer);
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function () {
|
||||||
|
Services.ww.unregisterNotification(observer);
|
||||||
|
let e = Services.ww.getWindowEnumerator();
|
||||||
|
while (e.hasMoreElements()) {
|
||||||
|
let window = e.getNext();
|
||||||
|
observer(window, "domwindowclosed", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let getTopLevelWindow = function (window) {
|
||||||
|
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||||
|
.rootTreeItem
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindow);
|
||||||
|
};
|
||||||
|
|
||||||
|
function reload(event) {
|
||||||
|
// We automatically reload the toolbox if we are on a browser tab
|
||||||
|
// with a toolbox already opened
|
||||||
|
let top = getTopLevelWindow(event.view)
|
||||||
|
let isBrowser = top.location.href.includes("/browser.xul") && top.gDevToolsBrowser;
|
||||||
|
let reloadToolbox = false;
|
||||||
|
if (isBrowser && top.gDevToolsBrowser.hasToolboxOpened) {
|
||||||
|
reloadToolbox = top.gDevToolsBrowser.hasToolboxOpened(top);
|
||||||
|
}
|
||||||
|
dump("Reload DevTools. (reload-toolbox:"+reloadToolbox+")\n");
|
||||||
|
|
||||||
|
// Invalidate xul cache in order to see changes made to chrome:// files
|
||||||
|
Services.obs.notifyObservers(null, "startupcache-invalidate", null);
|
||||||
|
|
||||||
|
// Ask the loader to update itself and reopen the toolbox if needed
|
||||||
|
const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||||
|
devtools.reload(reloadToolbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
let listener;
|
||||||
|
function startup() {
|
||||||
|
dump("DevTools addon started.\n");
|
||||||
|
listener = new MultiWindowKeyListener({
|
||||||
|
keyCode: Ci.nsIDOMKeyEvent.DOM_VK_R, ctrlKey: true, altKey: true,
|
||||||
|
callback: reload
|
||||||
|
});
|
||||||
|
listener.start();
|
||||||
|
}
|
||||||
|
function shutdown() {
|
||||||
|
listener.stop();
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
function install() {}
|
||||||
|
function uninstall() {}
|
|
@ -0,0 +1,6 @@
|
||||||
|
content devtools client/
|
||||||
|
skin devtools classic/1.0 client/themes/
|
||||||
|
resource devtools .
|
||||||
|
|
||||||
|
content webide client/webide/content/
|
||||||
|
skin webide classic/1.0 client/webide/themes/
|
|
@ -18,7 +18,7 @@ const CALL_STACK_PAGE_SIZE = 25; // frames
|
||||||
const EVENTS = {
|
const EVENTS = {
|
||||||
// When the debugger's source editor instance finishes loading or unloading.
|
// When the debugger's source editor instance finishes loading or unloading.
|
||||||
EDITOR_LOADED: "Debugger:EditorLoaded",
|
EDITOR_LOADED: "Debugger:EditorLoaded",
|
||||||
EDITOR_UNLOADED: "Debugger:EditorUnoaded",
|
EDITOR_UNLOADED: "Debugger:EditorUnloaded",
|
||||||
|
|
||||||
// When new sources are received from the debugger server.
|
// When new sources are received from the debugger server.
|
||||||
NEW_SOURCE: "Debugger:NewSource",
|
NEW_SOURCE: "Debugger:NewSource",
|
||||||
|
|
|
@ -1161,6 +1161,16 @@ var gDevToolsBrowser = {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hasToolboxOpened: function(win) {
|
||||||
|
let tab = win.gBrowser.selectedTab;
|
||||||
|
for (let [target, toolbox] of gDevTools._toolboxes) {
|
||||||
|
if (target.tab == tab) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the "Toggle Tools" checkbox in the developer tools menu. This is
|
* Update the "Toggle Tools" checkbox in the developer tools menu. This is
|
||||||
* called when a toolbox is created or destroyed.
|
* called when a toolbox is created or destroyed.
|
||||||
|
@ -1168,13 +1178,7 @@ var gDevToolsBrowser = {
|
||||||
_updateMenuCheckbox: function DT_updateMenuCheckbox() {
|
_updateMenuCheckbox: function DT_updateMenuCheckbox() {
|
||||||
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
|
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
|
||||||
|
|
||||||
let hasToolbox = false;
|
let hasToolbox = gDevToolsBrowser.hasToolboxOpened(win);
|
||||||
if (TargetFactory.isKnownTab(win.gBrowser.selectedTab)) {
|
|
||||||
let target = TargetFactory.forTab(win.gBrowser.selectedTab);
|
|
||||||
if (gDevTools._toolboxes.has(target)) {
|
|
||||||
hasToolbox = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let broadcaster = win.document.getElementById("devtoolsMenuBroadcaster_DevToolbox");
|
let broadcaster = win.document.getElementById("devtoolsMenuBroadcaster_DevToolbox");
|
||||||
if (hasToolbox) {
|
if (hasToolbox) {
|
||||||
|
|
|
@ -51,8 +51,7 @@ var TreeView = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
DOM.div({className: "domTable", cellPadding: 0, cellSpacing: 0,
|
DOM.div({className: "domTable", cellPadding: 0, cellSpacing: 0},
|
||||||
onClick: this.onClick},
|
|
||||||
children
|
children
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -151,8 +150,9 @@ var TreeNode = React.createFactory(React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
DOM.div({className: classNames.join(" "), onClick: this.onClick},
|
DOM.div({className: classNames.join(" ")},
|
||||||
DOM.span({className: "memberLabelCell"},
|
DOM.span({className: "memberLabelCell", onClick: this.onClick},
|
||||||
|
DOM.span({className: "memberIcon"}),
|
||||||
DOM.span({className: "memberLabel " + member.type + "Label"},
|
DOM.span({className: "memberLabel " + member.type + "Label"},
|
||||||
member.name)
|
member.name)
|
||||||
),
|
),
|
||||||
|
|
|
@ -22,7 +22,6 @@ const CONTRACT_ID = "@mozilla.org/devtools/jsonview-sniffer;1";
|
||||||
const CLASS_ID = "{4148c488-dca1-49fc-a621-2a0097a62422}";
|
const CLASS_ID = "{4148c488-dca1-49fc-a621-2a0097a62422}";
|
||||||
const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
|
const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
|
||||||
const JSON_VIEW_TYPE = "JSON View";
|
const JSON_VIEW_TYPE = "JSON View";
|
||||||
const JSON_EXTENSION = "json";
|
|
||||||
const CONTENT_SNIFFER_CATEGORY = "net-content-sniffers";
|
const CONTENT_SNIFFER_CATEGORY = "net-content-sniffers";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,10 +63,6 @@ var Sniffer = Class({
|
||||||
if (aRequest.contentType == JSON_TYPE) {
|
if (aRequest.contentType == JSON_TYPE) {
|
||||||
return JSON_VIEW_MIME_TYPE;
|
return JSON_VIEW_MIME_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetworkHelper.getFileExtension(aRequest.name) == JSON_EXTENSION) {
|
|
||||||
return JSON_VIEW_MIME_TYPE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.6 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.0 KiB |
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
.memberLabelCell {
|
.memberLabelCell {
|
||||||
padding: 2px 0 2px 0px;
|
padding: 2px 0 2px 0px;
|
||||||
vertical-align: top;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.memberValueCell {
|
.memberValueCell {
|
||||||
|
@ -31,7 +30,6 @@
|
||||||
.memberLabel {
|
.memberLabel {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-left: 18px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +58,11 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
.memberRow.hasChildren > .memberLabelCell > .memberIcon:hover,
|
||||||
|
.memberRow.cropped > .memberLabelCell > .memberIcon:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.memberRow.hasChildren > .memberLabelCell > .memberLabel:hover,
|
.memberRow.hasChildren > .memberLabelCell > .memberLabel:hover,
|
||||||
.memberRow.cropped > .memberLabelCell > .memberLabel:hover {
|
.memberRow.cropped > .memberLabelCell > .memberLabel:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -71,6 +74,10 @@
|
||||||
background-color: #EFEFEF;
|
background-color: #EFEFEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.memberRow {
|
||||||
|
padding: 3px 0 3px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.panelNode-dom .memberRow td,
|
.panelNode-dom .memberRow td,
|
||||||
.panelNode-domSide .memberRow td {
|
.panelNode-domSide .memberRow td {
|
||||||
border-bottom: 1px solid #EFEFEF;
|
border-bottom: 1px solid #EFEFEF;
|
||||||
|
@ -116,19 +123,38 @@
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Twisties */
|
/* Twisties */
|
||||||
|
|
||||||
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
|
.memberRow > .memberLabelCell > .memberIcon {
|
||||||
.memberRow.cropped > .memberLabelCell > .memberLabel {
|
height: 14px;
|
||||||
background-image: url(twisty-closed.svg);
|
width: 14px;
|
||||||
background-repeat: no-repeat;
|
display: inline-block;
|
||||||
background-position: 2px calc(0.5em - 3px);
|
line-height: 15px;
|
||||||
min-height: 12px;
|
vertical-align: bottom;
|
||||||
|
padding-right: 2px;
|
||||||
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,
|
.memberRow.hasChildren > .memberLabelCell > .memberIcon,
|
||||||
.memberRow.cropped.opened > .memberLabelCell > .memberLabel {
|
.memberRow.cropped > .memberLabelCell > .memberIcon {
|
||||||
background-image: url(twisty-open.svg);
|
background-image: url("./twisty-closed.svg");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
min-height: 12px;
|
}
|
||||||
|
|
||||||
|
.memberRow.hasChildren.opened > .memberLabelCell > .memberIcon,
|
||||||
|
.memberRow.cropped.opened > .memberLabelCell > .memberIcon {
|
||||||
|
background-image: url("./twisty-open.svg");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-resolution: 1.1dppx) {
|
||||||
|
.memberRow.hasChildren > .memberLabelCell > .memberIcon,
|
||||||
|
.memberRow.cropped > .memberLabelCell > .memberIcon {
|
||||||
|
background-image: url("./controls@2x.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.memberRow.hasChildren.opened > .memberLabelCell > .memberIcon,
|
||||||
|
.memberRow.cropped.opened > .memberLabelCell > .memberIcon {
|
||||||
|
background-image: url("./controls@2x.png");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -140,7 +166,6 @@
|
||||||
|
|
||||||
.memberLabelCell,
|
.memberLabelCell,
|
||||||
.memberValueCell {
|
.memberValueCell {
|
||||||
display: table-cell;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.memberLabelCell {
|
.memberLabelCell {
|
||||||
|
@ -150,3 +175,42 @@
|
||||||
.memberRow:hover {
|
.memberRow:hover {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* Themes */
|
||||||
|
|
||||||
|
.theme-light .memberRow.hasChildren > .memberLabelCell > .memberIcon,
|
||||||
|
.theme-light .memberRow.cropped > .memberLabelCell > .memberIcon {
|
||||||
|
background-image: url("./controls.png");
|
||||||
|
background-size: 56px 28px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 0 -14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-light .memberRow.hasChildren.opened > .memberLabelCell > .memberIcon,
|
||||||
|
.theme-light .memberRow.cropped.opened > .memberLabelCell > .memberIcon {
|
||||||
|
background-image: url("./controls.png");
|
||||||
|
background-size: 56px 28px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: -14px -14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .memberRow.hasChildren > .memberLabelCell > .memberIcon,
|
||||||
|
.theme-dark .memberRow.cropped > .memberLabelCell > .memberIcon {
|
||||||
|
background-image: url("./controls.png");
|
||||||
|
background-size: 56px 28px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: -28px -14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .memberRow.hasChildren.opened > .memberLabelCell > .memberIcon,
|
||||||
|
.theme-dark .memberRow.cropped.opened > .memberLabelCell > .memberIcon {
|
||||||
|
background-image: url("./controls.png");
|
||||||
|
background-size: 56px 28px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: -42px -14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .memberRow:hover {
|
||||||
|
background-color: var(--theme-selection-background-semitransparent);
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
|
|
||||||
DevToolsModules(
|
DevToolsModules(
|
||||||
|
'controls.png',
|
||||||
|
'controls@2x.png',
|
||||||
'dom-tree.css',
|
'dom-tree.css',
|
||||||
'general.css',
|
'general.css',
|
||||||
'headers-panel.css',
|
'headers-panel.css',
|
||||||
|
|
|
@ -175,7 +175,7 @@
|
||||||
|
|
||||||
.theme-dark .domLabel,
|
.theme-dark .domLabel,
|
||||||
.theme-light .domLabel {
|
.theme-light .domLabel {
|
||||||
color: var(--theme-highlight-bluegrey);
|
color: var(--theme-highlight-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-dark .objectBox-array .length,
|
.theme-dark .objectBox-array .length,
|
||||||
|
@ -207,7 +207,7 @@
|
||||||
.theme-light .objectBox-object {
|
.theme-light .objectBox-object {
|
||||||
font-family: Lucida Grande, sans-serif;
|
font-family: Lucida Grande, sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: var(--theme-highlight-bluegrey);
|
color: var(--theme-highlight-blue);
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,5 +215,5 @@
|
||||||
.theme-light .caption {
|
.theme-light .caption {
|
||||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: var(--theme-highlight-bluegrey);
|
color: var(--theme-highlight-blue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,10 @@ Services.prefs.setBoolPref("devtools.memory.enabled", true);
|
||||||
var { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
var { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
var { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
var { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||||
var { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
var { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||||
var { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
|
||||||
var { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
|
||||||
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
|
||||||
var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
|
var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
|
||||||
|
var { DebuggerServer } = require("devtools/server/main");
|
||||||
|
var { DebuggerClient } = require("devtools/shared/client/main");
|
||||||
|
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||||
var { TargetFactory } = require("devtools/client/framework/target");
|
var { TargetFactory } = require("devtools/client/framework/target");
|
||||||
var { Toolbox } = require("devtools/client/framework/toolbox");
|
var { Toolbox } = require("devtools/client/framework/toolbox");
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ body {
|
||||||
.devtools-toolbar,
|
.devtools-toolbar,
|
||||||
.devtools-sidebar-tabs tabs,
|
.devtools-sidebar-tabs tabs,
|
||||||
.devtools-sidebar-alltabs,
|
.devtools-sidebar-alltabs,
|
||||||
.CodeMirror-dialog { /* General toolbar styling */
|
.cm-s-mozilla .CodeMirror-dialog { /* General toolbar styling */
|
||||||
color: var(--theme-body-color-alt);
|
color: var(--theme-body-color-alt);
|
||||||
background-color: var(--theme-toolbar-background);
|
background-color: var(--theme-toolbar-background);
|
||||||
border-color: hsla(210,8%,5%,.6);
|
border-color: hsla(210,8%,5%,.6);
|
||||||
|
|
|
@ -171,7 +171,7 @@ body {
|
||||||
.devtools-toolbar,
|
.devtools-toolbar,
|
||||||
.devtools-sidebar-tabs tabs,
|
.devtools-sidebar-tabs tabs,
|
||||||
.devtools-sidebar-alltabs,
|
.devtools-sidebar-alltabs,
|
||||||
.CodeMirror-dialog { /* General toolbar styling */
|
.cm-s-mozilla .CodeMirror-dialog { /* General toolbar styling */
|
||||||
color: var(--theme-body-color-alt);
|
color: var(--theme-body-color-alt);
|
||||||
background-color: var(--theme-toolbar-background);
|
background-color: var(--theme-toolbar-background);
|
||||||
border-color: var(--theme-splitter-color);
|
border-color: var(--theme-splitter-color);
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||||
|
<Description about="urn:mozilla:install-manifest"
|
||||||
|
em:id="devtools@mozilla.org"
|
||||||
|
em:name="Developer Tools (local version)"
|
||||||
|
em:description="Add-on to load DevTools from local sources and easily reload them with Ctrl+Alt+r shortcut"
|
||||||
|
em:version="44.0a1"
|
||||||
|
em:type="2"
|
||||||
|
em:creator="Mozilla">
|
||||||
|
|
||||||
|
<em:bootstrap>true</em:bootstrap>
|
||||||
|
<em:targetApplication>
|
||||||
|
<Description>
|
||||||
|
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||||
|
<em:minVersion>44.0a1</em:minVersion>
|
||||||
|
<em:maxVersion>*</em:maxVersion>
|
||||||
|
</Description>
|
||||||
|
</em:targetApplication>
|
||||||
|
</Description>
|
||||||
|
</RDF>
|
|
@ -803,36 +803,6 @@ var NetworkHelper = {
|
||||||
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
||||||
aStore.set(aUrl, uri);
|
aStore.set(aUrl, uri);
|
||||||
return uri;
|
return uri;
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns extension for file URLs (e.g. 'json').
|
|
||||||
* Not everyURL has an extension and this method works as follows:
|
|
||||||
* 1) Remove query string
|
|
||||||
* 2) Get part after the last slash (a file name)
|
|
||||||
* 3) Look for the last dot (an extension)
|
|
||||||
*/
|
|
||||||
getFileExtension: function(aUrl) {
|
|
||||||
if (!aUrl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove query string from the URL if any.
|
|
||||||
let queryString = aUrl.indexOf("?");
|
|
||||||
if (queryString != -1) {
|
|
||||||
aUrl = aUrl.substr(0, queryString);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the part after last slash
|
|
||||||
var lastSlash = aUrl.lastIndexOf("/");
|
|
||||||
var fileName = aUrl.substr(lastSlash + 1);
|
|
||||||
if (!fileName) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now get the file extension.
|
|
||||||
var lastDot = fileName.lastIndexOf(".");
|
|
||||||
return fileName.substr(lastDot + 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4415,23 +4415,24 @@ ContentParent::HasNotificationPermission(const IPC::Principal& aPrincipal)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
|
ContentParent::RecvShowAlert(const AlertNotificationType& aAlert)
|
||||||
const nsString& aText, const bool& aTextClickable,
|
|
||||||
const nsString& aCookie, const nsString& aName,
|
|
||||||
const nsString& aBidi, const nsString& aLang,
|
|
||||||
const nsString& aData,
|
|
||||||
const IPC::Principal& aPrincipal,
|
|
||||||
const bool& aInPrivateBrowsing)
|
|
||||||
{
|
{
|
||||||
if (!HasNotificationPermission(aPrincipal)) {
|
nsCOMPtr<nsIAlertNotification> alert(dont_AddRef(aAlert));
|
||||||
|
if (NS_WARN_IF(!alert)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
nsresult rv = alert->GetPrincipal(getter_AddRefs(principal));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv)) ||
|
||||||
|
!HasNotificationPermission(IPC::Principal(principal))) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
|
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
|
||||||
if (sysAlerts) {
|
if (sysAlerts) {
|
||||||
sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable,
|
sysAlerts->ShowAlert(alert, this);
|
||||||
aCookie, this, aName, aBidi, aLang,
|
|
||||||
aData, aPrincipal, aInPrivateBrowsing);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -901,14 +901,7 @@ private:
|
||||||
|
|
||||||
bool HasNotificationPermission(const IPC::Principal& aPrincipal);
|
bool HasNotificationPermission(const IPC::Principal& aPrincipal);
|
||||||
|
|
||||||
virtual bool
|
virtual bool RecvShowAlert(const AlertNotificationType& aAlert) override;
|
||||||
RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
|
|
||||||
const nsString& aText, const bool& aTextClickable,
|
|
||||||
const nsString& aCookie, const nsString& aName,
|
|
||||||
const nsString& aBidi, const nsString& aLang,
|
|
||||||
const nsString& aData,
|
|
||||||
const IPC::Principal& aPrincipal,
|
|
||||||
const bool& aInPrivateBrowsing) override;
|
|
||||||
|
|
||||||
virtual bool RecvCloseAlert(const nsString& aName,
|
virtual bool RecvCloseAlert(const nsString& aName,
|
||||||
const IPC::Principal& aPrincipal) override;
|
const IPC::Principal& aPrincipal) override;
|
||||||
|
|
|
@ -74,6 +74,7 @@ include ProfilerTypes;
|
||||||
include "mozilla/dom/PContentBridgeParent.h";
|
include "mozilla/dom/PContentBridgeParent.h";
|
||||||
|
|
||||||
using GeoPosition from "nsGeoPositionIPCSerialiser.h";
|
using GeoPosition from "nsGeoPositionIPCSerialiser.h";
|
||||||
|
using AlertNotificationType from "mozilla/AlertNotificationIPCSerializer.h";
|
||||||
|
|
||||||
using struct ChromePackage from "mozilla/chrome/RegistryMessageUtils.h";
|
using struct ChromePackage from "mozilla/chrome/RegistryMessageUtils.h";
|
||||||
using struct SubstitutionMapping from "mozilla/chrome/RegistryMessageUtils.h";
|
using struct SubstitutionMapping from "mozilla/chrome/RegistryMessageUtils.h";
|
||||||
|
@ -881,17 +882,7 @@ parent:
|
||||||
CpowEntry[] aCpows, Principal aPrincipal)
|
CpowEntry[] aCpows, Principal aPrincipal)
|
||||||
returns (StructuredCloneData[] retval);
|
returns (StructuredCloneData[] retval);
|
||||||
|
|
||||||
ShowAlertNotification(nsString imageUrl,
|
ShowAlert(AlertNotificationType alert);
|
||||||
nsString title,
|
|
||||||
nsString text,
|
|
||||||
bool textClickable,
|
|
||||||
nsString cookie,
|
|
||||||
nsString name,
|
|
||||||
nsString bidi,
|
|
||||||
nsString lang,
|
|
||||||
nsString data,
|
|
||||||
Principal principal,
|
|
||||||
bool inPrivateBrowsing);
|
|
||||||
|
|
||||||
CloseAlert(nsString name, Principal principal);
|
CloseAlert(nsString name, Principal principal);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "mozilla/dom/DesktopNotificationBinding.h"
|
#include "mozilla/dom/DesktopNotificationBinding.h"
|
||||||
#include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
|
#include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
|
||||||
#include "mozilla/dom/ToJSValue.h"
|
#include "mozilla/dom/ToJSValue.h"
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsContentPermissionHelper.h"
|
#include "nsContentPermissionHelper.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
#include "mozilla/dom/PBrowserChild.h"
|
#include "mozilla/dom/PBrowserChild.h"
|
||||||
|
@ -114,16 +115,20 @@ DesktopNotification::PostDesktopNotification()
|
||||||
nsIPrincipal* principal = doc->NodePrincipal();
|
nsIPrincipal* principal = doc->NodePrincipal();
|
||||||
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
|
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
|
||||||
bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
|
bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
|
||||||
return alerts->ShowAlertNotification(mIconURL, mTitle, mDescription,
|
nsCOMPtr<nsIAlertNotification> alert =
|
||||||
|
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
|
||||||
|
nsresult rv = alert->Init(uniqueName, mIconURL, mTitle,
|
||||||
|
mDescription,
|
||||||
true,
|
true,
|
||||||
uniqueName,
|
uniqueName,
|
||||||
mObserver,
|
|
||||||
uniqueName,
|
|
||||||
NS_LITERAL_STRING("auto"),
|
NS_LITERAL_STRING("auto"),
|
||||||
EmptyString(),
|
EmptyString(),
|
||||||
EmptyString(),
|
EmptyString(),
|
||||||
principal,
|
principal,
|
||||||
inPrivateBrowsing);
|
inPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return alerts->ShowAlert(alert, mObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
DesktopNotification::DesktopNotification(const nsAString & title,
|
DesktopNotification::DesktopNotification(const nsAString & title,
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
|
#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
|
||||||
|
|
||||||
#include "nsAlertsUtils.h"
|
#include "nsAlertsUtils.h"
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsContentPermissionHelper.h"
|
#include "nsContentPermissionHelper.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsCRTGlue.h"
|
#include "nsCRTGlue.h"
|
||||||
|
@ -1787,11 +1788,19 @@ Notification::ShowInternal()
|
||||||
|
|
||||||
nsAutoString alertName;
|
nsAutoString alertName;
|
||||||
GetAlertName(alertName);
|
GetAlertName(alertName);
|
||||||
alertService->ShowAlertNotification(iconUrl, mTitle, mBody, true,
|
nsCOMPtr<nsIAlertNotification> alert =
|
||||||
uniqueCookie, alertObserver, alertName,
|
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
|
||||||
DirectionToString(mDir), mLang,
|
NS_ENSURE_TRUE_VOID(alert);
|
||||||
mDataAsBase64, GetPrincipal(),
|
rv = alert->Init(alertName, iconUrl, mTitle, mBody,
|
||||||
|
true,
|
||||||
|
uniqueCookie,
|
||||||
|
DirectionToString(mDir),
|
||||||
|
mLang,
|
||||||
|
mDataAsBase64,
|
||||||
|
GetPrincipal(),
|
||||||
inPrivateBrowsing);
|
inPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
alertService->ShowAlert(alert, alertObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
|
|
@ -98,15 +98,15 @@ function testNonDefaultContentToolbars(toolbars) {
|
||||||
function testNonDefaultChromeToolbars(toolbars) {
|
function testNonDefaultChromeToolbars(toolbars) {
|
||||||
// None of the toolbars should be visible if hidden with chrome privileges
|
// None of the toolbars should be visible if hidden with chrome privileges
|
||||||
ok(!toolbars.locationbar,
|
ok(!toolbars.locationbar,
|
||||||
"locationbar should be visible on default window.open()");
|
"locationbar should not be visible with location=no");
|
||||||
ok(!toolbars.menubar,
|
ok(!toolbars.menubar,
|
||||||
"menubar be visible on default window.open()");
|
"menubar should not be visible with menubar=no");
|
||||||
ok(!toolbars.personalbar,
|
ok(!toolbars.personalbar,
|
||||||
"personalbar should be visible on default window.open()");
|
"personalbar should not be visible with personalbar=no");
|
||||||
ok(!toolbars.statusbar,
|
ok(!toolbars.statusbar,
|
||||||
"statusbar should be visible on default window.open()");
|
"statusbar should not be visible with status=no");
|
||||||
ok(!toolbars.toolbar,
|
ok(!toolbars.toolbar,
|
||||||
"toolbar should be visible on default window.open()");
|
"toolbar should not be visible with toolbar=no");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,7 +147,42 @@ add_task(function*() {
|
||||||
let popupToolbars = yield getToolbarsFromBrowserContent(popupBrowser);
|
let popupToolbars = yield getToolbarsFromBrowserContent(popupBrowser);
|
||||||
testNonDefaultContentToolbars(popupToolbars);
|
testNonDefaultContentToolbars(popupToolbars);
|
||||||
|
|
||||||
// Cleanup
|
// Ensure that chrome toolbars agree with content
|
||||||
|
let chromeToolbars = getToolbarsFromWindowChrome(popupWindow);
|
||||||
|
testNonDefaultContentToolbars(chromeToolbars);
|
||||||
|
|
||||||
|
// Close the new window
|
||||||
|
yield BrowserTestUtils.closeWindow(popupWindow);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that toolbars of a window opened to about:blank in the content context
|
||||||
|
* have the correct visibility.
|
||||||
|
*
|
||||||
|
* A window opened with "location=no, personalbar=no, toolbar=no, scrollbars=no,
|
||||||
|
* menubar=no, status=no", should only have location visible.
|
||||||
|
*/
|
||||||
|
add_task(function*() {
|
||||||
|
yield BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: CONTENT_PAGE,
|
||||||
|
}, function*(browser) {
|
||||||
|
// Open a blank window with toolbars hidden
|
||||||
|
let winPromise = BrowserTestUtils.waitForNewWindow();
|
||||||
|
yield BrowserTestUtils.synthesizeMouseAtCenter("#winOpenNoURLNonDefault", {}, browser);
|
||||||
|
let popupWindow = yield winPromise;
|
||||||
|
|
||||||
|
// No need to wait for this window to load, since it's loading about:blank
|
||||||
|
let popupBrowser = popupWindow.gBrowser.selectedBrowser;
|
||||||
|
let popupToolbars = yield getToolbarsFromBrowserContent(popupBrowser);
|
||||||
|
testNonDefaultContentToolbars(popupToolbars);
|
||||||
|
|
||||||
|
// Ensure that chrome toolbars agree with content
|
||||||
|
let chromeToolbars = getToolbarsFromWindowChrome(popupWindow);
|
||||||
|
testNonDefaultContentToolbars(chromeToolbars);
|
||||||
|
|
||||||
|
// Close the new window
|
||||||
yield BrowserTestUtils.closeWindow(popupWindow);
|
yield BrowserTestUtils.closeWindow(popupWindow);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<p><a id="winOpenDefault" href="#" onclick="return openWindow();">Open a new window via window.open with default features.</a></p>
|
<p><a id="winOpenDefault" href="#" onclick="return openWindow();">Open a new window via window.open with default features.</a></p>
|
||||||
<p><a id="winOpenNonDefault" href="#" onclick="return openWindow('resizable=no, location=no, personalbar=no, toolbar=no, scrollbars=no, menubar=no, status=no, directories=no, height=100, width=500');">Open a new window via window.open with non-default features.</a></p>
|
<p><a id="winOpenNonDefault" href="#" onclick="return openWindow('resizable=no, location=no, personalbar=no, toolbar=no, scrollbars=no, menubar=no, status=no, directories=no, height=100, width=500');">Open a new window via window.open with non-default features.</a></p>
|
||||||
<p><a id="winOpenDialog" href="#" onclick="return openWindow('dialog=yes');">Open a new window via window.open with dialog=1.</a></p>
|
<p><a id="winOpenDialog" href="#" onclick="return openWindow('dialog=yes');">Open a new window via window.open with dialog=1.</a></p>
|
||||||
|
<p><a id="winOpenNoURLNonDefault" href="#" onclick="return openBlankWindow('location=no, toolbar=no, height=100, width=100');">Open a blank new window via window.open with non-default features.</a></p>
|
||||||
<p><a id="targetBlank" href="about:robots" target="_blank">Open a new window via target="_blank".</a></p>
|
<p><a id="targetBlank" href="about:robots" target="_blank">Open a new window via target="_blank".</a></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -16,4 +17,9 @@ function openWindow(aFeatures="") {
|
||||||
window.open("about:robots", "_blank", aFeatures);
|
window.open("about:robots", "_blank", aFeatures);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openBlankWindow(aFeatures="") {
|
||||||
|
window.open("", "_blank", aFeatures);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -29,26 +29,34 @@ var MockServices = (function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
var mockAlertsService = {
|
var mockAlertsService = {
|
||||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
showAlert: function(alert, alertListener) {
|
||||||
cookie, alertListener, name) {
|
|
||||||
var listener = SpecialPowers.wrap(alertListener);
|
var listener = SpecialPowers.wrap(alertListener);
|
||||||
activeAlertNotifications[name] = {
|
activeAlertNotifications[alert.name] = {
|
||||||
listener: listener,
|
listener: listener,
|
||||||
cookie: cookie,
|
cookie: alert.cookie,
|
||||||
title: title
|
title: alert.title
|
||||||
};
|
};
|
||||||
|
|
||||||
// fake async alert show event
|
// fake async alert show event
|
||||||
if (listener) {
|
if (listener) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
listener.observe(null, "alertshow", cookie);
|
listener.observe(null, "alertshow", alert.cookie);
|
||||||
}, 100);
|
}, 100);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
listener.observe(null, "alertclickcallback", cookie);
|
listener.observe(null, "alertclickcallback", alert.cookie);
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||||
|
cookie, alertListener, name) {
|
||||||
|
this.showAlert({
|
||||||
|
name: name,
|
||||||
|
cookie: cookie,
|
||||||
|
title: title
|
||||||
|
}, alertListener);
|
||||||
|
},
|
||||||
|
|
||||||
showAppNotification: function(aImageUrl, aTitle, aText, aAlertListener, aDetails) {
|
showAppNotification: function(aImageUrl, aTitle, aText, aAlertListener, aDetails) {
|
||||||
var listener = aAlertListener || (activeAlertNotifications[aDetails.id] ? activeAlertNotifications[aDetails.id].listener : undefined);
|
var listener = aAlertListener || (activeAlertNotifications[aDetails.id] ? activeAlertNotifications[aDetails.id].listener : undefined);
|
||||||
activeAppNotifications[aDetails.id] = {
|
activeAppNotifications[aDetails.id] = {
|
||||||
|
|
|
@ -8,17 +8,23 @@ var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager.
|
||||||
QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar);
|
QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar);
|
||||||
|
|
||||||
var mockAlertsService = {
|
var mockAlertsService = {
|
||||||
|
showAlert: function(alert, alertListener) {
|
||||||
|
// probably should do this async....
|
||||||
|
SpecialPowers.wrap(alertListener).observe(null, "alertshow", alert.cookie);
|
||||||
|
|
||||||
|
if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) {
|
||||||
|
SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", alert.cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpecialPowers.wrap(alertListener).observe(null, "alertfinished", alert.cookie);
|
||||||
|
},
|
||||||
|
|
||||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||||
cookie, alertListener, name, bidi,
|
cookie, alertListener, name, bidi,
|
||||||
lang, data) {
|
lang, data) {
|
||||||
// probably should do this async....
|
return this.showAlert({
|
||||||
SpecialPowers.wrap(alertListener).observe(null, "alertshow", cookie);
|
cookie: cookie
|
||||||
|
}, alertListener);
|
||||||
if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) {
|
|
||||||
SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecialPowers.wrap(alertListener).observe(null, "alertfinished", cookie);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showAppNotification: function(imageUrl, title, text, alertListener, details) {
|
showAppNotification: function(imageUrl, title, text, alertListener, details) {
|
||||||
|
|
|
@ -23,15 +23,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=782211
|
||||||
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
|
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
|
||||||
|
|
||||||
var mockAlertsService = {
|
var mockAlertsService = {
|
||||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
showAlert: function(alert, alertListener) {
|
||||||
cookie, alertListener, name, dir,
|
notificationsCreated.push(alert.name);
|
||||||
lang, data) {
|
|
||||||
notificationsCreated.push(name);
|
|
||||||
if (notificationsCreated.length == 3) {
|
if (notificationsCreated.length == 3) {
|
||||||
checkNotifications();
|
checkNotifications();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||||
|
cookie, alertListener, name, dir,
|
||||||
|
lang, data) {
|
||||||
|
this.showAlert({ name: name });
|
||||||
|
},
|
||||||
|
|
||||||
QueryInterface: function(aIID) {
|
QueryInterface: function(aIID) {
|
||||||
if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
|
if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
|
||||||
SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
|
SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
|
||||||
|
|
|
@ -23,13 +23,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=874090
|
||||||
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
|
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
|
||||||
|
|
||||||
var mockAlertsService = {
|
var mockAlertsService = {
|
||||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
showAlert: function(alert, alertListener) {
|
||||||
cookie, alertListener, name, dir, lang, data) {
|
ok(true, "System principal was granted permission and is able to call showAlert.");
|
||||||
ok(true, "System principal was granted permission and is able to call showAlertNotification.");
|
|
||||||
unregisterMock();
|
unregisterMock();
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||||
|
cookie, alertListener, name, dir, lang, data) {
|
||||||
|
this.showAlert();
|
||||||
|
},
|
||||||
|
|
||||||
QueryInterface: function(aIID) {
|
QueryInterface: function(aIID) {
|
||||||
if (aIID.equals(Components.interfaces.nsISupports) ||
|
if (aIID.equals(Components.interfaces.nsISupports) ||
|
||||||
aIID.equals(Components.interfaces.nsIAlertsService)) {
|
aIID.equals(Components.interfaces.nsIAlertsService)) {
|
||||||
|
|
|
@ -117,6 +117,9 @@ var AlertsService = {
|
||||||
"", ALERTS_SERVICE_CONTRACT_ID, null);
|
"", ALERTS_SERVICE_CONTRACT_ID, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showAlert: function() {
|
||||||
|
},
|
||||||
|
|
||||||
showAlertNotification: function() {
|
showAlertNotification: function() {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -2170,13 +2170,21 @@ public class BrowserApp extends GeckoApp
|
||||||
|
|
||||||
final Tab tab = Tabs.getInstance().getSelectedTab();
|
final Tab tab = Tabs.getInstance().getSelectedTab();
|
||||||
if (tab != null) {
|
if (tab != null) {
|
||||||
final String userRequested = tab.getUserRequested();
|
final String userSearchTerm = tab.getUserRequested();
|
||||||
|
|
||||||
// Check to see if there's a user-entered search term,
|
// Check to see if there's a user-entered search term,
|
||||||
// which we save whenever the user performs a search.
|
// which we save whenever the user performs a search.
|
||||||
url = (TextUtils.isEmpty(userRequested) ? tab.getURL() : userRequested);
|
final String telemetryMsg;
|
||||||
|
if (!TextUtils.isEmpty(userSearchTerm)) {
|
||||||
|
url = userSearchTerm;
|
||||||
|
telemetryMsg = "urlbar-userentered";
|
||||||
|
} else {
|
||||||
|
url = tab.getURL();
|
||||||
|
telemetryMsg = url.isEmpty() ? "urlbar-empty" : "urlbar-url";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.ACTIONBAR, telemetryMsg);
|
||||||
|
}
|
||||||
enterEditingMode(url);
|
enterEditingMode(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2210,7 +2218,12 @@ public class BrowserApp extends GeckoApp
|
||||||
|
|
||||||
mBrowserToolbar.startEditing(url, animator);
|
mBrowserToolbar.startEditing(url, animator);
|
||||||
|
|
||||||
|
final boolean isUserSearchTerm = !TextUtils.isEmpty(selectedTab.getUserRequested());
|
||||||
|
if (isUserSearchTerm && AppConstants.NIGHTLY_BUILD) {
|
||||||
|
showBrowserSearchAfterAnimation(animator);
|
||||||
|
} else {
|
||||||
showHomePagerWithAnimator(panelId, animator);
|
showHomePagerWithAnimator(panelId, animator);
|
||||||
|
}
|
||||||
|
|
||||||
animator.start();
|
animator.start();
|
||||||
Telemetry.startUISession(TelemetryContract.Session.AWESOMESCREEN);
|
Telemetry.startUISession(TelemetryContract.Session.AWESOMESCREEN);
|
||||||
|
@ -2622,6 +2635,24 @@ public class BrowserApp extends GeckoApp
|
||||||
refreshToolbarHeight();
|
refreshToolbarHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showBrowserSearchAfterAnimation(PropertyAnimator animator) {
|
||||||
|
if (animator == null) {
|
||||||
|
showBrowserSearch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() {
|
||||||
|
@Override
|
||||||
|
public void onPropertyAnimationStart() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPropertyAnimationEnd() {
|
||||||
|
showBrowserSearch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void showBrowserSearch() {
|
private void showBrowserSearch() {
|
||||||
if (mBrowserSearch.getUserVisibleHint()) {
|
if (mBrowserSearch.getUserVisibleHint()) {
|
||||||
return;
|
return;
|
||||||
|
@ -2672,7 +2703,7 @@ public class BrowserApp extends GeckoApp
|
||||||
|
|
||||||
// To prevent overdraw, the HomePager is hidden when BrowserSearch is displayed:
|
// To prevent overdraw, the HomePager is hidden when BrowserSearch is displayed:
|
||||||
// reverse that.
|
// reverse that.
|
||||||
mHomePagerContainer.setVisibility(View.VISIBLE);
|
showHomePager(Tabs.getInstance().getSelectedTab().getMostRecentHomePanel());
|
||||||
|
|
||||||
mBrowserSearchContainer.setVisibility(View.INVISIBLE);
|
mBrowserSearchContainer.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,11 @@ public class DownloadAction extends BaseAction {
|
||||||
|
|
||||||
temporaryFile = createTemporaryFile(context, content);
|
temporaryFile = createTemporaryFile(context, content);
|
||||||
|
|
||||||
|
if (!canWrite(temporaryFile, destinationFile)) {
|
||||||
|
throw new RecoverableDownloadContentException(RecoverableDownloadContentException.DISK_IO,
|
||||||
|
"Temporary or destination file not writeable");
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasEnoughDiskSpace(content, destinationFile, temporaryFile)) {
|
if (!hasEnoughDiskSpace(content, destinationFile, temporaryFile)) {
|
||||||
Log.d(LOGTAG, "Not enough disk space to save content. Skipping download.");
|
Log.d(LOGTAG, "Not enough disk space to save content. Skipping download.");
|
||||||
continue;
|
continue;
|
||||||
|
@ -336,4 +341,14 @@ public class DownloadAction extends BaseAction {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean canWrite(File... files) {
|
||||||
|
for (File file : files) {
|
||||||
|
if (!file.canWrite()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,7 @@ public class TestDownloadAction {
|
||||||
doReturn(file).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
doReturn(file).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
||||||
doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||||
|
|
||||||
|
doReturn(true).when(action).canWrite(any(File.class), any(File.class));
|
||||||
doReturn(false).when(action).verify(eq(file), anyString());
|
doReturn(false).when(action).verify(eq(file), anyString());
|
||||||
doNothing().when(action).download(any(HttpClient.class), anyString(), eq(file));
|
doNothing().when(action).download(any(HttpClient.class), anyString(), eq(file));
|
||||||
doReturn(true).when(action).verify(eq(file), anyString());
|
doReturn(true).when(action).verify(eq(file), anyString());
|
||||||
|
@ -202,6 +203,7 @@ public class TestDownloadAction {
|
||||||
|
|
||||||
DownloadAction action = spy(new DownloadAction(null));
|
DownloadAction action = spy(new DownloadAction(null));
|
||||||
doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
||||||
|
doReturn(true).when(action).canWrite(any(File.class), any(File.class));
|
||||||
|
|
||||||
File temporaryFile = mockFileWithSize(1337L);
|
File temporaryFile = mockFileWithSize(1337L);
|
||||||
doReturn(temporaryFile).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
doReturn(temporaryFile).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
||||||
|
@ -301,6 +303,7 @@ public class TestDownloadAction {
|
||||||
File destinationFile = mockNotExistingFile();
|
File destinationFile = mockNotExistingFile();
|
||||||
doReturn(destinationFile).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
doReturn(destinationFile).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||||
|
|
||||||
|
doReturn(true).when(action).canWrite(any(File.class), any(File.class));
|
||||||
doReturn(true).when(action).verify(eq(temporaryFile), anyString());
|
doReturn(true).when(action).verify(eq(temporaryFile), anyString());
|
||||||
doNothing().when(action).extract(eq(temporaryFile), eq(destinationFile), anyString());
|
doNothing().when(action).extract(eq(temporaryFile), eq(destinationFile), anyString());
|
||||||
|
|
||||||
|
@ -333,6 +336,7 @@ public class TestDownloadAction {
|
||||||
|
|
||||||
DownloadAction action = spy(new DownloadAction(null));
|
DownloadAction action = spy(new DownloadAction(null));
|
||||||
doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
||||||
|
doReturn(true).when(action).canWrite(any(File.class), any(File.class));
|
||||||
doNothing().when(action).download(any(HttpClient.class), anyString(), any(File.class));
|
doNothing().when(action).download(any(HttpClient.class), anyString(), any(File.class));
|
||||||
doReturn(false).when(action).verify(any(File.class), anyString());
|
doReturn(false).when(action).verify(any(File.class), anyString());
|
||||||
|
|
||||||
|
@ -443,6 +447,7 @@ public class TestDownloadAction {
|
||||||
doReturn(mockNotExistingFile()).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
doReturn(mockNotExistingFile()).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
||||||
doReturn(mockNotExistingFile()).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
doReturn(mockNotExistingFile()).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||||
doReturn(true).when(action).hasEnoughDiskSpace(eq(content), any(File.class), any(File.class));
|
doReturn(true).when(action).hasEnoughDiskSpace(eq(content), any(File.class), any(File.class));
|
||||||
|
doReturn(true).when(action).canWrite(any(File.class), any(File.class));
|
||||||
|
|
||||||
HttpClient client = mock(HttpClient.class);
|
HttpClient client = mock(HttpClient.class);
|
||||||
doThrow(IOException.class).when(client).execute(any(HttpUriRequest.class));
|
doThrow(IOException.class).when(client).execute(any(HttpUriRequest.class));
|
||||||
|
@ -499,6 +504,32 @@ public class TestDownloadAction {
|
||||||
verify(catalog, times(11)).rememberFailure(eq(content), anyInt());
|
verify(catalog, times(11)).rememberFailure(eq(content), anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario: Temporary or destination file is not writable.
|
||||||
|
*
|
||||||
|
* Verify that:
|
||||||
|
* * No download is performed
|
||||||
|
* * Error is counted as failure
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testNoDownIsPerformedIfFilesAreNotWritable() throws Exception{
|
||||||
|
DownloadContent content = createFont();
|
||||||
|
DownloadContentCatalog catalog = mockCatalogWithScheduledDownloads(content);
|
||||||
|
|
||||||
|
DownloadAction action = spy(new DownloadAction(null));
|
||||||
|
doReturn(true).when(action).isConnectedToNetwork(RuntimeEnvironment.application);
|
||||||
|
doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
||||||
|
doReturn(mockNotExistingFile()).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
||||||
|
doReturn(mockNotExistingFile()).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||||
|
doReturn(false).when(action).canWrite(any(File.class), any(File.class));
|
||||||
|
|
||||||
|
action.perform(RuntimeEnvironment.application, catalog);
|
||||||
|
|
||||||
|
verify(action).canWrite(any(File.class), any(File.class));
|
||||||
|
verify(action, never()).download(any(HttpClient.class), anyString(), any(File.class));
|
||||||
|
verify(catalog).rememberFailure(eq(content), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
private DownloadContent createFont() {
|
private DownloadContent createFont() {
|
||||||
return createFontWithSize(102400L);
|
return createFontWithSize(102400L);
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ public class AppMenuComponent extends BaseComponent {
|
||||||
* This method is dependent on not having two views with equivalent contentDescription / text.
|
* This method is dependent on not having two views with equivalent contentDescription / text.
|
||||||
*/
|
*/
|
||||||
private View findAppMenuItemView(String text) {
|
private View findAppMenuItemView(String text) {
|
||||||
mSolo.waitForText(text, 1, MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS);
|
mSolo.waitForText(String.format("^%s$", text), 1, MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS);
|
||||||
|
|
||||||
final List<View> views = mSolo.getViews();
|
final List<View> views = mSolo.getViews();
|
||||||
|
|
||||||
|
@ -298,7 +298,8 @@ public class AppMenuComponent extends BaseComponent {
|
||||||
|
|
||||||
private boolean isLegacyMoreMenuOpen() {
|
private boolean isLegacyMoreMenuOpen() {
|
||||||
// Check if the first menu option is visible.
|
// Check if the first menu option is visible.
|
||||||
return mSolo.searchText(mSolo.getString(R.string.share), true);
|
final String shareTitle = mSolo.getString(R.string.share);
|
||||||
|
return mSolo.searchText(String.format("^%s$", shareTitle), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -310,7 +311,7 @@ public class AppMenuComponent extends BaseComponent {
|
||||||
*/
|
*/
|
||||||
private boolean isMenuOpen(String menuItemTitle) {
|
private boolean isMenuOpen(String menuItemTitle) {
|
||||||
final View menuItemView = findAppMenuItemView(menuItemTitle);
|
final View menuItemView = findAppMenuItemView(menuItemTitle);
|
||||||
return isMenuOpen(menuItemView) ? true : mSolo.searchText(menuItemTitle, true);
|
return isMenuOpen(menuItemView) ? true : mSolo.searchText(String.format("^%s$", menuItemTitle), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Pub
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with t
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/AlertNotification.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION(AlertNotification, mPrincipal)
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AlertNotification)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertNotification)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIAlertNotification)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(AlertNotification)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(AlertNotification)
|
||||||
|
|
||||||
|
AlertNotification::AlertNotification()
|
||||||
|
: mTextClickable(false)
|
||||||
|
, mPrincipal(nullptr)
|
||||||
|
, mInPrivateBrowsing(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
AlertNotification::~AlertNotification()
|
||||||
|
{}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::Init(const nsAString& aName, const nsAString& aImageURL,
|
||||||
|
const nsAString& aTitle, const nsAString& aText,
|
||||||
|
bool aTextClickable, const nsAString& aCookie,
|
||||||
|
const nsAString& aDir, const nsAString& aLang,
|
||||||
|
const nsAString& aData, nsIPrincipal* aPrincipal,
|
||||||
|
bool aInPrivateBrowsing)
|
||||||
|
{
|
||||||
|
mName = aName;
|
||||||
|
mImageURL = aImageURL;
|
||||||
|
mTitle = aTitle;
|
||||||
|
mText = aText;
|
||||||
|
mTextClickable = aTextClickable;
|
||||||
|
mCookie = aCookie;
|
||||||
|
mDir = aDir;
|
||||||
|
mLang = aLang;
|
||||||
|
mData = aData;
|
||||||
|
mPrincipal = aPrincipal;
|
||||||
|
mInPrivateBrowsing = aInPrivateBrowsing;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetName(nsAString& aName)
|
||||||
|
{
|
||||||
|
aName = mName;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetImageURL(nsAString& aImageURL)
|
||||||
|
{
|
||||||
|
aImageURL = mImageURL;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetTitle(nsAString& aTitle)
|
||||||
|
{
|
||||||
|
aTitle = mTitle;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetText(nsAString& aText)
|
||||||
|
{
|
||||||
|
aText = mText;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetTextClickable(bool* aTextClickable)
|
||||||
|
{
|
||||||
|
*aTextClickable = mTextClickable;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetCookie(nsAString& aCookie)
|
||||||
|
{
|
||||||
|
aCookie = mCookie;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetDir(nsAString& aDir)
|
||||||
|
{
|
||||||
|
aDir = mDir;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetLang(nsAString& aLang)
|
||||||
|
{
|
||||||
|
aLang = mLang;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetData(nsAString& aData)
|
||||||
|
{
|
||||||
|
aData = mData;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||||
|
{
|
||||||
|
NS_IF_ADDREF(*aPrincipal = mPrincipal);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
AlertNotification::GetInPrivateBrowsing(bool* aInPrivateBrowsing)
|
||||||
|
{
|
||||||
|
*aInPrivateBrowsing = mInPrivateBrowsing;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_AlertNotification_h__
|
||||||
|
#define mozilla_AlertNotification_h__
|
||||||
|
|
||||||
|
#include "nsIAlertsService.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
#include "nsIPrincipal.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class AlertNotification final : public nsIAlertNotification
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(AlertNotification,
|
||||||
|
nsIAlertNotification)
|
||||||
|
NS_DECL_NSIALERTNOTIFICATION
|
||||||
|
AlertNotification();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~AlertNotification();
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsString mName;
|
||||||
|
nsString mImageURL;
|
||||||
|
nsString mTitle;
|
||||||
|
nsString mText;
|
||||||
|
bool mTextClickable;
|
||||||
|
nsString mCookie;
|
||||||
|
nsString mDir;
|
||||||
|
nsString mLang;
|
||||||
|
nsString mData;
|
||||||
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||||
|
bool mInPrivateBrowsing;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif /* mozilla_AlertNotification_h__ */
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_AlertNotificationIPCSerializer_h__
|
||||||
|
#define mozilla_AlertNotificationIPCSerializer_h__
|
||||||
|
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIAlertsService.h"
|
||||||
|
#include "nsIPrincipal.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
#include "ipc/IPCMessageUtils.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||||
|
|
||||||
|
typedef nsIAlertNotification* AlertNotificationType;
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<AlertNotificationType>
|
||||||
|
{
|
||||||
|
typedef AlertNotificationType paramType;
|
||||||
|
|
||||||
|
static void Write(Message* aMsg, const paramType& aParam)
|
||||||
|
{
|
||||||
|
bool isNull = !aParam;
|
||||||
|
if (isNull) {
|
||||||
|
WriteParam(aMsg, isNull);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString name, imageURL, title, text, cookie, dir, lang, data;
|
||||||
|
bool textClickable, inPrivateBrowsing;
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(aParam->GetName(name))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetImageURL(imageURL))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetTitle(title))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetText(text))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetTextClickable(&textClickable))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetCookie(cookie))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetDir(dir))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetLang(lang))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetData(data))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetPrincipal(getter_AddRefs(principal)))) ||
|
||||||
|
NS_WARN_IF(NS_FAILED(aParam->GetInPrivateBrowsing(&inPrivateBrowsing)))) {
|
||||||
|
|
||||||
|
// Write a `null` object if any getter returns an error. Otherwise, the
|
||||||
|
// receiver will try to deserialize an incomplete object and crash.
|
||||||
|
WriteParam(aMsg, /* isNull */ true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteParam(aMsg, isNull);
|
||||||
|
WriteParam(aMsg, name);
|
||||||
|
WriteParam(aMsg, imageURL);
|
||||||
|
WriteParam(aMsg, title);
|
||||||
|
WriteParam(aMsg, text);
|
||||||
|
WriteParam(aMsg, textClickable);
|
||||||
|
WriteParam(aMsg, cookie);
|
||||||
|
WriteParam(aMsg, dir);
|
||||||
|
WriteParam(aMsg, lang);
|
||||||
|
WriteParam(aMsg, data);
|
||||||
|
WriteParam(aMsg, IPC::Principal(principal));
|
||||||
|
WriteParam(aMsg, inPrivateBrowsing);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||||
|
{
|
||||||
|
bool isNull;
|
||||||
|
NS_ENSURE_TRUE(ReadParam(aMsg, aIter, &isNull), false);
|
||||||
|
if (isNull) {
|
||||||
|
*aResult = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString name, imageURL, title, text, cookie, dir, lang, data;
|
||||||
|
bool textClickable, inPrivateBrowsing;
|
||||||
|
IPC::Principal principal;
|
||||||
|
|
||||||
|
if (!ReadParam(aMsg, aIter, &name) ||
|
||||||
|
!ReadParam(aMsg, aIter, &imageURL) ||
|
||||||
|
!ReadParam(aMsg, aIter, &title) ||
|
||||||
|
!ReadParam(aMsg, aIter, &text) ||
|
||||||
|
!ReadParam(aMsg, aIter, &textClickable) ||
|
||||||
|
!ReadParam(aMsg, aIter, &cookie) ||
|
||||||
|
!ReadParam(aMsg, aIter, &dir) ||
|
||||||
|
!ReadParam(aMsg, aIter, &lang) ||
|
||||||
|
!ReadParam(aMsg, aIter, &data) ||
|
||||||
|
!ReadParam(aMsg, aIter, &principal) ||
|
||||||
|
!ReadParam(aMsg, aIter, &inPrivateBrowsing)) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAlertNotification> alert =
|
||||||
|
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
|
||||||
|
if (NS_WARN_IF(!alert)) {
|
||||||
|
*aResult = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
nsresult rv = alert->Init(name, imageURL, title, text, textClickable,
|
||||||
|
cookie, dir, lang, data, principal,
|
||||||
|
inPrivateBrowsing);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
*aResult = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
alert.forget(aResult);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace IPC
|
||||||
|
|
||||||
|
#endif /* mozilla_AlertNotificationIPCSerializer_h__ */
|
|
@ -16,7 +16,13 @@ EXPORTS += [
|
||||||
'nsAlertsUtils.h',
|
'nsAlertsUtils.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
EXPORTS.mozilla += [
|
||||||
|
'AlertNotification.h',
|
||||||
|
'AlertNotificationIPCSerializer.h',
|
||||||
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
'AlertNotification.cpp',
|
||||||
'nsAlertsService.cpp',
|
'nsAlertsService.cpp',
|
||||||
'nsAlertsUtils.cpp',
|
'nsAlertsUtils.cpp',
|
||||||
'nsXULAlerts.cpp',
|
'nsXULAlerts.cpp',
|
||||||
|
|
|
@ -73,40 +73,66 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl
|
||||||
nsIPrincipal * aPrincipal,
|
nsIPrincipal * aPrincipal,
|
||||||
bool aInPrivateBrowsing)
|
bool aInPrivateBrowsing)
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIAlertNotification> alert =
|
||||||
|
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
|
||||||
|
nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle,
|
||||||
|
aAlertText, aAlertTextClickable,
|
||||||
|
aAlertCookie, aBidi, aLang, aData,
|
||||||
|
aPrincipal, aInPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return ShowAlert(alert, aAlertListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsAlertsService::ShowAlert(nsIAlertNotification * aAlert,
|
||||||
|
nsIObserver * aAlertListener)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG(aAlert);
|
||||||
|
|
||||||
|
nsAutoString cookie;
|
||||||
|
nsresult rv = aAlert->GetCookie(cookie);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (XRE_IsContentProcess()) {
|
if (XRE_IsContentProcess()) {
|
||||||
ContentChild* cpc = ContentChild::GetSingleton();
|
ContentChild* cpc = ContentChild::GetSingleton();
|
||||||
|
|
||||||
if (aAlertListener)
|
if (aAlertListener)
|
||||||
cpc->AddRemoteAlertObserver(PromiseFlatString(aAlertCookie), aAlertListener);
|
cpc->AddRemoteAlertObserver(cookie, aAlertListener);
|
||||||
|
|
||||||
cpc->SendShowAlertNotification(PromiseFlatString(aImageUrl),
|
cpc->SendShowAlert(aAlert);
|
||||||
PromiseFlatString(aAlertTitle),
|
|
||||||
PromiseFlatString(aAlertText),
|
|
||||||
aAlertTextClickable,
|
|
||||||
PromiseFlatString(aAlertCookie),
|
|
||||||
PromiseFlatString(aAlertName),
|
|
||||||
PromiseFlatString(aBidi),
|
|
||||||
PromiseFlatString(aLang),
|
|
||||||
PromiseFlatString(aData),
|
|
||||||
IPC::Principal(aPrincipal),
|
|
||||||
aInPrivateBrowsing);
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoString imageUrl;
|
||||||
|
rv = aAlert->GetImageURL(imageUrl);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoString title;
|
||||||
|
rv = aAlert->GetTitle(title);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoString text;
|
||||||
|
rv = aAlert->GetText(text);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoString name;
|
||||||
|
rv = aAlert->GetName(name);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
rv = aAlert->GetPrincipal(getter_AddRefs(principal));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
mozilla::AndroidBridge::Bridge()->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertCookie,
|
mozilla::AndroidBridge::Bridge()->ShowAlertNotification(imageUrl, title, text, cookie,
|
||||||
aAlertListener, aAlertName, aPrincipal);
|
aAlertListener, name, principal);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
#else
|
#else
|
||||||
// Check if there is an optional service that handles system-level notifications
|
// Check if there is an optional service that handles system-level notifications
|
||||||
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
|
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
|
||||||
nsresult rv;
|
|
||||||
if (sysAlerts) {
|
if (sysAlerts) {
|
||||||
rv = sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
|
rv = sysAlerts->ShowAlert(aAlert, aAlertListener);
|
||||||
aAlertCookie, aAlertListener, aAlertName,
|
|
||||||
aBidi, aLang, aData,
|
|
||||||
IPC::Principal(aPrincipal),
|
|
||||||
aInPrivateBrowsing);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -114,14 +140,30 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl
|
||||||
if (!ShouldShowAlert()) {
|
if (!ShouldShowAlert()) {
|
||||||
// Do not display the alert. Instead call alertfinished and get out.
|
// Do not display the alert. Instead call alertfinished and get out.
|
||||||
if (aAlertListener)
|
if (aAlertListener)
|
||||||
aAlertListener->Observe(nullptr, "alertfinished", PromiseFlatString(aAlertCookie).get());
|
aAlertListener->Observe(nullptr, "alertfinished", cookie.get());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool textClickable;
|
||||||
|
rv = aAlert->GetTextClickable(&textClickable);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoString bidi;
|
||||||
|
rv = aAlert->GetDir(bidi);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoString lang;
|
||||||
|
rv = aAlert->GetLang(lang);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
bool inPrivateBrowsing;
|
||||||
|
rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Use XUL notifications as a fallback if above methods have failed.
|
// Use XUL notifications as a fallback if above methods have failed.
|
||||||
rv = mXULAlerts.ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
|
rv = mXULAlerts.ShowAlertNotification(imageUrl, title, text, textClickable,
|
||||||
aAlertCookie, aAlertListener, aAlertName,
|
cookie, aAlertListener, name,
|
||||||
aBidi, aLang, aPrincipal, aInPrivateBrowsing);
|
bidi, lang, principal, inPrivateBrowsing);
|
||||||
return rv;
|
return rv;
|
||||||
#endif // !MOZ_WIDGET_ANDROID
|
#endif // !MOZ_WIDGET_ANDROID
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,96 @@
|
||||||
|
|
||||||
interface nsIPrincipal;
|
interface nsIPrincipal;
|
||||||
|
|
||||||
[scriptable, uuid(9d0284bf-db40-42da-8f0d-c2769dbde7aa)]
|
%{C++
|
||||||
|
#define ALERT_NOTIFICATION_CONTRACTID "@mozilla.org/alert-notification;1"
|
||||||
|
%}
|
||||||
|
|
||||||
|
[scriptable, uuid(b26b4a67-81b0-4270-8311-1e00a097ef92)]
|
||||||
|
interface nsIAlertNotification : nsISupports
|
||||||
|
{
|
||||||
|
/** Initializes an alert notification. */
|
||||||
|
void init([optional] in AString name,
|
||||||
|
[optional] in AString imageURL,
|
||||||
|
[optional] in AString title,
|
||||||
|
[optional] in AString text,
|
||||||
|
[optional] in boolean textClickable,
|
||||||
|
[optional] in AString cookie,
|
||||||
|
[optional] in AString dir,
|
||||||
|
[optional] in AString lang,
|
||||||
|
[optional] in AString data,
|
||||||
|
[optional] in nsIPrincipal principal,
|
||||||
|
[optional] in boolean inPrivateBrowsing);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the notification. This is currently only used on Android and
|
||||||
|
* OS X. On Android, the name is hashed and used as a notification ID.
|
||||||
|
* Notifications will replace previous notifications with the same name.
|
||||||
|
*/
|
||||||
|
readonly attribute AString name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A URL identifying the image to put in the alert. The OS X backend limits
|
||||||
|
* the amount of time it will wait for the image to load to six seconds. After
|
||||||
|
* that time, the alert will show without an image.
|
||||||
|
*/
|
||||||
|
readonly attribute AString imageURL;
|
||||||
|
|
||||||
|
/** The title for the alert. */
|
||||||
|
readonly attribute AString title;
|
||||||
|
|
||||||
|
/** The contents of the alert. */
|
||||||
|
readonly attribute AString text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls the click behavior. If true, the alert listener will be notified
|
||||||
|
* when the user clicks on the alert.
|
||||||
|
*/
|
||||||
|
readonly attribute boolean textClickable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An opaque cookie that will be passed to the alert listener for each
|
||||||
|
* callback.
|
||||||
|
*/
|
||||||
|
readonly attribute AString cookie;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bidi override for the title and contents. Valid values are "auto", "ltr",
|
||||||
|
* or "rtl". Ignored if the backend doesn't support localization.
|
||||||
|
*/
|
||||||
|
readonly attribute AString dir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language of the title and text. Ignored if the backend doesn't support
|
||||||
|
* localization.
|
||||||
|
*/
|
||||||
|
readonly attribute AString lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Base64-encoded structured clone buffer containing data associated with
|
||||||
|
* this alert. Only used for web notifications. Chrome callers should use a
|
||||||
|
* cookie instead.
|
||||||
|
*/
|
||||||
|
readonly attribute AString data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The principal of the page that created the alert. Used for IPC security
|
||||||
|
* checks, and to determine whether the alert should show the source string
|
||||||
|
* and action buttons.
|
||||||
|
*/
|
||||||
|
readonly attribute nsIPrincipal principal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls the image loading behavior. If true, the image URL will be loaded
|
||||||
|
* in private browsing mode.
|
||||||
|
*/
|
||||||
|
readonly attribute boolean inPrivateBrowsing;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(f7a36392-d98b-4141-a7d7-4e46642684e3)]
|
||||||
interface nsIAlertsService : nsISupports
|
interface nsIAlertsService : nsISupports
|
||||||
{
|
{
|
||||||
|
void showAlert(in nsIAlertNotification alert,
|
||||||
|
[optional] in nsIObserver alertListener);
|
||||||
/**
|
/**
|
||||||
* Displays a sliding notification window.
|
* Displays a sliding notification window.
|
||||||
*
|
*
|
||||||
|
|
|
@ -97,6 +97,9 @@
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define ALERT_NOTIFICATION_CID \
|
||||||
|
{ 0x9a7b7a41, 0x0b47, 0x47f7, { 0xb6, 0x1b, 0x15, 0xa2, 0x10, 0xd6, 0xf0, 0x20 } }
|
||||||
|
|
||||||
// {A0CCAAF8-09DA-44D8-B250-9AC3E93C8117}
|
// {A0CCAAF8-09DA-44D8-B250-9AC3E93C8117}
|
||||||
#define NS_ALERTSSERVICE_CID \
|
#define NS_ALERTSSERVICE_CID \
|
||||||
{ 0xa0ccaaf8, 0x9da, 0x44d8, { 0xb2, 0x50, 0x9a, 0xc3, 0xe9, 0x3c, 0x81, 0x17 } }
|
{ 0xa0ccaaf8, 0x9da, 0x44d8, { 0xb2, 0x50, 0x9a, 0xc3, 0xe9, 0x3c, 0x81, 0x17 } }
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "nsParentalControlsService.h"
|
#include "nsParentalControlsService.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "mozilla/AlertNotification.h"
|
||||||
#include "nsAlertsService.h"
|
#include "nsAlertsService.h"
|
||||||
|
|
||||||
#include "nsDownloadManager.h"
|
#include "nsDownloadManager.h"
|
||||||
|
@ -82,6 +83,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsFindService)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsParentalControlsService)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsParentalControlsService)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(AlertNotification)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsService)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsService)
|
||||||
|
|
||||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDownloadManager,
|
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDownloadManager,
|
||||||
|
@ -138,6 +140,7 @@ NS_DEFINE_NAMED_CID(NS_TOOLKIT_PERFORMANCESTATSSERVICE_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_TOOLKIT_TERMINATOR_CID);
|
NS_DEFINE_NAMED_CID(NS_TOOLKIT_TERMINATOR_CID);
|
||||||
#endif
|
#endif
|
||||||
NS_DEFINE_NAMED_CID(NS_USERINFO_CID);
|
NS_DEFINE_NAMED_CID(NS_USERINFO_CID);
|
||||||
|
NS_DEFINE_NAMED_CID(ALERT_NOTIFICATION_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID);
|
NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID);
|
||||||
#if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
|
#if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
|
||||||
NS_DEFINE_NAMED_CID(NS_PARENTALCONTROLSSERVICE_CID);
|
NS_DEFINE_NAMED_CID(NS_PARENTALCONTROLSSERVICE_CID);
|
||||||
|
@ -173,6 +176,7 @@ static const Module::CIDEntry kToolkitCIDs[] = {
|
||||||
{ &kNS_TOOLKIT_PERFORMANCESTATSSERVICE_CID, false, nullptr, nsPerformanceStatsServiceConstructor },
|
{ &kNS_TOOLKIT_PERFORMANCESTATSSERVICE_CID, false, nullptr, nsPerformanceStatsServiceConstructor },
|
||||||
#endif // defined (MOZ_HAS_PERFSTATS)
|
#endif // defined (MOZ_HAS_PERFSTATS)
|
||||||
{ &kNS_USERINFO_CID, false, nullptr, nsUserInfoConstructor },
|
{ &kNS_USERINFO_CID, false, nullptr, nsUserInfoConstructor },
|
||||||
|
{ &kALERT_NOTIFICATION_CID, false, nullptr, AlertNotificationConstructor },
|
||||||
{ &kNS_ALERTSSERVICE_CID, false, nullptr, nsAlertsServiceConstructor },
|
{ &kNS_ALERTSSERVICE_CID, false, nullptr, nsAlertsServiceConstructor },
|
||||||
#if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
|
#if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
|
||||||
{ &kNS_PARENTALCONTROLSSERVICE_CID, false, nullptr, nsParentalControlsServiceConstructor },
|
{ &kNS_PARENTALCONTROLSSERVICE_CID, false, nullptr, nsParentalControlsServiceConstructor },
|
||||||
|
@ -210,6 +214,7 @@ static const Module::ContractIDEntry kToolkitContracts[] = {
|
||||||
{ NS_TOOLKIT_PERFORMANCESTATSSERVICE_CONTRACTID, &kNS_TOOLKIT_PERFORMANCESTATSSERVICE_CID },
|
{ NS_TOOLKIT_PERFORMANCESTATSSERVICE_CONTRACTID, &kNS_TOOLKIT_PERFORMANCESTATSSERVICE_CID },
|
||||||
#endif // defined (MOZ_HAS_PERFSTATS)
|
#endif // defined (MOZ_HAS_PERFSTATS)
|
||||||
{ NS_USERINFO_CONTRACTID, &kNS_USERINFO_CID },
|
{ NS_USERINFO_CONTRACTID, &kNS_USERINFO_CID },
|
||||||
|
{ ALERT_NOTIFICATION_CONTRACTID, &kALERT_NOTIFICATION_CID },
|
||||||
{ NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID },
|
{ NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID },
|
||||||
#if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
|
#if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
|
||||||
{ NS_PARENTALCONTROLSSERVICE_CONTRACTID, &kNS_PARENTALCONTROLSSERVICE_CID },
|
{ NS_PARENTALCONTROLSSERVICE_CONTRACTID, &kNS_PARENTALCONTROLSSERVICE_CID },
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "imgIRequest.h"
|
#include "imgIRequest.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "nsIAlertsService.h"
|
||||||
#include "nsIImageToPixbuf.h"
|
#include "nsIImageToPixbuf.h"
|
||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
|
@ -186,6 +187,11 @@ nsAlertsIconListener::ShowAlert(GdkPixbuf* aPixbuf)
|
||||||
if (!mNotification)
|
if (!mNotification)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obsServ =
|
||||||
|
do_GetService("@mozilla.org/observer-service;1");
|
||||||
|
if (obsServ)
|
||||||
|
obsServ->AddObserver(this, "quit-application", true);
|
||||||
|
|
||||||
if (aPixbuf)
|
if (aPixbuf)
|
||||||
notify_notification_set_icon_from_pixbuf(mNotification, aPixbuf);
|
notify_notification_set_icon_from_pixbuf(mNotification, aPixbuf);
|
||||||
|
|
||||||
|
@ -277,13 +283,8 @@ nsAlertsIconListener::Observe(nsISupports *aSubject, const char *aTopic,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl,
|
nsAlertsIconListener::InitAlertAsync(nsIAlertNotification* aAlert,
|
||||||
const nsAString & aAlertTitle,
|
nsIObserver* aAlertListener)
|
||||||
const nsAString & aAlertText,
|
|
||||||
bool aAlertTextClickable,
|
|
||||||
const nsAString & aAlertCookie,
|
|
||||||
nsIObserver * aAlertListener,
|
|
||||||
bool aInPrivateBrowsing)
|
|
||||||
{
|
{
|
||||||
if (!libNotifyHandle)
|
if (!libNotifyHandle)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -335,27 +336,38 @@ nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gHasActions && aAlertTextClickable)
|
nsresult rv = aAlert->GetTextClickable(&mAlertHasAction);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if (!gHasActions && mAlertHasAction)
|
||||||
return NS_ERROR_FAILURE; // No good, fallback to XUL
|
return NS_ERROR_FAILURE; // No good, fallback to XUL
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obsServ =
|
nsAutoString title;
|
||||||
do_GetService("@mozilla.org/observer-service;1");
|
rv = aAlert->GetTitle(title);
|
||||||
if (obsServ)
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
obsServ->AddObserver(this, "quit-application", true);
|
|
||||||
|
|
||||||
// Workaround for a libnotify bug - blank titles aren't dealt with
|
// Workaround for a libnotify bug - blank titles aren't dealt with
|
||||||
// properly so we use a space
|
// properly so we use a space
|
||||||
if (aAlertTitle.IsEmpty()) {
|
if (title.IsEmpty()) {
|
||||||
mAlertTitle = NS_LITERAL_CSTRING(" ");
|
mAlertTitle = NS_LITERAL_CSTRING(" ");
|
||||||
} else {
|
} else {
|
||||||
mAlertTitle = NS_ConvertUTF16toUTF8(aAlertTitle);
|
mAlertTitle = NS_ConvertUTF16toUTF8(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
mAlertText = NS_ConvertUTF16toUTF8(aAlertText);
|
nsAutoString text;
|
||||||
mAlertHasAction = aAlertTextClickable;
|
rv = aAlert->GetText(text);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
mAlertText = NS_ConvertUTF16toUTF8(text);
|
||||||
|
|
||||||
mAlertListener = aAlertListener;
|
mAlertListener = aAlertListener;
|
||||||
mAlertCookie = aAlertCookie;
|
|
||||||
|
|
||||||
return StartRequest(aImageUrl, aInPrivateBrowsing);
|
rv = aAlert->GetCookie(mAlertCookie);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoString imageUrl;
|
||||||
|
rv = aAlert->GetImageURL(imageUrl);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
bool inPrivateBrowsing;
|
||||||
|
rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return StartRequest(imageUrl, inPrivateBrowsing);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
class imgIRequest;
|
class imgIRequest;
|
||||||
|
class nsIAlertNotification;
|
||||||
|
|
||||||
struct NotifyNotification;
|
struct NotifyNotification;
|
||||||
|
|
||||||
|
@ -29,13 +30,8 @@ public:
|
||||||
|
|
||||||
nsAlertsIconListener();
|
nsAlertsIconListener();
|
||||||
|
|
||||||
nsresult InitAlertAsync(const nsAString & aImageUrl,
|
nsresult InitAlertAsync(nsIAlertNotification* aAlert,
|
||||||
const nsAString & aAlertTitle,
|
nsIObserver* aAlertListener);
|
||||||
const nsAString & aAlertText,
|
|
||||||
bool aAlertTextClickable,
|
|
||||||
const nsAString & aAlertCookie,
|
|
||||||
nsIObserver * aAlertListener,
|
|
||||||
bool aInPrivateBrowsing);
|
|
||||||
|
|
||||||
void SendCallback();
|
void SendCallback();
|
||||||
void SendClosed();
|
void SendClosed();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
#include "nsSystemAlertsService.h"
|
#include "nsSystemAlertsService.h"
|
||||||
#include "nsAlertsIconListener.h"
|
#include "nsAlertsIconListener.h"
|
||||||
|
@ -40,12 +41,27 @@ NS_IMETHODIMP nsSystemAlertsService::ShowAlertNotification(const nsAString & aIm
|
||||||
nsIPrincipal * aPrincipal,
|
nsIPrincipal * aPrincipal,
|
||||||
bool aInPrivateBrowsing)
|
bool aInPrivateBrowsing)
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIAlertNotification> alert =
|
||||||
|
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
|
||||||
|
nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle,
|
||||||
|
aAlertText, aAlertTextClickable,
|
||||||
|
aAlertCookie, aBidi, aLang, aData,
|
||||||
|
aPrincipal, aInPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return ShowAlert(alert, aAlertListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsSystemAlertsService::ShowAlert(nsIAlertNotification* aAlert,
|
||||||
|
nsIObserver* aAlertListener)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG(aAlert);
|
||||||
|
|
||||||
RefPtr<nsAlertsIconListener> alertListener = new nsAlertsIconListener();
|
RefPtr<nsAlertsIconListener> alertListener = new nsAlertsIconListener();
|
||||||
if (!alertListener)
|
if (!alertListener)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
return alertListener->InitAlertAsync(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
|
return alertListener->InitAlertAsync(aAlert, aAlertListener);
|
||||||
aAlertCookie, aAlertListener, aInPrivateBrowsing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsSystemAlertsService::CloseAlert(const nsAString& aAlertName,
|
NS_IMETHODIMP nsSystemAlertsService::CloseAlert(const nsAString& aAlertName,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "imgLoader.h"
|
#include "imgLoader.h"
|
||||||
#import "nsCocoaUtils.h"
|
#import "nsCocoaUtils.h"
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsObjCExceptions.h"
|
#include "nsObjCExceptions.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
@ -240,15 +241,39 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const
|
||||||
const nsAString & aData,
|
const nsAString & aData,
|
||||||
nsIPrincipal * aPrincipal,
|
nsIPrincipal * aPrincipal,
|
||||||
bool aInPrivateBrowsing)
|
bool aInPrivateBrowsing)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIAlertNotification> alert =
|
||||||
|
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
|
||||||
|
nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle,
|
||||||
|
aAlertText, aAlertTextClickable,
|
||||||
|
aAlertCookie, aBidi, aLang, aData,
|
||||||
|
aPrincipal, aInPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return ShowAlert(alert, aAlertListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
OSXNotificationCenter::ShowAlert(nsIAlertNotification* aAlert,
|
||||||
|
nsIObserver* aAlertListener)
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
|
||||||
|
NS_ENSURE_ARG(aAlert);
|
||||||
|
|
||||||
Class unClass = NSClassFromString(@"NSUserNotification");
|
Class unClass = NSClassFromString(@"NSUserNotification");
|
||||||
id<FakeNSUserNotification> notification = [[unClass alloc] init];
|
id<FakeNSUserNotification> notification = [[unClass alloc] init];
|
||||||
notification.title = nsCocoaUtils::ToNSString(aAlertTitle);
|
|
||||||
|
|
||||||
|
nsAutoString title;
|
||||||
|
nsresult rv = aAlert->GetTitle(title);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
notification.title = nsCocoaUtils::ToNSString(title);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
rv = aAlert->GetPrincipal(getter_AddRefs(principal));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
nsAutoString hostPort;
|
nsAutoString hostPort;
|
||||||
nsAlertsUtils::GetSourceHostPort(aPrincipal, hostPort);
|
nsAlertsUtils::GetSourceHostPort(principal, hostPort);
|
||||||
nsCOMPtr<nsIStringBundle> bundle;
|
nsCOMPtr<nsIStringBundle> bundle;
|
||||||
nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
|
nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
|
||||||
sbs->CreateBundle("chrome://alerts/locale/alert.properties", getter_AddRefs(bundle));
|
sbs->CreateBundle("chrome://alerts/locale/alert.properties", getter_AddRefs(bundle));
|
||||||
|
@ -263,12 +288,16 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const
|
||||||
notification.subtitle = nsCocoaUtils::ToNSString(notificationSource);
|
notification.subtitle = nsCocoaUtils::ToNSString(notificationSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.informativeText = nsCocoaUtils::ToNSString(aAlertText);
|
nsAutoString text;
|
||||||
|
rv = aAlert->GetText(text);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
notification.informativeText = nsCocoaUtils::ToNSString(text);
|
||||||
|
|
||||||
notification.soundName = NSUserNotificationDefaultSoundName;
|
notification.soundName = NSUserNotificationDefaultSoundName;
|
||||||
notification.hasActionButton = NO;
|
notification.hasActionButton = NO;
|
||||||
|
|
||||||
// If this is not an application/extension alert, show additional actions dealing with permissions.
|
// If this is not an application/extension alert, show additional actions dealing with permissions.
|
||||||
if (nsAlertsUtils::IsActionablePrincipal(aPrincipal)) {
|
if (nsAlertsUtils::IsActionablePrincipal(principal)) {
|
||||||
if (bundle) {
|
if (bundle) {
|
||||||
nsXPIDLString closeButtonTitle, actionButtonTitle, disableButtonTitle, settingsButtonTitle;
|
nsXPIDLString closeButtonTitle, actionButtonTitle, disableButtonTitle, settingsButtonTitle;
|
||||||
bundle->GetStringFromName(MOZ_UTF16("closeButton.title"),
|
bundle->GetStringFromName(MOZ_UTF16("closeButton.title"),
|
||||||
|
@ -307,24 +336,39 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NSString *alertName = nsCocoaUtils::ToNSString(aAlertName);
|
nsAutoString name;
|
||||||
|
rv = aAlert->GetName(name);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
NSString *alertName = nsCocoaUtils::ToNSString(name);
|
||||||
if (!alertName) {
|
if (!alertName) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
notification.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:alertName, nil]
|
notification.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:alertName, nil]
|
||||||
forKeys:[NSArray arrayWithObjects:@"name", nil]];
|
forKeys:[NSArray arrayWithObjects:@"name", nil]];
|
||||||
|
|
||||||
OSXNotificationInfo *osxni = new OSXNotificationInfo(alertName, aAlertListener, aAlertCookie);
|
nsAutoString cookie;
|
||||||
|
rv = aAlert->GetCookie(cookie);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
OSXNotificationInfo *osxni = new OSXNotificationInfo(alertName, aAlertListener, cookie);
|
||||||
|
|
||||||
|
nsAutoString imageUrl;
|
||||||
|
rv = aAlert->GetImageURL(imageUrl);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
bool inPrivateBrowsing;
|
||||||
|
rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Show the notification without waiting for an image if there is no icon URL or
|
// Show the notification without waiting for an image if there is no icon URL or
|
||||||
// notification icons are not supported on this version of OS X.
|
// notification icons are not supported on this version of OS X.
|
||||||
if (aImageUrl.IsEmpty() || ![unClass instancesRespondToSelector:@selector(setContentImage:)]) {
|
if (imageUrl.IsEmpty() || ![unClass instancesRespondToSelector:@selector(setContentImage:)]) {
|
||||||
CloseAlertCocoaString(alertName);
|
CloseAlertCocoaString(alertName);
|
||||||
mActiveAlerts.AppendElement(osxni);
|
mActiveAlerts.AppendElement(osxni);
|
||||||
[GetNotificationCenter() deliverNotification:notification];
|
[GetNotificationCenter() deliverNotification:notification];
|
||||||
[notification release];
|
[notification release];
|
||||||
if (aAlertListener) {
|
if (aAlertListener) {
|
||||||
aAlertListener->Observe(nullptr, "alertshow", PromiseFlatString(aAlertCookie).get());
|
aAlertListener->Observe(nullptr, "alertshow", cookie.get());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mPendingAlerts.AppendElement(osxni);
|
mPendingAlerts.AppendElement(osxni);
|
||||||
|
@ -332,13 +376,13 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const
|
||||||
RefPtr<imgLoader> il = imgLoader::GetInstance();
|
RefPtr<imgLoader> il = imgLoader::GetInstance();
|
||||||
if (il) {
|
if (il) {
|
||||||
nsCOMPtr<nsIURI> imageUri;
|
nsCOMPtr<nsIURI> imageUri;
|
||||||
NS_NewURI(getter_AddRefs(imageUri), aImageUrl);
|
NS_NewURI(getter_AddRefs(imageUri), imageUrl);
|
||||||
if (imageUri) {
|
if (imageUri) {
|
||||||
nsresult rv = il->LoadImage(imageUri, nullptr, nullptr,
|
rv = il->LoadImage(imageUri, nullptr, nullptr,
|
||||||
mozilla::net::RP_Default,
|
mozilla::net::RP_Default,
|
||||||
aPrincipal, nullptr,
|
principal, nullptr,
|
||||||
this, nullptr,
|
this, nullptr,
|
||||||
aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
|
inPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
|
||||||
nsIRequest::LOAD_NORMAL,
|
nsIRequest::LOAD_NORMAL,
|
||||||
nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE,
|
nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE,
|
||||||
EmptyString(),
|
EmptyString(),
|
||||||
|
|
Загрузка…
Ссылка в новой задаче