summaryrefslogtreecommitdiff
path: root/application/palemoon/modules
diff options
context:
space:
mode:
Diffstat (limited to 'application/palemoon/modules')
-rw-r--r--application/palemoon/modules/AboutHomeUtils.jsm2
-rw-r--r--application/palemoon/modules/AutoCompletePopup.jsm293
-rw-r--r--application/palemoon/modules/BrowserNewTabPreloader.jsm8
-rw-r--r--application/palemoon/modules/FormSubmitObserver.jsm16
-rw-r--r--application/palemoon/modules/FormValidationHandler.jsm10
-rw-r--r--application/palemoon/modules/NetworkPrioritizer.jsm8
-rw-r--r--application/palemoon/modules/PopupNotifications.jsm189
-rw-r--r--application/palemoon/modules/QuotaManager.jsm14
-rw-r--r--application/palemoon/modules/SharedFrame.jsm2
-rw-r--r--application/palemoon/modules/WindowsPreviewPerTab.jsm64
-rw-r--r--application/palemoon/modules/moz.build12
-rw-r--r--application/palemoon/modules/openLocationLastURL.jsm8
-rw-r--r--application/palemoon/modules/promise.js2
-rw-r--r--application/palemoon/modules/webrtcUI.jsm130
14 files changed, 625 insertions, 133 deletions
diff --git a/application/palemoon/modules/AboutHomeUtils.jsm b/application/palemoon/modules/AboutHomeUtils.jsm
index 1d4070eafa..72712e1f36 100644
--- a/application/palemoon/modules/AboutHomeUtils.jsm
+++ b/application/palemoon/modules/AboutHomeUtils.jsm
@@ -44,7 +44,7 @@ this.AboutHomeUtils = {
return !Services.prefs.getBoolPref("browser.EULA.override");
} catch (e) { }
-#ifndef MOZILLA_OFFICIAL
+#ifndef MC_OFFICIAL
// Non-official builds shouldn't show the notification.
return false;
#endif
diff --git a/application/palemoon/modules/AutoCompletePopup.jsm b/application/palemoon/modules/AutoCompletePopup.jsm
new file mode 100644
index 0000000000..c3698f9051
--- /dev/null
+++ b/application/palemoon/modules/AutoCompletePopup.jsm
@@ -0,0 +1,293 @@
+/* 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 Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+this.EXPORTED_SYMBOLS = [ "AutoCompletePopup" ];
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+// nsITreeView implementation that feeds the autocomplete popup
+// with the search data.
+var AutoCompleteTreeView = {
+ // nsISupports
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsITreeView,
+ Ci.nsIAutoCompleteController]),
+
+ // Private variables
+ treeBox: null,
+ results: [],
+
+ // nsITreeView
+ selection: null,
+
+ get rowCount() { return this.results.length; },
+ setTree: function(treeBox) { this.treeBox = treeBox; },
+ getCellText: function(idx, column) { return this.results[idx].value },
+ isContainer: function(idx) { return false; },
+ getCellValue: function(idx, column) { return false },
+ isContainerOpen: function(idx) { return false; },
+ isContainerEmpty: function(idx) { return false; },
+ isSeparator: function(idx) { return false; },
+ isSorted: function() { return false; },
+ isEditable: function(idx, column) { return false; },
+ canDrop: function(idx, orientation, dt) { return false; },
+ getLevel: function(idx) { return 0; },
+ getParentIndex: function(idx) { return -1; },
+ hasNextSibling: function(idx, after) { return idx < this.results.length - 1 },
+ toggleOpenState: function(idx) { },
+ getCellProperties: function(idx, column) { return this.results[idx].style || ""; },
+ getRowProperties: function(idx) { return ""; },
+ getImageSrc: function(idx, column) { return null; },
+ getProgressMode : function(idx, column) { },
+ cycleHeader: function(column) { },
+ cycleCell: function(idx, column) { },
+ selectionChanged: function() { },
+ performAction: function(action) { },
+ performActionOnCell: function(action, index, column) { },
+ getColumnProperties: function(column) { return ""; },
+
+ // nsIAutoCompleteController
+ get matchCount() {
+ return this.rowCount;
+ },
+
+ handleEnter: function(aIsPopupSelection) {
+ AutoCompletePopup.handleEnter(aIsPopupSelection);
+ },
+
+ stopSearch: function() {},
+
+ // Internal JS-only API
+ clearResults: function() {
+ this.results = [];
+ },
+
+ setResults: function(results) {
+ this.results = results;
+ },
+};
+
+this.AutoCompletePopup = {
+ MESSAGES: [
+ "FormAutoComplete:SelectBy",
+ "FormAutoComplete:GetSelectedIndex",
+ "FormAutoComplete:SetSelectedIndex",
+ "FormAutoComplete:MaybeOpenPopup",
+ "FormAutoComplete:ClosePopup",
+ "FormAutoComplete:Disconnect",
+ "FormAutoComplete:RemoveEntry",
+ "FormAutoComplete:Invalidate",
+ ],
+
+ init: function() {
+ for (let msg of this.MESSAGES) {
+ Services.mm.addMessageListener(msg, this);
+ }
+ },
+
+ uninit: function() {
+ for (let msg of this.MESSAGES) {
+ Services.mm.removeMessageListener(msg, this);
+ }
+ },
+
+ handleEvent: function(evt) {
+ switch (evt.type) {
+ case "popupshowing": {
+ this.sendMessageToBrowser("FormAutoComplete:PopupOpened");
+ break;
+ }
+
+ case "popuphidden": {
+ this.sendMessageToBrowser("FormAutoComplete:PopupClosed");
+ this.openedPopup = null;
+ this.weakBrowser = null;
+ evt.target.removeEventListener("popuphidden", this);
+ evt.target.removeEventListener("popupshowing", this);
+ break;
+ }
+ }
+ },
+
+ // Along with being called internally by the receiveMessage handler,
+ // this function is also called directly by the login manager, which
+ // uses a single message to fill in the autocomplete results. See
+ // "RemoteLogins:autoCompleteLogins".
+ showPopupWithResults: function({ browser, rect, dir, results }) {
+ if (!results.length || this.openedPopup) {
+ // We shouldn't ever be showing an empty popup, and if we
+ // already have a popup open, the old one needs to close before
+ // we consider opening a new one.
+ return;
+ }
+
+ let window = browser.ownerDocument.defaultView;
+ let tabbrowser = window.gBrowser;
+ if (Services.focus.activeWindow != window ||
+ tabbrowser.selectedBrowser != browser) {
+ // We were sent a message from a window or tab that went into the
+ // background, so we'll ignore it for now.
+ return;
+ }
+
+ this.weakBrowser = Cu.getWeakReference(browser);
+ this.openedPopup = browser.autoCompletePopup;
+ this.openedPopup.hidden = false;
+ // don't allow the popup to become overly narrow
+ this.openedPopup.setAttribute("width", Math.max(100, rect.width));
+ this.openedPopup.style.direction = dir;
+
+ AutoCompleteTreeView.setResults(results);
+ this.openedPopup.view = AutoCompleteTreeView;
+ this.openedPopup.selectedIndex = -1;
+ this.openedPopup.invalidate();
+
+ if (results.length) {
+ // Reset fields that were set from the last time the search popup was open
+ this.openedPopup.mInput = null;
+ this.openedPopup.showCommentColumn = false;
+ this.openedPopup.showImageColumn = false;
+ this.openedPopup.addEventListener("popuphidden", this);
+ this.openedPopup.addEventListener("popupshowing", this);
+ this.openedPopup.openPopupAtScreenRect("after_start", rect.left, rect.top,
+ rect.width, rect.height, false,
+ false);
+ } else {
+ this.closePopup();
+ }
+ },
+
+ invalidate(results) {
+ if (!this.openedPopup) {
+ return;
+ }
+
+ if (!results.length) {
+ this.closePopup();
+ } else {
+ AutoCompleteTreeView.setResults(results);
+ // We need to re-set the view in order for the
+ // tree to know the view has changed.
+ this.openedPopup.view = AutoCompleteTreeView;
+ this.openedPopup.invalidate();
+ }
+ },
+
+ closePopup() {
+ if (this.openedPopup) {
+ // Note that hidePopup() closes the popup immediately,
+ // so popuphiding or popuphidden events will be fired
+ // and handled during this call.
+ this.openedPopup.hidePopup();
+ }
+ AutoCompleteTreeView.clearResults();
+ },
+
+ removeLogin(login) {
+ Services.logins.removeLogin(login);
+ },
+
+ receiveMessage: function(message) {
+ if (!message.target.autoCompletePopup) {
+ // Returning false to pacify ESLint, but this return value is
+ // ignored by the messaging infrastructure.
+ return false;
+ }
+
+ switch (message.name) {
+ case "FormAutoComplete:SelectBy": {
+ this.openedPopup.selectBy(message.data.reverse, message.data.page);
+ break;
+ }
+
+ case "FormAutoComplete:GetSelectedIndex": {
+ if (this.openedPopup) {
+ return this.openedPopup.selectedIndex;
+ }
+ // If the popup was closed, then the selection
+ // has not changed.
+ return -1;
+ }
+
+ case "FormAutoComplete:SetSelectedIndex": {
+ let { index } = message.data;
+ if (this.openedPopup) {
+ this.openedPopup.selectedIndex = index;
+ }
+ break;
+ }
+
+ case "FormAutoComplete:MaybeOpenPopup": {
+ let { results, rect, dir } = message.data;
+ this.showPopupWithResults({ browser: message.target, rect, dir,
+ results });
+ break;
+ }
+
+ case "FormAutoComplete:Invalidate": {
+ let { results } = message.data;
+ this.invalidate(results);
+ break;
+ }
+
+ case "FormAutoComplete:ClosePopup": {
+ this.closePopup();
+ break;
+ }
+
+ case "FormAutoComplete:Disconnect": {
+ // The controller stopped controlling the current input, so clear
+ // any cached data. This is necessary cause otherwise we'd clear data
+ // only when starting a new search, but the next input could not support
+ // autocomplete and it would end up inheriting the existing data.
+ AutoCompleteTreeView.clearResults();
+ break;
+ }
+ }
+ // Returning false to pacify ESLint, but this return value is
+ // ignored by the messaging infrastructure.
+ return false;
+ },
+
+ /**
+ * Despite its name, this handleEnter is only called when the user clicks on
+ * one of the items in the popup since the popup is rendered in the parent process.
+ * The real controller's handleEnter is called directly in the content process
+ * for other methods of completing a selection (e.g. using the tab or enter
+ * keys) since the field with focus is in that process.
+ */
+ handleEnter(aIsPopupSelection) {
+ if (this.openedPopup) {
+ this.sendMessageToBrowser("FormAutoComplete:HandleEnter", {
+ selectedIndex: this.openedPopup.selectedIndex,
+ isPopupSelection: aIsPopupSelection,
+ });
+ }
+ },
+
+ /**
+ * If a browser exists that AutoCompletePopup knows about,
+ * sends it a message. Otherwise, this is a no-op.
+ *
+ * @param {string} msgName
+ * The name of the message to send.
+ * @param {object} data
+ * The optional data to send with the message.
+ */
+ sendMessageToBrowser(msgName, data) {
+ let browser = this.weakBrowser ? this.weakBrowser.get()
+ : null;
+ if (browser) {
+ browser.messageManager.sendAsyncMessage(msgName, data);
+ }
+ },
+
+ stopSearch: function() {}
+}
diff --git a/application/palemoon/modules/BrowserNewTabPreloader.jsm b/application/palemoon/modules/BrowserNewTabPreloader.jsm
index 719a9e05e2..778698fbaa 100644
--- a/application/palemoon/modules/BrowserNewTabPreloader.jsm
+++ b/application/palemoon/modules/BrowserNewTabPreloader.jsm
@@ -79,7 +79,7 @@ this.BrowserNewTabPreloader = {
Object.freeze(BrowserNewTabPreloader);
-let Initializer = {
+var Initializer = {
_timer: null,
_observing: false,
@@ -120,7 +120,7 @@ let Initializer = {
}
};
-let Preferences = {
+var Preferences = {
_enabled: null,
_branch: null,
@@ -157,7 +157,7 @@ let Preferences = {
},
};
-let HiddenBrowsers = {
+var HiddenBrowsers = {
_browsers: null,
_updateTimer: null,
@@ -379,7 +379,7 @@ HiddenBrowser.prototype = {
}
};
-let HostFrame = {
+var HostFrame = {
_frame: null,
_deferred: null,
diff --git a/application/palemoon/modules/FormSubmitObserver.jsm b/application/palemoon/modules/FormSubmitObserver.jsm
index 72c5ca601a..e4d3e765ed 100644
--- a/application/palemoon/modules/FormSubmitObserver.jsm
+++ b/application/palemoon/modules/FormSubmitObserver.jsm
@@ -9,14 +9,14 @@
"use strict";
-let Cc = Components.classes;
-let Ci = Components.interfaces;
-let Cu = Components.utils;
-
-let HTMLInputElement = Ci.nsIDOMHTMLInputElement;
-let HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
-let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
-let HTMLButtonElement = Ci.nsIDOMHTMLButtonElement;
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+
+var HTMLInputElement = Ci.nsIDOMHTMLInputElement;
+var HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
+var HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
+var HTMLButtonElement = Ci.nsIDOMHTMLButtonElement;
this.EXPORTED_SYMBOLS = [ "FormSubmitObserver" ];
diff --git a/application/palemoon/modules/FormValidationHandler.jsm b/application/palemoon/modules/FormValidationHandler.jsm
index 05be510e18..387c221d74 100644
--- a/application/palemoon/modules/FormValidationHandler.jsm
+++ b/application/palemoon/modules/FormValidationHandler.jsm
@@ -8,15 +8,15 @@
"use strict";
-let Cc = Components.classes;
-let Ci = Components.interfaces;
-let Cu = Components.utils;
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
this.EXPORTED_SYMBOLS = [ "FormValidationHandler" ];
Cu.import("resource://gre/modules/Services.jsm");
-let FormValidationHandler =
+var FormValidationHandler =
{
_panel: null,
_anchor: null,
@@ -122,7 +122,7 @@ let FormValidationHandler =
this._panel.hidden = false;
let tabBrowser = aWindow.gBrowser;
- this._anchor = tabBrowser.formValidationAnchor;
+ this._anchor = tabBrowser.popupAnchor;
this._anchor.left = aPanelData.contentRect.left;
this._anchor.top = aPanelData.contentRect.top;
this._anchor.width = aPanelData.contentRect.width;
diff --git a/application/palemoon/modules/NetworkPrioritizer.jsm b/application/palemoon/modules/NetworkPrioritizer.jsm
index ea4a877904..23d688a305 100644
--- a/application/palemoon/modules/NetworkPrioritizer.jsm
+++ b/application/palemoon/modules/NetworkPrioritizer.jsm
@@ -34,8 +34,8 @@ const PRIORITY_DELTA = -10;
// Variables
-let _lastFocusedWindow = null;
-let _windows = [];
+var _lastFocusedWindow = null;
+var _windows = [];
// Exported symbol
@@ -64,7 +64,7 @@ function _handleEvent(aEvent) {
// Methods that impact a browser. Put into single object for organization.
-let BrowserHelper = {
+var BrowserHelper = {
onOpen: function NP_BH_onOpen(aBrowser) {
// If the tab is in the focused window, leave priority as it is
if (aBrowser.ownerDocument.defaultView != _lastFocusedWindow)
@@ -91,7 +91,7 @@ let BrowserHelper = {
// Methods that impact a window. Put into single object for organization.
-let WindowHelper = {
+var WindowHelper = {
addWindow: function NP_WH_addWindow(aWindow) {
// Build internal data object
_windows.push({ window: aWindow, lastSelectedBrowser: null });
diff --git a/application/palemoon/modules/PopupNotifications.jsm b/application/palemoon/modules/PopupNotifications.jsm
index 9b2e8e5d16..0cb9702301 100644
--- a/application/palemoon/modules/PopupNotifications.jsm
+++ b/application/palemoon/modules/PopupNotifications.jsm
@@ -4,22 +4,23 @@
this.EXPORTED_SYMBOLS = ["PopupNotifications"];
-var Cc = Components.classes, Ci = Components.interfaces;
+var Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils;
-Components.utils.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
const NOTIFICATION_EVENT_DISMISSED = "dismissed";
const NOTIFICATION_EVENT_REMOVED = "removed";
const NOTIFICATION_EVENT_SHOWING = "showing";
const NOTIFICATION_EVENT_SHOWN = "shown";
+const NOTIFICATION_EVENT_SWAPPING = "swapping";
const ICON_SELECTOR = ".notification-anchor-icon";
const ICON_ATTRIBUTE_SHOWING = "showing";
const PREF_SECURITY_DELAY = "security.notification_enable_delay";
-let popupNotificationsMap = new WeakMap();
-let gNotificationParents = new WeakMap;
+var popupNotificationsMap = new WeakMap();
+var gNotificationParents = new WeakMap;
function getAnchorFromBrowser(aBrowser) {
let anchor = aBrowser.getAttribute("popupnotificationanchor") ||
@@ -33,6 +34,18 @@ function getAnchorFromBrowser(aBrowser) {
return null;
}
+function getNotificationFromElement(aElement) {
+ // Need to find the associated notification object, which is a bit tricky
+ // since it isn't associated with the element directly - this is kind of
+ // gross and very dependent on the structure of the popupnotification
+ // binding's content.
+ let notificationEl;
+ let parent = aElement;
+ while (parent && (parent = aElement.ownerDocument.getBindingParent(parent)))
+ notificationEl = parent;
+ return notificationEl;
+}
+
/**
* Notification object describes a single popup notification.
*
@@ -194,7 +207,8 @@ PopupNotifications.prototype = {
* - label (string): the button's label.
* - accessKey (string): the button's accessKey.
* - callback (function): a callback to be invoked when the button is
- * pressed.
+ * pressed, is passed an object that contains the following fields:
+ * - checkboxChecked: (boolean) If the optional checkbox is checked.
* If null, the notification will not have a button, and
* secondaryActions will be ignored.
* @param secondaryActions
@@ -224,9 +238,23 @@ PopupNotifications.prototype = {
* tabs)
* "removed": notification has been removed (due to
* location change or user action)
+ * "showing": notification is about to be shown
+ * (this can be fired multiple times as
+ * notifications are dismissed and re-shown)
* "shown": notification has been shown (this can be fired
* multiple times as notifications are dismissed
* and re-shown)
+ * "swapping": the docshell of the browser that created
+ * the notification is about to be swapped to
+ * another browser. A second parameter contains
+ * the browser that is receiving the docshell,
+ * so that the event callback can transfer stuff
+ * specific to this notification.
+ * If the callback returns true, the notification
+ * will be moved to the new browser.
+ * If the callback isn't implemented, returns false,
+ * or doesn't return any value, the notification
+ * will be removed.
* neverShow: Indicate that no popup should be shown for this
* notification. Useful for just showing the anchor icon.
* removeOnDismissal:
@@ -234,6 +262,26 @@ PopupNotifications.prototype = {
* removed when they would have otherwise been dismissed
* (i.e. any time the popup is closed due to user
* interaction).
+ * checkbox: An object that allows you to add a checkbox and
+ * control its behavior with these fields:
+ * label:
+ * (required) Label to be shown next to the checkbox.
+ * checked:
+ * (optional) Whether the checkbox should be checked
+ * by default. Defaults to false.
+ * checkedState:
+ * (optional) An object that allows you to customize
+ * the notification state when the checkbox is checked.
+ * disableMainAction:
+ * (optional) Whether the mainAction is disabled.
+ * Defaults to false.
+ * warningLabel:
+ * (optional) A (warning) text that is shown below the
+ * checkbox. Pass null to hide.
+ * uncheckedState:
+ * (optional) An object that allows you to customize
+ * the notification state when the checkbox is not checked.
+ * Has the same attributes as checkedState.
* popupIconURL:
* A string. URL of the image to be displayed in the popup.
* Normally specified in CSS using list-style-image and the
@@ -552,6 +600,25 @@ PopupNotifications.prototype = {
}
}
+ let checkbox = n.options.checkbox;
+ if (checkbox && checkbox.label) {
+ let checked = n._checkboxChecked != null ? n._checkboxChecked : !!checkbox.checked;
+
+ popupnotification.setAttribute("checkboxhidden", "false");
+ popupnotification.setAttribute("checkboxchecked", checked);
+ popupnotification.setAttribute("checkboxlabel", checkbox.label);
+
+ popupnotification.setAttribute("checkboxcommand", "PopupNotifications._onCheckboxCommand(event);");
+
+ if (checked) {
+ this._setNotificationUIState(popupnotification, checkbox.checkedState);
+ } else {
+ this._setNotificationUIState(popupnotification, checkbox.uncheckedState);
+ }
+ } else {
+ popupnotification.setAttribute("checkboxhidden", "true");
+ }
+
this.panel.appendChild(popupnotification);
// The popupnotification may be hidden if we got it from the chrome
@@ -560,6 +627,32 @@ PopupNotifications.prototype = {
}, this);
},
+ _setNotificationUIState(notification, state={}) {
+ notification.setAttribute("mainactiondisabled", state.disableMainAction || "false");
+
+ if (state.warningLabel) {
+ notification.setAttribute("warninglabel", state.warningLabel);
+ notification.setAttribute("warninghidden", "false");
+ } else {
+ notification.setAttribute("warninghidden", "true");
+ }
+ },
+
+ _onCheckboxCommand(event) {
+ let notificationEl = getNotificationFromElement(event.originalTarget);
+ let checked = notificationEl.checkbox.checked;
+ let notification = notificationEl.notification;
+
+ // Save checkbox state to be able to persist it when re-opening the doorhanger.
+ notification._checkboxChecked = checked;
+
+ if (checked) {
+ this._setNotificationUIState(notificationEl, notification.options.checkbox.checkedState);
+ } else {
+ this._setNotificationUIState(notificationEl, notification.options.checkbox.uncheckedState);
+ }
+ },
+
_showPanel: function PopupNotifications_showPanel(notificationsToShow, anchorElement) {
this.panel.hidden = false;
@@ -751,9 +844,60 @@ PopupNotifications.prototype = {
this._update(notifications, anchor);
},
- _fireCallback: function PopupNotifications_fireCallback(n, event) {
- if (n.options.eventCallback)
- n.options.eventCallback.call(n, event);
+ _swapBrowserNotifications: function PopupNotifications_swapBrowserNoficications(ourBrowser, otherBrowser) {
+ // When swaping browser docshells (e.g. dragging tab to new window) we need
+ // to update our notification map.
+
+ let ourNotifications = this._getNotificationsForBrowser(ourBrowser);
+ let other = otherBrowser.ownerDocument.defaultView.PopupNotifications;
+ if (!other) {
+ if (ourNotifications.length > 0)
+ Cu.reportError("unable to swap notifications: otherBrowser doesn't support notifications");
+ return;
+ }
+ let otherNotifications = other._getNotificationsForBrowser(otherBrowser);
+ if (ourNotifications.length < 1 && otherNotifications.length < 1) {
+ // No notification to swap.
+ return;
+ }
+
+ otherNotifications = otherNotifications.filter(n => {
+ if (this._fireCallback(n, NOTIFICATION_EVENT_SWAPPING, ourBrowser)) {
+ n.browser = ourBrowser;
+ n.owner = this;
+ return true;
+ }
+ other._fireCallback(n, NOTIFICATION_EVENT_REMOVED);
+ return false;
+ });
+
+ ourNotifications = ourNotifications.filter(n => {
+ if (this._fireCallback(n, NOTIFICATION_EVENT_SWAPPING, otherBrowser)) {
+ n.browser = otherBrowser;
+ n.owner = other;
+ return true;
+ }
+ this._fireCallback(n, NOTIFICATION_EVENT_REMOVED);
+ return false;
+ });
+
+ this._setNotificationsForBrowser(otherBrowser, ourNotifications);
+ other._setNotificationsForBrowser(ourBrowser, otherNotifications);
+
+ if (otherNotifications.length > 0)
+ this._update(otherNotifications, otherNotifications[0].anchorElement);
+ if (ourNotifications.length > 0)
+ other._update(ourNotifications, ourNotifications[0].anchorElement);
+ },
+
+ _fireCallback: function PopupNotifications_fireCallback(n, event, ...args) {
+ try {
+ if (n.options.eventCallback)
+ return n.options.eventCallback.call(n, event, ...args);
+ } catch (error) {
+ Cu.reportError(error);
+ }
+ return undefined;
},
_onPopupHidden: function PopupNotifications_onPopupHidden(event) {
@@ -789,15 +933,7 @@ PopupNotifications.prototype = {
},
_onButtonCommand: function PopupNotifications_onButtonCommand(event) {
- // Need to find the associated notification object, which is a bit tricky
- // since it isn't associated with the button directly - this is kind of
- // gross and very dependent on the structure of the popupnotification
- // binding's content.
- let target = event.originalTarget;
- let notificationEl;
- let parent = target;
- while (parent && (parent = target.ownerDocument.getBindingParent(parent)))
- notificationEl = parent;
+ let notificationEl = getNotificationFromElement(event.originalTarget);
if (!notificationEl)
throw "PopupNotifications_onButtonCommand: couldn't find notification element";
@@ -819,7 +955,14 @@ PopupNotifications.prototype = {
timeSinceShown + "ms");
return;
}
- notification.mainAction.callback.call();
+
+ try {
+ notification.mainAction.callback.call(undefined, {
+ checkboxChecked: notificationEl.checkbox.checked
+ });
+ } catch (error) {
+ Cu.reportError(error);
+ }
this._remove(notification);
this._update();
@@ -830,8 +973,16 @@ PopupNotifications.prototype = {
if (!target.action || !target.notification)
throw "menucommand target has no associated action/notification";
+ let notificationEl = target.parentElement;
event.stopPropagation();
- target.action.callback.call();
+
+ try {
+ target.action.callback.call(undefined, {
+ checkboxChecked: notificationEl.checkbox.checked
+ });
+ } catch (error) {
+ Cu.reportError(error);
+ }
this._remove(target.notification);
this._update();
diff --git a/application/palemoon/modules/QuotaManager.jsm b/application/palemoon/modules/QuotaManager.jsm
index e03161a693..48cfe88b3b 100644
--- a/application/palemoon/modules/QuotaManager.jsm
+++ b/application/palemoon/modules/QuotaManager.jsm
@@ -6,8 +6,9 @@ this.EXPORTED_SYMBOLS = ["QuotaManagerHelper"];
Components.utils.import('resource://gre/modules/Services.jsm');
-const Cc = Components.classes;
const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cu = Components.utils;
this.QuotaManagerHelper = {
clear: function(isShutDown) {
@@ -34,12 +35,17 @@ this.QuotaManagerHelper = {
}
}
}
- var qm = Cc["@mozilla.org/dom/quota/manager;1"].getService(Ci.nsIQuotaManager);
+ var qm = Cc["@mozilla.org/dom/quota-manager-service;1"]
+ .getService(Ci.nsIQuotaManagerService);
for (var dom in doms) {
var uri = Services.io.newURI(dom, null, null);
- qm.clearStoragesForURI(uri);
+ let principal = Services.scriptSecurityManager
+ .createCodebasePrincipal(uri, {});
+ qm.clearStoragesForPrincipal(principal);
}
}
- } catch(er) {}
+ } catch(er) {
+ Cu.reportError(er);
+ }
}
};
diff --git a/application/palemoon/modules/SharedFrame.jsm b/application/palemoon/modules/SharedFrame.jsm
index 4d248ae5ba..b9d59bfa98 100644
--- a/application/palemoon/modules/SharedFrame.jsm
+++ b/application/palemoon/modules/SharedFrame.jsm
@@ -18,7 +18,7 @@ const Cu = Components.utils;
* when another one of the placeholder is meant to be displayed.
* */
-let Frames = new Map();
+var Frames = new Map();
/**
* The Frames map is the main data structure that holds information
diff --git a/application/palemoon/modules/WindowsPreviewPerTab.jsm b/application/palemoon/modules/WindowsPreviewPerTab.jsm
index 41b38f0cf9..c1ed05c39e 100644
--- a/application/palemoon/modules/WindowsPreviewPerTab.jsm
+++ b/application/palemoon/modules/WindowsPreviewPerTab.jsm
@@ -62,9 +62,6 @@ const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
////////////////////////////////////////////////////////////////////////////////
//// Various utility properties
-XPCOMUtils.defineLazyServiceGetter(this, "ioSvc",
- "@mozilla.org/network/io-service;1",
- "nsIIOService");
XPCOMUtils.defineLazyServiceGetter(this, "imgTools",
"@mozilla.org/image/tools;1",
"imgITools");
@@ -73,8 +70,13 @@ XPCOMUtils.defineLazyServiceGetter(this, "faviconSvc",
"nsIFaviconService");
// nsIURI -> imgIContainer
-function _imageFromURI(uri, privateMode, callback) {
- let channel = ioSvc.newChannelFromURI(uri);
+function _imageFromURI(doc, uri, privateMode, callback) {
+ let channel = NetUtil.newChannel({
+ uri: uri,
+ loadUsingSystemPrincipal: true,
+ contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
+ });
+
try {
channel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
channel.setPrivate(privateMode);
@@ -93,17 +95,17 @@ function _imageFromURI(uri, privateMode, callback) {
// favicon).
let defaultURI = faviconSvc.defaultFavicon;
if (!defaultURI.equals(uri))
- _imageFromURI(defaultURI, callback);
+ _imageFromURI(doc, defaultURI, privateMode, callback);
}
});
}
// string? -> imgIContainer
-function getFaviconAsImage(iconurl, privateMode, callback) {
+function getFaviconAsImage(doc, iconurl, privateMode, callback) {
if (iconurl)
- _imageFromURI(NetUtil.newURI(iconurl), privateMode, callback);
+ _imageFromURI(doc, NetUtil.newURI(iconurl), privateMode, callback);
else
- _imageFromURI(faviconSvc.defaultFavicon, privateMode, callback);
+ _imageFromURI(doc, faviconSvc.defaultFavicon, privateMode, callback);
}
// Snaps the given rectangle to be pixel-aligned at the given scale
@@ -460,12 +462,16 @@ TabWindow.prototype = {
preview.visible = AeroPeek.enabled;
preview.active = this.tabbrowser.selectedTab == controller.tab;
// Grab the default favicon
- getFaviconAsImage(null, PrivateBrowsingUtils.isWindowPrivate(this.win), function (img) {
- // It is possible that we've already gotten the real favicon, so make sure
- // we have not set one before setting this default one.
- if (!preview.icon)
- preview.icon = img;
- });
+ getFaviconAsImage(
+ controller.linkedBrowser.contentWindow.document,
+ null,
+ PrivateBrowsingUtils.isWindowPrivate(this.win),
+ function (img) {
+ // It is possible that we've already gotten the real favicon, so make sure
+ // we have not set one before setting this default one.
+ if (!preview.icon)
+ preview.icon = img;
+ });
return preview;
},
@@ -510,7 +516,14 @@ TabWindow.prototype = {
// Previews are internally stored using a map, so we need to iterate over
// the tabbrowser's array of tabs to retrieve previews in the same order.
- let inorder = [previews.get(t) for (t of tabs) if (previews.has(t))];
+ // Tycho: let inorder = [previews.get(t) for (t of tabs) if (previews.has(t))];
+ let inorder = [];
+
+ for (let t of tabs) {
+ if (previews.has(t)) {
+ inorder.push(previews.get(t));
+ }
+ }
// Since the internal taskbar array has not yet been updated, we must force
// the sorting order of our local array on it. To do so, we must walk
@@ -545,14 +558,17 @@ TabWindow.prototype = {
//// Browser progress listener
onLinkIconAvailable: function (aBrowser, aIconURL) {
let self = this;
- getFaviconAsImage(aIconURL, PrivateBrowsingUtils.isWindowPrivate(this.win), function (img) {
- let index = self.tabbrowser.browsers.indexOf(aBrowser);
- // Only add it if we've found the index. The tab could have closed!
- if (index != -1) {
- let tab = self.tabbrowser.tabs[index];
- self.previews.get(tab).icon = img;
- }
- });
+ getFaviconAsImage(
+ aBrowser.contentWindow.document,
+ aIconURL,PrivateBrowsingUtils.isWindowPrivate(this.win),
+ function (img) {
+ let index = self.tabbrowser.browsers.indexOf(aBrowser);
+ // Only add it if we've found the index. The tab could have closed!
+ if (index != -1) {
+ let tab = self.tabbrowser.tabs[index];
+ self.previews.get(tab).icon = img;
+ }
+ });
}
}
diff --git a/application/palemoon/modules/moz.build b/application/palemoon/modules/moz.build
index b3459bcd5a..67fd22338f 100644
--- a/application/palemoon/modules/moz.build
+++ b/application/palemoon/modules/moz.build
@@ -9,6 +9,7 @@
EXTRA_JS_MODULES += [ 'promise.js' ]
EXTRA_JS_MODULES += [
+ 'AutoCompletePopup.jsm',
'BrowserNewTabPreloader.jsm',
'CharsetMenu.jsm',
'FormSubmitObserver.jsm',
@@ -19,10 +20,12 @@ EXTRA_JS_MODULES += [
'PageMenu.jsm',
'PopupNotifications.jsm',
'QuotaManager.jsm',
- 'SharedFrame.jsm',
- 'webrtcUI.jsm'
+ 'SharedFrame.jsm'
]
+if CONFIG['MOZ_WEBRTC']:
+ EXTRA_JS_MODULES += ['webrtcUI.jsm']
+
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXTRA_JS_MODULES += [
'Windows8WindowFrameColor.jsm',
@@ -35,5 +38,8 @@ EXTRA_PP_JS_MODULES += [
'RecentWindow.jsm',
]
+# Pass down 'official build' flags
+if CONFIG['MC_OFFICIAL']:
+ DEFINES['MC_OFFICIAL'] = 1
if CONFIG['MOZILLA_OFFICIAL']:
- DEFINES['MOZILLA_OFFICIAL'] = 1 \ No newline at end of file
+ DEFINES['MOZILLA_OFFICIAL'] = 1
diff --git a/application/palemoon/modules/openLocationLastURL.jsm b/application/palemoon/modules/openLocationLastURL.jsm
index 0d653df28b..3f58db8ceb 100644
--- a/application/palemoon/modules/openLocationLastURL.jsm
+++ b/application/palemoon/modules/openLocationLastURL.jsm
@@ -10,11 +10,11 @@ Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
this.EXPORTED_SYMBOLS = [ "OpenLocationLastURL" ];
-let prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
+var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
-let gOpenLocationLastURLData = "";
+var gOpenLocationLastURLData = "";
-let observer = {
+var observer = {
QueryInterface: function (aIID) {
if (aIID.equals(Components.interfaces.nsIObserver) ||
aIID.equals(Components.interfaces.nsISupports) ||
@@ -35,7 +35,7 @@ let observer = {
}
};
-let os = Components.classes["@mozilla.org/observer-service;1"]
+var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(observer, "last-pb-context-exited", true);
os.addObserver(observer, "browser:purge-session-history", true);
diff --git a/application/palemoon/modules/promise.js b/application/palemoon/modules/promise.js
index 7c96f02cf5..74065c8db5 100644
--- a/application/palemoon/modules/promise.js
+++ b/application/palemoon/modules/promise.js
@@ -24,7 +24,7 @@ module.metadata = {
'stability': 'unstable'
};
-let promised = (function() {
+var promised = (function() {
// Note: Define shortcuts and utility functions here in order to avoid
// slower property accesses and unnecessary closure creations on each
// call of this popular function.
diff --git a/application/palemoon/modules/webrtcUI.jsm b/application/palemoon/modules/webrtcUI.jsm
index c957bfd9ab..819ca181f1 100644
--- a/application/palemoon/modules/webrtcUI.jsm
+++ b/application/palemoon/modules/webrtcUI.jsm
@@ -11,9 +11,11 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/PluralForm.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
+ "resource://gre/modules/PluralForm.jsm");
+
XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
"@mozilla.org/mediaManagerService;1",
"nsIMediaManagerService");
@@ -128,62 +130,14 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message",
[ host ]);
- function listDevices(menupopup, devices) {
- while (menupopup.lastChild)
- menupopup.removeChild(menupopup.lastChild);
-
- let deviceIndex = 0;
- for (let device of devices) {
- addDeviceToList(menupopup, device.name, deviceIndex);
- deviceIndex++;
- }
- }
-
- function addDeviceToList(menupopup, deviceName, deviceIndex) {
- let menuitem = chromeDoc.createElement("menuitem");
- menuitem.setAttribute("value", deviceIndex);
- menuitem.setAttribute("label", deviceName);
- menuitem.setAttribute("tooltiptext", deviceName);
- menupopup.appendChild(menuitem);
- }
-
- chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length;
- chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length;
-
- let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup");
- let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup");
- listDevices(camMenupopup, videoDevices);
- listDevices(micMenupopup, audioDevices);
- if (requestType == "CameraAndMicrophone") {
- addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1");
- addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1");
- }
-
let mainAction = {
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
stringBundle.getString("getUserMedia.shareSelectedDevices.label")),
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
- callback: function () {
- let allowedDevices = Cc["@mozilla.org/supports-array;1"]
- .createInstance(Ci.nsISupportsArray);
- if (videoDevices.length) {
- let videoDeviceIndex = chromeDoc.getElementById("webRTC-selectCamera-menulist").value;
- if (videoDeviceIndex != "-1")
- allowedDevices.AppendElement(videoDevices[videoDeviceIndex]);
- }
- if (audioDevices.length) {
- let audioDeviceIndex = chromeDoc.getElementById("webRTC-selectMicrophone-menulist").value;
- if (audioDeviceIndex != "-1")
- allowedDevices.AppendElement(audioDevices[audioDeviceIndex]);
- }
-
- if (allowedDevices.Count() == 0) {
- denyRequest(aCallID);
- return;
- }
-
- Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID);
- }
+ // The real callback will be set during the "showing" event. The
+ // empty function here is so that PopupNotifications.show doesn't
+ // reject the action.
+ callback: function() {}
};
let secondaryActions = [{
@@ -194,7 +148,72 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
}
}];
- let options = null;
+ let options = {
+ eventCallback: function(aTopic, aNewBrowser) {
+ if (aTopic == "swapping")
+ return true;
+
+ if (aTopic != "showing")
+ return false;
+
+ let chromeDoc = this.browser.ownerDocument;
+
+ function listDevices(menupopup, devices) {
+ while (menupopup.lastChild)
+ menupopup.removeChild(menupopup.lastChild);
+
+ let deviceIndex = 0;
+ for (let device of devices) {
+ addDeviceToList(menupopup, device.name, deviceIndex);
+ deviceIndex++;
+ }
+ }
+
+ function addDeviceToList(menupopup, deviceName, deviceIndex) {
+ let menuitem = chromeDoc.createElement("menuitem");
+ menuitem.setAttribute("value", deviceIndex);
+ menuitem.setAttribute("label", deviceName);
+ menuitem.setAttribute("tooltiptext", deviceName);
+ menupopup.appendChild(menuitem);
+ }
+
+ chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length;
+ chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length;
+
+ let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup");
+ let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup");
+ listDevices(camMenupopup, videoDevices);
+ listDevices(micMenupopup, audioDevices);
+ if (requestType == "CameraAndMicrophone") {
+ let stringBundle = chromeDoc.defaultView.gNavigatorBundle;
+ addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1");
+ addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1");
+ }
+
+ this.mainAction.callback = function() {
+ let allowedDevices = Cc["@mozilla.org/supports-array;1"]
+ .createInstance(Ci.nsISupportsArray);
+ if (videoDevices.length) {
+ let videoDeviceIndex = chromeDoc.getElementById("webRTC-selectCamera-menulist").value;
+ if (videoDeviceIndex != "-1")
+ allowedDevices.AppendElement(videoDevices[videoDeviceIndex]);
+ }
+ if (audioDevices.length) {
+ let audioDeviceIndex = chromeDoc.getElementById("webRTC-selectMicrophone-menulist").value;
+ if (audioDeviceIndex != "-1")
+ allowedDevices.AppendElement(audioDevices[audioDeviceIndex]);
+ }
+
+ if (allowedDevices.Count() == 0) {
+ denyRequest(aCallID);
+ return;
+ }
+
+ Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID);
+ };
+ return true;
+ }
+ };
chromeWin.PopupNotifications.show(browser, "webRTC-shareDevices", message,
"webRTC-shareDevices-notification-icon", mainAction,
@@ -254,7 +273,8 @@ function showBrowserSpecificIndicator(aBrowser) {
}];
let options = {
hideNotNow: true,
- dismissed: true
+ dismissed: true,
+ eventCallback: function(aTopic) aTopic == "swapping"
};
chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message,
"webRTC-sharingDevices-notification-icon", mainAction,