diff options
Diffstat (limited to 'application')
73 files changed, 1668 insertions, 1320 deletions
diff --git a/application/palemoon/app/Makefile.in b/application/palemoon/app/Makefile.in index 6f9bbfaf0..c0f01212c 100644 --- a/application/palemoon/app/Makefile.in +++ b/application/palemoon/app/Makefile.in @@ -76,7 +76,7 @@ AB := $(firstword $(subst -, ,$(AB_CD))) clean clobber repackage:: $(RM) -r $(dist_dest) -MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/config/buildid) +MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/buildid.h) .PHONY: repackage tools repackage:: $(PROGRAM) diff --git a/application/palemoon/app/application.ini b/application/palemoon/app/application.ini new file mode 100644 index 000000000..c64ed9079 --- /dev/null +++ b/application/palemoon/app/application.ini @@ -0,0 +1,50 @@ +#if MOZ_APP_STATIC_INI +#ifdef MOZ_BUILD_APP_IS_BROWSER +; This file is not used. If you modify it and want the application to use +; your modifications, move it under the browser/ subdirectory and start with +; the "-app /path/to/browser/application.ini" argument. +#else +; This file is not used. If you modify it and want the application to use +; your modifications, start with the "-app /path/to/application.ini" +; argument. +#endif +#endif +#if 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/. +#endif +#filter substitution +#include @TOPOBJDIR@/buildid.h +#include @TOPOBJDIR@/source-repo.h + +[App] +# Vendor=@MOZ_APP_VENDOR@ +Vendor=Moonchild Productions +# Name=@MOZ_APP_BASENAME@ +Name=Pale Moon +RemotingName=@MOZ_APP_REMOTINGNAME@ +#ifdef MOZ_APP_DISPLAYNAME +CodeName=@MOZ_APP_DISPLAYNAME@ +#endif +Version=@MOZ_APP_VERSION@ +#ifdef MOZ_APP_PROFILE +Profile=@MOZ_APP_PROFILE@ +#endif +BuildID=@MOZ_BUILDID@ +#ifdef MOZ_SOURCE_REPO +SourceRepository=@MOZ_SOURCE_REPO@ +#endif +#ifdef MOZ_SOURCE_STAMP +SourceStamp=@MOZ_SOURCE_STAMP@ +#endif +ID=@MOZ_APP_ID@ + +[Gecko] +MinVersion=@GRE_MILESTONE@ +MaxVersion=@GRE_MILESTONE@ + +[XRE] +#ifdef MOZ_PROFILE_MIGRATOR +EnableProfileMigrator=1 +#endif
\ No newline at end of file diff --git a/application/palemoon/app/macversion.py b/application/palemoon/app/macversion.py index 8c360368e..839aac1ff 100644 --- a/application/palemoon/app/macversion.py +++ b/application/palemoon/app/macversion.py @@ -28,7 +28,7 @@ if not options.version: # builds), but also so that newly-built older versions (e.g. beta build) aren't # considered "newer" than previously-built newer versions (e.g. a trunk nightly) -buildid = open(options.buildid, 'r').read() +define, MOZ_BUILDID, buildid = open(options.buildid, 'r').read().split() # extract only the major version (i.e. "14" from "14.0b1") majorVersion = re.match(r'^(\d+)[^\d].*', options.version).group(1) diff --git a/application/palemoon/app/nsBrowserApp.cpp b/application/palemoon/app/nsBrowserApp.cpp index 5b866d6b4..8b0613528 100644 --- a/application/palemoon/app/nsBrowserApp.cpp +++ b/application/palemoon/app/nsBrowserApp.cpp @@ -26,9 +26,6 @@ #ifdef XP_WIN #define XRE_WANT_ENVIRON #define strcasecmp _stricmp -#ifdef MOZ_SANDBOX -#include "mozilla/sandboxing/SandboxInitialization.h" -#endif #endif #include "BinaryPath.h" @@ -38,8 +35,7 @@ #include "mozilla/Telemetry.h" #include "mozilla/WindowsDllBlocklist.h" -#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) \ - && !(defined(XP_LINUX) && defined(MOZ_SANDBOX)) +#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) #define MOZ_BROWSER_CAN_BE_CONTENTPROC #include "../../ipc/contentproc/plugin-container.cpp" #endif @@ -201,13 +197,7 @@ static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory) argv[i] = argv[i + 1]; } - XREShellData shellData; -#if defined(XP_WIN) && defined(MOZ_SANDBOX) - shellData.sandboxBrokerServices = - sandboxing::GetInitializedBrokerServices(); -#endif - - return XRE_XPCShellMain(--argc, argv, envp, &shellData); + return XRE_XPCShellMain(--argc, argv, envp); } if (appini) { @@ -257,18 +247,6 @@ static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory) DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0; #endif -#if defined(XP_WIN) && defined(MOZ_SANDBOX) - sandbox::BrokerServices* brokerServices = - sandboxing::GetInitializedBrokerServices(); -#if defined(MOZ_CONTENT_SANDBOX) - if (!brokerServices) { - Output("Couldn't initialize the broker services.\n"); - return 255; - } -#endif - appData.sandboxBrokerServices = brokerServices; -#endif - #ifdef LIBFUZZER if (getenv("LIBFUZZER")) XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main); @@ -370,15 +348,6 @@ int main(int argc, char* argv[], char* envp[]) // We are launching as a content process, delegate to the appropriate // main if (argc > 1 && IsArg(argv[1], "contentproc")) { -#if defined(XP_WIN) && defined(MOZ_SANDBOX) - // We need to initialize the sandbox TargetServices before InitXPCOMGlue - // because we might need the sandbox broker to give access to some files. - if (IsSandboxedProcess() && !sandboxing::GetInitializedTargetServices()) { - Output("Failed to initialize the sandbox target services."); - return 255; - } -#endif - nsresult rv = InitXPCOMGlue(argv[0], nullptr); if (NS_FAILED(rv)) { return 255; diff --git a/application/palemoon/app/profile/palemoon.js b/application/palemoon/app/profile/palemoon.js index ee4a95d38..90b4949b9 100644 --- a/application/palemoon/app/profile/palemoon.js +++ b/application/palemoon/app/profile/palemoon.js @@ -236,6 +236,15 @@ pref("general.useragent.complexOverride.moodle", false); // bug 797703 // At startup, check if we're the default browser and prompt user if not. pref("browser.shell.checkDefaultBrowser", true); pref("browser.shell.shortcutFavicons",true); +pref("browser.shell.mostRecentDateSetAsDefault", ""); +#ifdef RELEASE_OR_BETA +pref("browser.shell.skipDefaultBrowserCheckOnFirstRun", false); +#else +pref("browser.shell.skipDefaultBrowserCheckOnFirstRun", true); +#endif +pref("browser.shell.skipDefaultBrowserCheck", true); +pref("browser.shell.defaultBrowserCheckCount", 0); +pref("browser.defaultbrowser.notificationbar", false); // 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session // The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore @@ -756,6 +765,7 @@ pref("goanna.handlerService.allowRegisterFromDifferentHost", false); pref("browser.geolocation.warning.infoURL", "http://www.palemoon.org/info-url/geolocation.shtml"); pref("browser.mixedcontent.warning.infoURL", "http://www.palemoon.org/info-url/mixedcontent.shtml"); +pref("browser.push.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/push/"); pref("browser.EULA.version", 3); pref("browser.rights.version", 3); @@ -1048,11 +1058,6 @@ pref("browser.newtabpage.rows", 4); // Enable the DOM fullscreen API. pref("full-screen-api.enabled", true); -// True if the fullscreen API requires approval upon a domain entering fullscreen. -// Domains that have already had fullscreen permission granted won't re-request -// approval. -pref("full-screen-api.approval-required", true); - // about:permissions // Maximum number of sites to return from the places database. // 0-100 (currently) diff --git a/application/palemoon/base/content/browser-fullScreen.js b/application/palemoon/base/content/browser-fullScreen.js index 400340e77..6afd247be 100644 --- a/application/palemoon/base/content/browser-fullScreen.js +++ b/application/palemoon/base/content/browser-fullScreen.js @@ -5,16 +5,9 @@ var FullScreen = { _XULNS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", - get _fullScrToggler() { - delete this._fullScrToggler; - return this._fullScrToggler = document.getElementById("fullscr-toggler"); - }, - toggle: function (event) { - var enterFS = window.fullScreen; - // We get the fullscreen event _before_ the window transitions into or out of FS mode. - if (event && event.type == "fullscreen") - enterFS = !enterFS; + toggle: function () { + var enterFS = window.fullScreen; // Toggle the View:FullScreen command, which controls elements like the // fullscreen menuitem, menubars, and the appmenu. @@ -31,6 +24,12 @@ var FullScreen = { document.getElementById("exitFullScreenItem").hidden = !enterFS; #endif + if (!this._fullScrToggler) { + this._fullScrToggler = document.getElementById("fullscr-toggler"); + this._fullScrToggler.addEventListener("mouseover", this._expandCallback, false); + this._fullScrToggler.addEventListener("dragenter", this._expandCallback, false); + } + // On OS X Lion we don't want to hide toolbars when entering fullscreen, unless // we're entering DOM fullscreen, in which case we should hide the toolbars. // If we're leaving fullscreen, then we'll go through the exit code below to @@ -50,36 +49,17 @@ var FullScreen = { this.showXULChrome("toolbar", !enterFS); if (enterFS) { - // Add a tiny toolbar to receive mouseover and dragenter events, and provide affordance. - // This will help simulate the "collapse" metaphor while also requiring less code and - // events than raw listening of mouse coords. We don't add the toolbar in DOM full-screen - // mode, only browser full-screen mode. - if (!document.mozFullScreen) { - this._fullScrToggler.addEventListener("mouseover", this._expandCallback, false); - this._fullScrToggler.addEventListener("dragenter", this._expandCallback, false); - } - if (gPrefService.getBoolPref("browser.fullscreen.autohide")) - gBrowser.mPanelContainer.addEventListener("mousemove", - this._collapseCallback, false); - document.addEventListener("keypress", this._keyToggleCallback, false); document.addEventListener("popupshown", this._setPopupOpen, false); document.addEventListener("popuphidden", this._setPopupOpen, false); + this._shouldAnimate = true; // We don't animate the toolbar collapse if in DOM full-screen mode, // as the size of the content area would still be changing after the // mozfullscreenchange event fired, which could confuse content script. - this._shouldAnimate = !document.mozFullScreen; - this.mouseoverToggle(false); - - // Autohide prefs - gPrefService.addObserver("browser.fullscreen", this, false); + this.hideNavToolbox(document.mozFullScreen); } else { - // The user may quit fullscreen during an animation - this._cancelAnimation(); - gNavToolbox.style.marginTop = ""; - if (this._isChromeCollapsed) - this.mouseoverToggle(true); + this.showNavToolbox(false); // This is needed if they use the context menu to quit fullscreen this._isPopupOpen = false; @@ -111,7 +91,7 @@ var FullScreen = { if (!document.mozFullScreen) return; - // However, if we receive a "MozEnteredDomFullScreen" event for a document + // However, if we receive a "MozDOMFullscreen:NewOrigin" event for a document // which is not a subdocument of a currently active (ie. visible) browser // or iframe, we know that we've switched to a different frame since the // request to enter full-screen was made, so we should exit full-screen @@ -152,26 +132,16 @@ var FullScreen = { // Cancel any "hide the toolbar" animation which is in progress, and make // the toolbar hide immediately. - this._cancelAnimation(); - this.mouseoverToggle(false); - - // Remove listeners on the full-screen toggler, so that mouseover - // the top of the screen will not cause the toolbar to re-appear. - this._fullScrToggler.removeEventListener("mouseover", this._expandCallback, false); - this._fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); + this.hideNavToolbox(true); }, cleanup: function () { - if (window.fullScreen) { - gBrowser.mPanelContainer.removeEventListener("mousemove", - this._collapseCallback, false); + if (!window.fullScreen) { + MousePosTracker.removeListener(this); document.removeEventListener("keypress", this._keyToggleCallback, false); document.removeEventListener("popupshown", this._setPopupOpen, false); document.removeEventListener("popuphidden", this._setPopupOpen, false); - gPrefService.removeObserver("browser.fullscreen", this); - this._fullScrToggler.removeEventListener("mouseover", this._expandCallback, false); - this._fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); this.cancelWarning(); gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen); gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen); @@ -182,40 +152,30 @@ var FullScreen = { } }, - observe: function(aSubject, aTopic, aData) + getMouseTargetRect: function() { - if (aData == "browser.fullscreen.autohide") { - if (gPrefService.getBoolPref("browser.fullscreen.autohide")) { - gBrowser.mPanelContainer.addEventListener("mousemove", - this._collapseCallback, false); - } - else { - gBrowser.mPanelContainer.removeEventListener("mousemove", - this._collapseCallback, false); - } - } + return this._mouseTargetRect; }, // Event callbacks _expandCallback: function() { - FullScreen.mouseoverToggle(true); + FullScreen.showNavToolbox(); }, - _collapseCallback: function() + onMouseEnter: function() { - FullScreen.mouseoverToggle(false); + FullScreen.hideNavToolbox(); }, _keyToggleCallback: function(aEvent) { // if we can use the keyboard (eg Ctrl+L or Ctrl+E) to open the toolbars, we // should provide a way to collapse them too. if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) { - FullScreen._shouldAnimate = false; - FullScreen.mouseoverToggle(false, true); + FullScreen.hideNavToolbox(true); } // F6 is another shortcut to the address bar, but its not covered in OpenLocation() else if (aEvent.keyCode == aEvent.DOM_VK_F6) - FullScreen.mouseoverToggle(true); + FullScreen.showNavToolbox(); }, // Checks whether we are allowed to collapse the chrome @@ -269,47 +229,6 @@ var FullScreen = { // Animate the toolbars disappearing _shouldAnimate: true, - _isAnimating: false, - _animationTimeout: 0, - _animationHandle: 0, - _animateUp: function() { - // check again, the user may have done something before the animation was due to start - if (!window.fullScreen || !this._safeToCollapse(false)) { - this._isAnimating = false; - this._shouldAnimate = true; - return; - } - - this._animateStartTime = window.mozAnimationStartTime; - if (!this._animationHandle) - this._animationHandle = window.mozRequestAnimationFrame(this); - }, - - sample: function (timeStamp) { - const duration = 1500; - const timePassed = timeStamp - this._animateStartTime; - const pos = timePassed >= duration ? 1 : - 1 - Math.pow(1 - timePassed / duration, 4); - - if (pos >= 1) { - // We've animated enough - this._cancelAnimation(); - gNavToolbox.style.marginTop = ""; - this.mouseoverToggle(false); - return; - } - - gNavToolbox.style.marginTop = (gNavToolbox.boxObject.height * pos * -1) + "px"; - this._animationHandle = window.mozRequestAnimationFrame(this); - }, - - _cancelAnimation: function() { - window.cancelAnimationFrame(this._animationHandle); - this._animationHandle = 0; - clearTimeout(this._animationTimeout); - this._isAnimating = false; - this._shouldAnimate = false; - }, cancelWarning: function(event) { if (!this.warningBox) @@ -328,67 +247,20 @@ var FullScreen = { this.warningBox.setAttribute("hidden", true); this.warningBox.removeAttribute("fade-warning-out"); - this.warningBox.removeAttribute("obscure-browser"); this.warningBox = null; }, - setFullscreenAllowed: function(isApproved) { - // The "remember decision" checkbox is hidden when showing for documents that - // the permission manager can't handle (documents with URIs without a host). - // We simply require those to be approved every time instead. - let rememberCheckbox = document.getElementById("full-screen-remember-decision"); - let uri = this.fullscreenDoc.nodePrincipal.URI; - if (!rememberCheckbox.hidden) { - if (rememberCheckbox.checked) - Services.perms.add(uri, - "fullscreen", - isApproved ? Services.perms.ALLOW_ACTION : Services.perms.DENY_ACTION, - Services.perms.EXPIRE_NEVER); - else if (isApproved) { - // The user has only temporarily approved fullscren for this fullscreen - // session only. Add the permission (so Goanna knows to approve any further - // fullscreen requests for this host in this fullscreen session) but add - // a listener to revoke the permission when the chrome document exits - // fullscreen. - Services.perms.add(uri, - "fullscreen", - Services.perms.ALLOW_ACTION, - Services.perms.EXPIRE_SESSION); - let host = uri.host; - var onFullscreenchange = function onFullscreenchange(event) { - if (event.target == document && document.mozFullScreenElement == null) { - // The chrome document has left fullscreen. Remove the temporary permission grant. - Services.perms.remove(host, "fullscreen"); - document.removeEventListener("mozfullscreenchange", onFullscreenchange); - } - } - document.addEventListener("mozfullscreenchange", onFullscreenchange); - } - } - if (this.warningBox) - this.warningBox.setAttribute("fade-warning-out", "true"); - // If the document has been granted fullscreen, notify Goanna so it can resume - // any pending pointer lock requests, otherwise exit fullscreen; the user denied - // the fullscreen request. - if (isApproved) - Services.obs.notifyObservers(this.fullscreenDoc, "fullscreen-approved", ""); - else - document.mozCancelFullScreen(); - }, - warningBox: null, warningFadeOutTimeout: null, fullscreenDoc: null, - // Shows the fullscreen approval UI, or if the domain has already been approved - // for fullscreen, shows a warning that the site has entered fullscreen for a short - // duration. + // Shows a warning that the site has entered fullscreen for a short duration. showWarning: function(targetDoc) { - if (!document.mozFullScreen || - !gPrefService.getBoolPref("full-screen-api.approval-required")) + let timeout = gPrefService.getIntPref("full-screen-api.warning.timeout"); + if (!document.mozFullScreen || timeout <= 0) return; - // Set the strings on the fullscreen approval UI. + // Set the strings on the fullscreen warning UI. this.fullscreenDoc = targetDoc; let uri = this.fullscreenDoc.nodePrincipal.URI; let host = null; @@ -396,11 +268,8 @@ var FullScreen = { host = uri.host; } catch (e) { } let hostLabel = document.getElementById("full-screen-domain-text"); - let rememberCheckbox = document.getElementById("full-screen-remember-decision"); - let isApproved = false; if (host) { - // Document's principal's URI has a host. Display a warning including the hostname and - // show UI to enable the user to permanently grant this host permission to enter fullscreen. + // Document's principal's URI has a host. Display a warning including the hostname. let utils = {}; Cu.import("resource://gre/modules/DownloadUtils.jsm", utils); let displayHost = utils.DownloadUtils.getURIHost(uri.spec)[0]; @@ -408,17 +277,8 @@ var FullScreen = { hostLabel.textContent = bundle.formatStringFromName("fullscreen.entered", [displayHost], 1); hostLabel.removeAttribute("hidden"); - - rememberCheckbox.label = bundle.formatStringFromName("fullscreen.rememberDecision", [displayHost], 1); - rememberCheckbox.checked = false; - rememberCheckbox.removeAttribute("hidden"); - - // Note we only allow documents whose principal's URI has a host to - // store permission grants. - isApproved = Services.perms.testPermission(uri, "fullscreen") == Services.perms.ALLOW_ACTION; } else { hostLabel.setAttribute("hidden", "true"); - rememberCheckbox.setAttribute("hidden", "true"); } // Note: the warning box can be non-null if the warning box from the previous request @@ -436,77 +296,77 @@ var FullScreen = { this.warningBox.removeAttribute("fade-warning-out"); } - // If fullscreen mode has not yet been approved for the fullscreen - // document's domain, show the approval UI and don't auto fade out the - // fullscreen warning box. Otherwise, we're just notifying of entry into - // fullscreen mode. Note if the resource's host is null, we must be - // showing a local file or a local data URI, and we require explicit - // approval every time. - let authUI = document.getElementById("full-screen-approval-pane"); - if (isApproved) { - authUI.setAttribute("hidden", "true"); - this.warningBox.removeAttribute("obscure-browser"); - } else { - // Partially obscure the <browser> element underneath the approval UI. - this.warningBox.setAttribute("obscure-browser", "true"); - authUI.removeAttribute("hidden"); + // Set a timeout to fade the warning out after a few moments. + this.warningFadeOutTimeout = setTimeout(() => { + if (this.warningBox) { + this.warningBox.setAttribute("fade-warning-out", "true"); + } + }, timeout); + }, + + showNavToolbox: function(trackMouse = true) { + this._fullScrToggler.hidden = true; + gNavToolbox.removeAttribute("fullscreenShouldAnimate"); + gNavToolbox.style.marginTop = ""; + + if (!this._isChromeCollapsed) { + return; } - // If we're not showing the fullscreen approval UI, we're just notifying the user - // of the transition, so set a timeout to fade the warning out after a few moments. - if (isApproved) - this.warningFadeOutTimeout = - setTimeout( - function() { - if (this.warningBox) - this.warningBox.setAttribute("fade-warning-out", "true"); - }.bind(this), - 3000); + // Track whether mouse is near the toolbox + this._isChromeCollapsed = false; + if (trackMouse) { + let rect = gBrowser.mPanelContainer.getBoundingClientRect(); + this._mouseTargetRect = { + top: rect.top + 50, + bottom: rect.bottom, + left: rect.left, + right: rect.right + }; + MousePosTracker.addListener(this); + } }, - mouseoverToggle: function(aShow, forceHide) - { - // Don't do anything if: - // a) we're already in the state we want, - // b) we're animating and will become collapsed soon, or - // c) we can't collapse because it would be undesirable right now - if (aShow != this._isChromeCollapsed || (!aShow && this._isAnimating) || - (!aShow && !this._safeToCollapse(forceHide))) + hideNavToolbox: function(forceHide = false) { + this._fullScrToggler.hidden = document.mozFullScreen; + if (this._isChromeCollapsed) { + if (forceHide) { + gNavToolbox.removeAttribute("fullscreenShouldAnimate"); + } return; + } + if (!this._safeToCollapse(forceHide)) { + this._fullScrToggler.hidden = true; + return; + } // browser.fullscreen.animateUp // 0 - never animate up // 1 - animate only for first collapse after entering fullscreen (default for perf's sake) // 2 - animate every time it collapses - if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 0) + let animateUp = gPrefService.getIntPref("browser.fullscreen.animateUp"); + if (animateUp == 0) { this._shouldAnimate = false; - - if (!aShow && this._shouldAnimate) { - this._isAnimating = true; - this._shouldAnimate = false; - this._animationTimeout = setTimeout(this._animateUp.bind(this), 800); - return; - } - - // The chrome is collapsed so don't spam needless mousemove events - if (aShow) { - gBrowser.mPanelContainer.addEventListener("mousemove", - this._collapseCallback, false); + } else if (animateUp == 2) { + this._shouldAnimate = true; } - else { - gBrowser.mPanelContainer.removeEventListener("mousemove", - this._collapseCallback, false); + if (this._shouldAnimate && !forceHide) { + gNavToolbox.setAttribute("fullscreenShouldAnimate", true); + this._shouldAnimate = false; + // Hide the fullscreen toggler until the transition ends. + let listener = () => { + gNavToolbox.removeEventListener("transitionend", listener, true); + if (this._isChromeCollapsed) + this._fullScrToggler.hidden = false; + }; + gNavToolbox.addEventListener("transitionend", listener, true); + this._fullScrToggler.hidden = true; } - // Hiding/collapsing the toolbox interferes with the tab bar's scrollbox, - // so we just move it off-screen instead. See bug 430687. gNavToolbox.style.marginTop = - aShow ? "" : -gNavToolbox.getBoundingClientRect().height + "px"; - - this._fullScrToggler.collapsed = aShow; - this._isChromeCollapsed = !aShow; - if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2) - this._shouldAnimate = true; + -gNavToolbox.getBoundingClientRect().height + "px"; + this._isChromeCollapsed = true; + MousePosTracker.removeListener(this); }, showXULChrome: function(aTag, aShow) diff --git a/application/palemoon/base/content/browser-plugins.js b/application/palemoon/base/content/browser-plugins.js index 769ac6d8a..838268203 100644 --- a/application/palemoon/base/content/browser-plugins.js +++ b/application/palemoon/base/content/browser-plugins.js @@ -470,28 +470,12 @@ var gPluginHandler = { } }, - // Match the behaviour of nsPermissionManager - _getHostFromPrincipal: function PH_getHostFromPrincipal(principal) { - if (!principal.URI || principal.URI.schemeIs("moz-nullprincipal")) { - return "(null)"; - } - - try { - if (principal.URI.host) - return principal.URI.host; - } catch (e) {} - - return principal.origin; - }, - _makeCenterActions: function PH_makeCenterActions(notification) { let contentWindow = notification.browser.contentWindow; let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils); let principal = contentWindow.document.nodePrincipal; - // This matches the behavior of nsPermssionManager, used for display purposes only - let principalHost = this._getHostFromPrincipal(principal); let centerActions = []; let pluginsFound = new Set(); @@ -517,11 +501,11 @@ var gPluginHandler = { let permissionObj = Services.perms. getPermissionObject(principal, pluginInfo.permissionString, false); if (permissionObj) { - pluginInfo.pluginPermissionHost = permissionObj.host; + pluginInfo.pluginPermissionPrePath = permissionObj.principal.originNoSuffix; pluginInfo.pluginPermissionType = permissionObj.expireType; } else { - pluginInfo.pluginPermissionHost = principalHost; + pluginInfo.pluginPermissionPrePath = principal.originNoSuffix; pluginInfo.pluginPermissionType = undefined; } diff --git a/application/palemoon/base/content/browser.css b/application/palemoon/base/content/browser.css index 658655970..a2970aefc 100644 --- a/application/palemoon/base/content/browser.css +++ b/application/palemoon/base/content/browser.css @@ -504,6 +504,7 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(#nav-bar):not( width: 100%; height: 100%; z-index: 2147483647 !important; + pointer-events: none; } #full-screen-warning-container[fade-warning-out] { @@ -512,22 +513,13 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(#nav-bar):not( opacity: 0.0; } -/* When the modal fullscreen approval UI is showing, don't allow interaction - with the page, but when we're just showing the warning upon entering - fullscreen on an already approved page, do allow interaction with the page. - */ -#full-screen-warning-container:not([obscure-browser]) { - pointer-events: none; -} - #full-screen-warning-message { /* We must specify a max-width, otherwise word-wrap:break-word doesn't work in descendant <description> and <label> elements. Bug 630864. */ max-width: 800px; } -#full-screen-domain-text, -#full-screen-remember-decision > .checkbox-label-box > .checkbox-label { +#full-screen-domain-text { word-wrap: break-word; /* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */ min-width: 1px; @@ -760,3 +752,8 @@ toolbarbutton[pmkit-button="true"] > .toolbarbutton-badge-stack > .toolbarbutton #main-window[inFullscreen] #high-priority-global-notificationbox { visibility: collapse; } + +#navigator-toolbox[fullscreenShouldAnimate] { + transition: 0.7s margin-top ease-out; + transition-delay: 0.8s; +} diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index c9f0aa4aa..c1643caa4 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -10,6 +10,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource:///modules/RecentWindow.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu", "resource:///modules/CharsetMenu.jsm"); @@ -83,14 +86,8 @@ this.__defineSetter__("AddonManager", function (val) { return this.AddonManager = val; }); -this.__defineGetter__("PluralForm", function() { - Cu.import("resource://gre/modules/PluralForm.jsm"); - return this.PluralForm; -}); -this.__defineSetter__("PluralForm", function (val) { - delete this.PluralForm; - return this.PluralForm = val; -}); +XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", + "resource://gre/modules/PluralForm.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils", "resource:///modules/AboutHomeUtils.jsm"); @@ -125,7 +122,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", XPCOMUtils.defineLazyModuleGetter(this, "FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"); -let gInitialPages = [ +var gInitialPages = [ "about:blank", "about:newtab", "about:home", @@ -993,12 +990,23 @@ var gBrowserInit = { gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, uriToLoad); } - // window.arguments[2]: referrer (nsIURI) + // window.arguments[2]: referrer (nsIURI | string) // [3]: postData (nsIInputStream) // [4]: allowThirdPartyFixup (bool) + // [5]: referrerPolicy (int) else if (window.arguments.length >= 3) { - loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null, - window.arguments[4] || false); + let referrerURI = window.arguments[2]; + if (typeof(referrerURI) == "string") { + try { + referrerURI = makeURI(referrerURI); + } catch (e) { + referrerURI = null; + } + } + let referrerPolicy = (window.arguments[5] != undefined ? + window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT); + loadURI(uriToLoad, referrerURI, window.arguments[3] || null, + window.arguments[4] || false, referrerPolicy); window.focus(); } // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3. @@ -1149,7 +1157,7 @@ var gBrowserInit = { // Called when we enter DOM full-screen mode. Note we can already be in browser // full-screen mode when we enter DOM full-screen mode. - window.addEventListener("MozEnteredDomFullscreen", onMozEnteredDomFullscreen, true); + window.addEventListener("MozDOMFullscreen:NewOrigin", onMozEnteredDomFullscreen, true); if (window.fullScreen) onFullScreen(); @@ -1733,7 +1741,7 @@ function loadOneOrMoreURIs(aURIString) function focusAndSelectUrlBar() { if (gURLBar) { if (window.fullScreen) - FullScreen.mouseoverToggle(true); + FullScreen.showNavToolbox(); gURLBar.select(); if (document.activeElement == gURLBar.inputField) @@ -1886,7 +1894,7 @@ function BrowserTryToCloseWindow() window.close(); // WindowIsClosing does all the necessary checks } -function loadURI(uri, referrer, postData, allowThirdPartyFixup) { +function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy) { if (postData === undefined) postData = null; @@ -1897,92 +1905,135 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup) { } try { - gBrowser.loadURIWithFlags(uri, flags, referrer, null, postData); + gBrowser.loadURIWithFlags(uri, { + flags: flags, + referrerURI: referrer, + referrerPolicy: referrerPolicy, + postData: postData, + }); } catch (e) {} } -function getShortcutOrURI(aURL, aPostDataRef, aMayInheritPrincipal) { - // Initialize outparam to false - if (aMayInheritPrincipal) - aMayInheritPrincipal.value = false; +/** + * Given a urlbar value, discerns between URIs, keywords and aliases. + * + * @param url + * The urlbar value. + * @param callback (optional, deprecated) + * The callback function invoked when done. This parameter is + * deprecated, please use the Promise that is returned. + * + * @return Promise<{ postData, url, mayInheritPrincipal }> + */ +function getShortcutOrURIAndPostData(url, callback = null) { + if (callback) { + Deprecated.warning("Please use the Promise returned by " + + "getShortcutOrURIAndPostData() instead of passing a " + + "callback", + "https://bugzilla.mozilla.org/show_bug.cgi?id=1100294"); + } - var shortcutURL = null; - var keyword = aURL; - var param = ""; + return Task.spawn(function* () { + let mayInheritPrincipal = false; + let postData = null; + let shortcutURL = null; + let keyword = url; + let param = ""; - var offset = aURL.indexOf(" "); - if (offset > 0) { - keyword = aURL.substr(0, offset); - param = aURL.substr(offset + 1); - } + let offset = url.indexOf(" "); + if (offset > 0) { + keyword = url.substr(0, offset); + param = url.substr(offset + 1); + } - if (!aPostDataRef) - aPostDataRef = {}; + let engine = Services.search.getEngineByAlias(keyword); + if (engine) { + let submission = engine.getSubmission(param, null, "keyword"); + postData = submission.postData; + return { postData: submission.postData, url: submission.uri.spec, + mayInheritPrincipal }; + } - var engine = Services.search.getEngineByAlias(keyword); - if (engine) { - var submission = engine.getSubmission(param); - aPostDataRef.value = submission.postData; - return submission.uri.spec; - } + let entry = yield PlacesUtils.keywords.fetch(keyword); + if (entry) { + shortcutURL = entry.url.href; + postData = entry.postData; + } - [shortcutURL, aPostDataRef.value] = - PlacesUtils.getURLAndPostDataForKeyword(keyword); + if (!shortcutURL) { + return { postData, url, mayInheritPrincipal }; + } - if (!shortcutURL) - return aURL; + let escapedPostData = ""; + if (postData) + escapedPostData = unescape(postData); - var postData = ""; - if (aPostDataRef.value) - postData = unescape(aPostDataRef.value); + if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { + let charset = ""; + const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; + let matches = shortcutURL.match(re); - if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) { - var charset = ""; - const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; - var matches = shortcutURL.match(re); - if (matches) - [, shortcutURL, charset] = matches; - else { - // Try to get the saved character-set. - try { - // makeURI throws if URI is invalid. - // Will return an empty string if character-set is not found. - charset = PlacesUtils.history.getCharsetForURI(makeURI(shortcutURL)); - } catch (e) {} - } + if (matches) { + [, shortcutURL, charset] = matches; + } else { + let uri; + try { + // makeURI() throws if URI is invalid. + uri = makeURI(shortcutURL); + } catch (ex) {} + + if (uri) { + // Try to get the saved character-set. + // Will return an empty string if character-set is not found. + charset = yield PlacesUtils.getCharsetForURI(uri); + } + } - // encodeURIComponent produces UTF-8, and cannot be used for other charsets. - // escape() works in those cases, but it doesn't uri-encode +, @, and /. - // Therefore we need to manually replace these ASCII characters by their - // encodeURIComponent result, to match the behavior of nsEscape() with - // url_XPAlphas - var encodedParam = ""; - if (charset && charset != "UTF-8") - encodedParam = escape(convertFromUnicode(charset, param)). - replace(/[+@\/]+/g, encodeURIComponent); - else // Default charset is UTF-8 - encodedParam = encodeURIComponent(param); + // encodeURIComponent produces UTF-8, and cannot be used for other charsets. + // escape() works in those cases, but it doesn't uri-encode +, @, and /. + // Therefore we need to manually replace these ASCII characters by their + // encodeURIComponent result, to match the behavior of nsEscape() with + // url_XPAlphas + let encodedParam = ""; + if (charset && charset != "UTF-8") + encodedParam = escape(convertFromUnicode(charset, param)). + replace(/[+@\/]+/g, encodeURIComponent); + else // Default charset is UTF-8 + encodedParam = encodeURIComponent(param); - shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); + shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); - if (/%s/i.test(postData)) // POST keyword - aPostDataRef.value = getPostDataStream(postData, param, encodedParam, - "application/x-www-form-urlencoded"); - } - else if (param) { - // This keyword doesn't take a parameter, but one was provided. Just return - // the original URL. - aPostDataRef.value = null; + if (/%s/i.test(escapedPostData)) // POST keyword + postData = getPostDataStream(escapedPostData, param, encodedParam, + "application/x-www-form-urlencoded"); - return aURL; - } + // This URL came from a bookmark, so it's safe to let it inherit the current + // document's principal. + mayInheritPrincipal = true; + + return { postData, url: shortcutURL, mayInheritPrincipal }; + } + + if (param) { + // This keyword doesn't take a parameter, but one was provided. Just return + // the original URL. + postData = null; - // This URL came from a bookmark, so it's safe to let it inherit the current - // document's principal. - if (aMayInheritPrincipal) - aMayInheritPrincipal.value = true; + return { postData, url, mayInheritPrincipal }; + } + + // This URL came from a bookmark, so it's safe to let it inherit the current + // document's principal. + mayInheritPrincipal = true; - return shortcutURL; + return { postData, url: shortcutURL, mayInheritPrincipal }; + }).then(data => { + if (callback) { + callback(data); + } + + return data; + }); } function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) { @@ -2482,8 +2533,8 @@ function BrowserFullScreen() window.fullScreen = !window.fullScreen; } -function onFullScreen(event) { - FullScreen.toggle(event); +function onFullScreen() { + FullScreen.toggle(); } function onMozEnteredDomFullscreen(event) { @@ -2641,8 +2692,8 @@ var browserDragAndDrop = { } }, - drop: function (aEvent, aName, aDisallowInherit) { - return Services.droppedLinkHandler.dropLink(aEvent, aName, aDisallowInherit); + dropLinks: function (aEvent, aDisallowInherit) { + return Services.droppedLinkHandler.dropLinks(aEvent, aDisallowInherit); } }; @@ -2650,8 +2701,10 @@ var homeButtonObserver = { onDrop: function (aEvent) { // disallow setting home pages that inherit the principal - let url = browserDragAndDrop.drop(aEvent, {}, true); - setTimeout(openHomeDialog, 0, url); + let links = browserDragAndDrop.dropLinks(aEvent, true); + if (links.length) { + setTimeout(openHomeDialog, 0, links.map(link => link.url).join("|")); + } }, onDragOver: function (aEvent) @@ -2667,18 +2720,24 @@ var homeButtonObserver = { function openHomeDialog(aURL) { var promptTitle = gNavigatorBundle.getString("droponhometitle"); - var promptMsg = gNavigatorBundle.getString("droponhomemsg"); + var promptMsg; + if (aURL.includes("|")) { + promptMsg = gNavigatorBundle.getString("droponhomemsgMultiple"); + } else { + promptMsg = gNavigatorBundle.getString("droponhomemsg"); + } + var pressedVal = Services.prompt.confirmEx(window, promptTitle, promptMsg, Services.prompt.STD_YES_NO_BUTTONS, null, null, null, null, {value:0}); if (pressedVal == 0) { try { - var str = Components.classes["@mozilla.org/supports-string;1"] - .createInstance(Components.interfaces.nsISupportsString); - str.data = aURL; + var homepageStr = Components.classes["@mozilla.org/supports-string;1"] + .createInstance(Components.interfaces.nsISupportsString); + homepageStr.data = aURL; gPrefService.setComplexValue("browser.startup.homepage", - Components.interfaces.nsISupportsString, str); + Components.interfaces.nsISupportsString, homepageStr); } catch (ex) { dump("Failed to set the home page.\n"+ex+"\n"); } @@ -2726,13 +2785,16 @@ var newTabButtonObserver = { onDrop: function (aEvent) { - let url = browserDragAndDrop.drop(aEvent, { }); - var postData = {}; - url = getShortcutOrURI(url, postData); - if (url) { - // allow third-party services to fixup this URL - openNewTabWith(url, null, postData.value, aEvent, true); - } + let links = browserDragAndDrop.dropLinks(aEvent); + Task.spawn(function*() { + for (let link of links) { + let data = yield getShortcutOrURIAndPostData(link.url); + if (data.url) { + // allow third-party services to fixup this URL + openNewTabWith(data.url, null, data.postData, aEvent, true); + } + } + }); } } @@ -2746,13 +2808,16 @@ var newWindowButtonObserver = { }, onDrop: function (aEvent) { - let url = browserDragAndDrop.drop(aEvent, { }); - var postData = {}; - url = getShortcutOrURI(url, postData); - if (url) { - // allow third-party services to fixup this URL - openNewWindowWith(url, null, postData.value, true); - } + let links = browserDragAndDrop.dropLinks(aEvent); + Task.spawn(function*() { + for (let link of links) { + let data = yield getShortcutOrURIAndPostData(link.url); + if (data.url) { + // allow third-party services to fixup this URL + openNewWindowWith(data.url, null, data.postData, true); + } + } + }); } } @@ -2950,7 +3015,7 @@ const BrowserSearch = { #endif var searchBar = this.searchBar; if (searchBar && window.fullScreen) - FullScreen.mouseoverToggle(true); + FullScreen.showNavToolbox(); if (searchBar) searchBar.select(); if (!searchBar || document.activeElement != searchBar.textbox.inputField) @@ -4239,6 +4304,13 @@ nsBrowserAccess.prototype = { else aWhere = gPrefService.getIntPref("browser.link.open_newwindow"); } + + let referrer = aOpener ? makeURI(aOpener.location.href) : null; + let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT; + if (aOpener && aOpener.document) { + referrerPolicy = aOpener.document.referrerPolicy; + } + switch (aWhere) { case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW : // FIXME: Bug 408379. So how come this doesn't send the @@ -4277,6 +4349,7 @@ nsBrowserAccess.prototype = { let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", { referrerURI: referrer, + referrerPolicy: referrerPolicy, fromExternal: isExternal, inBackground: loadInBackground}); let browser = win.gBrowser.getBrowserForTab(tab); @@ -4292,11 +4365,14 @@ nsBrowserAccess.prototype = { default : // OPEN_CURRENTWINDOW or an illegal value newWindow = content; if (aURI) { - let referrer = aOpener ? makeURI(aOpener.location.href) : null; let loadflags = isExternal ? Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL : Ci.nsIWebNavigation.LOAD_FLAGS_NONE; - gBrowser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null); + gBrowser.loadURIWithFlags(aURI.spec, { + flags: loadflags, + referrerURI: referrer, + referrerPolicy: referrerPolicy, + }); } if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground")) window.focus(); @@ -5026,7 +5102,8 @@ function handleLinkClick(event, href, linkNode) { urlSecurityCheck(href, doc.nodePrincipal); openLinkIn(href, where, { referrerURI: doc.documentURIObject, - charset: doc.characterSet }); + charset: doc.characterSet, + referrerPolicy: doc.referrerPolicy }); event.preventDefault(); return true; } @@ -5040,36 +5117,81 @@ function middleMousePaste(event) { // bar's behavior (stripsurroundingwhitespace) clipboard = clipboard.replace(/\s*\n\s*/g, ""); - let mayInheritPrincipal = { value: false }; - let url = getShortcutOrURI(clipboard, mayInheritPrincipal); - try { - makeURI(url); - } catch (ex) { - // Not a valid URI. - return; + // if it's not the current tab, we don't need to do anything because the + // browser doesn't exist. + let where = whereToOpenLink(event, true, false); + let lastLocationChange; + if (where == "current") { + lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; } - try { - addToUrlbarHistory(url); - } catch (ex) { - // Things may go wrong when adding url to session history, - // but don't let that interfere with the loading of the url. - Cu.reportError(ex); - } + getShortcutOrURIAndPostData(clipboard).then(data => { + try { + makeURI(data.url); + } catch (ex) { + // Not a valid URI. + return; + } + + try { + addToUrlbarHistory(data.url); + } catch (ex) { + // Things may go wrong when adding url to session history, + // but don't let that interfere with the loading of the url. + Cu.reportError(ex); + } - openUILink(url, event, - { ignoreButton: true, - disallowInheritPrincipal: !mayInheritPrincipal.value }); + if (where != "current" || + lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) { + openUILink(data.url, event, + { ignoreButton: true, + disallowInheritPrincipal: !data.mayInheritPrincipal, + initiatingDoc: event ? event.target.ownerDocument : null }); + } + }); event.stopPropagation(); } -function handleDroppedLink(event, url, name) +// handleDroppedLink has the following 2 overloads: +// handleDroppedLink(event, url, name) +// handleDroppedLink(event, links) +function handleDroppedLink(event, urlOrLinks, name) { - let postData = { }; - let uri = getShortcutOrURI(url, postData); - if (uri) - loadURI(uri, null, postData.value, false); + let links; + if (Array.isArray(urlOrLinks)) { + links = urlOrLinks; + } else { + links = [{ url: urlOrLinks, name, type: "" }]; + } + + let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; + + let userContextId = gBrowser.selectedBrowser + .getAttribute("usercontextid") || 0; + + let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); + if (event.shiftKey) + inBackground = !inBackground; + + Task.spawn(function*() { + let urls = []; + let postDatas = []; + for (let link of links) { + let data = yield getShortcutOrURIAndPostData(link.url); + urls.push(data.url); + postDatas.push(data.postData); + } + if (lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) { + gBrowser.loadTabs(urls, { + inBackground, + replace: true, + allowThirdPartyFixup: false, + postDatas, + userContextId, + }); + } + }); // Keep the event from being handled by the dragDrop listeners // built-in to goanna if they happen to be above us. @@ -5184,7 +5306,6 @@ function charsetLoadListener() { } } - var gPageStyleMenu = { _getAllStyleSheets: function (frameset) { diff --git a/application/palemoon/base/content/browser.xul b/application/palemoon/base/content/browser.xul index c2553f295..f9030056e 100644 --- a/application/palemoon/base/content/browser.xul +++ b/application/palemoon/base/content/browser.xul @@ -941,7 +941,7 @@ </toolbarpalette> </toolbox> - <hbox id="fullscr-toggler" collapsed="true"/> + <hbox id="fullscr-toggler" hidden="true"/> <hbox flex="1" id="browser"> <vbox id="browser-border-start" hidden="true" layer="true"/> @@ -974,18 +974,6 @@ <vbox id="full-screen-warning-message" align="center"> <description id="full-screen-domain-text"/> <description class="full-screen-description" value="&fullscreenExitHint.value;"/> - <vbox id="full-screen-approval-pane" align="center"> - <description class="full-screen-description" value="&fullscreenApproval.value;"/> - <hbox> - <button label="&fullscreenAllowButton.label;" - oncommand="FullScreen.setFullscreenAllowed(true);" - class="full-screen-approval-button"/> - <button label="&fullscreenExitButton.label;" - oncommand="FullScreen.setFullscreenAllowed(false);" - class="full-screen-approval-button"/> - </hbox> - <checkbox id="full-screen-remember-decision"/> - </vbox> </vbox> </hbox> </hbox> diff --git a/application/palemoon/base/content/newtab/grid.js b/application/palemoon/base/content/newtab/grid.js index 46e0b804b..a614d0396 100644 --- a/application/palemoon/base/content/newtab/grid.js +++ b/application/palemoon/base/content/newtab/grid.js @@ -59,8 +59,13 @@ var gGrid = { * Refreshes the grid and re-creates all sites. */ refresh: function Grid_refresh() { + let cells = this.cells; + if (!cells) { + return; + } + // Remove all sites. - this.cells.forEach(function (cell) { + cells.forEach(function (cell) { let node = cell.node; let child = node.firstElementChild; diff --git a/application/palemoon/base/content/nsContextMenu.js b/application/palemoon/base/content/nsContextMenu.js index 830c20998..f389491d3 100644 --- a/application/palemoon/base/content/nsContextMenu.js +++ b/application/palemoon/base/content/nsContextMenu.js @@ -753,7 +753,8 @@ nsContextMenu.prototype = { urlSecurityCheck(this.linkURL, doc.nodePrincipal); openLinkIn(this.linkURL, "window", { charset: doc.characterSet, - referrerURI: doc.documentURIObject }); + referrerURI: doc.documentURIObject, + referrerPolicy: doc.referrerPolicy }); }, // Open linked-to URL in a new private window. @@ -763,6 +764,7 @@ nsContextMenu.prototype = { openLinkIn(this.linkURL, "window", { charset: doc.characterSet, referrerURI: doc.documentURIObject, + referrerPolicy: doc.referrerPolicy, private: true }); }, @@ -772,7 +774,8 @@ nsContextMenu.prototype = { urlSecurityCheck(this.linkURL, doc.nodePrincipal); openLinkIn(this.linkURL, "tab", { charset: doc.characterSet, - referrerURI: doc.documentURIObject }); + referrerURI: doc.documentURIObject, + referrerPolicy: doc.referrerPolicy }); }, // open URL in current tab diff --git a/application/palemoon/base/content/openLocation.js b/application/palemoon/base/content/openLocation.js index 316dfac70..f39e34666 100644 --- a/application/palemoon/base/content/openLocation.js +++ b/application/palemoon/base/content/openLocation.js @@ -61,45 +61,52 @@ function doEnabling() function open() { - var url; - var postData = {}; - var mayInheritPrincipal = {value: false}; - if (browser) - url = browser.getShortcutOrURI(dialog.input.value, postData, mayInheritPrincipal); - else - url = dialog.input.value; + getShortcutOrURIAndPostData(dialog.input.value).then(data => { + let url; + let postData = null; + let mayInheritPrincipal = false; + + if (browser) { + url = data.url; + postData = data.postData; + mayInheritPrincipal = data.mayInheritPrincipal; + } else { + url = dialog.input.value; + } - try { - // Whichever target we use for the load, we allow third-party services to - // fixup the URI - switch (dialog.openWhereList.value) { - case "0": - var webNav = Components.interfaces.nsIWebNavigation; - var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - if (!mayInheritPrincipal.value) - flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; - browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData.value); - break; - case "1": - window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no", - url, postData.value, null, null, true); - break; - case "3": - browser.delayedOpenTab(url, null, null, postData.value, true); - break; + try { + // Whichever target we use for the load, we allow third-party services to + // fixup the URI + switch (dialog.openWhereList.value) { + case "0": + var webNav = Components.interfaces.nsIWebNavigation; + var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | + webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; + if (!mayInheritPrincipal) + flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL; + browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData); + break; + case "1": + window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no", + url, postData, null, null, true); + break; + case "3": + browser.delayedOpenTab(url, null, null, postData, true); + break; + } + } + catch(exception) { } - } - catch(exception) { - } - if (pref) { - gOpenLocationLastURL.value = dialog.input.value; - pref.setIntPref("general.open_location.last_window_choice", dialog.openWhereList.value); - } + if (pref) { + gOpenLocationLastURL.value = dialog.input.value; + pref.setIntPref("general.open_location.last_window_choice", dialog.openWhereList.value); + } + + // Delay closing slightly to avoid timing bug on Linux. + window.close(); + }); - // Delay closing slightly to avoid timing bug on Linux. - window.close(); return false; } diff --git a/application/palemoon/base/content/pageinfo/pageInfo.js b/application/palemoon/base/content/pageinfo/pageInfo.js index 83f0ddb91..6b02bc370 100644 --- a/application/palemoon/base/content/pageinfo/pageInfo.js +++ b/application/palemoon/base/content/pageinfo/pageInfo.js @@ -1112,8 +1112,9 @@ var imagePermissionObserver = { var row = getSelectedRow(imageTree); var item = gImageView.data[row][COL_IMAGE_NODE]; var url = gImageView.data[row][COL_IMAGE_ADDRESS]; - if (makeURI(url).host == permission.host) + if (permission.matchesURI(makeURI(url), true)) { makeBlockImage(url); + } } } } diff --git a/application/palemoon/base/content/pageinfo/pageInfo.xul b/application/palemoon/base/content/pageinfo/pageInfo.xul index 5bca1b495..943fa805c 100644 --- a/application/palemoon/base/content/pageinfo/pageInfo.xul +++ b/application/palemoon/base/content/pageinfo/pageInfo.xul @@ -52,7 +52,6 @@ <command id="cmd_cookieDef" oncommand="onCheckboxClick('cookie');"/> <command id="cmd_desktop-notificationDef" oncommand="onCheckboxClick('desktop-notification');"/> <command id="cmd_installDef" oncommand="onCheckboxClick('install');"/> - <command id="cmd_fullscreenDef" oncommand="onCheckboxClick('fullscreen');"/> <command id="cmd_geoDef" oncommand="onCheckboxClick('geo');"/> <command id="cmd_indexedDBDef" oncommand="onCheckboxClick('indexedDB');"/> <command id="cmd_pluginsDef" oncommand="onCheckboxClick('plugins');"/> @@ -61,12 +60,9 @@ <command id="cmd_cookieToggle" oncommand="onRadioClick('cookie');"/> <command id="cmd_desktop-notificationToggle" oncommand="onRadioClick('desktop-notification');"/> <command id="cmd_installToggle" oncommand="onRadioClick('install');"/> - <command id="cmd_fullscreenToggle" oncommand="onRadioClick('fullscreen');"/> <command id="cmd_geoToggle" oncommand="onRadioClick('geo');"/> <command id="cmd_indexedDBToggle" oncommand="onRadioClick('indexedDB');"/> <command id="cmd_pluginsToggle" oncommand="onPluginRadioClick(event);"/> - <command id="cmd_pointerLockDef" oncommand="onCheckboxClick('pointerLock');"/> - <command id="cmd_pointerLockToggle" oncommand="onRadioClick('pointerLock');"/> </commandset> <keyset id="pageInfoKeySet"> @@ -405,31 +401,6 @@ </radiogroup> </hbox> </vbox> - <vbox class="permission" id="permFullscreenRow"> - <label class="permissionLabel" id="permFullscreenLabel" - value="&permFullscreen;" control="fullscreenRadioGroup"/> - <hbox id="permFullscreenBox" role="group" aria-labelledby="permFullscreenLabel"> - <checkbox id="fullscreenDef" command="cmd_fullscreenDef" label="&permUseDefault;"/> - <spacer flex="1"/> - <radiogroup id="fullscreenRadioGroup" orient="horizontal"> - <radio id="fullscreen#0" command="cmd_fullscreenToggle" label="&permAskAlways;"/> - <radio id="fullscreen#1" command="cmd_fullscreenToggle" label="&permAllow;"/> - <radio id="fullscreen#2" command="cmd_fullscreenToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> - <vbox class="permission" id="permPointerLockRow" > - <label class="permissionLabel" id="permPointerLockLabel" - value="&permPointerLock2;" control="pointerLockRadioGroup"/> - <hbox id="permPointerLockBox" role="group" aria-labelledby="permPointerLockLabel"> - <checkbox id="pointerLockDef" command="cmd_pointerLockDef" label="&permAskAlways;"/> - <spacer flex="1"/> - <radiogroup id="pointerLockRadioGroup" orient="horizontal"> - <radio id="pointerLock#1" command="cmd_pointerLockToggle" label="&permAllow;"/> - <radio id="pointerLock#2" command="cmd_pointerLockToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> </vbox> </vbox> diff --git a/application/palemoon/base/content/pageinfo/permissions.js b/application/palemoon/base/content/pageinfo/permissions.js index 2fa0cc303..e0fb01f76 100644 --- a/application/palemoon/base/content/pageinfo/permissions.js +++ b/application/palemoon/base/content/pageinfo/permissions.js @@ -76,20 +76,6 @@ var gPermObj = { { return UNKNOWN; }, - fullscreen: function getFullscreenDefaultPermissions() - { - if (!gPrefs.getBoolPref("full-screen-api.enabled")) { - return DENY; - } - return UNKNOWN; - }, - pointerLock: function getPointerLockPermissions() - { - if (!gPrefs.getBoolPref("full-screen-api.pointer-lock.enabled")) { - return DENY; - } - return ALLOW; - }, }; var permissionObserver = { @@ -98,7 +84,7 @@ var permissionObserver = { if (aTopic == "perm-changed") { var permission = aSubject.QueryInterface( Components.interfaces.nsIPermission); - if (permission.host == gPermURI.host) { + if (permission.matchesURI(gPermURI, true)) { if (permission.type in gPermObj) initRow(permission.type); else if (permission.type.startsWith("plugin")) @@ -119,7 +105,7 @@ function onLoadPermission(principal) gPermURI = uri; gPermPrincipal = principal; var hostText = document.getElementById("hostText"); - hostText.value = gPermURI.host; + hostText.value = gPermURI.prePath; for (var i in gPermObj) initRow(i); diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index a7cc6deea..1b8099785 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -570,6 +570,12 @@ const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; const nsIChannel = Components.interfaces.nsIChannel; + let location, originalLocation; + try { + aRequest.QueryInterface(nsIChannel) + location = aRequest.URI; + originalLocation = aRequest.originalURI; + } catch (ex) {} if (aStateFlags & nsIWebProgressListener.STATE_START) { this.mRequestCount++; @@ -588,16 +594,8 @@ if (aStateFlags & nsIWebProgressListener.STATE_START && aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { - // It's okay to clear what the user typed when we start - // loading a document. If the user types, this counter gets - // set to zero, if the document load ends without an - // onLocationChange, this counter gets decremented - // (so we keep it while switching tabs after failed loads) - // We need to add 2 because loadURIWithFlags may have - // cancelled a pending load which would have cleared - // its anchor scroll detection temporary increment. if (aWebProgress.isTopLevel) - this.mBrowser.userTypedClear += 2; + this.mBrowser.urlbarChangeTracker.startedLoad(); if (this._shouldShowProgress(aRequest)) { if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) { @@ -625,8 +623,8 @@ this.mTab.removeAttribute("progress"); if (aWebProgress.isTopLevel) { - if (!Components.isSuccessCode(aStatus) && - !isTabEmpty(this.mTab)) { + let isSuccessful = Components.isSuccessCode(aStatus); + if (!isSuccessful && !isTabEmpty(this.mTab)) { // Restore the current document's location in case the // request was stopped (possibly from a content script) // before the location changed. @@ -635,14 +633,8 @@ if (this.mTab.selected && gURLBar) URLBarSetURI(); - } else { - // The document is done loading, we no longer want the - // value cleared. - - if (this.mBrowser.userTypedClear > 1) - this.mBrowser.userTypedClear -= 2; - else if (this.mBrowser.userTypedClear > 0) - this.mBrowser.userTypedClear--; + } else if (isSuccessful) { + this.mBrowser.urlbarChangeTracker.finishedLoad(); } if (!this.mBrowser.mIconURL) @@ -652,8 +644,6 @@ if (this.mBlank) this.mBlank = false; - var location = aRequest.QueryInterface(nsIChannel).URI; - // For keyword URIs clear the user typed value since they will be changed into real URIs if (location.scheme == "keyword") this.mBrowser.userTypedValue = null; @@ -696,13 +686,12 @@ let topLevel = aWebProgress.isTopLevel; if (topLevel) { - // If userTypedClear > 0, the document loaded correctly and we should be - // clearing the user typed value. We also need to clear the typed value + // We need to clear the typed value // if the document failed to load, to make sure the urlbar reflects the // failed URI (particularly for SSL errors). However, don't clear the value // if the error page's URI is about:blank, because that causes complete // loss of urlbar contents for invalid URI errors (see bug 867957). - if (this.mBrowser.userTypedClear > 0 || + if (this.mBrowser.didStartLoadSinceLastUserTyping() || ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) && aLocation.spec != "about:blank")) this.mBrowser.userTypedValue = null; @@ -738,8 +727,10 @@ aFlags]); } - if (topLevel) + if (topLevel) { this.mBrowser.lastURI = aLocation; + this.mBrowser.lastLocationChange = Date.now(); + } }, onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) { @@ -1273,6 +1264,7 @@ <parameter name="aAllowThirdPartyFixup"/> <body> <![CDATA[ + var aReferrerPolicy; var aFromExternal; var aRelatedToCurrent; if (arguments.length == 2 && @@ -1280,6 +1272,7 @@ !(arguments[1] instanceof Ci.nsIURI)) { let params = arguments[1]; aReferrerURI = params.referrerURI; + aReferrerPolicy = params.referrerPolicy; aCharset = params.charset; aPostData = params.postData; aLoadInBackground = params.inBackground; @@ -1293,6 +1286,7 @@ var owner = bgLoad ? null : this.selectedTab; var tab = this.addTab(aURI, { referrerURI: aReferrerURI, + referrerPolicy: aReferrerPolicy, charset: aCharset, postData: aPostData, ownerTab: owner, @@ -1312,6 +1306,24 @@ <parameter name="aLoadInBackground"/> <parameter name="aReplace"/> <body><![CDATA[ + let aAllowThirdPartyFixup; + let aTargetTab; + let aNewIndex = -1; + let aPostDatas = []; + let aUserContextId; + if (arguments.length == 2 && + typeof arguments[1] == "object") { + let params = arguments[1]; + aLoadInBackground = params.inBackground; + aReplace = params.replace; + aAllowThirdPartyFixup = params.allowThirdPartyFixup; + aTargetTab = params.targetTab; + aNewIndex = typeof params.newIndex === "number" ? + params.newIndex : aNewIndex; + aPostDatas = params.postDatas || aPostDatas; + aUserContextId = params.userContextId; + } + if (!aURIs.length) return; @@ -1329,22 +1341,53 @@ var multiple = aURIs.length > 1; var owner = multiple || aLoadInBackground ? null : this.selectedTab; var firstTabAdded = null; + var targetTabIndex = -1; if (aReplace) { + let browser; + if (aTargetTab) { + browser = this.getBrowserForTab(aTargetTab); + targetTabIndex = aTargetTab._tPos; + } else { + browser = this.mCurrentBrowser; + targetTabIndex = this.tabContainer.selectedIndex; + } + let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; + if (aAllowThirdPartyFixup) { + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | + Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; + } try { - this.loadURI(aURIs[0], null, null); + browser.loadURIWithFlags(aURIs[0], { + flags, postData: aPostDatas[0] + }); } catch (e) { // Ignore failure in case a URI is wrong, so we can continue // opening the next ones. } + } else { + firstTabAdded = this.addTab(aURIs[0], { + ownerTab: owner, + skipAnimation: multiple, + allowThirdPartyFixup: aAllowThirdPartyFixup, + postData: aPostDatas[0], + userContextId: aUserContextId + }); + if (aNewIndex !== -1) { + this.moveTabTo(firstTabAdded, aNewIndex); + targetTabIndex = firstTabAdded._tPos; + } } - else - firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple}); - var tabNum = this.tabContainer.selectedIndex; + let tabNum = targetTabIndex; for (let i = 1; i < aURIs.length; ++i) { - let tab = this.addTab(aURIs[i], {skipAnimation: true}); - if (aReplace) + let tab = this.addTab(aURIs[i], { + skipAnimation: true, + allowThirdPartyFixup: aAllowThirdPartyFixup, + postData: aPostDatas[i], + userContextId: aUserContextId + }); + if (targetTabIndex !== -1) this.moveTabTo(tab, ++tabNum); } @@ -1369,6 +1412,7 @@ <body> <![CDATA[ const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + var aReferrerPolicy; var aFromExternal; var aRelatedToCurrent; var aSkipAnimation; @@ -1377,6 +1421,7 @@ !(arguments[1] instanceof Ci.nsIURI)) { let params = arguments[1]; aReferrerURI = params.referrerURI; + aReferrerPolicy = params.referrerPolicy; aCharset = params.charset; aPostData = params.postData; aOwner = params.ownerTab; @@ -1548,7 +1593,13 @@ if (aFromExternal) flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL; try { - b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData); + b.loadURIWithFlags(aURI, { + flags: flags, + referrerURI: aReferrerURI, + referrerPolicy: aReferrerPolicy, + charset: aCharset, + postData: aPostData, + }); } catch (ex) { Cu.reportError(ex); } @@ -2660,6 +2711,11 @@ <parameter name="aPostData"/> <body> <![CDATA[ + // Note - the callee understands both: + // (a) loadURIWithFlags(aURI, aFlags, ...) + // (b) loadURIWithFlags(aURI, { flags: aFlags, ... }) + // Forwarding it as (a) here actually supports both (a) and (b), + // so you can call us either way too. return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData); ]]> </body> @@ -2976,10 +3032,6 @@ ]]></body> </method> - <property name="userTypedClear" - onget="return this.mCurrentBrowser.userTypedClear;" - onset="return this.mCurrentBrowser.userTypedClear = val;"/> - <property name="userTypedValue" onget="return this.mCurrentBrowser.userTypedValue;" onset="return this.mCurrentBrowser.userTypedValue = val;"/> @@ -4456,40 +4508,35 @@ this.tabbrowser.updateCurrentBrowser(true); } else { // Pass true to disallow dropping javascript: or data: urls - let url; + let links; try { - url = browserDragAndDrop.drop(event, { }, true); + links = browserDragAndDrop.dropLinks(event, true); } catch (ex) {} // // valid urls don't contain spaces ' '; if we have a space it isn't a valid url. // if (!url || url.includes(" ")) //PMed - if (!url) //FF + if (!links || links.length === 0) //FF return; - let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); + let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); if (event.shiftKey) - bgLoad = !bgLoad; + inBackground = !inBackground; - let tab = this._getDragTargetTab(event); - if (!tab || dropEffect == "copy") { - // We're adding a new tab. - let newIndex = this._getDropIndex(event); - let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true}); - this.tabbrowser.moveTabTo(newTab, newIndex); - } else { - // Load in an existing tab. - try { - let webNav = Ci.nsIWebNavigation; - let flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - this.tabbrowser.getBrowserForTab(tab).loadURIWithFlags(url, flags); - if (!bgLoad) - this.selectedItem = tab; - } catch(ex) { - // Just ignore invalid urls - } - } + let targetTab = this._getDragTargetTab(event); + let userContextId = this.selectedItem + .getAttribute("usercontextid") || 0; + let replace = !(!targetTab || dropEffect == "copy"); + let newIndex = this._getDropIndex(event); + let urls = links.map(link => link.url); + this.tabbrowser.loadTabs(urls, { + inBackground, + replace, + allowThirdPartyFixup: true, + targetTab, + newIndex, + userContextId, + }); } if (draggedTab) { diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml index bf59ea164..d188e6658 100644 --- a/application/palemoon/base/content/urlbarBindings.xml +++ b/application/palemoon/base/content/urlbarBindings.xml @@ -263,6 +263,9 @@ var postData = null; var action = this._parseActionUrl(url); + let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; + + let matchLastLocationChange = true; if (action) { url = action.param; if (this.hasAttribute("actiontype")) { @@ -275,82 +278,94 @@ } return; } + continueOperation.call(this); } else { - [url, postData, mayInheritPrincipal] = this._canonizeURL(aTriggeringEvent); - if (!url) - return; - } - - this.value = url; - gBrowser.userTypedValue = url; - try { - addToUrlbarHistory(url); - } catch (ex) { - // Things may go wrong when adding url to session history, - // but don't let that interfere with the loading of the url. - Cu.reportError(ex); + this._canonizeURL(aTriggeringEvent, response => { + [url, postData, mayInheritPrincipal] = response; + if (url) { + matchLastLocationChange = (lastLocationChange == + gBrowser.selectedBrowser.lastLocationChange); + continueOperation.call(this); + } + }); } - function loadCurrent() { - let webnav = Ci.nsIWebNavigation; - let flags = webnav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - webnav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - // Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from - // inheriting the currently loaded document's principal, unless this - // URL is marked as safe to inherit (e.g. came from a bookmark - // keyword). - if (!mayInheritPrincipal) - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; - gBrowser.loadURIWithFlags(url, flags, null, null, postData); - } + function continueOperation() + { + this.value = url; + gBrowser.userTypedValue = url; + try { + addToUrlbarHistory(url); + } catch (ex) { + // Things may go wrong when adding url to session history, + // but don't let that interfere with the loading of the url. + Cu.reportError(ex); + } - // Focus the content area before triggering loads, since if the load - // occurs in a new tab, we want focus to be restored to the content - // area when the current tab is re-selected. - gBrowser.selectedBrowser.focus(); + function loadCurrent() { + let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; + // Pass LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL to prevent any loads from + // inheriting the currently loaded document's principal, unless this + // URL is marked as safe to inherit (e.g. came from a bookmark + // keyword). + if (!mayInheritPrincipal) + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL; + // If the value wasn't typed, we know that we decoded the value as + // UTF-8 (see losslessDecodeURI) + if (!this.valueIsTyped) + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_URI_IS_UTF8; + gBrowser.loadURIWithFlags(url, flags, null, null, postData); + } - let isMouseEvent = aTriggeringEvent instanceof MouseEvent; - let altEnter = !isMouseEvent && aTriggeringEvent && aTriggeringEvent.altKey; + // Focus the content area before triggering loads, since if the load + // occurs in a new tab, we want focus to be restored to the content + // area when the current tab is re-selected. + gBrowser.selectedBrowser.focus(); - if (altEnter) { - // XXX This was added a long time ago, and I'm not sure why it is - // necessary. Alt+Enter's default action might cause a system beep, - // or something like that? - aTriggeringEvent.preventDefault(); - aTriggeringEvent.stopPropagation(); - } + let isMouseEvent = aTriggeringEvent instanceof MouseEvent; - // If the current tab is empty, ignore Alt+Enter (just reuse this tab) - altEnter = altEnter && !isTabEmpty(gBrowser.selectedTab); + // If the current tab is empty, ignore Alt+Enter (just reuse this tab) + let altEnter = !isMouseEvent && aTriggeringEvent && + aTriggeringEvent.altKey && !isTabEmpty(gBrowser.selectedTab); - if (isMouseEvent || altEnter) { - // Use the standard UI link behaviors for clicks or Alt+Enter - let where = "tab"; - if (isMouseEvent) - where = whereToOpenLink(aTriggeringEvent, false, false); + if (isMouseEvent || altEnter) { + // Use the standard UI link behaviors for clicks or Alt+Enter + let where = "tab"; + if (isMouseEvent) + where = whereToOpenLink(aTriggeringEvent, false, false); - if (where == "current") { - loadCurrent(); + if (where == "current") { + if (matchLastLocationChange) { + loadCurrent(); + } + } else { + this.handleRevert(); + let params = { allowThirdPartyFixup: true, + postData: postData, + initiatingDoc: document }; + if (!this.valueIsTyped) + params.isUTF8 = true; + openUILinkIn(url, where, params); + } } else { - this.handleRevert(); - let params = { allowThirdPartyFixup: true, - postData: postData, - initiatingDoc: document }; - openUILinkIn(url, where, params); + if (matchLastLocationChange) { + loadCurrent(); + } } - } else { - loadCurrent(); } ]]></body> </method> <method name="_canonizeURL"> <parameter name="aTriggeringEvent"/> + <parameter name="aCallback"/> <body><![CDATA[ var url = this.value; - if (!url) - return ["", null, false]; + if (!url) { + aCallback(["", null, false]); + return; + } // Only add the suffix when the URL bar value isn't already "URL-like", // and only if we get a keyboard event, to match user expectations. @@ -403,11 +418,9 @@ } } - var postData = {}; - var mayInheritPrincipal = { value: false }; - url = getShortcutOrURI(url, postData, mayInheritPrincipal); - - return [url, postData.value, mayInheritPrincipal.value]; + getShortcutOrURIAndPostData(url).then(data => { + aCallback([data.url, data.postData, data.mayInheritPrincipal]); + }); ]]></body> </method> @@ -442,11 +455,12 @@ <method name="onDrop"> <parameter name="aEvent"/> <body><![CDATA[ - let url = browserDragAndDrop.drop(aEvent, { }) + let links = browserDragAndDrop.dropLinks(aEvent); // The URL bar automatically handles inputs with newline characters, // so we can get away with treating text/x-moz-url flavours as text/plain. - if (url) { + if (links.length > 0 && links[0].url) { + let url = links[0].url; aEvent.preventDefault(); this.value = url; SetPageProxyState("invalid"); @@ -1356,8 +1370,8 @@ return; } - let host = gPluginHandler._getHostFromPrincipal(this.notification.browser.contentWindow.document.nodePrincipal); - this._setupDescription("pluginActivateMultiple.message", null, host); + let prePath = this.notification.browser.contentWindow.document.nodePrincipal.URI.prePath; + this._setupDescription("pluginActivateMultiple.message", null, prePath); var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox"); @@ -1396,7 +1410,7 @@ <method name="_setupSingleState"> <body><![CDATA[ var action = this.notification.options.centerActions[0]; - var host = action.pluginPermissionHost; + var prePath = action.pluginPermissionPrePath; let label, linkLabel, linkUrl, button1, button2; @@ -1491,7 +1505,7 @@ Cu.reportError(Error("Unexpected blocklist state")); } } - this._setupDescription(label, action.pluginName, host); + this._setupDescription(label, action.pluginName, prePath); this._setupLink(linkLabel, action.detailsLink); this._primaryButton.label = gNavigatorBundle.getString(button1.label); @@ -1512,7 +1526,7 @@ <method name="_setupDescription"> <parameter name="baseString" /> <parameter name="pluginName" /> <!-- null for the multiple-plugin case --> - <parameter name="host" /> + <parameter name="prePath" /> <body><![CDATA[ var bsn = this._brandShortName; var span = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description"); @@ -1520,17 +1534,17 @@ span.removeChild(span.lastChild); } - var args = ["__host__", this._brandShortName]; + var args = ["__prepath__", this._brandShortName]; if (pluginName) { args.unshift(pluginName); } var bases = gNavigatorBundle.getFormattedString(baseString, args). - split("__host__", 2); + split("__prepath__", 2); span.appendChild(document.createTextNode(bases[0])); - var hostSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em"); - hostSpan.appendChild(document.createTextNode(host)); - span.appendChild(hostSpan); + var prePathSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em"); + prePathSpan.appendChild(document.createTextNode(prePath)); + span.appendChild(prePathSpan); span.appendChild(document.createTextNode(bases[1] + " ")); ]]></body> </method> diff --git a/application/palemoon/base/content/utilityOverlay.js b/application/palemoon/base/content/utilityOverlay.js index 86cc5cea5..633cb8853 100644 --- a/application/palemoon/base/content/utilityOverlay.js +++ b/application/palemoon/base/content/utilityOverlay.js @@ -104,7 +104,8 @@ function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup allowThirdPartyFixup: aAllowThirdPartyFixup, postData: aPostData, referrerURI: aReferrerURI, - initiatingDoc: event ? event.target.ownerDocument : null + referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT, + initiatingDoc: event ? event.target.ownerDocument : null, }; } @@ -196,7 +197,8 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI params = { allowThirdPartyFixup: aAllowThirdPartyFixup, postData: aPostData, - referrerURI: aReferrerURI + referrerURI: aReferrerURI, + referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT, }; } @@ -209,12 +211,16 @@ function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI function openLinkIn(url, where, params) { if (!where || !url) return; + const Cc = Components.classes; + const Ci = Components.interfaces; var aFromChrome = params.fromChrome; var aAllowThirdPartyFixup = params.allowThirdPartyFixup; var aPostData = params.postData; var aCharset = params.charset; var aReferrerURI = params.referrerURI; + var aReferrerPolicy = ('referrerPolicy' in params ? + params.referrerPolicy : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT); var aRelatedToCurrent = params.relatedToCurrent; var aForceAllowDataURI = params.forceAllowDataURI; var aInBackground = params.inBackground; @@ -229,11 +235,10 @@ function openLinkIn(url, where, params) { "where == 'save' but without initiatingDoc. See bug 814264."); return; } + // TODO(1073187): propagate referrerPolicy. saveURL(url, null, null, true, null, aReferrerURI, aInitiatingDoc); return; } - const Cc = Components.classes; - const Ci = Components.interfaces; var w = getTopWin(); if ((where == "tab" || where == "tabshifted") && @@ -243,6 +248,7 @@ function openLinkIn(url, where, params) { } if (!w || where == "window") { + // This propagates to window.arguments. // Strip referrer data when opening a new private window, to prevent // regular browsing data from leaking into it. if (aIsPrivate) { @@ -267,12 +273,23 @@ function openLinkIn(url, where, params) { createInstance(Ci.nsISupportsPRBool); allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup; + var referrerURISupports = null; + if (aReferrerURI && sendReferrerURI) { + referrerURISupports = Cc["@mozilla.org/supports-string;1"]. + createInstance(Ci.nsISupportsString); + referrerURISupports.data = aReferrerURI.spec; + } + + var referrerPolicySupports = Cc["@mozilla.org/supports-PRUint32;1"]. + createInstance(Ci.nsISupportsPRUint32); + referrerPolicySupports.data = aReferrerPolicy; + sa.AppendElement(wuri); sa.AppendElement(charset); - if (sendReferrerURI) - sa.AppendElement(aReferrerURI); + sa.AppendElement(referrerURISupports); sa.AppendElement(aPostData); sa.AppendElement(allowThirdPartyFixupSupports); + sa.AppendElement(referrerPolicySupports); let features = "chrome,dialog=no,all"; if (aIsPrivate) { @@ -316,11 +333,16 @@ function openLinkIn(url, where, params) { flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; } if (aDisallowInheritPrincipal) - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL; if (aForceAllowDataURI) { flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI; } - w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData); + w.gBrowser.loadURIWithFlags(url, { + flags: flags, + referrerURI: aReferrerURI, + referrerPolicy: aReferrerPolicy, + postData: aPostData, + }); break; case "tabshifted": loadInBackground = !loadInBackground; @@ -329,6 +351,7 @@ function openLinkIn(url, where, params) { let browser = w.gBrowser; browser.loadOneTab(url, { referrerURI: aReferrerURI, + referrerPolicy: aReferrerPolicy, charset: aCharset, postData: aPostData, inBackground: loadInBackground, @@ -577,9 +600,11 @@ function makeURLAbsolute(aBase, aUrl) * @param [optional] aReferrer * If aDocument is null, then this will be used as the referrer. * There will be no security check. + * @param [optional] aReferrerPolicy + * Referrer policy - Ci.nsIHttpChannel.REFERRER_POLICY_*. */ function openNewTabWith(aURL, aDocument, aPostData, aEvent, - aAllowThirdPartyFixup, aReferrer) { + aAllowThirdPartyFixup, aReferrer, aReferrerPolicy) { if (aDocument) urlSecurityCheck(aURL, aDocument.nodePrincipal); @@ -594,10 +619,13 @@ function openNewTabWith(aURL, aDocument, aPostData, aEvent, { charset: originCharset, postData: aPostData, allowThirdPartyFixup: aAllowThirdPartyFixup, - referrerURI: aDocument ? aDocument.documentURIObject : aReferrer }); + referrerURI: aDocument ? aDocument.documentURIObject : aReferrer, + referrerPolicy: aReferrerPolicy, + }); } -function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aReferrer) { +function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, + aReferrer, aReferrerPolicy) { if (aDocument) urlSecurityCheck(aURL, aDocument.nodePrincipal); @@ -614,7 +642,9 @@ function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aR { charset: originCharset, postData: aPostData, allowThirdPartyFixup: aAllowThirdPartyFixup, - referrerURI: aDocument ? aDocument.documentURIObject : aReferrer }); + referrerURI: aDocument ? aDocument.documentURIObject : aReferrer, + referrerPolicy: aReferrerPolicy, + }); } /** diff --git a/application/palemoon/base/jar.mn b/application/palemoon/base/jar.mn index fd2df79e1..622d8e0da 100644 --- a/application/palemoon/base/jar.mn +++ b/application/palemoon/base/jar.mn @@ -108,7 +108,7 @@ browser.jar: * content/browser/sanitize.xul (content/sanitize.xul) * content/browser/sanitizeDialog.js (content/sanitizeDialog.js) content/browser/sanitizeDialog.css (content/sanitizeDialog.css) -* content/browser/autocomplete.css (content/autocomplete.css) + content/browser/autocomplete.css (content/autocomplete.css) * content/browser/autocomplete.xml (content/autocomplete.xml) content/browser/tabbrowser.css (content/tabbrowser.css) * content/browser/tabbrowser.xml (content/tabbrowser.xml) diff --git a/application/palemoon/components/about/AboutRedirector.cpp b/application/palemoon/components/about/AboutRedirector.cpp index d52b873b9..27f6540b2 100644 --- a/application/palemoon/components/about/AboutRedirector.cpp +++ b/application/palemoon/components/about/AboutRedirector.cpp @@ -137,8 +137,13 @@ AboutRedirector::NewChannel(nsIURI* aURI, for (int i = 0; i < kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; - rv = ioService->NewChannel(nsDependentCString(kRedirMap[i].url), - nullptr, nullptr, getter_AddRefs(tempChannel)); + nsCOMPtr<nsIURI> tempURI; + rv = NS_NewURI(getter_AddRefs(tempURI), + nsDependentCString(kRedirMap[i].url)); + NS_ENSURE_SUCCESS(rv, rv); + rv = NS_NewChannelInternal(getter_AddRefs(tempChannel), + tempURI, + aLoadInfo); NS_ENSURE_SUCCESS(rv, rv); tempChannel->SetOriginalURI(aURI); diff --git a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js index 46e867068..054f0405f 100644 --- a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js +++ b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js @@ -41,22 +41,6 @@ const DOWNLOAD_VIEW_SUPPORTED_COMMANDS = const NOT_AVAILABLE = Number.MAX_VALUE; /** - * Download a URL. - * - * @param aURL - * the url to download (nsIURI object) - * @param [optional] aFileName - * the destination file name - */ -function DownloadURL(aURL, aFileName) { - // For private browsing, try to get document out of the most recent browser - // window, or provide our own if there's no browser window. - let browserWin = RecentWindow.getMostRecentBrowserWindow(); - let initiatingDoc = browserWin ? browserWin.document : document; - saveURL(aURL, aFileName, null, true, true, undefined, initiatingDoc); -} - -/** * A download element shell is responsible for handling the commands and the * displayed data for a single download view element. The download element * could represent either a past download (for which we get data from places) or @@ -654,7 +638,10 @@ DownloadElementShell.prototype = { // In future we may try to download into the same original target uri, when // we have it. Though that requires verifying the path is still valid and // may surprise the user if he wants to be requested every time. - DownloadURL(this.downloadURI, this.getDownloadMetaData().fileName); + let browserWin = RecentWindow.getMostRecentBrowserWindow(); + let initiatingDoc = browserWin ? browserWin.document : document; + DownloadURL(this.downloadURI, this.getDownloadMetaData().fileName, + initiatingDoc); }, /* nsIController */ @@ -1407,16 +1394,11 @@ DownloadsPlacesView.prototype = { _copySelectedDownloadsToClipboard: function DPV__copySelectedDownloadsToClipboard() { - let selectedElements = this._richlistbox.selectedItems; - // Tycho: let urls = [e._shell.downloadURI for each (e in selectedElements)]; - let urls = []; - - for each (e in selectedElements) { - urls.push(e._shell.downloadURI); - } + let urls = [for (element of this._richlistbox.selectedItems) + element._shell.downloadURI]; Cc["@mozilla.org/widget/clipboardhelper;1"]. - getService(Ci.nsIClipboardHelper).copyString(urls.join("\n"), document); + getService(Ci.nsIClipboardHelper).copyString(urls.join("\n")); }, _getURLFromClipboardData: function DPV__getURLFromClipboardData() { @@ -1450,10 +1432,16 @@ DownloadsPlacesView.prototype = { _downloadURLFromClipboard: function DPV__downloadURLFromClipboard() { let [url, name] = this._getURLFromClipboardData(); - DownloadURL(url, name); + let browserWin = RecentWindow.getMostRecentBrowserWindow(); + let initiatingDoc = browserWin ? browserWin.document : document; + DownloadURL(url, name, initiatingDoc); }, doCommand: function DPV_doCommand(aCommand) { + // Commands may be invoked with keyboard shortcuts even if disabled. + if (!this.isCommandEnabled(aCommand)) { + return; + } switch (aCommand) { case "cmd_copy": this._copySelectedDownloadsToClipboard(); @@ -1504,6 +1492,11 @@ DownloadsPlacesView.prototype = { else contextMenu.removeAttribute("state"); + if (state == nsIDM.DOWNLOAD_DOWNLOADING) { + // The resumable property of a download may change at any time, so + // ensure we update the related command now. + goUpdateCommand("downloadsCmd_pauseResume"); + } return true; }, @@ -1594,10 +1587,16 @@ DownloadsPlacesView.prototype = { if (dt.mozGetDataAt("application/x-moz-file", 0)) return; - let name = { }; - let url = Services.droppedLinkHandler.dropLink(aEvent, name); - if (url) - DownloadURL(url, name.value); + let links = Services.droppedLinkHandler.dropLinks(aEvent); + if (!links.length) + return; + let browserWin = RecentWindow.getMostRecentBrowserWindow(); + let initiatingDoc = browserWin ? browserWin.document : document; + for (let link of links) { + if (link.url.startsWith("about:")) + continue; + DownloadURL(link.url, link.name, initiatingDoc); + } } }; diff --git a/application/palemoon/components/downloads/content/downloads.js b/application/palemoon/components/downloads/content/downloads.js index 0412344bc..833d7d72f 100644 --- a/application/palemoon/components/downloads/content/downloads.js +++ b/application/palemoon/components/downloads/content/downloads.js @@ -507,8 +507,7 @@ const DownloadsPanel = { let uri = NetUtil.newURI(url); DownloadsCommon.log("Pasted URL seems valid. Starting download."); - saveURL(uri.spec, name || uri.spec, null, true, true, - undefined, document); + DownloadURL(uri.spec, name, document); } catch (ex) {} }, diff --git a/application/palemoon/components/downloads/content/indicator.js b/application/palemoon/components/downloads/content/indicator.js index e6a5bd012..1a2175a92 100644 --- a/application/palemoon/components/downloads/content/indicator.js +++ b/application/palemoon/components/downloads/content/indicator.js @@ -548,15 +548,18 @@ const DownloadsIndicatorView = { if (dt.mozGetDataAt("application/x-moz-file", 0)) return; - let name = {}; - let url = browserDragAndDrop.drop(aEvent, name); - if (url) { - if (url.startsWith("about:")) { - return; - } - - let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document; - saveURL(url, name.value, null, true, true, null, sourceDoc); + let links = browserDragAndDrop.dropLinks(aEvent); + if (!links.length) + return; + let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document; + let handled = false; + for (let link of links) { + if (link.url.startsWith("about:")) + continue; + saveURL(link.url, link.name, null, true, true, null, sourceDoc); + handled = true; + } + if (handled) { aEvent.preventDefault(); } }, diff --git a/application/palemoon/components/feeds/FeedWriter.js b/application/palemoon/components/feeds/FeedWriter.js index cbb146564..2ae31dffa 100644 --- a/application/palemoon/components/feeds/FeedWriter.js +++ b/application/palemoon/components/feeds/FeedWriter.js @@ -1173,7 +1173,7 @@ FeedWriter.prototype = { var secman = Cc["@mozilla.org/scriptsecuritymanager;1"]. getService(Ci.nsIScriptSecurityManager); - this._feedPrincipal = secman.getSimpleCodebasePrincipal(this._feedURI); + this._feedPrincipal = secman.createCodebasePrincipal(this._feedURI, {}); LOG("Subscribe Preview: feed uri = " + this._window.location.href); diff --git a/application/palemoon/components/nsBrowserGlue.js b/application/palemoon/components/nsBrowserGlue.js index 225cddd52..aa24d88ef 100644 --- a/application/palemoon/components/nsBrowserGlue.js +++ b/application/palemoon/components/nsBrowserGlue.js @@ -13,7 +13,11 @@ const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -// Define Lazy Module Gitters +// Define Lazy Service Getters +XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", + "@mozilla.org/alerts-service;1", "nsIAlertsService"); + +// Define Lazy Module Getters [ ["AddonManager", "resource://gre/modules/AddonManager.jsm"], ["NetUtil", "resource://gre/modules/NetUtil.jsm"], @@ -37,8 +41,19 @@ Cu.import("resource://gre/modules/Services.jsm"); ["FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"], ["AutoCompletePopup", "resource:///modules/AutoCompletePopup.jsm"], ["DateTimePickerHelper", "resource://gre/modules/DateTimePickerHelper.jsm"], + ["ShellService", "resource:///modules/ShellService.jsm"], ].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource)); +// Define Lazy Getters + +XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() { + return Services.strings.createBundle('chrome://branding/locale/brand.properties'); +}); + +XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() { + return Services.strings.createBundle('chrome://browser/locale/browser.properties'); +}); + const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser"; const PREF_PLUGINS_UPDATEURL = "plugins.update.url"; @@ -460,9 +475,7 @@ BrowserGlue.prototype = { if (!win) return; - let productName = Services.strings - .createBundle("chrome://branding/locale/brand.properties") - .GetStringFromName("brandFullName"); + let productName = gBrandBundle.GetStringFromName("brandFullName"); let message = win.gNavigatorBundle.getFormattedString("slowStartup.message", [productName]); let buttons = [ @@ -559,17 +572,17 @@ BrowserGlue.prototype = { } // Perform default browser checking. - var shell; - try { - shell = Components.classes["@mozilla.org/browser/shell-service;1"] - .getService(Components.interfaces.nsIShellService); - } catch (e) { } - if (shell) { -#ifdef DEBUG - let shouldCheck = false; -#else - let shouldCheck = shell.shouldCheckDefaultBrowser; -#endif + if (ShellService) { + let shouldCheck = ShellService.shouldCheckDefaultBrowser; + + const skipDefaultBrowserCheck = + Services.prefs.getBoolPref("browser.shell.skipDefaultBrowserCheckOnFirstRun") && + Services.prefs.getBoolPref("browser.shell.skipDefaultBrowserCheck"); + + const usePromptLimit = false; + let promptCount = + usePromptLimit ? Services.prefs.getIntPref("browser.shell.defaultBrowserCheckCount") : 0; + let willRecoverSession = false; try { let ss = Cc["@mozilla.org/browser/sessionstartup;1"]. @@ -579,9 +592,25 @@ BrowserGlue.prototype = { } catch (ex) { /* never mind; suppose SessionStore is broken */ } - let isDefault = shell.isDefaultBrowser(true, false); // startup check, check all assoc + // startup check, check all assoc + let isDefault = false; + let isDefaultError = false; + try { + isDefault = ShellService.isDefaultBrowser(true, false); + } catch (ex) { + isDefaultError = true; + } - if (shouldCheck && !isDefault && !willRecoverSession) { + if (isDefault) { + let now = (Math.floor(Date.now() / 1000)).toString(); + Services.prefs.setCharPref("browser.shell.mostRecentDateSetAsDefault", now); + } + + let willPrompt = shouldCheck && !isDefault && !willRecoverSession; + + // Skip the "Set Default Browser" check during first-run or after the + // browser has been run a few times. + if (willPrompt) { Services.tm.mainThread.dispatch(function() { var win = this.getMostRecentBrowserWindow(); var brandBundle = win.document.getElementById("bundle_brand"); @@ -610,9 +639,9 @@ BrowserGlue.prototype = { claimAllTypes = (parseFloat(version) < 6.2); } catch (ex) { } #endif - shell.setDefaultBrowser(claimAllTypes, false); + ShellService.setDefaultBrowser(claimAllTypes, false); } - shell.shouldCheckDefaultBrowser = checkEveryTime.value; + ShellService.shouldCheckDefaultBrowser = checkEveryTime.value; }.bind(this), Ci.nsIThread.DISPATCH_NORMAL); } } @@ -693,9 +722,8 @@ BrowserGlue.prototype = { let prompt = Services.prompt; let quitBundle = Services.strings.createBundle("chrome://browser/locale/quitDialog.properties"); - let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); - let appName = brandBundle.GetStringFromName("brandShortName"); + let appName = gBrandBundle.GetStringFromName("brandShortName"); let quitDialogTitle = quitBundle.formatStringFromName("quitDialogTitle", [appName], 1); let neverAskText = quitBundle.GetStringFromName("neverAsk2"); @@ -772,9 +800,7 @@ BrowserGlue.prototype = { var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"]. getService(Ci.nsIURLFormatter); - var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); - var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); - var appName = brandBundle.GetStringFromName("brandShortName"); + var appName = gBrandBundle.GetStringFromName("brandShortName"); function getNotifyString(aPropData) { var propValue = update.getProperty(aPropData.propName); @@ -782,11 +808,11 @@ BrowserGlue.prototype = { if (aPropData.prefName) propValue = formatter.formatURLPref(aPropData.prefName); else if (aPropData.stringParams) - propValue = browserBundle.formatStringFromName(aPropData.stringName, - aPropData.stringParams, - aPropData.stringParams.length); + propValue = gBrowserBundle.formatStringFromName(aPropData.stringName, + aPropData.stringParams, + aPropData.stringParams.length); else - propValue = browserBundle.GetStringFromName(aPropData.stringName); + propValue = gBrowserBundle.GetStringFromName(aPropData.stringName); } return propValue; } @@ -825,16 +851,6 @@ BrowserGlue.prototype = { if (actions.indexOf("showAlert") == -1) return; - let notifier; - try { - notifier = Cc["@mozilla.org/alerts-service;1"]. - getService(Ci.nsIAlertsService); - } - catch (e) { - // nsIAlertsService is not available for this platform - return; - } - let title = getNotifyString({propName: "alertTitle", stringName: "puAlertTitle", stringParams: [appName]}); @@ -856,10 +872,11 @@ BrowserGlue.prototype = { try { // This will throw NS_ERROR_NOT_AVAILABLE if the notification cannot // be displayed per the idl. - notifier.showAlertNotification(null, title, text, - true, url, clickCallback); + AlertsService.showAlertNotification(null, title, text, + true, url, clickCallback); } catch (e) { + Cu.reportError(e); } }, @@ -1156,8 +1173,7 @@ BrowserGlue.prototype = { * Show the notificationBox for a locked places database. */ _showPlacesLockedNotificationBox: function BG__showPlacesLockedNotificationBox() { - var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); - var applicationName = brandBundle.GetStringFromName("brandShortName"); + var applicationName = gBrandBundle.GetStringFromName("brandShortName"); var placesBundle = Services.strings.createBundle("chrome://browser/locale/places/places.properties"); var title = placesBundle.GetStringFromName("lockPrompt.title"); var text = placesBundle.formatStringFromName("lockPrompt.text", [applicationName], 1); @@ -1191,7 +1207,7 @@ BrowserGlue.prototype = { }, _migrateUI: function BG__migrateUI() { - const UI_VERSION = 15; + const UI_VERSION = 17; const BROWSER_DOCURL = "chrome://browser/content/browser.xul#"; let currentUIVersion = 0; try { @@ -1386,6 +1402,10 @@ BrowserGlue.prototype = { } } + if (currentUIVersion < 17) { + this._notifyNotificationsUpgrade(); + } + if (this._dirty) this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush(); @@ -1396,6 +1416,52 @@ BrowserGlue.prototype = { Services.prefs.setIntPref("browser.migration.version", UI_VERSION); }, + _hasExistingNotificationPermission: function BG__hasExistingNotificationPermission() { + let enumerator = Services.perms.enumerator; + while (enumerator.hasMoreElements()) { + let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission); + if (permission.type == "desktop-notification") { + return true; + } + } + return false; + }, + + _notifyNotificationsUpgrade: function BG__notifyNotificationsUpgrade() { + if (!this._hasExistingNotificationPermission()) { + return; + } + function clickCallback(subject, topic, data) { + if (topic != "alertclickcallback") + return; + let win = RecentWindow.getMostRecentBrowserWindow(); + win.openUILinkIn(data, "tab"); + } + // Show the application icon for XUL notifications. We assume system-level + // notifications will include their own icon. + let imageURL = this._hasSystemAlertsService() ? "" : + "chrome://branding/content/about-logo.png"; + let title = gBrowserBundle.GetStringFromName("webNotifications.upgradeTitle"); + let text = gBrowserBundle.GetStringFromName("webNotifications.upgradeBody"); + let url = Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"); + + try { + AlertsService.showAlertNotification(imageURL, title, text, + true, url, clickCallback); + } + catch (e) { + Cu.reportError(e); + } + }, + + _hasSystemAlertsService: function() { + try { + return !!Cc["@mozilla.org/system-alerts-service;1"].getService( + Ci.nsIAlertsService); + } catch (e) {} + return false; + }, + _getPersist: function BG__getPersist(aSource, aProperty) { var target = this._dataSource.GetTarget(aSource, aProperty, true); if (target instanceof Ci.nsIRDFLiteral) @@ -1645,6 +1711,16 @@ ContentPermissionPrompt.prototype = { return chromeWin; }, + _getBrowserForRequest: function (aRequest) { + let requestingWindow = aRequest.window.top; + // find the requesting browser or iframe + let browser = requestingWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell) + .chromeEventHandler; + return browser; + }, + /** * Show a permission prompt. * @@ -1665,8 +1741,6 @@ ContentPermissionPrompt.prototype = { popup.remove(); } - var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); - var requestingWindow = aRequest.window.top; var chromeWin = this._getChromeWindow(requestingWindow).wrappedJSObject; var browser = chromeWin.gBrowser.getBrowserForDocument(requestingWindow.document); @@ -1692,8 +1766,8 @@ ContentPermissionPrompt.prototype = { } var action = { - label: browserBundle.GetStringFromName(promptAction.stringId), - accessKey: browserBundle.GetStringFromName(promptAction.stringId + ".accesskey"), + label: gBrowserBundle.GetStringFromName(promptAction.stringId), + accessKey: gBrowserBundle.GetStringFromName(promptAction.stringId + ".accesskey"), callback: function() { if (promptAction.callback) { promptAction.callback(); @@ -1752,7 +1826,6 @@ ContentPermissionPrompt.prototype = { }, _promptGeo : function(aRequest) { - var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); var requestingURI = aRequest.principal.URI; var message; @@ -1768,11 +1841,11 @@ ContentPermissionPrompt.prototype = { }]; if (requestingURI.schemeIs("file")) { - message = browserBundle.formatStringFromName("geolocation.shareWithFile", - [requestingURI.path], 1); + message = gBrowserBundle.formatStringFromName("geolocation.shareWithFile", + [requestingURI.path], 1); } else { - message = browserBundle.formatStringFromName("geolocation.shareWithSite", - [requestingURI.host], 1); + message = gBrowserBundle.formatStringFromName("geolocation.shareWithSite", + [requestingURI.host], 1); // Always share location action. actions.push({ stringId: "geolocation.alwaysShareLocation", @@ -1803,47 +1876,63 @@ ContentPermissionPrompt.prototype = { }, _promptWebNotifications : function(aRequest) { - var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); var requestingURI = aRequest.principal.URI; - var message = browserBundle.formatStringFromName("webNotifications.showFromSite", - [requestingURI.host], 1); + var message = gBrowserBundle.formatStringFromName("webNotifications.showFromSite", + [requestingURI.host], 1); - var actions = [ - { - stringId: "webNotifications.showForSession", - action: Ci.nsIPermissionManager.ALLOW_ACTION, - expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, - callback: function() {}, - }, - { - stringId: "webNotifications.alwaysShow", - action: Ci.nsIPermissionManager.ALLOW_ACTION, - expireType: null, - callback: function() {}, - }, - { - stringId: "webNotifications.neverShow", - action: Ci.nsIPermissionManager.DENY_ACTION, - expireType: null, - callback: function() {}, - }, - ]; + var actions; + + var browser = this._getBrowserForRequest(aRequest); + // Only show "allow for session" in PB mode, we don't + // support "allow for session" in non-PB mode. + if (PrivateBrowsingUtils.isBrowserPrivate(browser)) { + actions = [ + { + stringId: "webNotifications.showForSession", + action: Ci.nsIPermissionManager.ALLOW_ACTION, + expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, + callback: function() {}, + }, + ]; + } else { + actions = [ + { + stringId: "webNotifications.showForSession", + action: Ci.nsIPermissionManager.ALLOW_ACTION, + expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, + callback: function() {}, + }, + { + stringId: "webNotifications.alwaysShow", + action: Ci.nsIPermissionManager.ALLOW_ACTION, + expireType: null, + callback: function() {}, + }, + { + stringId: "webNotifications.neverShow", + action: Ci.nsIPermissionManager.DENY_ACTION, + expireType: null, + callback: function() {}, + }, + ]; + } + var options = { + learnMoreURL: Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"), + }; this._showPrompt(aRequest, message, "desktop-notification", actions, "web-notifications", - "web-notifications-notification-icon", null); + "web-notifications-notification-icon", options); }, _promptPointerLock: function CPP_promtPointerLock(aRequest, autoAllow) { - - let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); let requestingURI = aRequest.principal.URI; let originString = requestingURI.schemeIs("file") ? requestingURI.path : requestingURI.host; - let message = browserBundle.formatStringFromName(autoAllow ? - "pointerLock.autoLock.title2" : "pointerLock.title2", - [originString], 1); + let message = gBrowserBundle.formatStringFromName(autoAllow ? + "pointerLock.autoLock.title2" : "pointerLock.title2", + [originString], 1); // If this is an autoAllow info prompt, offer no actions. // _showPrompt() will allow the request when it's dismissed. let actions = []; @@ -1875,7 +1964,6 @@ ContentPermissionPrompt.prototype = { }, prompt: function CPP_prompt(request) { - // Only allow exactly one permission rquest here. let types = request.types.QueryInterface(Ci.nsIArray); if (types.length != 1) { @@ -1921,15 +2009,15 @@ ContentPermissionPrompt.prototype = { // Show the prompt. switch (perm.type) { - case "geolocation": - this._promptGeo(request); - break; - case "desktop-notification": - this._promptWebNotifications(request); - break; - case "pointerLock": - this._promptPointerLock(request, autoAllow); - break; + case "geolocation": + this._promptGeo(request); + break; + case "desktop-notification": + this._promptWebNotifications(request); + break; + case "pointerLock": + this._promptPointerLock(request, autoAllow); + break; } }, diff --git a/application/palemoon/components/places/content/editBookmarkOverlay.js b/application/palemoon/components/places/content/editBookmarkOverlay.js index 43645cc73..69d7d32eb 100644 --- a/application/palemoon/components/places/content/editBookmarkOverlay.js +++ b/application/palemoon/components/places/content/editBookmarkOverlay.js @@ -12,6 +12,7 @@ var gEditItemOverlay = { _uris: [], _tags: [], _allTags: [], + _keyword: null, _multiEdit: false, _itemType: -1, _readOnly: false, @@ -139,9 +140,8 @@ var gEditItemOverlay = { this._itemType = PlacesUtils.bookmarks.getItemType(this._itemId); if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) { this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId); - this._initTextField("keywordField", - PlacesUtils.bookmarks - .getKeywordForBookmark(this._itemId)); + this._keyword = PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId); + this._initTextField("keywordField", this._keyword); this._element("loadInSidebarCheckbox").checked = PlacesUtils.annotations.itemHasAnnotation(this._itemId, PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO); @@ -610,9 +610,13 @@ var gEditItemOverlay = { }, onKeywordFieldBlur: function EIO_onKeywordFieldBlur() { - var keyword = this._element("keywordField").value; - if (keyword != PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId)) { - var txn = new PlacesEditBookmarkKeywordTransaction(this._itemId, keyword); + let oldKeyword = this._keyword; + let keyword = this._keyword = this._element("keywordField").value; + if (keyword != oldKeyword) { + let txn = new PlacesEditBookmarkKeywordTransaction(this._itemId, + keyword, + null, + oldKeyword); PlacesUtils.transactionManager.doTransaction(txn); } }, @@ -1004,9 +1008,8 @@ var gEditItemOverlay = { } break; case "keyword": - this._initTextField("keywordField", - PlacesUtils.bookmarks - .getKeywordForBookmark(this._itemId)); + this._keyword = PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId); + this._initTextField("keywordField", this._keyword); break; case PlacesUIUtils.DESCRIPTION_ANNO: this._initTextField("descriptionField", diff --git a/application/palemoon/components/preferences/aboutPermissions.js b/application/palemoon/components/preferences/aboutPermissions.js index 31b48f88e..9fb12d081 100644 --- a/application/palemoon/components/preferences/aboutPermissions.js +++ b/application/palemoon/components/preferences/aboutPermissions.js @@ -2,17 +2,25 @@ * 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"; + var Ci = Components.interfaces; var Cc = Components.classes; var Cu = Components.utils; +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/PluralForm.jsm"); Cu.import("resource://gre/modules/DownloadUtils.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); Cu.import("resource://gre/modules/NetUtil.jsm"); Cu.import("resource://gre/modules/ForgetAboutSite.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", + "resource://gre/modules/PluralForm.jsm"); + +var gSecMan = Cc["@mozilla.org/scriptsecuritymanager;1"]. + getService(Ci.nsIScriptSecurityManager); + var gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"]. getService(Ci.nsIFaviconService); @@ -22,7 +30,7 @@ var gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"]. clone(true); var gSitesStmt = gPlacesDatabase.createAsyncStatement( - "SELECT get_unreversed_host(rev_host) AS host " + + "SELECT url " + "FROM moz_places " + "WHERE rev_host > '.' " + "AND visit_count > 0 " + @@ -54,14 +62,11 @@ const MASTER_PASSWORD_MESSAGE = "User canceled master password entry"; const TEST_EXACT_PERM_TYPES = ["desktop-notification", "geo", "pointerLock"]; /** - * Site object represents a single site, uniquely identified by a host. + * Site object represents a single site, uniquely identified by a principal. */ -function Site(host) { - this.host = host; +function Site(principal) { + this.principal = principal; this.listitem = null; - - this.httpURI = NetUtil.newURI("http://" + this.host); - this.httpsURI = NetUtil.newURI("https://" + this.host); } Site.prototype = { @@ -83,16 +88,10 @@ Site.prototype = { } } - // Try to find favicon for both URIs, but always prefer the https favicon. - gFaviconService.getFaviconURLForPage(this.httpsURI, function(aURI) { + // Get the favicon for the origin + gFaviconService.getFaviconURLForPage(this.principal.URI, function (aURI) { if (aURI) { invokeCallback(aURI); - } else { - gFaviconService.getFaviconURLForPage(this.httpURI, function(aURI) { - if (aURI) { - invokeCallback(aURI); - } - }); } }.bind(this)); }, @@ -104,7 +103,9 @@ Site.prototype = { * A function that takes the visit count (a number) as a parameter. */ getVisitCount: function Site_getVisitCount(aCallback) { - let rev_host = this.host.split("").reverse().join("") + "."; + // XXX This won't be a very reliable system, as it will count both http: and https: visits + // Unfortunately, I don't think that there is a much better way to do it right now. + let rev_host = this.principal.URI.host.split("").reverse().join("") + "."; gVisitStmt.params.rev_host = rev_host; gVisitStmt.executeAsync({ handleResult: function(aResults) { @@ -147,9 +148,9 @@ Site.prototype = { let permissionValue; if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) { - permissionValue = Services.perms.testPermission(this.httpURI, aType); + permissionValue = Services.perms.testPermissionFromPrincipal(this.principal, aType); } else { - permissionValue = Services.perms.testExactPermission(this.httpURI, aType); + permissionValue = Services.perms.testExactPermissionFromPrincipal(this.principal, aType); } aResultObj.value = permissionValue; @@ -187,9 +188,7 @@ Site.prototype = { } } - // Using httpURI is kind of bogus, but the permission manager stores - // the permission for the host, so the right thing happens in the end. - Services.perms.add(this.httpURI, aType, aPerm); + Services.perms.addFromPrincipal(this.principal, aType, aPerm); }, /** @@ -200,7 +199,7 @@ Site.prototype = { * e.g. "cookie", "geo", "indexedDB", "popup", "image" */ clearPermission: function Site_clearPermission(aType) { - Services.perms.remove(this.host, aType); + Services.perms.removeFromPrincipal(this.principal, aType); }, /** @@ -210,11 +209,9 @@ Site.prototype = { */ get logins() { try { - let httpLogins = Services.logins.findLogins( - {}, this.httpURI.prePath, "", ""); - let httpsLogins = Services.logins.findLogins( - {}, this.httpsURI.prePath, "", ""); - return httpLogins.concat(httpsLogins); + let logins = Services.logins.findLogins({}, + this.principal.originNoSuffix, "", ""); + return logins; } catch (e) { if (!e.message.includes(MASTER_PASSWORD_MESSAGE)) { Cu.reportError("AboutPermissions: " + e); @@ -227,8 +224,7 @@ Site.prototype = { // Only say that login saving is blocked if it is blocked for both // http and https. try { - return Services.logins.getLoginSavingEnabled(this.httpURI.prePath) && - Services.logins.getLoginSavingEnabled(this.httpsURI.prePath); + return Services.logins.getLoginSavingEnabled(this.principal.originNoSuffix); } catch (e) { if (!e.message.includes(MASTER_PASSWORD_MESSAGE)) { Cu.reportError("AboutPermissions: " + e); @@ -239,8 +235,7 @@ Site.prototype = { set loginSavingEnabled(isEnabled) { try { - Services.logins.setLoginSavingEnabled(this.httpURI.prePath, isEnabled); - Services.logins.setLoginSavingEnabled(this.httpsURI.prePath, isEnabled); + Services.logins.setLoginSavingEnabled(this.principal.originNoSuffix, isEnabled); } catch (e) { if (!e.message.includes(MASTER_PASSWORD_MESSAGE)) { Cu.reportError("AboutPermissions: " + e); @@ -279,7 +274,11 @@ Site.prototype = { * Removes all data from the browser corresponding to the site. */ forgetSite: function Site_forgetSite() { - ForgetAboutSite.removeDataFromDomain(this.host) + // XXX This removes data for an entire domain, rather than just + // an origin. This may produce confusing results, as data will + // be cleared for the http:// as well as the https:// domain + // if you try to forget the https:// site. + ForgetAboutSite.removeDataFromDomain(this.principal.URI.host) .catch(Cu.reportError); } } @@ -419,31 +418,6 @@ var PermissionDefaults = { Services.prefs.setBoolPref("dom.indexedDB.enabled", value); }, - get fullscreen() { - if (!Services.prefs.getBoolPref("full-screen-api.enabled")) { - return this.DENY; - } - // We always ask for permission to fullscreen with a specific site, - // so there is no global ALLOW. - return this.UNKNOWN; - }, - set fullscreen(aValue) { - let value = (aValue != this.DENY); - Services.prefs.setBoolPref("full-screen-api.enabled", value); - }, - - get pointerLock() { - if (!Services.prefs.getBoolPref("full-screen-api.pointer-lock.enabled")) { - return this.DENY; - } - // We always ask for permission to hide the mouse pointer - // with a specific site, so there is no global ALLOW. - return this.UNKNOWN; - }, - set pointerLock(aValue) { - let value = (aValue != this.DENY); - Services.prefs.setBoolPref("full-screen-api.pointer-lock.enabled", value); - }, } /** @@ -461,10 +435,18 @@ var AboutPermissions = { LIST_BUILD_DELAY: 100, // delay between intervals /** - * Stores a mapping of host strings to Site objects. + * Stores a mapping of origin strings to Site objects. */ _sites: {}, + /** + * Using a getter for sitesFilter to avoid races with tests. + */ + get sitesFilter () { + delete this.sitesFilter; + return this.sitesFilter = document.getElementById("sites-filter"); + }, + sitesList: null, _selectedSite: null, @@ -482,14 +464,12 @@ var AboutPermissions = { * Potential future additions: "sts/use", "sts/subd" */ _supportedPermissions: ["password", "image", "popup", "cookie", - "desktop-notification", "install", "geo", "indexedDB", - "fullscreen", "pointerLock"], + "desktop-notification", "install", "geo", "indexedDB"], /** * Permissions that don't have a global "Allow" option. */ - _noGlobalAllow: ["desktop-notification", "geo", "indexedDB", "fullscreen", - "pointerLock"], + _noGlobalAllow: ["desktop-notification", "geo", "indexedDB"], /** * Permissions that don't have a global "Deny" option. @@ -536,8 +516,6 @@ var AboutPermissions = { Services.prefs.addObserver("geo.enabled", this, false); Services.prefs.addObserver("dom.indexedDB.enabled", this, false); Services.prefs.addObserver("plugins.click_to_play", this, false); - Services.prefs.addObserver("full-screen-api.enabled", this, false); - Services.prefs.addObserver("full-screen-api.pointer-lock.enabled", this, false); Services.prefs.addObserver("permissions.places-sites-limit", this, false); Services.obs.addObserver(this, "perm-changed", false); @@ -688,8 +666,6 @@ var AboutPermissions = { Services.prefs.removeObserver("geo.enabled", this, false); Services.prefs.removeObserver("dom.indexedDB.enabled", this, false); Services.prefs.removeObserver("plugins.click_to_play", this, false); - Services.prefs.removeObserver("full-screen-api.enabled", this, false); - Services.prefs.removeObserver("full-screen-api.pointer-lock.enabled", this, false); Services.prefs.removeObserver("permissions.places-sites-limit", this, false); Services.obs.removeObserver(this, "perm-changed"); @@ -721,9 +697,9 @@ var AboutPermissions = { break; } let permission = aSubject.QueryInterface(Ci.nsIPermission); - // We can't compare selectedSite.host and permission.host here because - // we need to handle the case where a parent domain was changed in - // a way that affects the subdomain. + // We can't compare selectedSite.principal and permission.principal here + // because we need to handle the case where a parent domain was changed + // in a way that affects the subdomain. if (this._supportedPermissions.indexOf(permission.type) != -1) { this.updatePermission(permission.type); } @@ -798,8 +774,11 @@ var AboutPermissions = { AboutPermissions.startSitesListBatch(); let row; while (row = aResults.getNextRow()) { - let host = row.getResultByName("host"); - AboutPermissions.addHost(host); + let spec = row.getResultByName("url"); + let uri = NetUtil.newURI(spec); + let principal = gSecMan.getNoAppCodebasePrincipal(uri); + + AboutPermissions.addPrincipal(principal); } AboutPermissions.endSitesListBatch(); }, @@ -853,7 +832,8 @@ var AboutPermissions = { // i.e.: "chrome://weave" (Sync) if (!aLogin.hostname.startsWith(schemeChrome + ":")) { let uri = NetUtil.newURI(aLogin.hostname); - this.addHost(uri.host); + let principal = gSecMan.getNoAppCodebasePrincipal(uri); + this.addPrincipal(principal); } } catch (e) { Cu.reportError("AboutPermissions: " + e); @@ -869,7 +849,8 @@ var AboutPermissions = { // i.e.: "chrome://weave" (Sync) if (!aHostname.startsWith(schemeChrome + ":")) { let uri = NetUtil.newURI(aHostname); - this.addHost(uri.host); + let principal = gSecMan.getNoAppCodebasePrincipal(uri); + this.addPrincipal(principal); } } catch (e) { Cu.reportError("AboutPermissions: " + e); @@ -887,7 +868,7 @@ var AboutPermissions = { let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission); // Only include sites with exceptions set for supported permission types. if (this._supportedPermissions.indexOf(permission.type) != -1) { - this.addHost(permission.host); + this.addPrincipal(permission.principal); } itemCnt++; } @@ -898,15 +879,15 @@ var AboutPermissions = { /** * Creates a new Site and adds it to _sites if it's not already there. * - * @param aHost - * A host string. + * @param aPrincipal + * A principal. */ - addHost: function(aHost) { - if (aHost in this._sites) { + addPrincipal: function(aPrincipal) { + if (aPrincipal.origin in this._sites) { return; } - let site = new Site(aHost); - this._sites[aHost] = site; + let site = new Site(aPrincipal); + this._sites[aPrincipal.origin] = site; this.addToSitesList(site); }, @@ -919,7 +900,7 @@ var AboutPermissions = { addToSitesList: function(aSite) { let item = document.createElement("richlistitem"); item.setAttribute("class", "site"); - item.setAttribute("value", aSite.host); + item.setAttribute("value", aSite.principal.origin); aSite.getFavicon(function(aURL) { item.setAttribute("favicon", aURL); @@ -927,9 +908,8 @@ var AboutPermissions = { aSite.listitem = item; // Make sure to only display relevant items when list is filtered. - let filterValue = - document.getElementById("sites-filter").value.toLowerCase(); - item.collapsed = aSite.host.toLowerCase().indexOf(filterValue) == -1; + let filterValue = this.sitesFilter.value.toLowerCase(); + item.collapsed = aSite.principal.origin.toLowerCase().indexOf(filterValue) == -1; (this._listFragment || this.sitesList).appendChild(item); }, @@ -951,8 +931,7 @@ var AboutPermissions = { */ filterSitesList: function() { let siteItems = this.sitesList.children; - let filterValue = - document.getElementById("sites-filter").value.toLowerCase(); + let filterValue = this.sitesFilter.value.toLowerCase(); if (filterValue == "") { for (let i = 0, iLen = siteItems.length; i < iLen; i++) { @@ -983,9 +962,9 @@ var AboutPermissions = { * The host string corresponding to the site to delete. */ deleteFromSitesList: function(aHost) { - for (let host in this._sites) { - let site = this._sites[host]; - if (site.host.hasRootDomain(aHost)) { + for (let origin in this._sites) { + let site = this._sites[origin]; + if (site.principal.URI.host.hasRootDomain(aHost)) { if (site == this._selectedSite) { // Replace site-specific interface with "All Sites" interface. this.sitesList.selectedItem = @@ -993,7 +972,7 @@ var AboutPermissions = { } this.sitesList.removeChild(site.listitem); - delete this._sites[site.host]; + delete this._sites[site.principal.origin]; } } }, @@ -1009,9 +988,9 @@ var AboutPermissions = { return; } - let host = event.target.value; - let site = this._selectedSite = this._sites[host]; - document.getElementById("site-label").value = host; + let origin = event.target.value; + let site = this._selectedSite = this._sites[origin]; + document.getElementById("site-label").value = origin; document.getElementById("header-deck").selectedPanel = document.getElementById("site-header"); @@ -1245,19 +1224,19 @@ var AboutPermissions = { * Opens password manager dialog. */ managePasswords: function() { - let selectedHost = ""; + let selectedOrigin = ""; if (this._selectedSite) { - selectedHost = this._selectedSite.host; + selectedOrigin = this._selectedSite.principal.URI.prePath; } let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager"); if (win) { - win.setFilter(selectedHost); + win.setFilter(selectedOrigin); win.focus(); } else { window.openDialog("chrome://passwordmgr/content/passwordManager.xul", "Toolkit:PasswordManager", "", - {filterString : selectedHost}); + {filterString : selectedOrigin}); } }, @@ -1313,10 +1292,12 @@ var AboutPermissions = { * Opens cookie manager dialog. */ manageCookies: function() { + // Cookies are stored by-host, and thus we filter the cookie window + // using only the host of the selected principal's origin let selectedHost = ""; let selectedDomain = ""; if (this._selectedSite) { - selectedHost = this._selectedSite.host; + selectedHost = this._selectedSite.principal.URI.host; selectedDomain = this.domainFromHost(selectedHost); } @@ -1328,6 +1309,13 @@ var AboutPermissions = { window.openDialog("chrome://browser/content/preferences/cookies.xul", "Browser:Cookies", "", {filterString : selectedDomain}); } + }, + + /** + * Focusses the filter box. + */ + focusFilterBox: function() { + this.sitesFilter.focus(); } } diff --git a/application/palemoon/components/preferences/aboutPermissions.xul b/application/palemoon/components/preferences/aboutPermissions.xul index bd5a205c7..56d6cfbbf 100644 --- a/application/palemoon/components/preferences/aboutPermissions.xul +++ b/application/palemoon/components/preferences/aboutPermissions.xul @@ -25,6 +25,10 @@ <script type="application/javascript" src="chrome://browser/content/preferences/aboutPermissions.js"/> + <keyset> + <key key="&focusSearch.key;" modifiers="accel" oncommand="AboutPermissions.focusFilterBox();"/> + </keyset> + <hbox flex="1" id="permissions-header"> <label id="permissions-pagetitle">&permissionsManager.title;</label> </hbox> @@ -332,65 +336,6 @@ <vbox id="plugins-box"/> </vbox> </hbox> - - <!-- Fullscreen --> - <hbox id="fullscreen-pref-item" - class="pref-item" align="top"> - <image class="pref-icon" type="fullscreen"/> - <vbox> - <hbox> - <label class="pref-title" value="&fullscreen.label;"/> - <label id="fullscreen-default" class="pref-default" value="*"/> - </hbox> - <hbox align="center"> - <menulist id="fullscreen-menulist" - class="pref-menulist" - type="fullscreen" - oncommand="AboutPermissions.onPermissionCommand(event, false);"> - <menupopup> - <menuitem id="fullscreen-0" value="0" label="&permission.alwaysAsk;"/> - <menuitem id="fullscreen-1" value="1" label="&permission.allow;"/> - <menuitem id="fullscreen-2" value="2" label="&permission.block;"/> - </menupopup> - </menulist> - <button id="fullscreen-set-default" - class="pref-set-default" - label="&permission.default;" - type="fullscreen" - oncommand="AboutPermissions.onPermissionCommand(event, true);"/> - </hbox> - </vbox> - </hbox> - - <!-- PointerLock --> - <hbox id="pointerLock-pref-item" - class="pref-item" align="top"> - <image class="pref-icon" type="pointerLock"/> - <vbox> - <hbox> - <label class="pref-title" value="&pointerLock.label;"/> - <label id="pointerLock-default" class="pref-default" value="*"/> - </hbox> - <hbox> - <menulist id="pointerLock-menulist" - class="pref-menulist" - type="pointerLock" - oncommand="AboutPermissions.onPermissionCommand(event, false);"> - <menupopup> - <menuitem id="pointerLock-0" value="0" label="&permission.alwaysAsk;"/> - <menuitem id="pointerLock-1" value="1" label="&permission.allow;"/> - <menuitem id="pointerLock-2" value="2" label="&permission.block;"/> - </menupopup> - </menulist> - <button id="pointerLock-set-default" - class="pref-set-default" - label="&permission.default;" - type="pointerLock" - oncommand="AboutPermissions.onPermissionCommand(event, true);"/> - </hbox> - </vbox> - </hbox> - </vbox> </hbox> diff --git a/application/palemoon/components/preferences/advanced.js b/application/palemoon/components/preferences/advanced.js index 429a0c419..0803496fe 100644 --- a/application/palemoon/components/preferences/advanced.js +++ b/application/palemoon/components/preferences/advanced.js @@ -8,6 +8,7 @@ Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); Components.utils.import("resource://gre/modules/ctypes.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/LoadContextInfo.jsm"); +Components.utils.import("resource://gre/modules/BrowserUtils.jsm"); var gAdvancedPane = { _inited: false, @@ -377,7 +378,7 @@ var gAdvancedPane = { }, // XXX: duplicated in browser.js - _getOfflineAppUsage: function (host, groups) + _getOfflineAppUsage: function (perm, groups) { var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"]. getService(Components.interfaces.nsIApplicationCacheService); @@ -390,7 +391,7 @@ var gAdvancedPane = { var usage = 0; for (var i = 0; i < groups.length; i++) { var uri = ios.newURI(groups[i], null, null); - if (uri.asciiHost == host) { + if (perm.matchesURI(uri, true)) { var cache = cacheService.getActiveCache(groups[i]); usage += cache.usage; } @@ -427,9 +428,9 @@ var gAdvancedPane = { var row = document.createElement("listitem"); row.id = ""; row.className = "offlineapp"; - row.setAttribute("host", perm.host); + row.setAttribute("origin", perm.principal.origin); var converted = DownloadUtils. - convertByteUnits(this._getOfflineAppUsage(perm.host, groups)); + convertByteUnits(this._getOfflineAppUsage(perm, groups)); row.setAttribute("usage", bundle.getFormattedString("offlineAppUsage", converted)); @@ -453,7 +454,8 @@ var gAdvancedPane = { { var list = document.getElementById("offlineAppsList"); var item = list.selectedItem; - var host = item.getAttribute("host"); + var origin = item.getAttribute("origin"); + var principal = BrowserUtils.principalFromOrigin(origin); var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService); @@ -462,35 +464,34 @@ var gAdvancedPane = { var bundle = document.getElementById("bundlePreferences"); var title = bundle.getString("offlineAppRemoveTitle"); - var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]); + var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [principal.URI.prePath]); var confirm = bundle.getString("offlineAppRemoveConfirm"); var result = prompts.confirmEx(window, title, prompt, flags, confirm, null, null, null, {}); if (result != 0) return; - // clear offline cache entries - var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"]. - getService(Components.interfaces.nsIApplicationCacheService); - var ios = Components.classes["@mozilla.org/network/io-service;1"]. - getService(Components.interfaces.nsIIOService); - var groups = cacheService.getGroups(); - for (var i = 0; i < groups.length; i++) { - var uri = ios.newURI(groups[i], null, null); - if (uri.asciiHost == host) { + // get the permission + var pm = Components.classes["@mozilla.org/permissionmanager;1"] + .getService(Components.interfaces.nsIPermissionManager); + var perm = pm.getPermissionObject(principal, "offline-app"); + if (perm) { + // clear offline cache entries + try { + var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"]. + getService(Components.interfaces.nsIApplicationCacheService); + var groups = cacheService.getGroups(); + for (var i = 0; i < groups.length; i++) { + var uri = Services.io.newURI(groups[i], null, null); + if (perm.matchesURI(uri, true)) { var cache = cacheService.getActiveCache(groups[i]); cache.discard(); + } } - } - - // remove the permission - var pm = Components.classes["@mozilla.org/permissionmanager;1"] - .getService(Components.interfaces.nsIPermissionManager); - pm.remove(host, "offline-app", - Components.interfaces.nsIPermissionManager.ALLOW_ACTION); - pm.remove(host, "offline-app", - Components.interfaces.nsIOfflineCacheUpdateService.ALLOW_NO_WARN); + } catch (e) {} + pm.removePermission(perm); + } list.removeChild(item); gAdvancedPane.offlineAppSelected(); this.updateActualAppCacheSize(); diff --git a/application/palemoon/components/preferences/content.js b/application/palemoon/components/preferences/content.js index 0775c6270..5ae84c2f7 100644 --- a/application/palemoon/components/preferences/content.js +++ b/application/palemoon/components/preferences/content.js @@ -38,33 +38,11 @@ var gContentPane = { */ updateMSE: function () { - var checkboxMSENFR = document.getElementById('videoMSENFR'); var checkboxMSEMP4 = document.getElementById('videoMSEMP4'); var checkboxMSEWebM = document.getElementById('videoMSEWebM'); var preference = document.getElementById('media.mediasource.enabled'); - checkboxMSENFR.disabled = preference.value != true; checkboxMSEMP4.disabled = preference.value != true; checkboxMSEWebM.disabled = preference.value != true; - // Check and disable WebM if necessary - if (preference.value == true) { - this.updateMSEWebM(); - } - }, - - /** - * Utility function to enable/disable the checkbox for MSE+WebM depending - * on the value of media.mediasource.format-reader. - */ - updateMSEWebM: function () - { - var checkboxMSEWebM = document.getElementById('videoMSEWebM'); - var preference = document.getElementById('media.mediasource.format-reader'); - checkboxMSEWebM.disabled = preference.value == true; - if (preference.value == true) { - // Switch off incompatible format - Services.prefs.setBoolPref('media.mediasource.webm.enabled', false); - checkboxMSEWebM.checked = false; - } }, // BEGIN UI CODE diff --git a/application/palemoon/components/preferences/content.xul b/application/palemoon/components/preferences/content.xul index 22b6ce229..23d942e45 100644 --- a/application/palemoon/components/preferences/content.xul +++ b/application/palemoon/components/preferences/content.xul @@ -33,10 +33,7 @@ onchange="gContentPane._rebuildFonts();"/> <!-- VIDEO --> - <preference id="media.mediasource.enabled" name="media.mediasource.enabled" type="bool" - onchange="gContentPane.updateMSE();" /> - <preference id="media.mediasource.format-reader" name="media.mediasource.format-reader" type="bool" - onchange="gContentPane.updateMSEWebM();" /> + <preference id="media.mediasource.enabled" name="media.mediasource.enabled" type="bool"/> <preference id="media.mediasource.mp4.enabled" name="media.mediasource.mp4.enabled" type="bool"/> <preference id="media.mediasource.webm.enabled" name="media.mediasource.webm.enabled" type="bool"/> @@ -163,8 +160,6 @@ <checkbox id="videoMSE" preference="media.mediasource.enabled" label="&videoMSE.label;" accesskey="&videoMSE.accesskey;" onsyncfrompreference="gContentPane.updateMSE();"/> - <checkbox class="indent" id="videoMSENFR" preference="media.mediasource.format-reader" - label="&videoMSENFR.label;" accesskey="&videoMSENFR.accesskey;"/> <checkbox class="indent" id="videoMSEMP4" preference="media.mediasource.mp4.enabled" label="&videoMSEMP4.label;" accesskey="&videoMSEMP4.accesskey;"/> <checkbox class="indent" id="videoMSEWebM" preference="media.mediasource.webm.enabled" diff --git a/application/palemoon/components/preferences/cookies.js b/application/palemoon/components/preferences/cookies.js index 543aeb186..4ef30d48e 100644 --- a/application/palemoon/components/preferences/cookies.js +++ b/application/palemoon/components/preferences/cookies.js @@ -732,8 +732,13 @@ var gCookiesWindow = { }, onCookieKeyPress: function (aEvent) { - if (aEvent.keyCode == 46) + if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE +#ifdef XP_MACOSX + || aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE +#endif + ) { this.deleteCookie(); + } }, _lastSortProperty : "", diff --git a/application/palemoon/components/preferences/handlers.xml b/application/palemoon/components/preferences/handlers.xml index d60792803..5fb915cee 100644 --- a/application/palemoon/components/preferences/handlers.xml +++ b/application/palemoon/components/preferences/handlers.xml @@ -72,7 +72,7 @@ extends="chrome://global/content/bindings/listbox.xml#listitem"> <content> <children> - <xul:listcell xbl:inherits="label=host"/> + <xul:listcell xbl:inherits="label=origin"/> <xul:listcell xbl:inherits="label=usage"/> </children> </content> diff --git a/application/palemoon/components/preferences/jar.mn b/application/palemoon/components/preferences/jar.mn index a27784305..798a2dae4 100644 --- a/application/palemoon/components/preferences/jar.mn +++ b/application/palemoon/components/preferences/jar.mn @@ -15,7 +15,7 @@ browser.jar: * content/browser/preferences/applicationManager.js * content/browser/preferences/colors.xul * content/browser/preferences/cookies.xul - content/browser/preferences/cookies.js +* content/browser/preferences/cookies.js content/browser/preferences/content.xul content/browser/preferences/content.js * content/browser/preferences/connection.xul @@ -28,8 +28,8 @@ browser.jar: content/browser/preferences/languages.js * content/browser/preferences/main.xul content/browser/preferences/main.js -* content/browser/preferences/permissions.xul - content/browser/preferences/permissions.js + content/browser/preferences/permissions.xul +* content/browser/preferences/permissions.js * content/browser/preferences/preferences.xul content/browser/preferences/privacy.xul content/browser/preferences/privacy.js diff --git a/application/palemoon/components/preferences/permissions.js b/application/palemoon/components/preferences/permissions.js index 785e26d5e..4b1bf41b2 100644 --- a/application/palemoon/components/preferences/permissions.js +++ b/application/palemoon/components/preferences/permissions.js @@ -3,38 +3,40 @@ * 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/. */ +Components.utils.import("resource://gre/modules/Services.jsm"); + const nsIPermissionManager = Components.interfaces.nsIPermissionManager; const nsICookiePermission = Components.interfaces.nsICookiePermission; const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions"; -function Permission(host, rawHost, type, capability, perm) +function Permission(principal, type, capability) { - this.host = host; - this.rawHost = rawHost; + this.principal = principal; + this.origin = principal.origin; this.type = type; this.capability = capability; - this.perm = perm; } var gPermissionManager = { - _type : "", - _permissions : [], - _pm : Components.classes["@mozilla.org/permissionmanager;1"] - .getService(Components.interfaces.nsIPermissionManager), - _bundle : null, - _tree : null, - + _type : "", + _permissions : [], + _permissionsToAdd : new Map(), + _permissionsToDelete : new Map(), + _bundle : null, + _tree : null, + _observerRemoved : false, + _view: { _rowCount: 0, - get rowCount() - { - return this._rowCount; + get rowCount() + { + return this._rowCount; }, getCellText: function (aRow, aColumn) { if (aColumn.id == "siteCol") - return gPermissionManager._permissions[aRow].rawHost; + return gPermissionManager._permissions[aRow].origin; else if (aColumn.id == "statusCol") return gPermissionManager._permissions[aRow].capability; return ""; @@ -57,7 +59,7 @@ var gPermissionManager = { return ""; } }, - + _getCapabilityString: function (aCapability) { var stringKey = null; @@ -77,44 +79,66 @@ var gPermissionManager = { } return this._bundle.getString(stringKey); }, - + addPermission: function (aCapability) { var textbox = document.getElementById("url"); - var host = textbox.value.replace(/^\s*([-\w]*:\/+)?/, ""); // trim any leading space and scheme + var input_url = textbox.value.replace(/^\s*/, ""); // trim any leading space + let principal; try { - var ioService = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - var uri = ioService.newURI("http://"+host, null, null); - host = uri.host; + // The origin accessor on the principal object will throw if the + // principal doesn't have a canonical origin representation. This will + // help catch cases where the URI parser parsed something like + // `localhost:8080` as having the scheme `localhost`, rather than being + // an invalid URI. A canonical origin representation is required by the + // permission manager for storage, so this won't prevent any valid + // permissions from being entered by the user. + let uri; + try { + uri = Services.io.newURI(input_url, null, null); + principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri); + // If we have ended up with an unknown scheme, the following will throw. + principal.origin; + } catch(ex) { + uri = Services.io.newURI("http://" + input_url, null, null); + principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri); + // If we have ended up with an unknown scheme, the following will throw. + principal.origin; + } } catch(ex) { - var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Components.interfaces.nsIPromptService); var message = this._bundle.getString("invalidURI"); var title = this._bundle.getString("invalidURITitle"); - promptService.alert(window, title, message); + Services.prompt.alert(window, title, message); return; } var capabilityString = this._getCapabilityString(aCapability); // check whether the permission already exists, if not, add it - var exists = false; + let permissionExists = false; + let capabilityExists = false; for (var i = 0; i < this._permissions.length; ++i) { - if (this._permissions[i].rawHost == host) { - // Avoid calling the permission manager if the capability settings are - // the same. Otherwise allow the call to the permissions manager to - // update the listbox for us. - exists = this._permissions[i].perm == aCapability; + if (this._permissions[i].principal.equals(principal)) { + permissionExists = true; + capabilityExists = this._permissions[i].capability == capabilityString; + if (!capabilityExists) { + this._permissions[i].capability = capabilityString; + } break; } } - if (!exists) { - host = (host.charAt(0) == ".") ? host.substring(1,host.length) : host; - var uri = ioService.newURI("http://" + host, null, null); - this._pm.add(uri, this._type, aCapability); + + let permissionParams = {principal: principal, type: this._type, capability: aCapability}; + if (!permissionExists) { + this._permissionsToAdd.set(principal.origin, permissionParams); + this._addPermission(permissionParams); + } + else if (!capabilityExists) { + this._permissionsToAdd.set(principal.origin, permissionParams); + this._handleCapabilityChange(); } + textbox.value = ""; textbox.focus(); @@ -124,14 +148,58 @@ var gPermissionManager = { // enable "remove all" button as needed document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0; }, - + + _removePermission: function(aPermission) + { + this._removePermissionFromList(aPermission.principal); + + // If this permission was added during this session, let's remove + // it from the pending adds list to prevent calls to the + // permission manager. + let isNewPermission = this._permissionsToAdd.delete(aPermission.principal.origin); + + if (!isNewPermission) { + this._permissionsToDelete.set(aPermission.principal.origin, aPermission); + } + + }, + + _handleCapabilityChange: function () + { + // Re-do the sort, if the status changed from Block to Allow + // or vice versa, since if we're sorted on status, we may no + // longer be in order. + if (this._lastPermissionSortColumn == "statusCol") { + this._resortPermissions(); + } + this._tree.treeBoxObject.invalidate(); + }, + + _addPermission: function(aPermission) + { + this._addPermissionToList(aPermission); + ++this._view._rowCount; + this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, 1); + // Re-do the sort, since we inserted this new item at the end. + this._resortPermissions(); + }, + + _resortPermissions: function() + { + gTreeUtils.sort(this._tree, this._view, this._permissions, + this._lastPermissionSortColumn, + this._permissionsComparator, + this._lastPermissionSortColumn, + !this._lastPermissionSortAscending); // keep sort direction + }, + onHostInput: function (aSiteField) { document.getElementById("btnSession").disabled = !aSiteField.value; document.getElementById("btnBlock").disabled = !aSiteField.value; document.getElementById("btnAllow").disabled = !aSiteField.value; }, - + onWindowKeyPress: function (aEvent) { if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) @@ -143,14 +211,14 @@ var gPermissionManager = { if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN) document.getElementById("btnAllow").click(); }, - + onLoad: function () { this._bundle = document.getElementById("bundlePreferences"); var params = window.arguments[0]; this.init(params); }, - + init: function (aParams) { if (this._type) { @@ -160,14 +228,14 @@ var gPermissionManager = { this._type = aParams.permissionType; this._manageCapability = aParams.manageCapability; - + var permissionsText = document.getElementById("permissionsText"); while (permissionsText.hasChildNodes()) permissionsText.removeChild(permissionsText.firstChild); permissionsText.appendChild(document.createTextNode(aParams.introText)); document.title = aParams.windowTitle; - + document.getElementById("btnBlock").hidden = !aParams.blockVisible; document.getElementById("btnSession").hidden = !aParams.sessionVisible; document.getElementById("btnAllow").hidden = !aParams.allowVisible; @@ -183,64 +251,64 @@ var gPermissionManager = { var urlLabel = document.getElementById("urlLabel"); urlLabel.hidden = !urlFieldVisible; - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.notifyObservers(null, NOTIFICATION_FLUSH_PERMISSIONS, this._type); - os.addObserver(this, "perm-changed", false); + let treecols = document.getElementsByTagName("treecols")[0]; + treecols.addEventListener("click", event => { + if (event.target.nodeName != "treecol" || event.button != 0) { + return; + } + + let sortField = event.target.getAttribute("data-field-name"); + if (!sortField) { + return; + } + + gPermissionManager.onPermissionSort(sortField); + }); + + Services.obs.notifyObservers(null, NOTIFICATION_FLUSH_PERMISSIONS, this._type); + Services.obs.addObserver(this, "perm-changed", false); this._loadPermissions(); - + urlField.focus(); }, - + uninit: function () { - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.removeObserver(this, "perm-changed"); + if (!this._observerRemoved) { + Services.obs.removeObserver(this, "perm-changed"); + + this._observerRemoved = true; + } }, - + observe: function (aSubject, aTopic, aData) { if (aTopic == "perm-changed") { var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); + + // Ignore unrelated permission types. + if (permission.type != this._type) + return; + if (aData == "added") { - this._addPermissionToList(permission); - ++this._view._rowCount; - this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, 1); - // Re-do the sort, since we inserted this new item at the end. - gTreeUtils.sort(this._tree, this._view, this._permissions, - this._lastPermissionSortColumn, - this._permissionsComparator, - this._lastPermissionSortColumn, - !this._lastPermissionSortAscending); // keep sort direction + this._addPermission(permission); } else if (aData == "changed") { for (var i = 0; i < this._permissions.length; ++i) { - if (this._permissions[i].host == permission.host) { + if (permission.matches(this._permissions[i].principal, true)) { this._permissions[i].capability = this._getCapabilityString(permission.capability); break; } } - // Re-do the sort, if the status changed from Block to Allow - // or vice versa, since if we're sorted on status, we may no - // longer be in order. - if (this._lastPermissionSortColumn == "statusCol") { - gTreeUtils.sort(this._tree, this._view, this._permissions, - this._lastPermissionSortColumn, - this._permissionsComparator, - this._lastPermissionSortColumn, - !this._lastPermissionSortAscending); // keep sort direction - } - this._tree.treeBoxObject.invalidate(); + this._handleCapabilityChange(); + } + else if (aData == "deleted") { + this._removePermissionFromList(permission.principal); } - // No UI other than this window causes this method to be sent a "deleted" - // notification, so we don't need to implement it since Delete is handled - // directly by the Permission Removal handlers. If that ever changes, those - // implementations will have to move into here. } }, - + onPermissionSelected: function () { var hasSelection = this._tree.view.selection.count > 0; @@ -257,8 +325,8 @@ var gPermissionManager = { gTreeUtils.deleteSelectedItems(this._tree, this._view, this._permissions, removedPermissions); for (var i = 0; i < removedPermissions.length; ++i) { var p = removedPermissions[i]; - this._pm.remove(p.host, p.type); - } + this._removePermission(p); + } document.getElementById("removePermission").disabled = !this._permissions.length; document.getElementById("removeAllPermissions").disabled = !this._permissions.length; }, @@ -271,18 +339,23 @@ var gPermissionManager = { gTreeUtils.deleteAll(this._tree, this._view, this._permissions, removedPermissions); for (var i = 0; i < removedPermissions.length; ++i) { var p = removedPermissions[i]; - this._pm.remove(p.host, p.type); - } + this._removePermission(p); + } document.getElementById("removePermission").disabled = true; document.getElementById("removeAllPermissions").disabled = true; }, - + onPermissionKeyPress: function (aEvent) { - if (aEvent.keyCode == 46) + if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE +#ifdef XP_MACOSX + || aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE +#endif + ) { this.onPermissionDeleted(); + } }, - + _lastPermissionSortColumn: "", _lastPermissionSortAscending: false, _permissionsComparator : function (a, b) @@ -293,16 +366,34 @@ var gPermissionManager = { onPermissionSort: function (aColumn) { - this._lastPermissionSortAscending = gTreeUtils.sort(this._tree, - this._view, + this._lastPermissionSortAscending = gTreeUtils.sort(this._tree, + this._view, this._permissions, aColumn, this._permissionsComparator, - this._lastPermissionSortColumn, + this._lastPermissionSortColumn, this._lastPermissionSortAscending); this._lastPermissionSortColumn = aColumn; }, - + + onApplyChanges: function() + { + // Stop observing permission changes since we are about + // to write out the pending adds/deletes and don't need + // to update the UI + this.uninit(); + + for (let permissionParams of this._permissionsToAdd.values()) { + Services.perms.addFromPrincipal(permissionParams.principal, permissionParams.type, permissionParams.capability); + } + + for (let p of this._permissionsToDelete.values()) { + Services.perms.removeFromPrincipal(p.principal, p.type); + } + + window.close(); + }, + _loadPermissions: function () { this._tree = document.getElementById("permissionsTree"); @@ -310,48 +401,59 @@ var gPermissionManager = { // load permissions into a table var count = 0; - var enumerator = this._pm.enumerator; + var enumerator = Services.perms.enumerator; while (enumerator.hasMoreElements()) { var nextPermission = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission); this._addPermissionToList(nextPermission); } - + this._view._rowCount = this._permissions.length; // sort and display the table this._tree.view = this._view; - this.onPermissionSort("rawHost"); + this.onPermissionSort("origin"); // disable "remove all" button if there are none document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0; }, - + _addPermissionToList: function (aPermission) { if (aPermission.type == this._type && (!this._manageCapability || (aPermission.capability == this._manageCapability))) { - var host = aPermission.host; + var principal = aPermission.principal; var capabilityString = this._getCapabilityString(aPermission.capability); - var p = new Permission(host, - (host.charAt(0) == ".") ? host.substring(1,host.length) : host, + var p = new Permission(principal, aPermission.type, - capabilityString, - aPermission.capability); + capabilityString); this._permissions.push(p); - } + } }, - - setHost: function (aHost) + + _removePermissionFromList: function (aPrincipal) + { + for (let i = 0; i < this._permissions.length; ++i) { + if (this._permissions[i].principal.equals(aPrincipal)) { + this._permissions.splice(i, 1); + this._view._rowCount--; + this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, -1); + this._tree.treeBoxObject.invalidate(); + break; + } + } + }, + + setOrigin: function (aOrigin) { - document.getElementById("url").value = aHost; + document.getElementById("url").value = aOrigin; } }; -function setHost(aHost) +function setOrigin(aOrigin) { - gPermissionManager.setHost(aHost); + gPermissionManager.setOrigin(aOrigin); } function initWithParams(aParams) diff --git a/application/palemoon/components/preferences/permissions.xul b/application/palemoon/components/preferences/permissions.xul index fd550e8f7..33806cc27 100644 --- a/application/palemoon/components/preferences/permissions.xul +++ b/application/palemoon/components/preferences/permissions.xul @@ -1,12 +1,12 @@ <?xml version="1.0"?> -# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -# 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/. +<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- --> +<!-- 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/. --> -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?> <!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/permissions.dtd" > @@ -35,7 +35,7 @@ <separator class="thin"/> <label id="urlLabel" control="url" value="&address.label;" accesskey="&address.accesskey;"/> <hbox align="start"> - <textbox id="url" flex="1" + <textbox id="url" flex="1" oninput="gPermissionManager.onHostInput(event.target);" onkeypress="gPermissionManager.onHostKeyPress(event);"/> </hbox> @@ -54,30 +54,32 @@ onselect="gPermissionManager.onPermissionSelected();"> <treecols> <treecol id="siteCol" label="&treehead.sitename.label;" flex="3" - onclick="gPermissionManager.onPermissionSort('rawHost');" persist="width"/> + data-field-name="origin" persist="width"/> <splitter class="tree-splitter"/> <treecol id="statusCol" label="&treehead.status.label;" flex="1" - onclick="gPermissionManager.onPermissionSort('capability');" persist="width"/> + data-field-name="capability" persist="width"/> </treecols> <treechildren/> </tree> </vbox> - <hbox align="end"> - <hbox class="actionButtons" flex="1"> + <vbox> + <hbox class="actionButtons" align="left" flex="1"> <button id="removePermission" disabled="true" accesskey="&removepermission.accesskey;" icon="remove" label="&removepermission.label;" oncommand="gPermissionManager.onPermissionDeleted();"/> <button id="removeAllPermissions" icon="clear" label="&removeallpermissions.label;" - accesskey="&removeallpermissions.accesskey;" + accesskey="&removeallpermissions.accesskey;" oncommand="gPermissionManager.onAllPermissionsDeleted();"/> - <spacer flex="1"/> -#ifndef XP_MACOSX + </hbox> + <spacer flex="1"/> + <hbox class="actionButtons" align="right" flex="1"> <button oncommand="close();" icon="close" - label="&button.close.label;" accesskey="&button.close.accesskey;"/> -#endif + label="&button.cancel.label;" accesskey="&button.cancel.accesskey;" /> + <button id="btnApplyChanges" oncommand="gPermissionManager.onApplyChanges();" icon="save" + label="&button.ok.label;" accesskey="&button.ok.accesskey;"/> </hbox> <resizer type="window" dir="bottomend"/> - </hbox> + </vbox> </window> diff --git a/application/palemoon/components/preferences/security.js b/application/palemoon/components/preferences/security.js index 56664bf66..9d5f302a2 100644 --- a/application/palemoon/components/preferences/security.js +++ b/application/palemoon/components/preferences/security.js @@ -131,9 +131,21 @@ var gSecurityPane = { */ showPasswordExceptions: function () { + let bundlePrefs = document.getElementById("bundlePreferences"); + let params = { + blockVisible: true, + sessionVisible: false, + allowVisible: false, + hideStatusColumn: true, + prefilledHost: "", + permissionType: "login-saving", + windowTitle: bundlePrefs.getString("savedLoginsExceptions_title"), + introText: bundlePrefs.getString("savedLoginsExceptions_desc") + }; + document.documentElement.openWindow("Toolkit:PasswordManagerExceptions", - "chrome://passwordmgr/content/passwordManagerExceptions.xul", - "", null); + "chrome://browser/content/preferences/permissions.xul", + null, params); }, /** diff --git a/application/palemoon/components/sessionstore/SessionStore.jsm b/application/palemoon/components/sessionstore/SessionStore.jsm index f7c495be8..4f95f10a7 100644 --- a/application/palemoon/components/sessionstore/SessionStore.jsm +++ b/application/palemoon/components/sessionstore/SessionStore.jsm @@ -1951,7 +1951,13 @@ var SessionStoreInternal = { // userTypedValue. if (browser.userTypedValue) { tabData.userTypedValue = browser.userTypedValue; - tabData.userTypedClear = browser.userTypedClear; + // We always used to keep track of the loading state as an integer, where + // '0' indicated the user had typed since the last load (or no load was + // ongoing), and any positive value indicated we had started a load since + // the last time the user typed in the URL bar. Mimic this to keep the + // session store representation in sync, even though we now represent this + // more explicitly: + tabData.userTypedClear = browser.didStartLoadSinceLastUserTyping() ? 1 : 0; } else { delete tabData.userTypedValue; delete tabData.userTypedClear; @@ -2079,7 +2085,7 @@ var SessionStoreInternal = { } catch (ex) { debug(ex); } // POSTDATA is tricky - especially since some extensions don't get it right - if (aEntry.owner) { + if (aEntry.triggeringPrincipal) { // Not catching anything specific here, just possible errors // from writeCompoundObject and the like. try { @@ -2088,19 +2094,19 @@ var SessionStoreInternal = { var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe); pipe.init(false, false, 0, 0xffffffff, null); binaryStream.setOutputStream(pipe.outputStream); - binaryStream.writeCompoundObject(aEntry.owner, Ci.nsISupports, true); + binaryStream.writeCompoundObject(aEntry.triggeringPrincipal, Ci.nsIPrincipal, true); binaryStream.close(); // Now we want to read the data from the pipe's input end and encode it. var scriptableStream = Cc["@mozilla.org/binaryinputstream;1"]. createInstance(Ci.nsIBinaryInputStream); scriptableStream.setInputStream(pipe.inputStream); - var ownerBytes = + var triggeringPrincipalBytes = scriptableStream.readByteArray(scriptableStream.available()); // We can stop doing base64 encoding once our serialization into JSON // is guaranteed to handle all chars in strings, including embedded // nulls. - entry.owner_b64 = btoa(String.fromCharCode.apply(null, ownerBytes)); + entry.triggeringPrincipal_b64 = btoa(String.fromCharCode.apply(null, triggeringPrincipalBytes)); } catch (ex) { debug(ex); } } @@ -3394,16 +3400,24 @@ var SessionStoreInternal = { } } - if (aEntry.owner_b64) { - var ownerInput = Cc["@mozilla.org/io/string-input-stream;1"]. - createInstance(Ci.nsIStringInputStream); - var binaryData = atob(aEntry.owner_b64); - ownerInput.setData(binaryData, binaryData.length); + // The field aEntry.owner_b64 got renamed to aEntry.triggeringPricipal_b64 in + // Bug 1286472. To remain backward compatible we still have to support that + // field for a few cycles before we can remove it within Bug 1289785. + if (aEntry.owner_b64) { + aEntry.triggeringPrincipal_b64 = aEntry.owner_b64; + delete aEntry.owner_b64; + } + + if (aEntry.triggeringPrincipal_b64) { + var triggeringPrincipalInput = Cc["@mozilla.org/io/string-input-stream;1"]. + createInstance(Ci.nsIStringInputStream); + var binaryData = atob(aEntry.triggeringPrincipal_b64); + triggeringPrincipalInput.setData(binaryData, binaryData.length); var binaryStream = Cc["@mozilla.org/binaryinputstream;1"]. createInstance(Ci.nsIObjectInputStream); - binaryStream.setInputStream(ownerInput); + binaryStream.setInputStream(triggeringPrincipalInput); try { // Catch possible deserialization exceptions - shEntry.owner = binaryStream.readObject(true); + shEntry.triggeringPrincipal = binaryStream.readObject(true); } catch (ex) { debug(ex); } } diff --git a/application/palemoon/confvars.sh b/application/palemoon/confvars.sh index 8a1d00c68..5109c0829 100644 --- a/application/palemoon/confvars.sh +++ b/application/palemoon/confvars.sh @@ -79,12 +79,6 @@ MOZ_JSDOWNLOADS=1 # conformant implementations. MOZ_WEBGL_CONFORMANT=1 -# Platform Feature: Windows Maintaince Service -# XXX: This is never used -if test "$OS_ARCH" = "WINNT"; then - MOZ_MAINTENANCE_SERVICE= -fi - # Set the chrome packing format # Possible values are omni, jar, and flat # Currently, only omni and flat are supported @@ -103,3 +97,11 @@ if test "$OS_ARCH" = "WINNT" -o \ "$OS_ARCH" = "Linux"; then MOZ_BUNDLED_FONTS=1 fi + +# Short-circuit a few services to be removed +MOZ_MAINTENANCE_SERVICE= +MOZ_SERVICES_HEALTHREPORT= +MOZ_ADDON_SIGNING=0 +MOZ_REQUIRE_SIGNING=0 +MOZ_PROFILE_MIGRATOR= + diff --git a/application/palemoon/installer/package-manifest.in b/application/palemoon/installer/package-manifest.in index f7b12838b..e6a4d49db 100644 --- a/application/palemoon/installer/package-manifest.in +++ b/application/palemoon/installer/package-manifest.in @@ -35,11 +35,9 @@ #ifdef XP_MACOSX ; Mac bundle stuff @APPNAME@/Contents/Info.plist -@APPNAME@/Contents/Library/LaunchServices @APPNAME@/Contents/PkgInfo @RESPATH@/firefox.icns @RESPATH@/document.icns -@RESPATH@/@LPROJ_ROOT@.lproj/* #endif [@AB_CD@] @@ -176,8 +174,6 @@ #endif #ifdef MOZ_ENABLE_PROFILER_SPS #endif -#ifdef ENABLE_INTL_API -#endif #ifdef NECKO_WIFI #endif #ifdef MOZ_WEBRTC @@ -334,21 +330,6 @@ @RESPATH@/chrome/pippki@JAREXT@ @RESPATH@/chrome/pippki.manifest -; For process sandboxing -#if defined(MOZ_SANDBOX) -#if defined(XP_WIN) -#if defined(WOW_HELPER) -@BINPATH@/wow_helper.exe -#endif -#endif -#endif - -#if defined(MOZ_SANDBOX) -#if defined(XP_LINUX) -@BINPATH@/@DLL_PREFIX@mozsandbox@DLL_SUFFIX@ -#endif -#endif - ; for Solaris SPARC #ifdef SOLARIS bin/libfreebl_32fpu_3.so diff --git a/application/palemoon/locales/en-US/chrome/browser/browser.dtd b/application/palemoon/locales/en-US/chrome/browser/browser.dtd index 65cc34fa0..3d5f22b33 100644 --- a/application/palemoon/locales/en-US/chrome/browser/browser.dtd +++ b/application/palemoon/locales/en-US/chrome/browser/browser.dtd @@ -107,9 +107,6 @@ These should match what Safari and other Apple applications use on OS X Lion. -- <!ENTITY fullScreenAutohide.accesskey "H"> <!ENTITY fullScreenExit.label "Exit Full Screen Mode"> <!ENTITY fullScreenExit.accesskey "F"> -<!ENTITY fullscreenAllowButton.label "Allow"> -<!ENTITY fullscreenExitButton.label "Deny"> -<!ENTITY fullscreenApproval.value "Allow fullscreen?"> <!ENTITY fullscreenExitHint.value "Press ESC at any time to exit fullscreen."> <!ENTITY leaveDOMFullScreen.label "Exit Full Screen"> diff --git a/application/palemoon/locales/en-US/chrome/browser/browser.properties b/application/palemoon/locales/en-US/chrome/browser/browser.properties index bf363d103..5dce994fe 100644 --- a/application/palemoon/locales/en-US/chrome/browser/browser.properties +++ b/application/palemoon/locales/en-US/chrome/browser/browser.properties @@ -7,6 +7,7 @@ openFile=Open File droponhometitle=Set Home Page droponhomemsg=Do you want this document to be your new home page? +droponhomemsgMultiple=Do you want these documents to be your new home pages? # context menu strings @@ -58,7 +59,8 @@ addonError-1=The add-on could not be downloaded because of a connection failure addonError-2=The add-on from #2 could not be installed because it does not match the add-on #3 expected. addonError-3=The add-on downloaded from #2 could not be installed because it appears to be corrupt. addonError-4=#1 could not be installed because #3 cannot modify the needed file. -addonError-5=The add-on downloaded from #2 could not be installed because #3 does not support WebExtensions. +addonError-8=The add-on downloaded from #2 could not be installed because #3 does not support Jetpack (SDK) extensions. +addonError-9=The add-on downloaded from #2 could not be installed because #3 does not support WebExtensions. # LOCALIZATION NOTE (addonLocalError-1, addonLocalError-2, addonLocalError-3, addonLocalError-4, addonErrorIncompatible, addonErrorBlocklisted): # #1 is the add-on name, #3 is the application name, #4 is the application version @@ -66,10 +68,11 @@ addonLocalError-1=This add-on could not be installed because of a filesystem err addonLocalError-2=This add-on could not be installed because it does not match the add-on #3 expected. addonLocalError-3=This add-on could not be installed because it appears to be corrupt. addonLocalError-4=#1 could not be installed because #3 cannot modify the needed file. -addonLocalError-5=This add-on could not be installed because #3 does not support WebExtensions. +addonLocalError-8=This add-on could not be installed because #3 does not support Jetpack (SDK) extensions. +addonLocalError-9=This add-on could not be installed because #3 does not support WebExtensions. addonErrorIncompatible=#1 could not be installed because it is not compatible with #3 #4. addonErrorBlocklisted=#1 could not be installed because it has a high risk of causing stability or security problems. -addonErrorJetSDK=#1 could not be installed because it is a Jetpack/SDK extension which are not supported in #3 #4. + # LOCALIZATION NOTE (lwthemeInstallRequest.message): %S will be replaced with # the host name of the site. @@ -304,6 +307,10 @@ webNotifications.alwaysShow.accesskey=A webNotifications.neverShow=Always Block Notifications webNotifications.neverShow.accesskey=N webNotifications.showFromSite=Would you like to show notifications from %S? +# LOCALIZATION NOTE (webNotifications.upgradeTitle): When using native notifications on OS X, the title may be truncated around 32 characters. +webNotifications.upgradeTitle=Upgraded notifications +# LOCALIZATION NOTE (webNotifications.upgradeBody): When using native notifications on OS X, the body may be truncated around 100 characters in some views. +webNotifications.upgradeBody=You can now receive notifications from sites that are not currently loaded. Click to learn more. # Pointer lock UI @@ -370,8 +377,6 @@ dataReportingNotification.button.accessKey = C # LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com). fullscreen.entered=%S is now fullscreen. -# LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com). -fullscreen.rememberDecision=Remember decision for %S # LOCALIZATION NOTE (getUserMedia.shareCamera.message, getUserMedia.shareMicrophone.message, getUserMedia.shareCameraAndMicrophone.message): %S is the website origin (e.g. www.mozilla.org) # LOCALIZATION NOTE (getUserMedia.shareSelectedDevices.label): diff --git a/application/palemoon/locales/en-US/chrome/browser/pageInfo.dtd b/application/palemoon/locales/en-US/chrome/browser/pageInfo.dtd index 7f3797276..70c2bbc13 100644 --- a/application/palemoon/locales/en-US/chrome/browser/pageInfo.dtd +++ b/application/palemoon/locales/en-US/chrome/browser/pageInfo.dtd @@ -66,8 +66,6 @@ <!ENTITY permInstall "Install Extensions or Themes"> <!ENTITY permGeo "Share Location"> <!ENTITY permPlugins "Activate Plugins"> -<!ENTITY permFullscreen "Enter Fullscreen"> -<!ENTITY permPointerLock2 "Hide the Mouse Pointer"> <!ENTITY permIndexedDB "Maintain Offline Storage"> <!ENTITY permClearStorage "Clear Storage"> diff --git a/application/palemoon/locales/en-US/chrome/browser/preferences/aboutPermissions.dtd b/application/palemoon/locales/en-US/chrome/browser/preferences/aboutPermissions.dtd index ff1da3dd0..14412607a 100644 --- a/application/palemoon/locales/en-US/chrome/browser/preferences/aboutPermissions.dtd +++ b/application/palemoon/locales/en-US/chrome/browser/preferences/aboutPermissions.dtd @@ -51,6 +51,4 @@ <!ENTITY popup.label "Open Pop-up Windows"> -<!ENTITY fullscreen.label "Fullscreen"> - -<!ENTITY pointerLock.label "Hide the Mouse Pointer"> +<!ENTITY focusSearch.key "f"> diff --git a/application/palemoon/locales/en-US/chrome/browser/preferences/content.dtd b/application/palemoon/locales/en-US/chrome/browser/preferences/content.dtd index 928e599d8..91abab069 100644 --- a/application/palemoon/locales/en-US/chrome/browser/preferences/content.dtd +++ b/application/palemoon/locales/en-US/chrome/browser/preferences/content.dtd @@ -33,8 +33,6 @@ <!ENTITY video.label "Video"> <!ENTITY videoMSE.label "Enable Media Source Extensions (MSE)"> <!ENTITY videoMSE.accesskey "M"> -<!ENTITY videoMSENFR.label "Use MSE asynchronously"> -<!ENTITY videoMSENFR.accesskey "U"> <!ENTITY videoMSEMP4.label "Enable MSE for MP4 video"> <!ENTITY videoMSEMP4.accesskey "4"> <!ENTITY videoMSEWebM.label "Enable MSE for WebM video"> diff --git a/application/palemoon/locales/en-US/chrome/browser/preferences/permissions.dtd b/application/palemoon/locales/en-US/chrome/browser/preferences/permissions.dtd index f6a9c466c..e61228b76 100644 --- a/application/palemoon/locales/en-US/chrome/browser/preferences/permissions.dtd +++ b/application/palemoon/locales/en-US/chrome/browser/preferences/permissions.dtd @@ -3,7 +3,7 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <!ENTITY window.title "Exceptions"> -<!ENTITY window.width "36em"> +<!ENTITY window.width "45em"> <!ENTITY treehead.sitename.label "Site"> <!ENTITY treehead.status.label "Status"> @@ -21,6 +21,8 @@ <!ENTITY allow.accesskey "A"> <!ENTITY windowClose.key "w"> -<!ENTITY button.close.label "Close"> -<!ENTITY button.close.accesskey "C"> +<!ENTITY button.cancel.label "Cancel"> +<!ENTITY button.cancel.accesskey "C"> +<!ENTITY button.ok.label "Save Changes"> +<!ENTITY button.ok.accesskey "S"> diff --git a/application/palemoon/locales/en-US/chrome/browser/preferences/preferences.properties b/application/palemoon/locales/en-US/chrome/browser/preferences/preferences.properties index 356922982..3eebbcbec 100644 --- a/application/palemoon/locales/en-US/chrome/browser/preferences/preferences.properties +++ b/application/palemoon/locales/en-US/chrome/browser/preferences/preferences.properties @@ -23,6 +23,8 @@ popuppermissionstext=You can specify which websites are allowed to open pop-up w popuppermissionstitle=Allowed Sites - Pop-ups invalidURI=Please enter a valid hostname invalidURITitle=Invalid Hostname Entered +savedLoginsExceptions_title=Exceptions - Saved Logins +savedLoginsExceptions_desc=Logins for the following sites will not be saved: #### Master Password diff --git a/application/palemoon/modules/PopupNotifications.jsm b/application/palemoon/modules/PopupNotifications.jsm index 15c8915ed..0cb970230 100644 --- a/application/palemoon/modules/PopupNotifications.jsm +++ b/application/palemoon/modules/PopupNotifications.jsm @@ -12,6 +12,7 @@ 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"; @@ -237,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: @@ -829,13 +844,60 @@ PopupNotifications.prototype = { this._update(notifications, anchor); }, - _fireCallback: function PopupNotifications_fireCallback(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) - n.options.eventCallback.call(n, event); + return n.options.eventCallback.call(n, event, ...args); } catch (error) { Cu.reportError(error); } + return undefined; }, _onPopupHidden: function PopupNotifications_onPopupHidden(event) { diff --git a/application/palemoon/modules/webrtcUI.jsm b/application/palemoon/modules/webrtcUI.jsm index c957bfd9a..819ca181f 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, diff --git a/application/palemoon/themes/linux/browser.css b/application/palemoon/themes/linux/browser.css index 4f4964db8..dbdc06235 100644 --- a/application/palemoon/themes/linux/browser.css +++ b/application/palemoon/themes/linux/browser.css @@ -1169,6 +1169,10 @@ toolbar[iconsize="small"] #webrtc-status-button { list-style-image: url(chrome://browser/skin/Geolocation-64.png); } +.popup-notification-icon[popupid="push"] { + list-style-image: url(chrome://browser/skin/Push-64.png); +} + .popup-notification-icon[popupid="xpinstall-disabled"], .popup-notification-icon[popupid="addon-progress"], .popup-notification-icon[popupid="addon-install-cancelled"], @@ -1374,7 +1378,18 @@ toolbar[iconsize="small"] #webrtc-status-button { .web-notifications-notification-icon, #web-notifications-notification-icon { - list-style-image: url(chrome://browser/skin/notification-16.png); + list-style-image: url(chrome://browser/skin/web-notifications-tray.svg); + -moz-image-region: rect(0, 16px, 16px, 0); +} + +.web-notifications-notification-icon:hover, +#web-notifications-notification-icon:hover { + -moz-image-region: rect(0, 32px, 16px, 16px); +} + +.web-notifications-notification-icon:hover:active, +#web-notifications-notification-icon:hover:active { + -moz-image-region: rect(0, 48px, 16px, 32px); } #pointerLock-notification-icon { @@ -2052,10 +2067,6 @@ toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon { box-shadow: 0 0 2px white; } -#full-screen-warning-container[obscure-browser] { - background-color: rgba(0,0,0,0.3); -} - .full-screen-description { font-size: 150%; } @@ -2064,11 +2075,6 @@ toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon { font-size: 300%; } -.full-screen-approval-button, -#full-screen-remember-decision { - font-size: 120%; -} - %ifdef MOZ_DEVTOOLS %include ../../../../devtools/client/themes/responsivedesign.inc.css %include ../../../../devtools/client/themes/commandline.inc.css diff --git a/application/palemoon/themes/linux/jar.mn b/application/palemoon/themes/linux/jar.mn index 7e67d0129..3c2ac406e 100644 --- a/application/palemoon/themes/linux/jar.mn +++ b/application/palemoon/themes/linux/jar.mn @@ -36,8 +36,6 @@ browser.jar: skin/classic/browser/mixed-content-blocked-64.png skin/classic/browser/monitor.png skin/classic/browser/monitor_16-10.png - skin/classic/browser/notification-16.png - skin/classic/browser/notification-64.png * skin/classic/browser/pageInfo.css skin/classic/browser/pageInfo.png skin/classic/browser/page-livemarks.png @@ -54,6 +52,8 @@ browser.jar: skin/classic/browser/Toolbar.png skin/classic/browser/Toolbar-small.png skin/classic/browser/urlbar-arrow.png + skin/classic/browser/web-notifications-icon.svg + skin/classic/browser/web-notifications-tray.svg #ifdef MOZ_WEBRTC skin/classic/browser/webRTC-shareDevice-16.png skin/classic/browser/webRTC-shareDevice-64.png diff --git a/application/palemoon/themes/linux/notification-16.png b/application/palemoon/themes/linux/notification-16.png Binary files differdeleted file mode 100644 index 6b2df7341..000000000 --- a/application/palemoon/themes/linux/notification-16.png +++ /dev/null diff --git a/application/palemoon/themes/linux/notification-64.png b/application/palemoon/themes/linux/notification-64.png Binary files differdeleted file mode 100644 index a01d0ab77..000000000 --- a/application/palemoon/themes/linux/notification-64.png +++ /dev/null diff --git a/application/palemoon/themes/linux/preferences/aboutPermissions.css b/application/palemoon/themes/linux/preferences/aboutPermissions.css index 406568831..2ad833fb2 100644 --- a/application/palemoon/themes/linux/preferences/aboutPermissions.css +++ b/application/palemoon/themes/linux/preferences/aboutPermissions.css @@ -90,7 +90,7 @@ list-style-image: url(chrome://global/skin/icons/question-64.png); } .pref-icon[type="desktop-notification"] { - list-style-image: url(chrome://browser/skin/notification-64.png); + list-style-image: url(chrome://browser/skin/web-notifications-icon.svg); } .pref-icon[type="install"] { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); @@ -104,12 +104,6 @@ .pref-icon[type="plugins"] { list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png); } -.pref-icon[type="fullscreen"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} -.pref-icon[type="pointerLock"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} .pref-title { font-size: 125%; diff --git a/application/palemoon/themes/linux/web-notifications-icon.svg b/application/palemoon/themes/linux/web-notifications-icon.svg new file mode 100644 index 000000000..f7186c727 --- /dev/null +++ b/application/palemoon/themes/linux/web-notifications-icon.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" width="64" height="64" viewBox="0 0 64 64"> + <defs> + <style> + .icon { + fill: #a6a6a6; + fill-rule: evenodd; + } + </style> + </defs> + <path d="M57,48 L46,48 L46,60.016 L32.482,48 L7,48 C5.343,48 4,46.657 4,45 L4,11.031 C4,9.374 5.343,8.031 7,8.031 L57,8.031 C58.657,8.031 60,9.374 60,11.031 L60,45 C60,46.657 58.657,48 57,48 ZM36,16.031 C36,14.927 35.105,14.031 34,14.031 L30,14.031 C28.895,14.031 28,14.927 28,16.031 L28,30.031 C28,31.136 28.895,32.031 30,32.031 L34,32.031 C35.105,32.031 36,31.136 36,30.031 L36,16.031 ZM36,37.5 C36,36.672 35.328,36 34.5,36 L29.5,36 C28.672,36 28,36.672 28,37.5 L28,40.5 C28,41.328 28.672,42 29.5,42 L34.5,42 C35.328,42 36,41.328 36,40.5 L36,37.5 Z" class="icon"/> +</svg> diff --git a/application/palemoon/themes/linux/web-notifications-tray.svg b/application/palemoon/themes/linux/web-notifications-tray.svg new file mode 100644 index 000000000..314026a10 --- /dev/null +++ b/application/palemoon/themes/linux/web-notifications-tray.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="16" viewBox="0 0 96 32"> + <defs> + <style> + .style-icon-notification { + fill: #666666; + } + .style-icon-notification.hover { + fill: #808080; + } + .style-icon-notification.active { + fill: #4d4d4d; + } + </style> + <path id="shape-notifcations-push" d="M27,23.969 L24,23.969 L24,29.977 L17.241,23.969 L5,23.969 C3.343,23.969 2,22.626 2,20.969 L2,6.969 C2,5.312 3.343,3.969 5,3.969 L27,3.969 C28.657,3.969 30,5.312 30,6.969 L30,20.969 C30,22.626 28.657,23.969 27,23.969 ZM18,8.969 C18,7.864 17.105,6.969 16,6.969 C14.895,6.969 14,7.864 14,8.969 L14,13.969 C14,15.073 14.895,15.969 16,15.969 C17.105,15.969 18,15.073 18,13.969 L18,8.969 ZM16.5,17.969 L15.5,17.969 C14.672,17.969 14,18.640 14,19.469 C14,20.297 14.672,20.969 15.5,20.969 L16.5,20.969 C17.328,20.969 18,20.297 18,19.469 C18,18.640 17.328,17.969 16.5,17.969 Z"/> + </defs> + <use xlink:href="#shape-notifcations-push" class="style-icon-notification"/> + <use xlink:href="#shape-notifcations-push" transform="translate(32)" class="style-icon-notification hover"/> + <use xlink:href="#shape-notifcations-push" transform="translate(64)" class="style-icon-notification active"/> +</svg> diff --git a/application/palemoon/themes/osx/browser.css b/application/palemoon/themes/osx/browser.css index 8d709d8e1..6307c5f58 100644 --- a/application/palemoon/themes/osx/browser.css +++ b/application/palemoon/themes/osx/browser.css @@ -2061,7 +2061,18 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { .web-notifications-notification-icon, #web-notifications-notification-icon { - list-style-image: url(chrome://browser/skin/notification-16.png); + list-style-image: url(chrome://browser/skin/web-notifications-tray.svg); + -moz-image-region: rect(0, 16px, 16px, 0); +} + +.web-notifications-notification-icon:hover, +#web-notifications-notification-icon:hover { + -moz-image-region: rect(0, 32px, 16px, 16px); +} + +.web-notifications-notification-icon:hover:active, +#web-notifications-notification-icon:hover:active { + -moz-image-region: rect(0, 48px, 16px, 32px); } #pointerLock-notification-icon { @@ -2335,10 +2346,6 @@ toolbar[brighttext] #addonbar-closebutton { box-shadow: 0 0 2px white; } -#full-screen-warning-container[obscure-browser] { - background-color: rgba(0,0,0,0.3); -} - .full-screen-description { font-size: 150%; } @@ -2347,11 +2354,6 @@ toolbar[brighttext] #addonbar-closebutton { font-size: 300%; } -.full-screen-approval-button, -#full-screen-remember-decision { - font-size: 120%; -} - %ifdef MOZ_DEVTOOLS %include ../../../../devtools/client/themes/responsivedesign.inc.css %include ../../../../devtools/client/themes/commandline.inc.css diff --git a/application/palemoon/themes/osx/jar.mn b/application/palemoon/themes/osx/jar.mn index 186cd8a75..a085c5f81 100644 --- a/application/palemoon/themes/osx/jar.mn +++ b/application/palemoon/themes/osx/jar.mn @@ -41,8 +41,6 @@ browser.jar: skin/classic/browser/mixed-content-blocked-64.png skin/classic/browser/monitor.png skin/classic/browser/monitor_16-10.png - skin/classic/browser/notification-16.png - skin/classic/browser/notification-64.png skin/classic/browser/pageInfo.css skin/classic/browser/pageInfo.png skin/classic/browser/page-livemarks.png @@ -70,6 +68,8 @@ browser.jar: skin/classic/browser/urlbar-history-dropmarker.png skin/classic/browser/webapps-16.png skin/classic/browser/webapps-64.png + skin/classic/browser/web-notifications-icon.svg + skin/classic/browser/web-notifications-tray.svg skin/classic/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png) skin/classic/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png) skin/classic/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png) diff --git a/application/palemoon/themes/osx/notification-16.png b/application/palemoon/themes/osx/notification-16.png Binary files differdeleted file mode 100644 index 6b2df7341..000000000 --- a/application/palemoon/themes/osx/notification-16.png +++ /dev/null diff --git a/application/palemoon/themes/osx/notification-64.png b/application/palemoon/themes/osx/notification-64.png Binary files differdeleted file mode 100644 index a01d0ab77..000000000 --- a/application/palemoon/themes/osx/notification-64.png +++ /dev/null diff --git a/application/palemoon/themes/osx/preferences/aboutPermissions.css b/application/palemoon/themes/osx/preferences/aboutPermissions.css index cfb941bbb..de636f5c4 100644 --- a/application/palemoon/themes/osx/preferences/aboutPermissions.css +++ b/application/palemoon/themes/osx/preferences/aboutPermissions.css @@ -93,7 +93,7 @@ list-style-image: url(chrome://global/skin/icons/question-64.png); } .pref-icon[type="desktop-notification"] { - list-style-image: url(chrome://browser/skin/notification-64.png); + list-style-image: url(chrome://browser/skin/web-notifications-icon.svg); } .pref-icon[type="install"] { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); @@ -107,12 +107,6 @@ .pref-icon[type="plugins"] { list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png); } -.pref-icon[type="fullscreen"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} -.pref-icon[type="pointerLock"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} .pref-title { font-size: 125%; diff --git a/application/palemoon/themes/osx/web-notifications-icon.svg b/application/palemoon/themes/osx/web-notifications-icon.svg new file mode 100644 index 000000000..f7186c727 --- /dev/null +++ b/application/palemoon/themes/osx/web-notifications-icon.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" width="64" height="64" viewBox="0 0 64 64"> + <defs> + <style> + .icon { + fill: #a6a6a6; + fill-rule: evenodd; + } + </style> + </defs> + <path d="M57,48 L46,48 L46,60.016 L32.482,48 L7,48 C5.343,48 4,46.657 4,45 L4,11.031 C4,9.374 5.343,8.031 7,8.031 L57,8.031 C58.657,8.031 60,9.374 60,11.031 L60,45 C60,46.657 58.657,48 57,48 ZM36,16.031 C36,14.927 35.105,14.031 34,14.031 L30,14.031 C28.895,14.031 28,14.927 28,16.031 L28,30.031 C28,31.136 28.895,32.031 30,32.031 L34,32.031 C35.105,32.031 36,31.136 36,30.031 L36,16.031 ZM36,37.5 C36,36.672 35.328,36 34.5,36 L29.5,36 C28.672,36 28,36.672 28,37.5 L28,40.5 C28,41.328 28.672,42 29.5,42 L34.5,42 C35.328,42 36,41.328 36,40.5 L36,37.5 Z" class="icon"/> +</svg> diff --git a/application/palemoon/themes/osx/web-notifications-tray.svg b/application/palemoon/themes/osx/web-notifications-tray.svg new file mode 100644 index 000000000..314026a10 --- /dev/null +++ b/application/palemoon/themes/osx/web-notifications-tray.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="16" viewBox="0 0 96 32"> + <defs> + <style> + .style-icon-notification { + fill: #666666; + } + .style-icon-notification.hover { + fill: #808080; + } + .style-icon-notification.active { + fill: #4d4d4d; + } + </style> + <path id="shape-notifcations-push" d="M27,23.969 L24,23.969 L24,29.977 L17.241,23.969 L5,23.969 C3.343,23.969 2,22.626 2,20.969 L2,6.969 C2,5.312 3.343,3.969 5,3.969 L27,3.969 C28.657,3.969 30,5.312 30,6.969 L30,20.969 C30,22.626 28.657,23.969 27,23.969 ZM18,8.969 C18,7.864 17.105,6.969 16,6.969 C14.895,6.969 14,7.864 14,8.969 L14,13.969 C14,15.073 14.895,15.969 16,15.969 C17.105,15.969 18,15.073 18,13.969 L18,8.969 ZM16.5,17.969 L15.5,17.969 C14.672,17.969 14,18.640 14,19.469 C14,20.297 14.672,20.969 15.5,20.969 L16.5,20.969 C17.328,20.969 18,20.297 18,19.469 C18,18.640 17.328,17.969 16.5,17.969 Z"/> + </defs> + <use xlink:href="#shape-notifcations-push" class="style-icon-notification"/> + <use xlink:href="#shape-notifcations-push" transform="translate(32)" class="style-icon-notification hover"/> + <use xlink:href="#shape-notifcations-push" transform="translate(64)" class="style-icon-notification active"/> +</svg> diff --git a/application/palemoon/themes/windows/Push-16.png b/application/palemoon/themes/windows/Push-16.png Binary files differnew file mode 100644 index 000000000..d710e7336 --- /dev/null +++ b/application/palemoon/themes/windows/Push-16.png diff --git a/application/palemoon/themes/windows/Push-64.png b/application/palemoon/themes/windows/Push-64.png Binary files differnew file mode 100644 index 000000000..27fecb858 --- /dev/null +++ b/application/palemoon/themes/windows/Push-64.png diff --git a/application/palemoon/themes/windows/browser.css b/application/palemoon/themes/windows/browser.css index 1c51accae..b87b50732 100644 --- a/application/palemoon/themes/windows/browser.css +++ b/application/palemoon/themes/windows/browser.css @@ -2548,7 +2548,18 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { .web-notifications-notification-icon, #web-notifications-notification-icon { - list-style-image: url(chrome://browser/skin/notification-16.png); + list-style-image: url(chrome://browser/skin/web-notifications-tray.svg); + -moz-image-region: rect(0, 16px, 16px, 0); +} + +.web-notifications-notification-icon:hover, +#web-notifications-notification-icon:hover { + -moz-image-region: rect(0, 32px, 16px, 16px); +} + +.web-notifications-notification-icon:hover:active, +#web-notifications-notification-icon:hover:active { + -moz-image-region: rect(0, 48px, 16px, 32px); } #pointerLock-notification-icon { @@ -2809,10 +2820,6 @@ toolbar[brighttext] #addonbar-closebutton { box-shadow: 0 0 2px white; } -#full-screen-warning-container[obscure-browser] { - background-color: rgba(0,0,0,0.3); -} - .full-screen-description { font-size: 150%; } @@ -2821,11 +2828,6 @@ toolbar[brighttext] #addonbar-closebutton { font-size: 300%; } -.full-screen-approval-button, -#full-screen-remember-decision { - font-size: 120%; -} - %ifdef MOZ_DEVTOOLS %include ../../../../devtools/client/themes/responsivedesign.inc.css %include ../../../../devtools/client/themes/commandline.inc.css diff --git a/application/palemoon/themes/windows/jar.mn b/application/palemoon/themes/windows/jar.mn index a66714b13..8c0d9a5cc 100644 --- a/application/palemoon/themes/windows/jar.mn +++ b/application/palemoon/themes/windows/jar.mn @@ -42,8 +42,6 @@ browser.jar: skin/classic/browser/mixed-content-blocked-64.png skin/classic/browser/monitor.png skin/classic/browser/monitor_16-10.png - skin/classic/browser/notification-16.png - skin/classic/browser/notification-64.png skin/classic/browser/pageInfo.css skin/classic/browser/pageInfo.png skin/classic/browser/page-livemarks.png (feeds/feedIcon16.png) @@ -72,6 +70,8 @@ browser.jar: skin/classic/browser/urlbar-history-dropmarker.png skin/classic/browser/webapps-16.png skin/classic/browser/webapps-64.png + skin/classic/browser/web-notifications-icon.svg + skin/classic/browser/web-notifications-tray.svg skin/classic/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png) skin/classic/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png) skin/classic/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png) diff --git a/application/palemoon/themes/windows/notification-16.png b/application/palemoon/themes/windows/notification-16.png Binary files differdeleted file mode 100644 index 6b2df7341..000000000 --- a/application/palemoon/themes/windows/notification-16.png +++ /dev/null diff --git a/application/palemoon/themes/windows/notification-64.png b/application/palemoon/themes/windows/notification-64.png Binary files differdeleted file mode 100644 index a01d0ab77..000000000 --- a/application/palemoon/themes/windows/notification-64.png +++ /dev/null diff --git a/application/palemoon/themes/windows/preferences/aboutPermissions.css b/application/palemoon/themes/windows/preferences/aboutPermissions.css index d9db6ccbf..c985150de 100644 --- a/application/palemoon/themes/windows/preferences/aboutPermissions.css +++ b/application/palemoon/themes/windows/preferences/aboutPermissions.css @@ -93,7 +93,7 @@ list-style-image: url(chrome://global/skin/icons/question-48.png); } .pref-icon[type="desktop-notification"] { - list-style-image: url(chrome://browser/skin/notification-64.png); + list-style-image: url(chrome://browser/skin/web-notifications-icon.svg); } .pref-icon[type="install"] { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-48.png); @@ -107,12 +107,6 @@ .pref-icon[type="plugins"] { list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric-48.png); } -.pref-icon[type="fullscreen"] { - list-style-image: url(chrome://global/skin/icons/question-48.png); -} -.pref-icon[type="pointerLock"] { - list-style-image: url(chrome://global/skin/icons/question-48.png); -} .pref-title { font-size: 125%; diff --git a/application/palemoon/themes/windows/web-notifications-icon.svg b/application/palemoon/themes/windows/web-notifications-icon.svg new file mode 100644 index 000000000..f7186c727 --- /dev/null +++ b/application/palemoon/themes/windows/web-notifications-icon.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" width="64" height="64" viewBox="0 0 64 64"> + <defs> + <style> + .icon { + fill: #a6a6a6; + fill-rule: evenodd; + } + </style> + </defs> + <path d="M57,48 L46,48 L46,60.016 L32.482,48 L7,48 C5.343,48 4,46.657 4,45 L4,11.031 C4,9.374 5.343,8.031 7,8.031 L57,8.031 C58.657,8.031 60,9.374 60,11.031 L60,45 C60,46.657 58.657,48 57,48 ZM36,16.031 C36,14.927 35.105,14.031 34,14.031 L30,14.031 C28.895,14.031 28,14.927 28,16.031 L28,30.031 C28,31.136 28.895,32.031 30,32.031 L34,32.031 C35.105,32.031 36,31.136 36,30.031 L36,16.031 ZM36,37.5 C36,36.672 35.328,36 34.5,36 L29.5,36 C28.672,36 28,36.672 28,37.5 L28,40.5 C28,41.328 28.672,42 29.5,42 L34.5,42 C35.328,42 36,41.328 36,40.5 L36,37.5 Z" class="icon"/> +</svg> diff --git a/application/palemoon/themes/windows/web-notifications-tray.svg b/application/palemoon/themes/windows/web-notifications-tray.svg new file mode 100644 index 000000000..314026a10 --- /dev/null +++ b/application/palemoon/themes/windows/web-notifications-tray.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="16" viewBox="0 0 96 32"> + <defs> + <style> + .style-icon-notification { + fill: #666666; + } + .style-icon-notification.hover { + fill: #808080; + } + .style-icon-notification.active { + fill: #4d4d4d; + } + </style> + <path id="shape-notifcations-push" d="M27,23.969 L24,23.969 L24,29.977 L17.241,23.969 L5,23.969 C3.343,23.969 2,22.626 2,20.969 L2,6.969 C2,5.312 3.343,3.969 5,3.969 L27,3.969 C28.657,3.969 30,5.312 30,6.969 L30,20.969 C30,22.626 28.657,23.969 27,23.969 ZM18,8.969 C18,7.864 17.105,6.969 16,6.969 C14.895,6.969 14,7.864 14,8.969 L14,13.969 C14,15.073 14.895,15.969 16,15.969 C17.105,15.969 18,15.073 18,13.969 L18,8.969 ZM16.5,17.969 L15.5,17.969 C14.672,17.969 14,18.640 14,19.469 C14,20.297 14.672,20.969 15.5,20.969 L16.5,20.969 C17.328,20.969 18,20.297 18,19.469 C18,18.640 17.328,17.969 16.5,17.969 Z"/> + </defs> + <use xlink:href="#shape-notifcations-push" class="style-icon-notification"/> + <use xlink:href="#shape-notifcations-push" transform="translate(32)" class="style-icon-notification hover"/> + <use xlink:href="#shape-notifcations-push" transform="translate(64)" class="style-icon-notification active"/> +</svg> |