diff options
Diffstat (limited to 'browser/base/content')
140 files changed, 0 insertions, 41404 deletions
diff --git a/browser/base/content/aboutDialog.css b/browser/base/content/aboutDialog.css deleted file mode 100644 index aa79b0795..000000000 --- a/browser/base/content/aboutDialog.css +++ /dev/null @@ -1,70 +0,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/. */ - -#PMaboutDialog { - width: 620px; -} - -#PMrightBox { - background-image: url("chrome://branding/content/about-wordmark.png"); - background-repeat: no-repeat; - /* padding-top creates room for the wordmark */ - padding-top: 38px; - margin-top:20px; -} - -#PMrightBox:-moz-locale-dir(rtl) { - background-position: 100% 0; -} - -#PMbottomBox { - padding: 15px 10px 0; -} - -#PMversion { - margin-top: 10px; - -moz-margin-start: 0; - -moz-user-select: text; - -moz-user-focus: normal; - cursor: text; -} - -#distribution, -#distributionId { - font-weight: bold; - display: none; - margin-top: 0; - margin-bottom: 0; -} - -.text-blurb { - margin-bottom: 10px; - -moz-margin-start: 0; - -moz-padding-start: 0; -} - -#updateButton, -#updateDeck > hbox > label { - -moz-margin-start: 0; - -moz-padding-start: 0; -} - -.update-throbber { - width: 16px; - min-height: 16px; - -moz-margin-end: 3px; - list-style-image: url("chrome://global/skin/icons/loading_16.png"); -} - -.text-link, -.text-link:focus { - margin: 0px; - padding: 0px; -} - -.bottom-link, -.bottom-link:focus { - text-align: center; - margin: 0 40px; -} diff --git a/browser/base/content/aboutDialog.js b/browser/base/content/aboutDialog.js deleted file mode 100644 index f4c2a990c..000000000 --- a/browser/base/content/aboutDialog.js +++ /dev/null @@ -1,590 +0,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/. - -// Services = object with smart getters for common XPCOM services -Components.utils.import("resource://gre/modules/Services.jsm"); - -function init(aEvent) -{ - if (aEvent.target != document) - return; - - try { - var distroId = Services.prefs.getCharPref("distribution.id"); - if (distroId) { - var distroVersion = Services.prefs.getCharPref("distribution.version"); - - var distroIdField = document.getElementById("distributionId"); - distroIdField.value = distroId + " - " + distroVersion; - distroIdField.style.display = "block"; - - try { - // This is in its own try catch due to bug 895473 and bug 900925. - var distroAbout = Services.prefs.getComplexValue("distribution.about", - Components.interfaces.nsISupportsString); - var distroField = document.getElementById("distribution"); - distroField.value = distroAbout; - distroField.style.display = "block"; - } - catch (ex) { - // Pref is unset - Components.utils.reportError(ex); - } - } - } - catch (e) { - // Pref is unset - } - - // Include the build ID if this is an "a#" or "b#" build - let version = Services.appinfo.version; - if (/[ab]\d+$/.test(version)) { - let buildID = Services.appinfo.appBuildID; - let buildDate = buildID.slice(0,4) + "-" + buildID.slice(4,6) + "-" + buildID.slice(6,8); - document.getElementById("PMversion").textContent += " (" + buildDate + ")"; - } - -#ifdef MOZ_UPDATER - gAppUpdater = new appUpdater(); -#endif - -#ifdef XP_MACOSX - // it may not be sized at this point, and we need its width to calculate its position - window.sizeToContent(); - window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5); -#endif - -// get release notes URL from prefs - var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] - .getService(Components.interfaces.nsIURLFormatter); - var releaseNotesURL = formatter.formatURLPref("app.releaseNotesURL"); - if (releaseNotesURL != "about:blank") { - var relnotes = document.getElementById("releaseNotesURL"); - relnotes.setAttribute("href", releaseNotesURL); - } -} - -#ifdef MOZ_UPDATER -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -var gAppUpdater; - -function onUnload(aEvent) { - if (gAppUpdater.isChecking) - gAppUpdater.checker.stopChecking(Components.interfaces.nsIUpdateChecker.CURRENT_CHECK); - // Safe to call even when there isn't a download in progress. - gAppUpdater.removeDownloadListener(); - gAppUpdater = null; -} - - -function appUpdater() -{ - this.updateDeck = document.getElementById("updateDeck"); - - // Hide the update deck when there is already an update window open to avoid - // syncing issues between them. - if (Services.wm.getMostRecentWindow("Update:Wizard")) { - this.updateDeck.hidden = true; - return; - } - - XPCOMUtils.defineLazyServiceGetter(this, "aus", - "@mozilla.org/updates/update-service;1", - "nsIApplicationUpdateService"); - XPCOMUtils.defineLazyServiceGetter(this, "checker", - "@mozilla.org/updates/update-checker;1", - "nsIUpdateChecker"); - XPCOMUtils.defineLazyServiceGetter(this, "um", - "@mozilla.org/updates/update-manager;1", - "nsIUpdateManager"); - - this.bundle = Services.strings. - createBundle("chrome://browser/locale/browser.properties"); - - this.updateBtn = document.getElementById("updateButton"); - - // The button label value must be set so its height is correct. - this.setupUpdateButton("update.checkInsideButton"); - - let manualURL = Services.urlFormatter.formatURLPref("app.update.url.manual"); - let manualLink = document.getElementById("manualLink"); - manualLink.value = manualURL; - manualLink.href = manualURL; - document.getElementById("failedLink").href = manualURL; - - if (this.updateDisabledAndLocked) { - this.selectPanel("adminDisabled"); - return; - } - - if (this.isPending || this.isApplied) { - this.setupUpdateButton("update.restart." + - (this.isMajor ? "upgradeButton" : "updateButton")); - return; - } - - if (this.aus.isOtherInstanceHandlingUpdates) { - this.selectPanel("otherInstanceHandlingUpdates"); - return; - } - - if (this.isDownloading) { - this.startDownload(); - return; - } - - if (this.updateEnabled && this.updateAuto) { - this.selectPanel("checkingForUpdates"); - this.isChecking = true; - this.checker.checkForUpdates(this.updateCheckListener, true); - return; - } -} - -appUpdater.prototype = -{ - // true when there is an update check in progress. - isChecking: false, - - // true when there is an update already staged / ready to be applied. - get isPending() { - if (this.update) { - return this.update.state == "pending" || - this.update.state == "pending-service"; - } - return this.um.activeUpdate && - (this.um.activeUpdate.state == "pending" || - this.um.activeUpdate.state == "pending-service"); - }, - - // true when there is an update already installed in the background. - get isApplied() { - if (this.update) - return this.update.state == "applied" || - this.update.state == "applied-service"; - return this.um.activeUpdate && - (this.um.activeUpdate.state == "applied" || - this.um.activeUpdate.state == "applied-service"); - }, - - // true when there is an update download in progress. - get isDownloading() { - if (this.update) - return this.update.state == "downloading"; - return this.um.activeUpdate && - this.um.activeUpdate.state == "downloading"; - }, - - // true when the update type is major. - get isMajor() { - if (this.update) - return this.update.type == "major"; - return this.um.activeUpdate.type == "major"; - }, - - // true when updating is disabled by an administrator. - get updateDisabledAndLocked() { - return !this.updateEnabled && - Services.prefs.prefIsLocked("app.update.enabled"); - }, - - // true when updating is enabled. - get updateEnabled() { - try { - return Services.prefs.getBoolPref("app.update.enabled"); - } - catch (e) { } - return true; // Firefox default is true - }, - - // true when updating in background is enabled. - get backgroundUpdateEnabled() { - return this.updateEnabled && - gAppUpdater.aus.canStageUpdates; - }, - - // true when updating is automatic. - get updateAuto() { - try { - return Services.prefs.getBoolPref("app.update.auto"); - } - catch (e) { } - return true; // Firefox default is true - }, - - /** - * Sets the deck's selected panel. - * - * @param aChildID - * The id of the deck's child to select. - */ - selectPanel: function(aChildID) { - this.updateDeck.selectedPanel = document.getElementById(aChildID); - this.updateBtn.disabled = (aChildID != "updateButtonBox"); - }, - - /** - * Sets the update button's label and accesskey. - * - * @param aKeyPrefix - * The prefix for the properties file entry to use for setting the - * label and accesskey. - */ - setupUpdateButton: function(aKeyPrefix) { - this.updateBtn.label = this.bundle.GetStringFromName(aKeyPrefix + ".label"); - this.updateBtn.accessKey = this.bundle.GetStringFromName(aKeyPrefix + ".accesskey"); - if (!document.commandDispatcher.focusedElement || - document.commandDispatcher.focusedElement == this.updateBtn) - this.updateBtn.focus(); - }, - - /** - * Handles oncommand for the update button. - */ - buttonOnCommand: function() { - if (this.isPending || this.isApplied) { - // Notify all windows that an application quit has been requested. - let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]. - createInstance(Components.interfaces.nsISupportsPRBool); - Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart"); - - // Something aborted the quit process. - if (cancelQuit.data) - return; - - let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]. - getService(Components.interfaces.nsIAppStartup); - - // If already in safe mode restart in safe mode (bug 327119) - if (Services.appinfo.inSafeMode) { - appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit); - return; - } - - appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit | - Components.interfaces.nsIAppStartup.eRestart); - return; - } - - const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul"; - // Firefox no longer displays a license for updates and the licenseURL check - // is just in case a distibution does. - if (this.update) { - var ary = null; - ary = Components.classes["@mozilla.org/supports-array;1"]. - createInstance(Components.interfaces.nsISupportsArray); - ary.AppendElement(this.update); - var openFeatures = "chrome,centerscreen,dialog=no,resizable=no,titlebar,toolbar=no"; - Services.ww.openWindow(null, URI_UPDATE_PROMPT_DIALOG, "", openFeatures, ary); - window.close(); - return; - } - - this.selectPanel("checkingForUpdates"); - this.isChecking = true; - this.checker.checkForUpdates(this.updateCheckListener, true); - }, - - /** - * Implements nsIUpdateCheckListener. The methods implemented by - * nsIUpdateCheckListener are in a different scope from nsIIncrementalDownload - * to make it clear which are used by each interface. - */ - updateCheckListener: { - /** - * See nsIUpdateService.idl - */ - onCheckComplete: function(aRequest, aUpdates, aUpdateCount) { - gAppUpdater.isChecking = false; - gAppUpdater.update = gAppUpdater.aus. - selectUpdate(aUpdates, aUpdates.length); - if (!gAppUpdater.update) { - gAppUpdater.selectPanel("noUpdatesFound"); - return; - } - - if (gAppUpdater.update.unsupported) { - if (gAppUpdater.update.detailsURL) { - let unsupportedLink = document.getElementById("unsupportedLink"); - unsupportedLink.href = gAppUpdater.update.detailsURL; - } - gAppUpdater.selectPanel("unsupportedSystem"); - return; - } - - if (!gAppUpdater.aus.canApplyUpdates) { - gAppUpdater.selectPanel("manualUpdate"); - return; - } - - gAppUpdater.selectPanel("updateButtonBox"); - gAppUpdater.setupUpdateButton("update.openUpdateUI." + - (this.isMajor ? "upgradeButton" - : "applyButton")); - }, - - /** - * See nsIUpdateService.idl - */ - onError: function(aRequest, aUpdate) { - // Errors in the update check are treated as no updates found. If the - // update check fails repeatedly without a success the user will be - // notified with the normal app update user interface so this is safe. - gAppUpdater.isChecking = false; - gAppUpdater.selectPanel("noUpdatesFound"); - }, - - /** - * See nsISupports.idl - */ - QueryInterface: function(aIID) { - if (!aIID.equals(Components.interfaces.nsIUpdateCheckListener) && - !aIID.equals(Components.interfaces.nsISupports)) - throw Components.results.NS_ERROR_NO_INTERFACE; - return this; - } - }, - - /** - * Checks the compatibility of add-ons for the application update. - */ - checkAddonCompatibility: function() { - var self = this; - AddonManager.getAllAddons(function(aAddons) { - self.addons = []; - self.addonsCheckedCount = 0; - aAddons.forEach(function(aAddon) { - // Protect against code that overrides the add-ons manager and doesn't - // implement the isCompatibleWith or the findUpdates method. - if (!("isCompatibleWith" in aAddon) || !("findUpdates" in aAddon)) { - let errMsg = "Add-on doesn't implement either the isCompatibleWith " + - "or the findUpdates method!"; - if (aAddon.id) - errMsg += " Add-on ID: " + aAddon.id; - Components.utils.reportError(errMsg); - return; - } - - // If an add-on isn't appDisabled and isn't userDisabled then it is - // either active now or the user expects it to be active after the - // restart. If that is the case and the add-on is not installed by the - // application and is not compatible with the new application version - // then the user should be warned that the add-on will become - // incompatible. If an addon's type equals plugin it is skipped since - // checking plugins compatibility information isn't supported and - // getting the scope property of a plugin breaks in some environments - // (see bug 566787). - try { - if (aAddon.type != "plugin" && aAddon.isCompatible && - !aAddon.appDisabled && !aAddon.userDisabled && - aAddon.scope != AddonManager.SCOPE_APPLICATION && - !aAddon.isCompatibleWith(self.update.appVersion, - self.update.platformVersion)) - self.addons.push(aAddon); - } - catch (e) { - Components.utils.reportError(e); - } - }); - self.addonsTotalCount = self.addons.length; - if (self.addonsTotalCount == 0) { - self.startDownload(); - return; - } - - self.checkAddonsForUpdates(); - }); - }, - - /** - * Checks if there are updates for add-ons that are incompatible with the - * application update. - */ - checkAddonsForUpdates: function() { - this.addons.forEach(function(aAddon) { - aAddon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, - this.update.appVersion, - this.update.platformVersion); - }, this); - }, - - /** - * See XPIProvider.jsm - */ - onCompatibilityUpdateAvailable: function(aAddon) { - for (var i = 0; i < this.addons.length; ++i) { - if (this.addons[i].id == aAddon.id) { - this.addons.splice(i, 1); - break; - } - } - }, - - /** - * See XPIProvider.jsm - */ - onUpdateAvailable: function(aAddon, aInstall) { - if (!Services.blocklist.isAddonBlocklisted(aAddon.id, aInstall.version, - this.update.appVersion, - this.update.platformVersion)) { - // Compatibility or new version updates mean the same thing here. - this.onCompatibilityUpdateAvailable(aAddon); - } - }, - - /** - * See XPIProvider.jsm - */ - onUpdateFinished: function(aAddon) { - ++this.addonsCheckedCount; - - if (this.addonsCheckedCount < this.addonsTotalCount) - return; - - if (this.addons.length == 0) { - // Compatibility updates or new version updates were found for all add-ons - this.startDownload(); - return; - } - - this.selectPanel("updateButtonBox"); - this.setupUpdateButton("update.openUpdateUI." + - (this.isMajor ? "upgradeButton" : "applyButton")); - }, - - /** - * Starts the download of an update mar. - */ - startDownload: function() { - if (!this.update) - this.update = this.um.activeUpdate; - this.update.QueryInterface(Components.interfaces.nsIWritablePropertyBag); - this.update.setProperty("foregroundDownload", "true"); - - this.aus.pauseDownload(); - let state = this.aus.downloadUpdate(this.update, false); - if (state == "failed") { - this.selectPanel("downloadFailed"); - return; - } - - this.setupDownloadingUI(); - }, - - /** - * Switches to the UI responsible for tracking the download. - */ - setupDownloadingUI: function() { - this.downloadStatus = document.getElementById("downloadStatus"); - this.downloadStatus.value = - DownloadUtils.getTransferTotal(0, this.update.selectedPatch.size); - this.selectPanel("downloading"); - this.aus.addDownloadListener(this); - }, - - removeDownloadListener: function() { - if (this.aus) { - this.aus.removeDownloadListener(this); - } - }, - - /** - * See nsIRequestObserver.idl - */ - onStartRequest: function(aRequest, aContext) { - }, - - /** - * See nsIRequestObserver.idl - */ - onStopRequest: function(aRequest, aContext, aStatusCode) { - switch (aStatusCode) { - case Components.results.NS_ERROR_UNEXPECTED: - if (this.update.selectedPatch.state == "download-failed" && - (this.update.isCompleteUpdate || this.update.patchCount != 2)) { - // Verification error of complete patch, informational text is held in - // the update object. - this.removeDownloadListener(); - this.selectPanel("downloadFailed"); - break; - } - // Verification failed for a partial patch, complete patch is now - // downloading so return early and do NOT remove the download listener! - break; - case Components.results.NS_BINDING_ABORTED: - // Do not remove UI listener since the user may resume downloading again. - break; - case Components.results.NS_OK: - this.removeDownloadListener(); - if (this.backgroundUpdateEnabled) { - this.selectPanel("applying"); - let update = this.um.activeUpdate; - let self = this; - Services.obs.addObserver(function (aSubject, aTopic, aData) { - // Update the UI when the background updater is finished - let status = aData; - if (status == "applied" || status == "applied-service" || - status == "pending" || status == "pending-service") { - // If the update is successfully applied, or if the updater has - // fallen back to non-staged updates, show the Restart to Update - // button. - self.selectPanel("updateButtonBox"); - self.setupUpdateButton("update.restart." + - (self.isMajor ? "upgradeButton" : "updateButton")); - } else if (status == "failed") { - // Background update has failed, let's show the UI responsible for - // prompting the user to update manually. - self.selectPanel("downloadFailed"); - } else if (status == "downloading") { - // We've fallen back to downloading the full update because the - // partial update failed to get staged in the background. - // Therefore we need to keep our observer. - self.setupDownloadingUI(); - return; - } - Services.obs.removeObserver(arguments.callee, "update-staged"); - }, "update-staged", false); - } else { - this.selectPanel("updateButtonBox"); - this.setupUpdateButton("update.restart." + - (this.isMajor ? "upgradeButton" : "updateButton")); - } - break; - default: - this.removeDownloadListener(); - this.selectPanel("downloadFailed"); - break; - } - - }, - - /** - * See nsIProgressEventSink.idl - */ - onStatus: function(aRequest, aContext, aStatus, aStatusArg) { - }, - - /** - * See nsIProgressEventSink.idl - */ - onProgress: function(aRequest, aContext, aProgress, aProgressMax) { - this.downloadStatus.value = - DownloadUtils.getTransferTotal(aProgress, aProgressMax); - }, - - /** - * See nsISupports.idl - */ - QueryInterface: function(aIID) { - if (!aIID.equals(Components.interfaces.nsIProgressEventSink) && - !aIID.equals(Components.interfaces.nsIRequestObserver) && - !aIID.equals(Components.interfaces.nsISupports)) - throw Components.results.NS_ERROR_NO_INTERFACE; - return this; - } -}; -#endif diff --git a/browser/base/content/aboutDialog.xul b/browser/base/content/aboutDialog.xul deleted file mode 100644 index 743ff21df..000000000 --- a/browser/base/content/aboutDialog.xul +++ /dev/null @@ -1,124 +0,0 @@ -<?xml version="1.0"?> <!-- -*- Mode: HTML -*- --> - -# 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/content/aboutDialog.css" type="text/css"?> -<?xml-stylesheet href="chrome://branding/content/aboutDialog.css" type="text/css"?> - -<!DOCTYPE window [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > -%brandDTD; -<!ENTITY % aboutDialogDTD SYSTEM "chrome://browser/locale/aboutDialog.dtd" > -%aboutDialogDTD; -]> - -#ifdef XP_MACOSX -<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?> -#endif - -<window xmlns:html="http://www.w3.org/1999/xhtml" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - id="PMaboutDialog" - windowtype="Browser:About" - onload="init(event);" -#ifdef MOZ_UPDATER - onunload="onUnload(event);" -#endif -#ifdef XP_MACOSX - inwindowmenu="false" -#else - title="&aboutDialog.title;" -#endif - role="dialog" - aria-describedby="version distribution distributionId communityDesc contributeDesc trademark" - > - - <script type="application/javascript" src="chrome://browser/content/aboutDialog.js"/> - - <vbox id="aboutPMDialogContainer"> - <hbox id="PMclientBox"> - <vbox id="PMleftBox" flex="1"/> - <vbox id="PMrightBox" flex="1"> -#ifdef HAVE_64BIT_BUILD -#expand <label id="PMversion">Version: __MOZ_APP_VERSION__ (64-bit)</label> -#else -#expand <label id="PMversion">Version: __MOZ_APP_VERSION__ (32-bit)</label> -#endif - <label id="distribution" class="text-blurb"/> - <label id="distributionId" class="text-blurb"/> - - <vbox id="detailsBox"> - <vbox id="updateBox"> -#ifdef MOZ_UPDATER - <deck id="updateDeck" orient="vertical"> - <hbox id="updateButtonBox" align="center"> - <button id="updateButton" align="start" - oncommand="gAppUpdater.buttonOnCommand();"/> - <spacer flex="1"/> - </hbox> - <hbox id="checkingForUpdates" align="center"> - <image class="update-throbber"/><label>&update.checkingForUpdates;</label> - </hbox> - <hbox id="checkingAddonCompat" align="center"> - <image class="update-throbber"/><label>&update.checkingAddonCompat;</label> - </hbox> - <hbox id="downloading" align="center"> - <image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label> - </hbox> - <hbox id="applying" align="center"> - <image class="update-throbber"/><label>&update.applying;</label> - </hbox> - <hbox id="downloadFailed" align="center"> - <label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label> - </hbox> - <hbox id="adminDisabled" align="center"> - <label>&update.adminDisabled;</label> - </hbox> - <hbox id="noUpdatesFound" align="center"> - <label>&update.noUpdatesFound;</label> - </hbox> - <hbox id="manualUpdate" align="center"> - <label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label> - </hbox> - </deck> -#endif - </vbox> - - <description class="text-pmcreds"> -#ifdef MC_PRIVATE_BUILD - This is a private build of Pale Moon. If you did not manually build this copy from source yourself, then please download an official version from the <label class="text-link" href="http://www.palemoon.org/">Pale Moon website</label>. -#else - Pale Moon is released by <label class="text-link" href="http://www.moonchildproductions.info">Moonchild Productions</label>. - </description> - <description class="text-pmcreds"> - Special thanks to all our supporters and donors for making this browser possible! - </description> - <description class="text-blurb"> - If you wish to contribute, please consider helping out by providing support to other users on the <label class="text-link" href="https://forum.palemoon.org/">Pale Moon forum</label> - or getting involved in our development by tackling some of the issues found in our GitHub issue tracker. -#endif - </description> - </vbox> - </vbox> - </hbox> - <vbox id="PMbottomBox"> - <hbox pack="center"> - <label class="text-link bottom-link" href="about:license">Licensing information</label> - <label class="text-link bottom-link" href="about:rights">End-user rights</label> - <label class="text-link bottom-link" id="releaseNotesURL">Release notes</label> - </hbox> - <description id="PMtrademark">&trademarkInfo.part1;</description> - </vbox> - </vbox> - - <keyset> - <key keycode="VK_ESCAPE" oncommand="window.close();"/> - </keyset> - -#ifdef XP_MACOSX -#include browserMountPoints.inc -#endif -</window> diff --git a/browser/base/content/aboutRobots-icon.png b/browser/base/content/aboutRobots-icon.png Binary files differdeleted file mode 100644 index 1c4899aaf..000000000 --- a/browser/base/content/aboutRobots-icon.png +++ /dev/null diff --git a/browser/base/content/aboutRobots-widget-left.png b/browser/base/content/aboutRobots-widget-left.png Binary files differdeleted file mode 100644 index 3a1e48d5f..000000000 --- a/browser/base/content/aboutRobots-widget-left.png +++ /dev/null diff --git a/browser/base/content/aboutRobots.xhtml b/browser/base/content/aboutRobots.xhtml deleted file mode 100644 index 23fe3ba17..000000000 --- a/browser/base/content/aboutRobots.xhtml +++ /dev/null @@ -1,108 +0,0 @@ -<?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/. --> - -<!DOCTYPE html [ - <!ENTITY % htmlDTD - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "DTD/xhtml1-strict.dtd"> - %htmlDTD; - <!ENTITY % netErrorDTD - SYSTEM "chrome://global/locale/netError.dtd"> - %netErrorDTD; - <!ENTITY % globalDTD - SYSTEM "chrome://global/locale/global.dtd"> - %globalDTD; - <!ENTITY % aboutrobotsDTD - SYSTEM "chrome://browser/locale/aboutRobots.dtd"> - %aboutrobotsDTD; -]> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <title>&robots.pagetitle;</title> - <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" /> - <link rel="icon" type="image/png" id="favicon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAACGFjVEwAAAASAAAAAJNtBPIAAAAaZmNUTAAAAAAAAAAQAAAAEAAAAAAAAAAALuAD6AABhIDeugAAALhJREFUOI2Nk8sNxCAMRDlGohauXFOMpfTiAlxICqAELltHLqlgctg1InzMRhpFAc%2BLGWTnmoeZYamt78zXdZmaQtQMADlnU0OIAlbmJUBEcO4bRKQY2rUXIPmAGnDuG%2FBx3%2FfvOPVaDUg%2BoAPUf1PArIMCSD5glMEsUGaG%2BkyAFWIBaCsKuA%2BHGCNijLgP133XgOEtaPFMy2vUolEGJoCIzBmoRUR9%2B7rxj16DZaW%2FmgtmxnJ8V3oAnApQwNS5zpcAAAAaZmNUTAAAAAEAAAAQAAAAEAAAAAAAAAAAAB4D6AIB52fclgAAACpmZEFUAAAAAjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9WF%2Bu8QAAABpmY1RMAAAAAwAAABAAAAAQAAAAAAAAAAAAHgPoAgEK8Q9%2FAAAAFmZkQVQAAAAEOI1jYBgFo2AUjAIIAAAEEAAB0xIn4wAAABpmY1RMAAAABQAAABAAAAAQAAAAAAAAAAAAHgPoAgHnO30FAAAAQGZkQVQAAAAGOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVfozYcAAAABpmY1RMAAAABwAAABAAAAAQAAAAAAAAAAAAHgPoAgEKra7sAAAAFmZkQVQAAAAIOI1jYBgFo2AUjAIIAAAEEAABM9s3hAAAABpmY1RMAAAACQAAABAAAAAQAAAAAAAAAAAAHgPoAgHn3p%2BwAAAAKmZkQVQAAAAKOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F1BhPl6AAAAGmZjVEwAAAALAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQpITFkAAAAWZmRBVAAAAAw4jWNgGAWjYBSMAggAAAQQAAHaszpmAAAAGmZjVEwAAAANAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeeCPiMAAABAZmRBVAAAAA44jWNgGJ5gpxrDf2LEcIL%2FpzAVYxPDavP%2FUwz%2FpW79%2F%2F%2F%2FFMP%2FnWoQjC5GOxcgu4QYsVEwCmAAAOE0KxUmBL0KAAAAGmZjVEwAAAAPAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQoU7coAAAAWZmRBVAAAABA4jWNgGAWjYBSMAggAAAQQAAEpOBELAAAAGmZjVEwAAAARAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeYVWtoAAAAqZmRBVAAAABI4jWNgGAVYQXNz839ixHBq3qnG8B9ZAzYx2rlgFIwCcgAA8psX%2FWvpAecAAAAaZmNUTAAAABMAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC4OJMwAAABZmZEFUAAAAFDiNY2AYBaNgFIwCCAAABBAAAcBQHOkAAAAaZmNUTAAAABUAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5kn7SQAAAEBmZEFUAAAAFjiNY2AYnmCnGsN%2FYsRwgv%2BnMBVjE8Nq8%2F9TDP%2Blbv3%2F%2F%2F8Uw%2F%2BdahCMLkY7FyC7hBixUTAKYAAA4TQrFc%2BcEoQAAAAaZmNUTAAAABcAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC98ooAAAABZmZEFUAAAAGDiNY2AYBaNgFIwCCAAABBAAASCZDI4AAAAaZmNUTAAAABkAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5qwZ%2FAAAACpmZEFUAAAAGjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9cjJWbAAAABpmY1RMAAAAGwAAABAAAAAQAAAAAAAAAAAAHgPoAgELOsoVAAAAFmZkQVQAAAAcOI1jYBgFo2AUjAIIAAAEEAAByfEBbAAAABpmY1RMAAAAHQAAABAAAAAQAAAAAAAAAAAAHgPoAgHm8LhvAAAAQGZkQVQAAAAeOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVlxR3%2FgAAABpmY1RMAAAAHwAAABAAAAAQAAAAAAAAAAAAHgPoAgELZmuGAAAAFmZkQVQAAAAgOI1jYBgFo2AUjAIIAAAEEAABHP5cFQAAABpmY1RMAAAAIQAAABAAAAAQAAAAAAAAAAAAHgPoAgHlgtAOAAAAKmZkQVQAAAAiOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F0%2FMvDdAAAAAElFTkSuQmCC"/> - - <script type="application/javascript"><![CDATA[ - var buttonClicked = false; - function robotButton() - { - var button = document.getElementById('errorTryAgain'); - if (buttonClicked) { - button.style.visibility = "hidden"; - } else { - var newLabel = button.getAttribute("label2"); - button.textContent = newLabel; - buttonClicked = true; - } - } - ]]></script> - - <style type="text/css"><![CDATA[ - #errorPageContainer { - background-image: none; - } - - #errorPageContainer:before { - content: url('chrome://browser/content/aboutRobots-icon.png'); - position: absolute; - } - - body[dir=rtl] #icon, - body[dir=rtl] #errorPageContainer:before { - transform: scaleX(-1); - } - ]]></style> - </head> - - <body dir="&locale.dir;"> - - <!-- PAGE CONTAINER (for styling purposes only) --> - <div id="errorPageContainer"> - - <!-- Error Title --> - <div id="errorTitle"> - <h1 id="errorTitleText">&robots.errorTitleText;</h1> - </div> - - <!-- LONG CONTENT (the section most likely to require scrolling) --> - <div id="errorLongContent"> - - <!-- Short Description --> - <div id="errorShortDesc"> - <p id="errorShortDescText">&robots.errorShortDescText;</p> - </div> - - <!-- Long Description (Note: See netError.dtd for used XHTML tags) --> - <div id="errorLongDesc"> - <ul> - <li>&robots.errorLongDesc1;</li> - <li>&robots.errorLongDesc2;</li> - <li>&robots.errorLongDesc3;</li> - <li>&robots.errorLongDesc4;</li> - </ul> - </div> - - <!-- Short Description --> - <div id="errorTrailerDesc"> - <p id="errorTrailerDescText">&robots.errorTrailerDescText;</p> - </div> - - </div> - - <!-- Button --> - <button id="errorTryAgain" - label2="&robots.dontpress;" - onclick="robotButton();">&retry.label;</button> - - <img src="chrome://browser/content/aboutRobots-widget-left.png" - style="position: absolute; bottom: -12px; left: -10px;"/> - <img src="chrome://browser/content/aboutRobots-widget-left.png" - style="position: absolute; bottom: -12px; right: -10px; transform: scaleX(-1);"/> - </div> - - </body> -</html> diff --git a/browser/base/content/abouthome/aboutHome.css b/browser/base/content/abouthome/aboutHome.css deleted file mode 100644 index 73c686202..000000000 --- a/browser/base/content/abouthome/aboutHome.css +++ /dev/null @@ -1,339 +0,0 @@ -%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 - -html { - font: message-box; - font-size: 100%; - background-color: hsl(0,0%,90%); - color: #000; - height: 100%; -} - -body { - margin: 0; - display: -moz-box; - -moz-box-orient: vertical; - width: 100%; - height: 100%; - background-image: url(chrome://browser/content/abouthome/noise.png), - linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4)); -} - -input, -button { - font-size: inherit; - font-family: inherit; -} - -a { - color: -moz-nativehyperlinktext; - text-decoration: none; -} - -.spacer { - -moz-box-flex: 1; -} - -#topSection { - text-align: center; -} - -#brandLogo { - height: 192px; - width: 192px; - margin: 22px auto 31px; - background-image: url("chrome://branding/content/about-logo.png"); - background-size: 192px auto; - background-position: center center; - background-repeat: no-repeat; -} - -#searchForm { - width: 470px; -} - -#searchForm { - display: -moz-box; -} - -#searchLogoContainer { - display: -moz-box; - -moz-box-align: center; - padding-top: 2px; - -moz-padding-end: 8px; -} - -#searchLogoContainer[hidden] { - display: none; -} - -#searchEngineLogo { - display: inline-block; - height: 28px; - width: 70px; - min-width: 70px; -} - -#searchText { - -moz-box-flex: 1; - padding: 6px 8px; - background: hsla(0,0%,100%,.9) padding-box; - border: 1px solid; - border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2); - box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset, - 0 0 2px hsla(210,65%,9%,.1) inset, - 0 1px 0 hsla(0,0%,100%,.2); - border-radius: 2.5px 0 0 2.5px; -} - -#searchText:-moz-dir(rtl) { - border-radius: 0 2.5px 2.5px 0; -} - -#searchText:focus, -#searchText[autofocus] { - border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6); -} - -#searchSubmit { - -moz-margin-start: -1px; - background: linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box; - padding: 0 9px; - border: 1px solid; - border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2); - -moz-border-start: 1px solid transparent; - border-radius: 0 2.5px 2.5px 0; - box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset, - 0 1px 0 hsla(0,0%,100%,.2); - cursor: pointer; - transition-property: background-color, border-color, box-shadow; - transition-duration: 150ms; -} - -#searchSubmit:-moz-dir(rtl) { - border-radius: 2.5px 0 0 2.5px; -} - -#searchText:focus + #searchSubmit, -#searchText + #searchSubmit:hover, -#searchText[autofocus] + #searchSubmit { - border-color: #59b5fc #45a3e7 #3294d5; - color: white; -} - -#searchText:focus + #searchSubmit, -#searchText[autofocus] + #searchSubmit { - background-image: linear-gradient(#4cb1ff, #1793e5); - box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset, - 0 0 0 1px hsla(0,0%,100%,.1) inset, - 0 1px 0 hsla(210,54%,20%,.03); -} - -#searchText + #searchSubmit:hover { - background-image: linear-gradient(#66bdff, #0d9eff); - box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset, - 0 0 0 1px hsla(0,0%,100%,.1) inset, - 0 1px 0 hsla(210,54%,20%,.03), - 0 0 4px hsla(206,100%,20%,.2); -} - -#searchText + #searchSubmit:hover:active { - box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset, - 0 0 1px hsla(211,79%,6%,.2) inset; - transition-duration: 0ms; -} - -#launcher { - display: -moz-box; - -moz-box-align: center; - -moz-box-pack: center; - width: 100%; - background-color: hsla(0,0%,0%,.03); - border-top: 1px solid hsla(0,0%,0%,.03); - box-shadow: 0 1px 2px hsla(0,0%,0%,.02) inset, - 0 -1px 0 hsla(0,0%,100%,.25); -} - -#launcher:not([session]), -body[narrow] #launcher[session] { - display: block; /* display separator and restore button on separate lines */ - text-align: center; - white-space: nowrap; /* prevent navigational buttons from wrapping */ -} - -.launchButton { - display: -moz-box; - -moz-box-orient: vertical; - margin: 16px 1px; - padding: 14px 6px; - min-width: 88px; - max-width: 176px; - max-height: 85px; - vertical-align: top; - white-space: normal; - background: transparent padding-box; - border: 1px solid transparent; - border-radius: 2.5px; - color: #525c66; - font-size: 75%; - cursor: pointer; - transition-property: background-color, border-color, box-shadow; - transition-duration: 150ms; -} - -body[narrow] #launcher[session] > .launchButton { - margin: 4px 1px; -} - -.launchButton:hover { - background-color: hsla(211,79%,6%,.03); - border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2); -} - -.launchButton:hover:active { - background-image: linear-gradient(hsla(211,79%,6%,.02), hsla(211,79%,6%,.05)); - border-color: hsla(210,54%,20%,.2) hsla(210,54%,20%,.23) hsla(210,54%,20%,.25); - box-shadow: 0 1px 1px hsla(211,79%,6%,.05) inset, - 0 0 1px hsla(211,79%,6%,.1) inset; - transition-duration: 0ms; -} - -.launchButton[hidden], -#launcher:not([session]) > #restorePreviousSessionSeparator, -#launcher:not([session]) > #restorePreviousSession { - display: none; -} - -#restorePreviousSessionSeparator { - width: 3px; - height: 116px; - margin: 0 10px; - background-image: linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)), - linear-gradient(hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)), - linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)); - background-position: left top, center, right bottom; - background-size: 1px auto; - background-repeat: no-repeat; -} - -body[narrow] #restorePreviousSessionSeparator { - margin: 0 auto; - width: 512px; - height: 3px; - background-image: linear-gradient(to right, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)), - linear-gradient(to right, hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)), - linear-gradient(to right, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)); - background-size: auto 1px; -} - -#restorePreviousSession { - max-width: none; - font-size: 90%; -} - -body[narrow] #restorePreviousSession { - font-size: 80%; -} - -.launchButton::before { - display: block; - width: 32px; - height: 32px; - margin: 0 auto 6px; - line-height: 0; /* remove extra vertical space due to non-zero font-size */ -} - -#downloads::before { - content: url("chrome://browser/content/abouthome/downloads.png"); -} - -#bookmarks::before { - content: url("chrome://browser/content/abouthome/bookmarks.png"); -} - -#history::before { - content: url("chrome://browser/content/abouthome/history.png"); -} - -#addons::before { - content: url("chrome://browser/content/abouthome/addons.png"); -} - -#sync::before { - content: url("chrome://browser/content/abouthome/sync.png"); -} - -#settings::before { - content: url("chrome://browser/content/abouthome/settings.png"); -} - -#restorePreviousSession::before { - content: url("chrome://browser/content/abouthome/restore-large.png"); - height: 48px; - width: 48px; - display: inline-block; /* display on same line as text label */ - vertical-align: middle; - margin-bottom: 0; - -moz-margin-end: 8px; -} - -#restorePreviousSession:-moz-dir(rtl)::before { - transform: scaleX(-1); -} - -body[narrow] #restorePreviousSession::before { - content: url("chrome://browser/content/abouthome/restore.png"); - height: 32px; - width: 32px; -} - -/* [HiDPI] - * At resolutions above 1dppx, prefer downscaling the 2x Retina graphics - * rather than upscaling the original-size ones (bug 818940). - */ -@media not all and (max-resolution: 1dppx) { - #brandLogo { - background-image: url("chrome://branding/content/about-logo@2x.png"); - } - - .launchButton::before { - transform: scale(.5); - transform-origin: 0 0; - } - - #downloads::before { - content: url("chrome://browser/content/abouthome/downloads@2x.png"); - } - - #bookmarks::before { - content: url("chrome://browser/content/abouthome/bookmarks@2x.png"); - } - - #history::before { - content: url("chrome://browser/content/abouthome/history@2x.png"); - } - - #addons::before { - content: url("chrome://browser/content/abouthome/addons@2x.png"); - } - - #sync::before { - content: url("chrome://browser/content/abouthome/sync@2x.png"); - } - - #settings::before { - content: url("chrome://browser/content/abouthome/settings@2x.png"); - } - - #restorePreviousSession::before { - content: url("chrome://browser/content/abouthome/restore-large@2x.png"); - } - - body[narrow] #restorePreviousSession::before { - content: url("chrome://browser/content/abouthome/restore@2x.png"); - } -} - diff --git a/browser/base/content/abouthome/aboutHome.js b/browser/base/content/abouthome/aboutHome.js deleted file mode 100644 index 9e826b69e..000000000 --- a/browser/base/content/abouthome/aboutHome.js +++ /dev/null @@ -1,354 +0,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/. */ - -const SEARCH_ENGINES = { - "Google": { - // This is the "2x" image designed for OS X retina resolution, Windows at 192dpi, etc.; - // it will be scaled down as necessary on lower-dpi displays. - image: "data:image/png;base64," + - "iVBORw0KGgoAAAANSUhEUgAAAIwAAAA4CAYAAAAvmxBdAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ" + - "bWFnZVJlYWR5ccllPAAAGrFJREFUeNrtfHt4VdW172+utZOASLJ5+BaIFrUeXkFsa0Fl++gDnznV" + - "VlvFxt7aqvUUarXtse3Bau35ak/rZ9XT26NtfOvV6wFET+FYCQEKWqsQIT5RCAgSXnlnrzXneNw/" + - "1lphJSSQ8BB7bub3zW+LO3uN+fiNMcf4jTEX0N/6W3/rb/2tv30smtnXB3zmRi2FQakxQNKX3WkW" + - "9S/tgW3HLpmQM543A0BWVSHMYGIwOTDxzxrOf3/RQQfMZ2/SLAvKhTFVBGUqKFONH2QAzwOMF38a" + - "wHhYZAxWAqhe/iszp3+b970d/sInc57vz/J8L2eMB2MAEYkBQ6DQ3dRw4dq7AUjcP3rAfPZmLWXC" + - "LHKoIAcQAUxaB5EaEfc6AEBhjDEwmcx43/fO9HxT4vkReBIAAZgjgodW3NcPnn1sHgD/iHknn+0d" + - "6s8XEUhsXXac/34WAAGw8afuT8GZ3X055YeSJcIsG+pMZwFn0UihezRofPt3G54f/0E8cNMN+Myo" + - "8jVTCgYd823PLzrPeIBnABiUQ1F+UoWsVOYb33mkoKp/7/dKyT0AGc47X4s0sjBEoLxbBqAQAMfW" + - "Rfe38B4BM+VHUkYOs8mi1FrABbK4dcvK73zwp1M3xYPOxANKBqbpCdXNGb0UwPKRF74xpfDQ0t+K" + - "54+IvlKoahmAhaO/mv/ZmicG3tqPgT61ZM2dZMQJOYhIdByRM/F3dCCOox4Bc3oEliqyyNoQCPPu" + - "sXceKZqRsigu7pwaWBowiRb46+f9Q1V2wl1nDx09/R7jF30x9adNlN8yPx4DHwht+B/cBIBoRqeI" + - "E4hE/oshTcB0wNbT6/o/zrhFyohR5ZxmrVWE+fDxdx4puhGAH4OkPe5B6pykeJAc/7cDEMZ/095Y" + - "870P339m+BXs2v4kbCFsm9u2vnpJ3bzR7wAo2B/R2v+PjSnyXcRxtOLUSXFxwAFz5i2SZUIVO82S" + - "BWye/vLOIwNvjL8OYqCEfXCmJAZPHkC7sK1REbj2+lmbq86qTVmmfuuyN2cTiREWKCvACgml9kDL" + - "7HQksehsZmSdA6yVpsa6P38v3swg7m4vN1dGXrThKGP8yS5fP33j/LEvxKDbl2f2A0YFCtkZQDOa" + - "PjLAnP4jrmBGjh1AVhG2ttxfX33++vjY2eeNXf/siLUAzgEwMJZrY2vF/Vu/t4BRqCqgCmj07wMV" + - "HXUCzJQfUlZE72ICnANcqNj21h8eiK1AX46gXh29KT9H+rd9XxBjYGCgig7QHOgjPgMAKigXQZYp" + - "si4uCOc3v35zY2wF9ufGSgxA7fdd9g8ho9ol4P4ojiQWnSUMMANECrJNy1NWYH8eGfsEvJbLv1IK" + - "1XIAUwEtA0xplJMwjcaYlTDeShg8dOgjj6/cJxNYfWIWkHJoh5yyjkSZ8RbB89YBZq4/pXafGeuz" + - "b9WciXJxo2B2houqgAjABJCLOwFMqFv57+bBxMIAJm1det3avnl1OYCLAeSgWhofaY1QXQSRuYc+" + - "/OiD3QLmUzNdqTBKhRVMADsF5beuToXJB90KtFz+lVIVniXOVUAUqjpXVB4WwPjGTPB8/0zjeTnj" + - "ezl43szmKy6vNkDF4MeeXNc3oJyUhfAMkJsJkSxUVrLos6o6z/O8Ucb3phrPzyHKeVTwkpPXseg3" + - "Cqe+1SfG+swfaw6KGTAoJ5eyGF3IBeEIJB2AcXxb0FI/L45uFQBMGiu6Z3ai9eqrclBUClFWVatV" + - "5GERNT5wEVQnQLUcIuVNX75kFjn60rA5c1d0AoywlkcxfdwZ2LSgbOmBZAv70povu7RcyFUqcZYd" + - "Pbxix44fnLv8pbYUOWh+P3ZM9uJRo34xoLDgq8b3YTxvqhqsaPzyJTdmn36msjdyqPqkMhWqBFGZ" + - "MtV8uDX4zMjp2zemyEoPgGn4zyOvGzy48A54GcD3Sz1jFrqqE+4uOOvdmb0ASlYEs5mQE9afUdhy" + - "0yv3lHzwya/8ZcjgI0+5yssU3QKYkgQ4Ivp60LL1n8kBQfOWuvdnj6uLldgHQKoKxU7HV/eg2y1X" + - "XXmXEs1U0ZVb29o//4k5c5P5eQB+s+68aVeUFBTcCxUoS6kRWfjhueecc9SfX3ytA9QTr7eVACqY" + - "FDYEwnbB2qcHHg6gLY6ODhpomi77coUyVaojhKH9+ZHzF/wqXiztEg34APxNX/jCvQOLCi83fpy8" + - "UsCJXHLYnGdn785S0uKTyyBUBXJZcW5x4bSN56ciyLQcD4Bf/+ThVwwbUvRb+JkoswqAWX5b9Lm1" + - "M3uSM/UnUiaCKiZk2blvvnxX0ePxuBNAmpMur51wyLBPzjVeBBoVwIXBk6vuP+SG+LkcuwkWAA96" + - "/JjZKnKxkACkkFb5Nztz220xX9bJlWi+6opKFalQlpqlmzZNu6B6SaJ0knKJ/DW5qd8p8TO3x6AB" + - "qza1EE06cdmy9wDAY5LjmBTMkQnUnZ42H0ywNF52aU6FK4UY5NySI+cv+E3MCnMM5HyqtwFoO3rB" + - "gmuDMFjGjiCOIEQwzH9c+7lzju+JTaYlJ2ehUqXMWWFqeurFxqsAFMVf25Ss9kTOEZdvebClJbxT" + - "yUGZoEzwlL/b9tzRX+pOztSfSBZApSqyIrL45buKnkaUJEzLCN5+csxr+ab6fyILkI2OIZYBlx9/" + - "2bYvpLgw2+EqKLKdwoceVKJp+tfuEpYKZcaW1tZbLqheEsbj3GV+oxdV3x0GwQZrHUIiWKIST3Vm" + - "DG54zFrKrBBWiGgSyx9Uv6Xh0n/MKlGlOII4h80trQ+kuJt8HGklZHg6FZF/Y/uOb7O1YOvAzkGt" + - "Kxmoehe6SYNEpkErwZIFC4I2fuLKf2tLtDOPzumPhA6wAPJDLt1yuzjaAEcAMUCMApXfvPP7IcO6" + - "gkYFs4RRpgy49qanUsAPu/T8W48e/YwL6S/kYtBYwM8U/yu6KVlQUShr9CkKyK7b1vDVy0qVeaYy" + - "gaxbdeK85/8a/z7sYR3zgXM1gXUInEPoCEw8PR6z8YQxaidQPh6RrgrPEOZS4chKjFuydEEKFD1x" + - "QgrAnfO3V98Jw/B5dhFgmByU+MK/nnrq6K6gcQtPyqlIubJAibCxPv/fsVVNgCI9yGEAQdBq71NH" + - "UEdQIoBo5PBBeklazuQfSpYFM0UAFsDmd2yMf9+1XkUT3otc8AiRwpFChCBCI0detGbSLtYr5uw6" + - "tk26XctZwgxhRt65ZSmr1t389M1Jk85wzKcHRAiJkCfasDnI/0sMGN+jlLMrAigMhp0+f+TBBIw4" + - "milEYOcQBHZZAoZeEIgKgIIgeJbD2MqEFhxaDAFmdAWMisxQFigzlAUnX9e4rA9yeHuTna3koBQB" + - "RogxwOPvxNbQAAA7VHQEFKSQKEFIu4lA5d3HiiuFNB4XQZlhUHBK11QO0oRdD7ouROVCkeJZG7ak" + - "/KBOYHlz4sTy1WVlVY5oYego2+bs82+3tFw6YcVrp01dteqpxNfyhKQuGlxCMSsKBh570ABT/8XP" + - "5dhRVpyDWAd2Ns0O9yrhWdfcMpvCEByEoNCCwhBgvgBdM+PM5TH5FPW+1ZLo8de2viehe12dhVoH" + - "OAtDPO61O4o+kYCTnE5wVuGsxlzKHul7BUDKdomKgwpB2QHAyNiP2Dl+0Z2WRXZ9YP0F55WJczvX" + - "0jp09U3fLiurWD1+/NqQaHZIVNbu3O1vt7aM+fSqVRWXvPvu0pRldwAkQ5brjO+NMh0kgMIvGjYZ" + - "wIKETPxIrYt1U5M8iThKJil9yZGc++ab298dP36Jb8wZohqhQHRErKEeAA6fG5FT5yIlYYI6tzfO" + - "vtiQni3MYDw0ChqEgUMyejyAdwGwDeW4ZI9FAGQOmwzgv/cERmZbDXhnKBNUGMJkUhGVduSSJJ1P" + - "6rw8HIalJo7ilBkchgCgL48fVzLceDc4kZnWUdap1AQi10x+660n4jXyk1M7ZXEZgHhMUkMO4Njp" + - "hQGMf8h56Fx++ZE1a+1xZC2Szjs3sk9uUEhUbSMvP3LeyOGZ0tKJiearo1J1DHVRPYmS7JUcG2g1" + - "pxxUsooBnpmQWAOb10YbKGygcKFCZOC0XqxrRKokCBQG5euX77In2k1P+2hhWEZBAAoCuCCEcW7E" + - "2xMn/m6oYo0jyjnmuc3Off6UN96YMvmtt5LILSmQ61r3xAA0I+xqPBiIejAd1f7e2MPPfvm4LQs/" + - "89a+bP6nZuSzfsaU+T7g+UBixYQVRFGS01kFO22srRy0EgA4CEvFRHS3MANMY/fGbybmlQqAFSBV" + - "sCp8kWwCGA5dqefFShnnRV77ecHYU37iXuqLoB0tsuIo34v3NfJR1GlJsrnOuiXGy1y8k+rwxh57" + - "3srSD/6rbLdra7yMqgjUCGAULR8uWr0LJPYAGApCeCbKNygLPKIxJ65YOSU+YpLUUCYGiqBzQVy3" + - "Ft1zbevnJl60UARqACgcVDo9ZZr63Mqua68QxlpmrWJC1FmrmLSKCFVktcpZrbKhzg4D26E5Lgjg" + - "8vnoMwwh1hU/dvTRo/qcDyJqcESw5Dp6o3XNHVrqLDSubAdFjuXwwWZcX+Wc9APboKxQUoiLurXa" + - "IYfCpjlCDsoxZ6OCouLRt+xpbY3nA8aDMR6E2+9vffOWxl02cQ+Bbdjevt7l83D5ABRaKNHYO484" + - "YmgMkoJ4jElCOL8Lz9NN87YumrRDxc2DElQZKgIVhZcZcO1hZ74wtK/H0thvtuXGXdM2S0S/ziQ1" + - "FPJiG7pHwvbgDhtKnQ0VNhCEeUHQLmiuf2fymieGvJGY8DCfX+yCEC5xWIlwtO+P6+s4VESJGS4+" + - "liwxKjZ/2FGRZvPhYgktxEZdHWOAr2P34ihWIQWTgJ2CnWJbo9Ymz1g/5+h1QsF9wgKJ19Z4hV87" + - "4fKNE3cnx8v4V8H4UOjqhvce+zW6qdWVlOvSjQsDlw/WUT4A5QNQGIJDizMPHXR+CiRBb4GSzlYr" + - "26Z7vYKSC42nUOPBqA9VU1I0ZOJPEYWj1NvVW/3AoEUAFgO4IzZ1hYk2jf9WUw7IjCIXHUVhXrFp" + - "/sQtKZPIoXXr/PjoSkZeoHo6gP/bFyeciECqcHG3IrXp37a2SF3xQNPxRAXgq5nS1bHsDWCYALYA" + - "u+h0W/impI8Pad9ec/vAoWVTjV84Nsn5FAwcvmDMN5rOqf1jyatdHzjuGjvThloKYH3b5qVXt775" + - "44ZuN1QEKknF3a6ImfDee4tWjBrV6R5Qoeq1AP6Avaxx8gDolhdPXAh2qzQmZFQ4ZhALrj/mvLpT" + - "+qhxya0BP5VVZQBkA6jNR0AJ2xUUcjKGjsx4k3PVYUwaJU6rJ3reLiHlHppjBjF3fLYSzU/noEZ8" + - "3611VusoVJBVsFWAdezim/3jemSFe+SNIsvCpAhCXf7TBZI+PnTr4nO2t2xcME3ZroYKIouEEqDo" + - "xfHfav/GxOttFgBOucGWll0XVqrqXYDWNLz3aG7bsovWp4i2TvkhScLqNBezq/M/zxLBxV2Yx/75" + - "yCPP6usc04CJ+B3bcLMwQTiK+0UIwgz1ip8+4pyaYX0x0SnWMkjnYGygkm9nBO0MGzoI2TTDyQBw" + - "7ubNawPmeZYZNt5wZhrxX8OHX9yXSTJzGcVgIWasbs8/hc7XRzXM670cg0Vs5H+MHm6u74ucrb/K" + - "lAlFPoySoqFFn+rm+OCGV762df2cYWe4fP0M5qDWhoowRIm1/h+s1YZx3wrVOV1LDhXMaGzfXntF" + - "46vXtMQRS/clsqRRT9SNd0GMBo6edRStZbKeg4D//ciQIcP2CTDbqsdVKQePq1JMFkXxv4qO9AaM" + - "fPGoaeuG9kXp0LkU0wGgMFC1gYAdAeyg0m3IrE3W3mtTvodjRpHq9X3xL4h5Qsq63P/z9ra6LqSc" + - "vvmBPkwOTex2lnf4wNee/47fa99NGGVJ8Zl1qP3UPfwkdr15mDDV+Y3Pf+Kh9c9kz9pee89J7dve" + - "vaRt+7qLbVv47y5UUKggp3BB/okNz0/aHI8332OaIgELxWDpptQtt6X+Qcu03nVYGQYxjxzl+7/e" + - "GyvjdYrCtv31JiW7QTjy6qWj83jF4AeP/MLaodiHRtZBXAihEEIWkq4eSgGmvKGhqpX5d1YEVhiW" + - "BaI6Zf6QITN7s5ELhw4tZZavkwhIZMOC1rZfo5s64nPv4+1NzXot2/hYiqKckglH4/7eRojCOosp" + - "St6u2ijfS1Hv3I0SdVy5aam9ecumBeOqN8w7aRkxSlMVdRDmRHa4m5xWPKPEusUA6maIrcy/cCKw" + - "InASKaCoXrlo2LAH+xpMpAEjLauu2ObaNnxVmZqUHaI8SaR+KnIhTPHCo6ZtOn6vk4qUPNNGnV2P" + - "J0ptENweMq92zHBMcMwwIrfMLS6etKdJEnMlCYOZm9YE4dUPkWvsIUckJ/+SZwd5PCEOEBc5rh7j" + - "grqf+VfvSc7mO/xZSihVAra3YMY/PqqrUhZVe7C8yRHTBqAVQJuQN5idgJ2ASQAz4PJjptWevKc0" + - "RZQ0TQATRWDd/dmFDQ2VeaLH0z4dRVTK9EXZ7IqFJSXH7W6eLw0blntp2NAydGOSqPGVs/5mW9Zc" + - "JGKbRSxELIRDCFuIuAmiBa8eMW37rcdc1JDtM+3PYdSp43k9/ulPgmDrsnz+vFBktRWBZYEVKSlU" + - "feH5wYPP7u5Hfy4uzi4oLq50IjkSaXrf2vIfBPnV6PlKiwKg0XfyNe2BPkmJ8+oUGeh/bLjNu7En" + - "0Gy+w5sppLcyKRra9IZJ98hTvciop9MPSSFUwGTnEjHICsgpyKHYHzjquWMvrJ+wewUENPFjCIAx" + - "k3uStyIMbw5FVieWJvJpBE5kgqq+X1VcPGdRcfHMxSUluSUlJbmlUZ+1tKRkLRGVnrZ9Rw12rSLt" + - "sDpFg8vmfbpw0HH3wcuMMSaiao2XAbwMjPFhPL/ReN6DfsY8tHHekN0WXR929vqsCpWruFshPEqF" + - "o3IyADuWTxgea1rYTbRVeEMmc+SnCwp+OcB4l3kmLq0D4BnzkA/MMUBjvDMXC1DBqlkCFr9N9E//" + - "HIZpPyDsQVuTFwsMfP273k8GFeLbvo9izwe8DGA8VMPgIc/D2piALlPFDGWUMqNuazOun/RbeQU7" + - "L/zl0cfC+SPOXjG84NBRawCvJNoSE7PiBgr5Xx/MKf7jLnzIbUPKlHVF5C11KgJfD9+shY8Vxjd3" + - "0780rEvP8bFDDvnVQGO+lU5MeTDwzM5aTbOzNyrw/XNbWx9JFLknk+sjqjobUHJq9XS/cNj3jZcZ" + - "Ac9PwBIDyAeMD2O8RhhvpTFYqYpGqMQOM2UhlFOhsvjfgNJ6ofxyoZaXbHPt8mDNjDU9ACYBbyGA" + - "AT/KZEZ/MpO5qciYyRlgROeJGSh0nQCL21Ufmx4EL8dMpqScRt4DFVAAYMCtORx+0Rhz7aFF+GJB" + - "BmNM/JKklGo1KlBtHZ474U79P9hZOZcQYb0unD/mwu05qADCZwE4C8Y7I3kTk4kFx+mUuzfMKf5e" + - "+rn+rUMq4PR4hFII0gw0xpdvGAWGoDqHf9m8IuV8m2Qtf1pQMPok37+50JhpHlC8EzwRcAzwOqs+" + - "Vkv06I+da04nInd3RvuxgCIAhcUTF5zvFQ79oucP+Cy8zIjE6qQnt5Pviu5IqAogVKNCNSrBUte6" + - "blnrqi/Vo3O9rI3Pc7cbP6sgGQcAf7rvl3zK908uBKjAGK5jrrmNKKHj/RS3E6L3V2USLUzkZAB4" + - "i75pTivwwQMyoKYQ685+QOtScvzUHPbIlJ54ZVsuDPTrZDmnQqUQggo1qkoNRDyFeJ6XGQfjF0fW" + - "3O9YWxW6adNzw36Dzm/JKEJ0k7QgtfiSygd1vSrkdZ3jlb6fneT7Y+MN1xrmVX9gbkw9q1MdsemF" + - "U5wkpwqSRSw49gfZAcPPHOsVlIww/sBjjPEVnqfGZEQlWKVCjWK31TW/dv56pCruU126TGxPl+US" + - "IrAgNQ7TQ+pNukQqfalLNimApvMt6CZMTvsiu3VOJ17XnrNWZ9m85oK8Qmz4sFB+CeXrF29dfOqG" + - "1PwKs6fOKyvKjrnb8wrHGD8TWfCOEoX85zb96dgXY9leN2NM+y3SJZG4u7XsSldIykFPz09NHxbR" + - "T2U3M11AsKf8aRqtnBqQoG91oWkGOS0/XaQo2Pf3u5mUDK9LukD7Mv5Tv9teSQ4VzipsINUtW9Zc" + - "t/mFiRu7WbcOuQNP+MXQ4hGX3mEKBl1mjB9bbwAqSz6cf+TZ8Qaabta/u6hM92ItpZs5dvyor5R/" + - "dwvp9QAa6eFzfxRlpVMk2mXh93czeyPn1Bn5ShWtYAJsyEve+OPgC7Hzmgx3USDtejQedlbtDX7h" + - "0Ns6HChV5LcvP7rpb1+qx/690dHrtewL05c2c7ZLtrM91fOpDGjXyvT9+WYBPQAg3NPcey1n4vVt" + - "FUJSIfGNjJZNy2ekkqzpazIJOefSoTaA9q1VY+5Wbvs9NAoYVBkFh5Sesi9lJ/u6lt5+WETpoi2M" + - "PpZU/k9szmKGtVGRWBjQ6g3zP78pxfSGKb+tJ4LPAsi31S/+uXCUlVZmCIc+DlI15L4Cpr/1FA1d" + - "0VLqAilzgcCGChdQc5eoTXqpkNS66hv1YLsUElURiG1sOZj7lunf3v3fwlBKjRfX9EjEHKcscV98" + - "D40zRKIqgEpz4yvTVnfjU/VbmL/r4yhwTTbPCNsZNi8g50/OnvbCsXu5wQqVURCBuOb7seu98n7A" + - "/L23Tc8NX8mW6pL73UoOhYPH/GJv/I7Dzlqbg5pRUG1q++A//+Ng+4f9gDlATVzLHfErZiHioKrn" + - "H37uhgeG597sdYnIYeeszypQqQawre9dHNbd0Yj9/5KnfsB8DJpuXXj8Q+ryj3dUZglD1Uz3MsWv" + - "HX7uh1fv6QGHn7upAmrWQpEV2zSt+bVptamw+6C9VaP/hcoHrvkABgydUjPLywy6Oboh6HW6PgLj" + - "LYqStqYRQHKDMQflMhXOQrnata27tvGvufrEn8ZBfmdPP2AO7NpmAAw85B8qTyjKlt1svAHTjPGL" + - "k4w0jAcTAyllnBoh9Kxw/tEdS8cuT0WyH4vX1PYD5qMBzQDE2eFDxz09zsscWuwVHX6a8YwaFAiM" + - "NAkHr4vdUdf82rQN6JwnSl4N4vAxeKdxP2A+mjXuKTvcXcY9TdOnyxPk4zKZ/vbRAqe75C3QfZZY" + - "0P/y6/7299z+H4QrdGsoib8JAAAAAElFTkSuQmCC" - }, - "DuckDuckGo": { - image: "data:image/png;base64," + - "iVBORw0KGgoAAAANSUhEUgAAAIwAAAA4CAYAAAAvmxBdAAAVhUlEQVR4Xu3dd5SU1d3A8e/vPs/0" + - "2crussBSdkHEAgoomEQSUTAW3hRbfMUeUwgSj9FoorGXqDGxBHvMazRGE0KsBQuiEVRUEEEM0pfO" + - "1tndmZ32PPf3knDCUZAlIYsxOfM553f2v91/vnufOzP33BFV5TOnQFQ1snFN/YCVb88Z6S2dd1B8" + - "3Qf7lTSv6R9PNle4uXQEVNRxvUy4qL29pPeGRNXA5d6g4fOLhoyYN2C/oe8Vl5QmAoFAnm72GQqm" + - "oKO9vXj5e/NHtr48/fjq92eOq2xYOsixvuMpKFuhfJywjQMYI5oKF7evrR09t/LE7z3Ze9TYZyPx" + - "+FpjjPdfEkxBY0ND9ftP//7EkpceOLNm/cJh+J6rylYWcIwSiCHhuEo4ggRdMCLq+UomK5pJq2Y7" + - "BD8HqoIAAmKhPdKjuX7EMc9WnfCde/YZOfot13Xz/6HBFKi1pdmlCya23Dz5PPeDN/eygCqAqIn3" + - "ULduiAb2Ha3BfUYgJeUgBhxHRAwgoupbfF/wPcXL461bRX7xm5Jb8q7Yhno0lzUYMIANx9Lh0y99" + - "svjEc292YkXzAfufE0yBse0tX+qY+uNrOp/+9SGo5yggTlADQw72I4efQGDf4Wg6RW7xO5Jf8g7+" + - "ulVi21rRXAr8HKpWRBzFCSGRIpyKSnX6701wv0PU7Vunms2RmfO0ZGc/Z/zWjSKiAqJOdV1LyUVT" + - "7wkdcuQvENP8mQ+mQGPZt2ZelLj2nCl+Q30ZAqijoVFH+rGTJiHROJnXniE75znxN64yms8AKghd" + - "062DEZVIqQbq9tHwYcdpcL+DNDvvFUlNv1dsywYHA0jAjx512lslF956vkSL5n5Wgymwfq+O/7vx" + - "jvZfX/0/+FkXC27N3n7xlOvVlFdp8pFfSnbuC0bTbYKqIOw+BcSoKeut0WNPtZEjjtPOx++X1FMP" + - "GPysAXD777epxy1PXuj2qXsEsJ+hYArUy9e2Xn7GtPTLj44AFVVHY1/7tld0+g8l+cht2vnE/Y7N" + - "p0S2htJ9FEDUlPWxxZOusE5VjSRunIK3YbkrAhIpzlRMfeGy4P6jbwH8z0AwBZrPDWqacvQzmfkv" + - "D0ZETbxCS3/wC9/t1ZeWq78t3oZlDqiwp6nRyJiveMXnXEL7fdeTef1JV9UKKlp118wrQgeNvX5X" + - "0Rj2uMJjqOmik/6UmbclFkSdylrb4/qHfU0naTzvK463fqkLKijo1oGt0/3ESudrT7jNPznTxL8x" + - "iehXvuUhroJKw6RxV+aWzJ8MyL9vhSmIJm778fT2h244CiPqVg+0Pa64TzPzZtv2X18XUD8jAIiB" + - "3nWEK6rBDaHZTmyiCb+lGe1MoGpB6FZOWR+/7KJbbXb+n0lOv8tV64mJlnX2mr74ZKei11PshMue" + - "UmA6X3nyqrbf/uxIAKe4l5ZdcqdNz5vNllhc9TKCAIAaQ6puNLEzzqN86EhQRTs78BvWkX3/bTpf" + - "mkZm3p/RbAoM3cJrWe+03PB9yn881drOlJd85gHXT7VGG77/1TvK7n1pRThe/MGnuMIU+M2bj91w" + - "wrBHbUdDnEDUVlx2n29TbbT8/AIXLy18hAQiFJ8wmdD44wnvPwoxZvs9ENlFb9D2qxvIzH0BxNId" + - "VMGtGuBXXPNrm7j7OskueNkBKDnjkudKp1x7ItD5KQRToNavaLzgGy91vjr9ABAtPuUCL/LFo2m8" + - "8ETHJlsMwsek9zqEztMvRbw8TjBMqLSU4spKiquqicVjiAgANtVBx8O3kbjvOtTPgPCvUwjufZBX" + - "ftEt2njBScZv2+gYN5KvfvCN84N7H3DHpxBMQerNmZc3nHvU5ajnBGqHedW3Psam848jv+I9F2FH" + - "4qA4gIJvkHgZgeGHEvzSUZSMP4FQccnHVpvk0w+Seu73ZN57Hc11guFfo6JFX/+uFzpgNE1XnOUi" + - "KpEDvriy4p4XxrrB0Jo9GExB0+bNtanvjX/VX7mor6jR6rtmeOk3ZpJ46CZXRKWrx4MTK6fkrB8S" + - "n3AqTnkVuAFEgO0qU1Xw8ngbVpO462o6ZjyCGMu/RB3tOfUZr+03t5B5+/kAIhq7/g8/rTrqhEv3" + - "YDAFCx+889qiWyZfahVihx2fL598haw7ebRRmzbshCgEBgyj+rY/Eui/F/8UVVp+eTmt918HRvlX" + - "hOqGexWX3q4bvn2kg582nZW1awc9vuhL4Whs1R4IpqC1ubnXhm8d/mp45cK9cEK29/0v+22P3Elq" + - "xsMBhJ3Ssj7U/OYVwv0GsTvU99h03nGkXnsKEXabqqNVV96b75z9vCRf+kPAEWi5+P4fjvzfs2/e" + - "Ay+rC96f9fzYPqsX11mF2EGH+yYal9TMJ4wCKJ9ILAQmXbXbsWSyeVLpPGUX3ULm3Tfxk43sNrG0" + - "/eE+Uz7pMk29/Li1Nmeyj917QsexJ9xbVFzcDmDoFgWe5wWysx7/mvq+o1Y0NuEUOp6bpjaXEgV2" + - "Nuke/Sg6+n8B8H3LklWNzJq7gtXrW7BW6UpzopN7fj+X+6bNZdqCNuKnnof6oOzmqEr2w/cc9fMa" + - "2OsAtQoVq947YPVfFu/XzStMQWtTU1WPJXNHWwWnR28bHjZKWu+9AUVFlE+mkDxoPEXxCNYq055f" + - "yKamJGNHD0REUFVA2JlgwOGbJxxMLBKkrSNDONWTjkfvxG/dwO6yXobO2TMl+sVjNPPBO+pmM+FV" + - "s18cP3T0597oxmAKNqxYtm9R07oaayG0/0HqNW4mt26Vg4LyycSD7N6jcIFM3iMWDTH5lKEEXId/" + - "RFEsxN+VFkfQWDXxcceReHQqGHaPqnS+NctUXnyzlUBIfS8jzvzXxnieF3ZdN+PSLQo6PlhwcMxa" + - "Y30IH/h5Mu+/o9bLsCu58l4AhIMuR4/ZG9cx/LNS6RwbGzuorSkjfuTxtP7hLsBntwjkNq0T9TxM" + - "RV/1Ni2jdPUH+3q5XNFfgzF0hwLHXfmXA3wFcRwN7zuC9HvviKqC0uXkjYsCIrItlpa2TmbM/pCV" + - "a5tR1a5DTWWZ+MNHuPTWGbwwZxnBQfvi9hwAym6PptvFb20kWDsQtRBNbO6ZSyX7dNcjqUA1HG9a" + - "308VJF6qblVvydUvQa2KCjtlFGwqScazRAMOAIn2NOdc9kfqN7Ry8jEHcvyRQ6mrKWdn1m5KsHJd" + - "C9Fw4G97oKMO+SrBQUPIbVgBwu5RJbP8Qwn03UvVn4FR39H21kFUVi0wdIeCYDjRWKkKpqiHqlr1" + - "WpsEdvGfDLgNa2nPeADbVpctEeD7lufnLGXpqka6MnhAJRMnDKdf7zLO/NpIxA0QqKlF7XZ/a+uA" + - "bB0UdGcrjKrkN9QT6N0fFVEVcFJt3bXCFKiq6zdtKlYFJxoDL49NZ1GlawLRVYtozfhUFwFA76pi" + - "vvyFvXnpjWVUlcU4aP8auuI6hovPOQxVRUQAMOE4WFC2MmEI9YaiUUJ0X0F9yKyGxIuW3AZA+DgF" + - "v61ZnPJKRQEFL9FS3k3BFAjq4uWCqkAoiFormvdF6ZoKRFcupjnt8XfhUIDLJx3BN48/mMqyGPFY" + - "iF1jWyyqis21E6iGyF5CdD8hMkQI9gYJCFgAiB6oaN7Q8LAFYQeay6iJRFQFVMHx8+HuC6ZAsCoA" + - "iICqKICyS6H1S9mcaEf7Fm1bIYJBl9qacrqm4DWguTWgafDbIL8O0u9R/qWn6HGEgxMTAFC2soAB" + - "P6G0zrS0PKEggPIxqqBWQURQUO3mE3cF4uG6nirYnAeOYzGOURB2wSTb8NavJrNPLyIBh11jayTN" + - "v0TbHgevETQHeKAWALcYQEDZSkBEyayDtlmWttlKvpGthE8WDInN5nRbLMZ43RdMgS/hWEqh3E+m" + - "RNygEgqqtrNrCsFlC2g79OBdB6OKpl5G10+C7CpAQYRtRPgYB/x2JTlfScxSUksUzW4XirIDtWDi" + - "ZeolWrEWACQUaeuuYApEck5JeTNKX789gRhHnJJS8pvXIkKX1ED0w3m0ZM+muoguaXYxWj8R/CYQ" + - "AQSskmsCJw5OVEDA71BSi5S217b+9FOg2/ekXUcc6NmX/MZ1YFUQcGJFm7ormAIh41b1Wm+VAzXZ" + - "gteR0GDNYNJL39cthF0IL1tIUzIPFXStcy74jSAGAFWl/lpLxzuKBMCJAgb8JKgHOHyMKv8QMUZD" + - "g4aQnPMiKoCIOqU9VnZbMAWSD9UN+QDlWJvJSeYv7xMeOpzEzD8h7Fpw43Kam5rw+xXjGGGnIsPB" + - "REHTgGDTkF6tqANY8JJsgwEUAJSPPL0EULoWjGmgujfp5R8KgImVtG0JZhWAoVsUlIz/2jtqRUGl" + - "8903NDb8EMSEUNjlmM40/pplpHIeXZHwUKTHZMAFwIkJ1acZghWAgNqPjAIGnDhE66DHl4Wacw0D" + - "LjGE+8FOP7VQcCur1cSKNbe+XhSIjfjCMhONd+cepiBYO/hdU1TW6idbyjvemWuqzv2JBqr62OzG" + - "FQ67oh7BD9+l/YjDKA4H2CkJID0vJ1OfQJvvI1QjlI8zFB0sZJYr2U3gd4I44JZAsEoI9gS3FCQo" + - "CEpmDXgZ2PnLftkS+xc0/eH7+Ml2wUB05Ji54jipbgymwEQi6yNDhi1Mvv3KYdk1SyW3ZqUWjz3G" + - "Njw81QgqdEFVCS9ZQFPGUlNC10yUxBt9aLjXEttHKB4txIcKsf3lb+GgoApYthLAQm6j0vqK0vSs" + - "Jd8CIjuPsnjcMdoy7TeiqBjj+LERh7wIaDcGUyCO27klkGc7tgSDlzctT/7eVpx8Ng2/uwfVHLsS" + - "Wv0+ifYUWhVBROiKWh8vBe3v6t/GhCHYE6IDhUidEKoGEwIvCZl6SP1F6Vyh+B2AbB1lRyiEB+zl" + - "B/v0p+PtOQaBQJ8BqyN77/c2QDcHU1AybsLTm35184Vec0NVYsbjUn3uj6Ro9OFe++szAghdcho3" + - "0LlpI7naHoRcoStueSXKNvgZSK+GzlWKiO74ASMg0vV7LwCqRstPPlsTzz2Gl2wTMVB82DHPumXl" + - "mwvXfewB6vvO6h+c/mDLE787Ra1or8mXeMWHHcmHJx3uiPiGLqgE2XTlg3z+xK9THg3SlbZZM1h+" + - "1gTApzsFq+u8QQ8+ydKTxomX2OSYaFHH4N++OD42YvTcPbDCFIjj+JWnn3tX2ysvTMgnmoo3P3CH" + - "6XHyWfT46kS/6YmHBFTYCdEcgSXvksh+lfIoXQrVDsKUVOIlNrGdrhaRrlmjvS66yjb+7n7JNW9y" + - "cUR7njFlRmz4qPl78H6YgtiBo96s/t4lz6iKesmEs/6Gy2yvC66QQGU/q12djbEQWrqI5lSOXa8E" + - "fQgP2ptP+n1N8SCpoPPPnbBT0dIj/icfrhssmx+611GBQGXftupvnX8bIvk9G0xhlfGqTv/2jZEB" + - "+zQAND89zU0teFv7Xn6TlUDUdtEMwbVLaG9N4FslmW+gKbOGjN+5wzFNE45QPGY8WFAAC4niEHdM" + - "GMjJU0bw4Ji+GPsP9qIQqq6zfS6+Rtb85HzRXMqAY/v+6PpH3PKKN9mOc+WVV9K9CiQQ3Bzdd1iw" + - "afrDX1LNO8m359LzrO+pW1yh7W+/blAr7AjJWzoOPZaaAX2Yu/lWHls1ldc2z2VjOklJsILiQBwR" + - "wVefXDRAy1N/gnyWv4yu4s4zhzCztox2DAIctaABlF1y4mW29md32y2bdJqfneYCUnzI4cv6XnrD" + - "d8SYxKd1e0OBaqz+yose23j/z8cBFA3/gjfw9l/Lxjt+rg2P/soFX9iBQ+OP7mTUWWeyoOkaXtv0" + - "KqtTsDxpSfoVfLn34YzoU8bsxnksb23EeWMxxwRyvDGigqVJWJ5U2vLQvznNA3cuIJLz6YqEiuyA" + - "a27x1fOov+J8x+bTxo2Xdw6btfDUYK8+j32aN1AViKT6/eS6ye1zXn45tWR+Tce7r7v1V/zQ73/N" + - "L0R9z2+Y9oCzQzTWx/1wEa1pH8SwlWDE0JBp5oHVv2eB+jQnhdaUoWNQnIE1LmQUUP4uHzDkHEOY" + - "nQSjYCJFtt9lN/kmFmflxZMdm0sbxbGDpj50+5ZYngT49IMpPJqW7TP9pVPf/fy+T3qJTcUtM59y" + - "FPEGXHuLOOUV3oZ7fuGieeEjgsvfo7WjE9cN8FECOI5gEEQEgJyFVF7ZnhXBIqiyA1UIlFb5tdff" + - "ZlFY+aMpjt/ebFSh/yU/nV467pgrAf/fdItmgVtS9uqwF98620TK0mCl5aUn3OWTT6dq4tky8Of3" + - "eSZSZlXZJrC+nmRTC0aibE/4OFVFAWv4GMcqxirbUysaG3yAN+S3T2i+sYHlF37H8doajSr0Ovv7" + - "s/qce+E5QPbffO1qQah33+kH/nnhaYHKfq2qKm3vvOYu/to43LIKhr0415aOOTpvNaBWwSSayNav" + - "QrR0hzhcP86g6H4MjNUyuuJArjrwO9w06hGOesWl3+oOgr5iBEpSecJZH2vZOiqKG7N9Jl3k7f2b" + - "P7Hp/+7RlZed7/rpdqM4ts+5lz5be+2txyHS/hm62Lkg39x05AenfOWejoVv9hdUkIBWTzzHqznv" + - "YumYN1fX//JnJvXBItNy7k8lftpgZm28iRVJZXM2yoiKcXx3yERqi3qxvaY/Pcqyb09kc0WQRf3i" + - "lKY8Rq5IYBF1wnFKDxtva6ZcaHONTdRffZF0Ll/iYsAEI/m6a29/qPq0b56/LZbPVjAFNpMeuvrK" + - "i2/f+ODdY9TmHXwI1dT6vSedpz3GHyvJhfN1VUMSjhljFrb/UuLBfeRzPY+hX7w/O2PzORYePYbk" + - "orcQFRXXJVBdo+Vjj7QVx5+MuAHZcPdt2vTsYw54gkKopq55yN2/vano4M/dBmQBPqvBFKiWtc56" + - "4YJlF3x3Unb96nIEUKOR2sG28usnafmErxOoHUwwGkLEiCDCNgg70paXnmPNjVdr0fCRWjJmLOEB" + - "daRXraDxj7+j9dUXjc2kBFTEuH7VSWfOrbvqpkvc0rI/Awrw2Q+mwPgdHaPX3X3rj9dNvfEom0kF" + - "VAEVdYvLtGjoAVo85ggtGf05CfcbqMGqKjGhMB9pRwEBUN/Ha23R9OrlZFatlMRrL2v73NclXb/C" + - "qJ8XMQCyJaZD1g687hdTi0aMvh+Rlv/AL9gq0Hw+3PbWnMPX3n7jlLY5s8baXDYEgIIiagIh3NIe" + - "Gqqq1EBVb9zyCtxoXDFGbT5n/PaE5ho2mtzmjeSbW/A720R9X8SwTbimf33Pb5zxUO9vTv5VoKKq" + - "/r/gK/wKbDYTTi1eNHTzH393SvPzT0/IrF5Zp2KNCFtpF8cqBba/ndVEYqmKCcfP6Xn8xEeLRx78" + - "rFtS2oCIAvx3BVMgms/H8q3N+zc9/cTYphlPf/6vIWU3ru+jnufySUTULSpujwzca9mWPcy8skMP" + - "e6Xkc4fODlb32iyOk6cb/T/N+faHj8AX2gAAAABJRU5ErkJggg==" - } -}; - -// This global tracks if the page has been set up before, to prevent double inits -let gInitialized = false; -let gObserver = new MutationObserver(function (mutations) { - for (let mutation of mutations) { - if (mutation.attributeName == "searchEngineURL") { - setupSearchEngine(); - if (!gInitialized) { - gInitialized = true; - } - return; - } - } -}); - -window.addEventListener("pageshow", function () { - // Delay search engine setup, cause browser.js::BrowserOnAboutPageLoad runs - // later and may use asynchronous getters. - window.gObserver.observe(document.documentElement, { attributes: true }); - fitToWidth(); - window.addEventListener("resize", fitToWidth); -}); - -window.addEventListener("pagehide", function() { - window.gObserver.disconnect(); - window.removeEventListener("resize", fitToWidth); -}); - -function onSearchSubmit(aEvent) -{ - let searchTerms = document.getElementById("searchText").value; - let searchURL = document.documentElement.getAttribute("searchEngineURL"); - - if (searchURL && searchTerms.length > 0) { - // Send an event that a search was performed. This was originally - // added so Firefox Health Report could record that a search from - // about:home had occurred. - let engineName = document.documentElement.getAttribute("searchEngineName"); - let event = new CustomEvent("AboutHomeSearchEvent", {detail: engineName}); - document.dispatchEvent(event); - - const SEARCH_TOKEN = "_searchTerms_"; - let searchPostData = document.documentElement.getAttribute("searchEnginePostData"); - if (searchPostData) { - // Check if a post form already exists. If so, remove it. - const POST_FORM_NAME = "searchFormPost"; - let form = document.forms[POST_FORM_NAME]; - if (form) { - form.parentNode.removeChild(form); - } - - // Create a new post form. - form = document.body.appendChild(document.createElement("form")); - form.setAttribute("name", POST_FORM_NAME); - // Set the URL to submit the form to. - form.setAttribute("action", searchURL.replace(SEARCH_TOKEN, searchTerms)); - form.setAttribute("method", "post"); - - // Create new <input type=hidden> elements for search param. - searchPostData = searchPostData.split("&"); - for (let postVar of searchPostData) { - let [name, value] = postVar.split("="); - if (value == SEARCH_TOKEN) { - value = searchTerms; - } - let input = document.createElement("input"); - input.setAttribute("type", "hidden"); - input.setAttribute("name", name); - input.setAttribute("value", value); - form.appendChild(input); - } - // Submit the form. - form.submit(); - } else { - searchURL = searchURL.replace(SEARCH_TOKEN, encodeURIComponent(searchTerms)); - window.location.href = searchURL; - } - } - - aEvent.preventDefault(); -} - - -function setupSearchEngine() -{ - // The "autofocus" attribute doesn't focus the form element - // immediately when the element is first drawn, so the - // attribute is also used for styling when the page first loads. - let searchText = document.getElementById("searchText"); - searchText.addEventListener("blur", function searchText_onBlur() { - searchText.removeEventListener("blur", searchText_onBlur); - searchText.removeAttribute("autofocus"); - }); - - let searchEngineName = document.documentElement.getAttribute("searchEngineName"); - let searchEngineInfo = SEARCH_ENGINES[searchEngineName]; - let logoElt = document.getElementById("searchEngineLogo"); - - // Add search engine logo. - if (searchEngineInfo && searchEngineInfo.image) { - logoElt.parentNode.hidden = false; - logoElt.src = searchEngineInfo.image; - logoElt.alt = searchEngineName; - searchText.placeholder = ""; - } - else { - logoElt.parentNode.hidden = true; - searchText.placeholder = searchEngineName; - } - -} - -function fitToWidth() { - if (window.scrollMaxX) { - document.body.setAttribute("narrow", "true"); - } else if (document.body.hasAttribute("narrow")) { - document.body.removeAttribute("narrow"); - fitToWidth(); - } -} diff --git a/browser/base/content/abouthome/aboutHome.xhtml b/browser/base/content/abouthome/aboutHome.xhtml deleted file mode 100644 index cb3fa634a..000000000 --- a/browser/base/content/abouthome/aboutHome.xhtml +++ /dev/null @@ -1,60 +0,0 @@ -<?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/. --> - -<!DOCTYPE html [ - <!ENTITY % htmlDTD - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "DTD/xhtml1-strict.dtd"> - %htmlDTD; - <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> - %globalDTD; - <!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd"> - %aboutHomeDTD; - <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" > - %browserDTD; -]> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <title>&abouthome.pageTitle;</title> - - <link rel="icon" type="image/png" id="favicon" - href="chrome://branding/content/icon32.png"/> - <link rel="stylesheet" type="text/css" media="all" - href="chrome://browser/content/abouthome/aboutHome.css"/> - - <script type="text/javascript;version=1.8" - src="chrome://browser/content/abouthome/aboutHome.js"/> - </head> - - <body dir="&locale.dir;"> - <div class="spacer"/> - <div id="topSection"> - <div id="brandLogo"></div> - - <div id="searchContainer"> - <form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)"> - <div id="searchLogoContainer"><img id="searchEngineLogo"/></div> - <input type="text" name="q" value="" id="searchText" maxlength="256" - autofocus="autofocus"/> - <input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;"/> - </form> - </div> - </div> - <div class="spacer"/> - - <div id="launcher"> - <button class="launchButton" id="downloads">&abouthome.downloadsButton.label;</button> - <button class="launchButton" id="bookmarks">&abouthome.bookmarksButton.label;</button> - <button class="launchButton" id="history">&abouthome.historyButton.label;</button> - <button class="launchButton" id="addons">&abouthome.addonsButton.label;</button> - <button class="launchButton" id="sync">&abouthome.syncButton.label;</button> - <button class="launchButton" id="settings">&abouthome.settingsButton.label;</button> - <div id="restorePreviousSessionSeparator"/> - <button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button> - </div> - </body> -</html> diff --git a/browser/base/content/abouthome/addons.png b/browser/base/content/abouthome/addons.png Binary files differdeleted file mode 100644 index 41519ce49..000000000 --- a/browser/base/content/abouthome/addons.png +++ /dev/null diff --git a/browser/base/content/abouthome/addons@2x.png b/browser/base/content/abouthome/addons@2x.png Binary files differdeleted file mode 100644 index d4d04ee8c..000000000 --- a/browser/base/content/abouthome/addons@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/bookmarks.png b/browser/base/content/abouthome/bookmarks.png Binary files differdeleted file mode 100644 index 5c7e194a6..000000000 --- a/browser/base/content/abouthome/bookmarks.png +++ /dev/null diff --git a/browser/base/content/abouthome/bookmarks@2x.png b/browser/base/content/abouthome/bookmarks@2x.png Binary files differdeleted file mode 100644 index 7ede00744..000000000 --- a/browser/base/content/abouthome/bookmarks@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/downloads.png b/browser/base/content/abouthome/downloads.png Binary files differdeleted file mode 100644 index 3d4d10e7a..000000000 --- a/browser/base/content/abouthome/downloads.png +++ /dev/null diff --git a/browser/base/content/abouthome/downloads@2x.png b/browser/base/content/abouthome/downloads@2x.png Binary files differdeleted file mode 100644 index d384a22c6..000000000 --- a/browser/base/content/abouthome/downloads@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/history.png b/browser/base/content/abouthome/history.png Binary files differdeleted file mode 100644 index ae742b1aa..000000000 --- a/browser/base/content/abouthome/history.png +++ /dev/null diff --git a/browser/base/content/abouthome/history@2x.png b/browser/base/content/abouthome/history@2x.png Binary files differdeleted file mode 100644 index 696902e7c..000000000 --- a/browser/base/content/abouthome/history@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/noise.png b/browser/base/content/abouthome/noise.png Binary files differdeleted file mode 100644 index 3467cf4d4..000000000 --- a/browser/base/content/abouthome/noise.png +++ /dev/null diff --git a/browser/base/content/abouthome/restore-large.png b/browser/base/content/abouthome/restore-large.png Binary files differdeleted file mode 100644 index ef593e6e1..000000000 --- a/browser/base/content/abouthome/restore-large.png +++ /dev/null diff --git a/browser/base/content/abouthome/restore-large@2x.png b/browser/base/content/abouthome/restore-large@2x.png Binary files differdeleted file mode 100644 index d5c71d0b0..000000000 --- a/browser/base/content/abouthome/restore-large@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/restore.png b/browser/base/content/abouthome/restore.png Binary files differdeleted file mode 100644 index 5c3d6f437..000000000 --- a/browser/base/content/abouthome/restore.png +++ /dev/null diff --git a/browser/base/content/abouthome/restore@2x.png b/browser/base/content/abouthome/restore@2x.png Binary files differdeleted file mode 100644 index 5acb63052..000000000 --- a/browser/base/content/abouthome/restore@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/settings.png b/browser/base/content/abouthome/settings.png Binary files differdeleted file mode 100644 index 4b0c30990..000000000 --- a/browser/base/content/abouthome/settings.png +++ /dev/null diff --git a/browser/base/content/abouthome/settings@2x.png b/browser/base/content/abouthome/settings@2x.png Binary files differdeleted file mode 100644 index c77cb9a92..000000000 --- a/browser/base/content/abouthome/settings@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/snippet1.png b/browser/base/content/abouthome/snippet1.png Binary files differdeleted file mode 100644 index ce2ec55c2..000000000 --- a/browser/base/content/abouthome/snippet1.png +++ /dev/null diff --git a/browser/base/content/abouthome/snippet1@2x.png b/browser/base/content/abouthome/snippet1@2x.png Binary files differdeleted file mode 100644 index f57cd0a82..000000000 --- a/browser/base/content/abouthome/snippet1@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/snippet2.png b/browser/base/content/abouthome/snippet2.png Binary files differdeleted file mode 100644 index e0724fb6d..000000000 --- a/browser/base/content/abouthome/snippet2.png +++ /dev/null diff --git a/browser/base/content/abouthome/snippet2@2x.png b/browser/base/content/abouthome/snippet2@2x.png Binary files differdeleted file mode 100644 index 40577f52f..000000000 --- a/browser/base/content/abouthome/snippet2@2x.png +++ /dev/null diff --git a/browser/base/content/abouthome/sync.png b/browser/base/content/abouthome/sync.png Binary files differdeleted file mode 100644 index 11e40cc93..000000000 --- a/browser/base/content/abouthome/sync.png +++ /dev/null diff --git a/browser/base/content/abouthome/sync@2x.png b/browser/base/content/abouthome/sync@2x.png Binary files differdeleted file mode 100644 index 6354f5bf9..000000000 --- a/browser/base/content/abouthome/sync@2x.png +++ /dev/null diff --git a/browser/base/content/autorecovery.js b/browser/base/content/autorecovery.js deleted file mode 100644 index 29ccaed3f..000000000 --- a/browser/base/content/autorecovery.js +++ /dev/null @@ -1,60 +0,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/. */ - -/* Auto-recovery module. - * This module aims to catch fatal browser initialization errors and either - * automatically correct likely causes from them, or automatically restarting - * the browser in safe mode. This is hooked into the browser's "onload" - * event because it can be assumed that at that point, everything must - * have been properly initialized already. - */ - -let Cc = Components.classes; -let Ci = Components.interfaces; -let Cu = Components.utils; - -// Services = object with smart getters for common XPCOM services -Cu.import("resource://gre/modules/Services.jsm"); - -var browser_autoRecovery = -{ - onLoad: function() { - - var nsIAS = Ci.nsIAppStartup; // Application startup interface - - if (typeof gBrowser === "undefined") { - // gBrowser should always be defined at this point, but if it is not, then most likely - // it is due to an incompatible or outdated language pack being installed and selected. - // In this case, we reset "general.useragent.locale" to try to recover browser startup. - if (Services.prefs.prefHasUserValue("general.useragent.locale")) { - // Restart automatically in en-US. - Services.prefs.clearUserPref("general.useragent.locale"); - Cc["@mozilla.org/toolkit/app-startup;1"].getService(nsIAS).quit(nsIAS.eRestart | nsIAS.eAttemptQuit); - } else if (!Services.appinfo.inSafeMode) { - // gBrowser isn't defined, and we're not using a custom locale. Most likely - // a user-installed add-on causes issues here, so we restart in Safe Mode. - let RISM = Services.prompt.confirm(null, "Error", - "The Browser didn't start properly!\n"+ - "This is usually caused by an add-on or misconfiguration.\n\n"+ - "Restart in Safe Mode?"); - if (RISM) { - Cc["@mozilla.org/toolkit/app-startup;1"].getService(nsIAS).restartInSafeMode(nsIAS.eRestart | nsIAS.eAttemptQuit); - } else { - // Force quit application - Cc["@mozilla.org/toolkit/app-startup;1"].getService(nsIAS).quit(nsIAS.eForceQuit); - } - } - // Something else caused this issue and we're already in Safe Mode, so we return - // without doing anything else, and let normal error handling take place. - return; - } // gBrowser undefined - - // Other checks than gBrowser undefined can go here! - - // Remove our listener, since we don't want this to fire on every load. - window.removeEventListener("load", browser_autoRecovery.onLoad, false); - } -}; - -window.addEventListener("load", browser_autoRecovery.onLoad, false); diff --git a/browser/base/content/autorecovery.xul b/browser/base/content/autorecovery.xul deleted file mode 100644 index 866bdf288..000000000 --- a/browser/base/content/autorecovery.xul +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> - -<overlay - id="autorecovery" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<script type="application/x-javascript" src="chrome://browser/content/autorecovery.js"/> - -<!-- This is an empty overlay to allow separation of the script into its - own context (needed for locale issues preventing browser start) --> - -</overlay> diff --git a/browser/base/content/baseMenuOverlay.xul b/browser/base/content/baseMenuOverlay.xul deleted file mode 100644 index c6c1b16dc..000000000 --- a/browser/base/content/baseMenuOverlay.xul +++ /dev/null @@ -1,100 +0,0 @@ -<?xml version="1.0"?> - -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -<!DOCTYPE overlay [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> -%brandDTD; -<!ENTITY % baseMenuOverlayDTD SYSTEM "chrome://browser/locale/baseMenuOverlay.dtd"> -%baseMenuOverlayDTD; -]> -<overlay id="baseMenuOverlay" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/> - -#ifdef XP_MACOSX -<!-- nsMenuBarX hides these and uses them to build the Application menu. - When using Carbon widgets for Mac OS X widgets, some of these are not - used as they only apply to Cocoa widget builds. All version of Firefox - through Firefox 2 will use Carbon widgets. --> - <menupopup id="menu_ToolsPopup"> - <menuitem id="menu_preferences" label="&preferencesCmdMac.label;" key="key_preferencesCmdMac" oncommand="openPreferences();"/> - <menuitem id="menu_mac_services" label="&servicesMenuMac.label;"/> - <menuitem id="menu_mac_hide_app" label="&hideThisAppCmdMac.label;" key="key_hideThisAppCmdMac"/> - <menuitem id="menu_mac_hide_others" label="&hideOtherAppsCmdMac.label;" key="key_hideOtherAppsCmdMac"/> - <menuitem id="menu_mac_show_all" label="&showAllAppsCmdMac.label;"/> - </menupopup> -<!-- Mac window menu --> -#include ../../../toolkit/content/macWindowMenu.inc -#endif - -#ifdef XP_WIN - <menu id="helpMenu" - label="&helpMenuWin.label;" - accesskey="&helpMenuWin.accesskey;"> -#else - <menu id="helpMenu" - label="&helpMenu.label;" - accesskey="&helpMenu.accesskey;"> -#endif - <menupopup id="menu_HelpPopup" onpopupshowing="buildHelpMenu();"> - <menuitem id="menu_openHelp" - oncommand="openHelpLink('firefox-help')" - onclick="checkForMiddleClick(this, event);" - label="&productHelp.label;" - accesskey="&productHelp.accesskey;" -#ifdef XP_MACOSX - key="key_openHelpMac"/> -#else - /> -#endif - <menuitem id="troubleShooting" - accesskey="&helpTroubleshootingInfo.accesskey;" - label="&helpTroubleshootingInfo.label;" - oncommand="openTroubleshootingPage()" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="feedbackPage" - accesskey="&helpFeedbackPage.accesskey;" - label="&helpFeedbackPage.label;" - oncommand="openFeedbackPage()" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="helpSafeMode" - accesskey="&helpSafeMode.accesskey;" - label="&helpSafeMode.label;" - oncommand="restart(true);"/> - <menuseparator id="aboutSeparator"/> - <menuitem id="aboutName" - accesskey="&aboutProduct.accesskey;" - label="&aboutProduct.label;" - oncommand="openAboutDialog();"/> - </menupopup> - </menu> - - <keyset id="baseMenuKeyset"> -#ifdef XP_MACOSX - <key id="key_openHelpMac" - oncommand="openHelpLink('firefox-osxkey');" - key="&helpMac.commandkey;" - modifiers="accel"/> -<!-- These are used to build the Application menu under Cocoa widgets --> - <key id="key_preferencesCmdMac" - key="&preferencesCmdMac.commandkey;" - modifiers="accel"/> - <key id="key_hideThisAppCmdMac" - key="&hideThisAppCmdMac.commandkey;" - modifiers="accel"/> - <key id="key_hideOtherAppsCmdMac" - key="&hideOtherAppsCmdMac.commandkey;" - modifiers="accel,alt"/> -#endif - </keyset> - - <stringbundleset id="stringbundleset"> - <stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/> - <stringbundle id="bundle_browser_region" src="chrome://browser-region/locale/region.properties"/> - </stringbundleset> -</overlay> diff --git a/browser/base/content/blockedSite.xhtml b/browser/base/content/blockedSite.xhtml deleted file mode 100644 index b56875eb6..000000000 --- a/browser/base/content/blockedSite.xhtml +++ /dev/null @@ -1,193 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!DOCTYPE html [ - <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> - %htmlDTD; - <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> - %globalDTD; - <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > - %brandDTD; - <!ENTITY % blockedSiteDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd"> - %blockedSiteDTD; -]> - -<!-- 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/. --> - -<html xmlns="http://www.w3.org/1999/xhtml" class="blacklist"> - <head> - <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" /> - <link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/blacklist_favicon.png"/> - - <script type="application/javascript"><![CDATA[ - // Error url MUST be formatted like this: - // about:blocked?e=error_code&u=url - - // Note that this file uses document.documentURI to get - // the URL (with the format from above). This is because - // document.location.href gets the current URI off the docshell, - // which is the URL displayed in the location bar, i.e. - // the URI that the user attempted to load. - - function getErrorCode() - { - var url = document.documentURI; - var error = url.search(/e\=/); - var duffUrl = url.search(/\&u\=/); - return decodeURIComponent(url.slice(error + 2, duffUrl)); - } - - function getURL() - { - var url = document.documentURI; - var match = url.match(/&u=([^&]+)&/); - - // match == null if not found; if so, return an empty string - // instead of what would turn out to be portions of the URI - if (!match) - return ""; - - url = decodeURIComponent(match[1]); - - // If this is a view-source page, then get then real URI of the page - if (url.startsWith("view-source:")) - url = url.slice(12); - return url; - } - - /** - * Attempt to get the hostname via document.location. Fail back - * to getURL so that we always return something meaningful. - */ - function getHostString() - { - try { - return document.location.hostname; - } catch (e) { - return getURL(); - } - } - - function initPage() - { - // Handoff to the appropriate initializer, based on error code - switch (getErrorCode()) { - case "malwareBlocked" : - initPage_malware(); - break; - case "phishingBlocked" : - initPage_phishing(); - break; - } - } - - /** - * Initialize custom strings and functionality for blocked malware case - */ - function initPage_malware() - { - // Remove phishing strings - var el = document.getElementById("errorTitleText_phishing"); - el.parentNode.removeChild(el); - - el = document.getElementById("errorShortDescText_phishing"); - el.parentNode.removeChild(el); - - el = document.getElementById("errorLongDescText_phishing"); - el.parentNode.removeChild(el); - - // Set sitename - document.getElementById("malware_sitename").textContent = getHostString(); - document.title = document.getElementById("errorTitleText_malware") - .innerHTML; - } - - /** - * Initialize custom strings and functionality for blocked phishing case - */ - function initPage_phishing() - { - // Remove malware strings - var el = document.getElementById("errorTitleText_malware"); - el.parentNode.removeChild(el); - - el = document.getElementById("errorShortDescText_malware"); - el.parentNode.removeChild(el); - - el = document.getElementById("errorLongDescText_malware"); - el.parentNode.removeChild(el); - - // Set sitename - document.getElementById("phishing_sitename").textContent = getHostString(); - document.title = document.getElementById("errorTitleText_phishing") - .innerHTML; - } - ]]></script> - <style type="text/css"> - /* Style warning button to look like a small text link in the - bottom right. This is preferable to just using a text link - since there is already a mechanism in browser.js for trapping - oncommand events from unprivileged chrome pages (BrowserOnCommand).*/ - #ignoreWarningButton { - -moz-appearance: none; - background: transparent; - border: none; - color: white; /* Hard coded because netError.css forces this page's background to dark red */ - text-decoration: underline; - margin: 0; - padding: 0; - position: relative; - top: 23px; - left: 20px; - font-size: smaller; - } - - #ignoreWarning { - text-align: right; - } - </style> - </head> - - <body dir="&locale.dir;"> - <div id="errorPageContainer"> - - <!-- Error Title --> - <div id="errorTitle"> - <h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title;</h1> - <h1 id="errorTitleText_malware">&safeb.blocked.malwarePage.title;</h1> - </div> - - <div id="errorLongContent"> - - <!-- Short Description --> - <div id="errorShortDesc"> - <p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc;</p> - <p id="errorShortDescText_malware">&safeb.blocked.malwarePage.shortDesc;</p> - </div> - - <!-- Long Description --> - <div id="errorLongDesc"> - <p id="errorLongDescText_phishing">&safeb.blocked.phishingPage.longDesc;</p> - <p id="errorLongDescText_malware">&safeb.blocked.malwarePage.longDesc;</p> - </div> - - <!-- Action buttons --> - <div id="buttons"> - <!-- Commands handled in browser.js --> - <button id="getMeOutButton">&safeb.palm.accept.label;</button> - <button id="reportButton">&safeb.palm.reportPage.label;</button> - </div> - </div> - <div id="ignoreWarning"> - <button id="ignoreWarningButton">&safeb.palm.decline.label;</button> - </div> - </div> - <!-- - - Note: It is important to run the script this way, instead of using - - an onload handler. This is because error pages are loaded as - - LOAD_BACKGROUND, which means that onload handlers will not be executed. - --> - <script type="application/javascript">initPage();</script> - </body> -</html> diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js deleted file mode 100644 index 7993a0c9c..000000000 --- a/browser/base/content/browser-addons.js +++ /dev/null @@ -1,536 +0,0 @@ -# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -# 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/. - -// Removes a doorhanger notification if all of the installs it was notifying -// about have ended in some way. -function removeNotificationOnEnd(notification, installs) { - let count = installs.length; - - function maybeRemove(install) { - install.removeListener(this); - - if (--count == 0) { - // Check that the notification is still showing - let current = PopupNotifications.getNotification(notification.id, notification.browser); - if (current === notification) - notification.remove(); - } - } - - for (let install of installs) { - install.addListener({ - onDownloadCancelled: maybeRemove, - onDownloadFailed: maybeRemove, - onInstallFailed: maybeRemove, - onInstallEnded: maybeRemove - }); - } -} - -const gXPInstallObserver = { - _findChildShell: function (aDocShell, aSoughtShell) - { - if (aDocShell == aSoughtShell) - return aDocShell; - - var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeItem); - for (var i = 0; i < node.childCount; ++i) { - var docShell = node.getChildAt(i); - docShell = this._findChildShell(docShell, aSoughtShell); - if (docShell == aSoughtShell) - return docShell; - } - return null; - }, - - _getBrowser: function (aDocShell) - { - for (let browser of gBrowser.browsers) { - if (this._findChildShell(browser.docShell, aDocShell)) - return browser; - } - return null; - }, - - observe: function (aSubject, aTopic, aData) - { - var brandBundle = document.getElementById("bundle_brand"); - var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo); - var browser = installInfo.browser; - - // Make sure the browser is still alive. - if (!browser || gBrowser.browsers.indexOf(browser) == -1) - return; - - const anchorID = "addons-notification-icon"; - var messageString, action; - var brandShortName = brandBundle.getString("brandShortName"); - - var notificationID = aTopic; - // Make notifications persist a minimum of 30 seconds - var options = { - timeout: Date.now() + 30000 - }; - - switch (aTopic) { - case "addon-install-disabled": - notificationID = "xpinstall-disabled" - - if (gPrefService.prefIsLocked("xpinstall.enabled")) { - messageString = gNavigatorBundle.getString("xpinstallDisabledMessageLocked"); - buttons = []; - } - else { - messageString = gNavigatorBundle.getString("xpinstallDisabledMessage"); - - action = { - label: gNavigatorBundle.getString("xpinstallDisabledButton"), - accessKey: gNavigatorBundle.getString("xpinstallDisabledButton.accesskey"), - callback: function editPrefs() { - gPrefService.setBoolPref("xpinstall.enabled", true); - } - }; - } - - PopupNotifications.show(browser, notificationID, messageString, anchorID, - action, null, options); - break; - case "addon-install-origin-blocked": { - messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarningOrigin", - [brandShortName]); - - let popup = PopupNotifications.show(browser, notificationID, - messageString, anchorID, - null, null, options); - removeNotificationOnEnd(popup, installInfo.installs); - break; } - case "addon-install-blocked": - let originatingHost; - try { - originatingHost = installInfo.originatingURI.host; - } catch (ex) { - // Need to deal with missing originatingURI and with about:/data: URIs more gracefully, - // see bug 1063418 - but for now, bail: - return; - } - messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarning", - [brandShortName, originatingHost]); - - action = { - label: gNavigatorBundle.getString("xpinstallPromptAllowButton"), - accessKey: gNavigatorBundle.getString("xpinstallPromptAllowButton.accesskey"), - callback: function() { - installInfo.install(); - } - }; - - let popup = PopupNotifications.show(browser, notificationID, messageString, - anchorID, action, null, options); - removeNotificationOnEnd(popup, installInfo.installs); - break; - case "addon-install-started": - var needsDownload = function needsDownload(aInstall) { - return aInstall.state != AddonManager.STATE_DOWNLOADED; - } - // If all installs have already been downloaded then there is no need to - // show the download progress - if (!installInfo.installs.some(needsDownload)) - return; - notificationID = "addon-progress"; - messageString = gNavigatorBundle.getString("addonDownloading"); - messageString = PluralForm.get(installInfo.installs.length, messageString); - options.installs = installInfo.installs; - options.contentWindow = browser.contentWindow; - options.sourceURI = browser.currentURI; - options.eventCallback = function(aEvent) { - if (aEvent != "removed") - return; - options.contentWindow = null; - options.sourceURI = null; - }; - PopupNotifications.show(browser, notificationID, messageString, anchorID, - null, null, options); - break; - case "addon-install-failed": - // TODO This isn't terribly ideal for the multiple failure case - for (let install of installInfo.installs) { - let host = (installInfo.originatingURI instanceof Ci.nsIStandardURL) && - installInfo.originatingURI.host; - if (!host) - host = (install.sourceURI instanceof Ci.nsIStandardURL) && - install.sourceURI.host; - - let error = (host || install.error == 0) ? "addonError" : "addonLocalError"; - if (install.error != 0) - error += install.error; - else if (install.addon.jetsdk) - error += "JetSDK"; - else if (install.addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) - error += "Blocklisted"; - else - error += "Incompatible"; - - messageString = gNavigatorBundle.getString(error); - messageString = messageString.replace("#1", install.name); - if (host) - messageString = messageString.replace("#2", host); - messageString = messageString.replace("#3", brandShortName); - messageString = messageString.replace("#4", Services.appinfo.version); - - PopupNotifications.show(browser, notificationID, messageString, anchorID, - action, null, options); - } - break; - case "addon-install-complete": - var needsRestart = installInfo.installs.some(function(i) { - return i.addon.pendingOperations != AddonManager.PENDING_NONE; - }); - - if (needsRestart) { - messageString = gNavigatorBundle.getString("addonsInstalledNeedsRestart"); - action = { - label: gNavigatorBundle.getString("addonInstallRestartButton"), - accessKey: gNavigatorBundle.getString("addonInstallRestartButton.accesskey"), - callback: function() { - Application.restart(); - } - }; - } - else { - messageString = gNavigatorBundle.getString("addonsInstalled"); - action = null; - } - - messageString = PluralForm.get(installInfo.installs.length, messageString); - messageString = messageString.replace("#1", installInfo.installs[0].name); - messageString = messageString.replace("#2", installInfo.installs.length); - messageString = messageString.replace("#3", brandShortName); - - // Remove notificaion on dismissal, since it's possible to cancel the - // install through the addons manager UI, making the "restart" prompt - // irrelevant. - options.removeOnDismissal = true; - - PopupNotifications.show(browser, notificationID, messageString, anchorID, - action, null, options); - break; - } - } -}; - -/* - * When addons are installed/uninstalled, check and see if the number of items - * on the add-on bar changed: - * - If an add-on was installed, incrementing the count, show the bar. - * - If an add-on was uninstalled, and no more items are left, hide the bar. - */ -let AddonsMgrListener = { - get addonBar() document.getElementById("addon-bar"), - get statusBar() document.getElementById("status-bar"), - getAddonBarItemCount: function() { - // Take into account the contents of the status bar shim for the count. - var itemCount = this.statusBar.childNodes.length; - - var defaultOrNoninteractive = this.addonBar.getAttribute("defaultset") - .split(",") - .concat(["separator", "spacer", "spring"]); - for (let item of this.addonBar.currentSet.split(",")) { - if (defaultOrNoninteractive.indexOf(item) == -1) - itemCount++; - } - - return itemCount; - }, - onInstalling: function(aAddon) { - this.lastAddonBarCount = this.getAddonBarItemCount(); - }, - onInstalled: function(aAddon) { - if (this.getAddonBarItemCount() > this.lastAddonBarCount) - setToolbarVisibility(this.addonBar, true); - }, - onUninstalling: function(aAddon) { - this.lastAddonBarCount = this.getAddonBarItemCount(); - }, - onUninstalled: function(aAddon) { - if (this.getAddonBarItemCount() == 0) - setToolbarVisibility(this.addonBar, false); - }, - onEnabling: function(aAddon) this.onInstalling(), - onEnabled: function(aAddon) this.onInstalled(), - onDisabling: function(aAddon) this.onUninstalling(), - onDisabled: function(aAddon) this.onUninstalled(), -}; - - -var LightWeightThemeWebInstaller = { - handleEvent: function (event) { - switch (event.type) { - case "InstallBrowserTheme": - case "PreviewBrowserTheme": - case "ResetBrowserThemePreview": - // ignore requests from background tabs - if (event.target.ownerDocument.defaultView.top != content) - return; - } - switch (event.type) { - case "InstallBrowserTheme": - this._installRequest(event); - break; - case "PreviewBrowserTheme": - this._preview(event); - break; - case "ResetBrowserThemePreview": - this._resetPreview(event); - break; - case "pagehide": - case "TabSelect": - this._resetPreview(); - break; - } - }, - - get _manager () { - var temp = {}; - Cu.import("resource://gre/modules/LightweightThemeManager.jsm", temp); - delete this._manager; - return this._manager = temp.LightweightThemeManager; - }, - - _installRequest: function (event) { - var node = event.target; - var data = this._getThemeFromNode(node); - if (!data) - return; - - if (this._isAllowed(node)) { - this._install(data); - return; - } - - var allowButtonText = - gNavigatorBundle.getString("lwthemeInstallRequest.allowButton"); - var allowButtonAccesskey = - gNavigatorBundle.getString("lwthemeInstallRequest.allowButton.accesskey"); - var message = - gNavigatorBundle.getFormattedString("lwthemeInstallRequest.message", - [node.ownerDocument.location.host]); - var buttons = [{ - label: allowButtonText, - accessKey: allowButtonAccesskey, - callback: function () { - LightWeightThemeWebInstaller._install(data); - } - }]; - - this._removePreviousNotifications(); - - var notificationBox = gBrowser.getNotificationBox(); - var notificationBar = - notificationBox.appendNotification(message, "lwtheme-install-request", "", - notificationBox.PRIORITY_INFO_MEDIUM, - buttons); - notificationBar.persistence = 1; - }, - - _install: function (newLWTheme) { - var previousLWTheme = this._manager.currentTheme; - - var listener = { - onEnabling: function(aAddon, aRequiresRestart) { - if (!aRequiresRestart) - return; - - let messageString = gNavigatorBundle.getFormattedString("lwthemeNeedsRestart.message", - [aAddon.name], 1); - - let action = { - label: gNavigatorBundle.getString("lwthemeNeedsRestart.button"), - accessKey: gNavigatorBundle.getString("lwthemeNeedsRestart.accesskey"), - callback: function () { - Application.restart(); - } - }; - - let options = { - timeout: Date.now() + 30000 - }; - - PopupNotifications.show(gBrowser.selectedBrowser, "addon-theme-change", - messageString, "addons-notification-icon", - action, null, options); - }, - - onEnabled: function(aAddon) { - LightWeightThemeWebInstaller._postInstallNotification(newLWTheme, previousLWTheme); - } - }; - - AddonManager.addAddonListener(listener); - this._manager.currentTheme = newLWTheme; - AddonManager.removeAddonListener(listener); - }, - - _postInstallNotification: function (newTheme, previousTheme) { - function text(id) { - return gNavigatorBundle.getString("lwthemePostInstallNotification." + id); - } - - var buttons = [{ - label: text("undoButton"), - accessKey: text("undoButton.accesskey"), - callback: function () { - LightWeightThemeWebInstaller._manager.forgetUsedTheme(newTheme.id); - LightWeightThemeWebInstaller._manager.currentTheme = previousTheme; - } - }, { - label: text("manageButton"), - accessKey: text("manageButton.accesskey"), - callback: function () { - BrowserOpenAddonsMgr("addons://list/theme"); - } - }]; - - this._removePreviousNotifications(); - - var notificationBox = gBrowser.getNotificationBox(); - var notificationBar = - notificationBox.appendNotification(text("message"), - "lwtheme-install-notification", "", - notificationBox.PRIORITY_INFO_MEDIUM, - buttons); - notificationBar.persistence = 1; - notificationBar.timeout = Date.now() + 20000; // 20 seconds - }, - - _removePreviousNotifications: function () { - var box = gBrowser.getNotificationBox(); - - ["lwtheme-install-request", - "lwtheme-install-notification"].forEach(function (value) { - var notification = box.getNotificationWithValue(value); - if (notification) - box.removeNotification(notification); - }); - }, - - _previewWindow: null, - _preview: function (event) { - if (!this._isAllowed(event.target)) - return; - - var data = this._getThemeFromNode(event.target); - if (!data) - return; - - this._resetPreview(); - - this._previewWindow = event.target.ownerDocument.defaultView; - this._previewWindow.addEventListener("pagehide", this, true); - gBrowser.tabContainer.addEventListener("TabSelect", this, false); - - this._manager.previewTheme(data); - }, - - _resetPreview: function (event) { - if (!this._previewWindow || - event && !this._isAllowed(event.target)) - return; - - this._previewWindow.removeEventListener("pagehide", this, true); - this._previewWindow = null; - gBrowser.tabContainer.removeEventListener("TabSelect", this, false); - - this._manager.resetPreview(); - }, - - _isAllowed: function (node) { - var pm = Services.perms; - - var uri = node.ownerDocument.documentURIObject; - return pm.testPermission(uri, "install") == pm.ALLOW_ACTION; - }, - - _getThemeFromNode: function (node) { - return this._manager.parseTheme(node.getAttribute("data-browsertheme"), - node.baseURI); - } -} - -/* - * Listen for Lightweight Theme styling changes and update the browser's theme accordingly. - */ -let LightweightThemeListener = { - _modifiedStyles: [], - - init: function () { - XPCOMUtils.defineLazyGetter(this, "styleSheet", function() { - for (let i = document.styleSheets.length - 1; i >= 0; i--) { - let sheet = document.styleSheets[i]; - if (sheet.href == "chrome://browser/skin/browser-lightweightTheme.css") - return sheet; - } - }); - - Services.obs.addObserver(this, "lightweight-theme-styling-update", false); - Services.obs.addObserver(this, "lightweight-theme-optimized", false); - if (document.documentElement.hasAttribute("lwtheme")) - this.updateStyleSheet(document.documentElement.style.backgroundImage); - }, - - uninit: function () { - Services.obs.removeObserver(this, "lightweight-theme-styling-update"); - Services.obs.removeObserver(this, "lightweight-theme-optimized"); - }, - - /** - * Append the headerImage to the background-image property of all rulesets in - * browser-lightweightTheme.css. - * - * @param headerImage - a string containing a CSS image for the lightweight theme header. - */ - updateStyleSheet: function(headerImage) { - if (!this.styleSheet) - return; - this.substituteRules(this.styleSheet.cssRules, headerImage); - }, - - substituteRules: function(ruleList, headerImage, existingStyleRulesModified = 0) { - let styleRulesModified = 0; - for (let i = 0; i < ruleList.length; i++) { - let rule = ruleList[i]; - if (rule instanceof Ci.nsIDOMCSSGroupingRule) { - // Add the number of modified sub-rules to the modified count - styleRulesModified += this.substituteRules(rule.cssRules, headerImage, existingStyleRulesModified + styleRulesModified); - } else if (rule instanceof Ci.nsIDOMCSSStyleRule) { - if (!rule.style.backgroundImage) - continue; - let modifiedIndex = existingStyleRulesModified + styleRulesModified; - if (!this._modifiedStyles[modifiedIndex]) - this._modifiedStyles[modifiedIndex] = { backgroundImage: rule.style.backgroundImage }; - - rule.style.backgroundImage = this._modifiedStyles[modifiedIndex].backgroundImage + ", " + headerImage; - styleRulesModified++; - } else { - Cu.reportError("Unsupported rule encountered"); - } - } - return styleRulesModified; - }, - - // nsIObserver - observe: function (aSubject, aTopic, aData) { - if ((aTopic != "lightweight-theme-styling-update" && aTopic != "lightweight-theme-optimized") || - !this.styleSheet) - return; - - if (aTopic == "lightweight-theme-optimized" && aSubject != window) - return; - - let themeData = JSON.parse(aData); - if (!themeData) - return; - this.updateStyleSheet("url(" + themeData.headerURL + ")"); - }, -}; diff --git a/browser/base/content/browser-appmenu.inc b/browser/base/content/browser-appmenu.inc deleted file mode 100644 index 835bf22bc..000000000 --- a/browser/base/content/browser-appmenu.inc +++ /dev/null @@ -1,394 +0,0 @@ -# -*- Mode: HTML -*- -# 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/. - -<menupopup id="appmenu-popup" - onpopupshowing="if (event.target == this) { - updateEditUIVisibility(); -#ifdef MOZ_SERVICES_SYNC - gSyncUI.updateUI(); -#endif - return; - } - updateCharacterEncodingMenuState(); - if (event.target.parentNode.parentNode.parentNode.parentNode == this) - this._currentPopup = event.target;"> - <hbox> - <vbox id="appmenuPrimaryPane"> - <menuitem id="appmenu_newTab_popup" - label="&tabCmd.label;" - command="cmd_newNavigatorTab" - key="key_newNavigatorTab"/> - <menuitem id="appmenu_newNavigator" - label="&newNavigatorCmd.label;" - command="cmd_newNavigator" - key="key_newNavigator"/> - <menuitem id="appmenu_newPrivateWindow" - class="menuitem-iconic menuitem-iconic-tooltip" - label="&newPrivateWindow.label;" - command="Tools:PrivateBrowsing" - key="key_privatebrowsing"/> - <menuitem label="&goOfflineCmd.label;" - id="appmenu_offlineModeRecovery" - type="checkbox" - observes="workOfflineMenuitemState" - oncommand="BrowserOffline.toggleOfflineStatus();"/> - <menuseparator class="appmenu-menuseparator"/> - <hbox> - <menuitem id="appmenu-edit-label" - label="&appMenuEdit.label;" - disabled="true"/> - <toolbarbutton id="appmenu-cut" - class="appmenu-edit-button" - command="cmd_cut" - onclick="if (!this.disabled) hidePopup();" - tooltiptext="&cutButton.tooltip;"/> - <toolbarbutton id="appmenu-copy" - class="appmenu-edit-button" - command="cmd_copy" - onclick="if (!this.disabled) hidePopup();" - tooltiptext="©Button.tooltip;"/> - <toolbarbutton id="appmenu-paste" - class="appmenu-edit-button" - command="cmd_paste" - onclick="if (!this.disabled) hidePopup();" - tooltiptext="&pasteButton.tooltip;"/> - <spacer flex="1"/> - <menu id="appmenu-editmenu"> - <menupopup id="appmenu-editmenu-menupopup"> - <menuitem id="appmenu-editmenu-cut" - class="menuitem-iconic" - label="&cutCmd.label;" - key="key_cut" - command="cmd_cut"/> - <menuitem id="appmenu-editmenu-copy" - class="menuitem-iconic" - label="©Cmd.label;" - key="key_copy" - command="cmd_copy"/> - <menuitem id="appmenu-editmenu-paste" - class="menuitem-iconic" - label="&pasteCmd.label;" - key="key_paste" - command="cmd_paste"/> - <menuseparator/> - <menuitem id="appmenu-editmenu-undo" - label="&undoCmd.label;" - key="key_undo" - command="cmd_undo"/> - <menuitem id="appmenu-editmenu-redo" - label="&redoCmd.label;" - key="key_redo" - command="cmd_redo"/> - <menuseparator/> - <menuitem id="appmenu-editmenu-selectAll" - label="&selectAllCmd.label;" - key="key_selectAll" - command="cmd_selectAll"/> - <menuseparator/> - <menuitem id="appmenu-editmenu-delete" - label="&deleteCmd.label;" - key="key_delete" - command="cmd_delete"/> - </menupopup> - </menu> - </hbox> - <menuitem id="appmenu_find" - class="menuitem-tooltip" - label="&appMenuFind.label;" - command="cmd_find" - key="key_find"/> - <menuseparator class="appmenu-menuseparator"/> - <menuitem id="appmenu_openFile" - label="&openFileCmd.label;" - command="Browser:OpenFile" - key="openFileKb"/> - <menuitem id="appmenu_savePage" - class="menuitem-tooltip" - label="&savePageCmd.label;" - command="Browser:SavePage" - key="key_savePage"/> - <menuitem id="appmenu_sendLink" - label="&emailPageCmd.label;" - command="Browser:SendLink"/> - <splitmenu id="appmenu_print" - iconic="true" - label="&printCmd.label;" - command="cmd_print"> - <menupopup> - <menuitem id="appmenu_print_popup" - class="menuitem-iconic" - label="&printCmd.label;" - command="cmd_print" - key="printKb"/> - <menuitem id="appmenu_printPreview" - label="&printPreviewCmd.label;" - command="cmd_printPreview"/> - <menuitem id="appmenu_printSetup" - label="&printSetupCmd.label;" - command="cmd_pageSetup"/> - </menupopup> - </splitmenu> - <menuseparator class="appmenu-menuseparator"/> - <splitmenu id="appmenu_webDeveloper" - command="Tools:DevToolbox" - label="&appMenuWebDeveloper.label;"> - <menupopup id="appmenu_webDeveloper_popup"> -#ifdef MOZ_DEVTOOLS - <menuitem id="appmenu_devToolbox" - observes="devtoolsMenuBroadcaster_DevToolbox"/> - <menuseparator id="appmenu_devtools_separator"/> - <menuitem id="appmenu_devToolbar" - observes="devtoolsMenuBroadcaster_DevToolbar"/> - <menuitem id="appmenu_chromeDebugger" - observes="devtoolsMenuBroadcaster_ChromeDebugger"/> - <menuitem id="appmenu_browserConsole" - observes="devtoolsMenuBroadcaster_BrowserConsole"/> - <menuitem id="appmenu_responsiveUI" - observes="devtoolsMenuBroadcaster_ResponsiveUI"/> - <menuitem id="appmenu_eyedropper" - observes="devtoolsMenuBroadcaster_Eyedropper"/> - <menuitem id="appmenu_scratchpad" - observes="devtoolsMenuBroadcaster_Scratchpad"/> -#endif - <menuitem id="appmenu_pageSource" - observes="devtoolsMenuBroadcaster_PageSource"/> - <menuitem id="appmenu_errorConsole" - observes="devtoolsMenuBroadcaster_ErrorConsole"/> -#ifdef MOZ_DEVTOOLS - <menuitem id="appmenu_devtools_connect" - observes="devtoolsMenuBroadcaster_connect"/> -#endif - <menuseparator id="appmenu_devToolsEndSeparator"/> - <menuitem id="appmenu_getMoreDevtools" - observes="devtoolsMenuBroadcaster_GetMoreTools"/> - <menuseparator/> -#define ID_PREFIX appmenu_developer_ -#define OMIT_ACCESSKEYS -#include browser-charsetmenu.inc -#undef ID_PREFIX -#undef OMIT_ACCESSKEYS - <menuitem label="&goOfflineCmd.label;" - type="checkbox" - observes="workOfflineMenuitemState" - oncommand="BrowserOffline.toggleOfflineStatus();"/> - </menupopup> - </splitmenu> - <menuseparator class="appmenu-menuseparator"/> -#define ID_PREFIX appmenu_ -#define OMIT_ACCESSKEYS -#include browser-charsetmenu.inc -#undef ID_PREFIX -#undef OMIT_ACCESSKEYS - <menuitem id="appmenu_fullScreen" - class="menuitem-tooltip" - label="&fullScreenCmd.label;" - type="checkbox" - observes="View:FullScreen" - key="key_fullScreen"/> - <menuitem id="appmenu_restart" - class="menuitem-iconic" - label="&appMenuRestart.label;" - command="cmd_restartApplication"/> - <menuitem id="appmenu-quit" - class="menuitem-iconic" -#ifdef XP_WIN - label="&quitApplicationCmdWin.label;" -#else - label="&quitApplicationCmd.label;" -#endif - command="cmd_quitApplication"/> - </vbox> - <vbox id="appmenuSecondaryPane"> - <splitmenu id="appmenu_bookmarks" - iconic="true" - label="&bookmarksMenu.label;" - command="Browser:ShowAllBookmarks"> - <menupopup id="appmenu_bookmarksPopup" - placespopup="true" - context="placesContext" - openInTabs="children" - oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);" - onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);" - onpopupshowing="BookmarkingUI.onPopupShowing(event); - if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');" - tooltip="bhTooltip" - popupsinherittooltip="true"> - <menuitem id="appmenu_showAllBookmarks" - class="menuitem-iconic" - label="&organizeBookmarks.label;" - command="Browser:ShowAllBookmarks" - context="" - key="manBookmarkKb"/> - <menuseparator/> - <menuitem id="appmenu_bookmarkThisPage" - class="menuitem-iconic" - label="&bookmarkThisPageCmd.label;" - command="Browser:AddBookmarkAs" - key="addBookmarkAsKb"/> - <menuitem id="appmenu_subscribeToPage" - class="menuitem-iconic" - label="&subscribeToPageMenuitem.label;" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);" - observes="singleFeedMenuitemState"/> - <menu id="appmenu_subscribeToPageMenu" - class="menu-iconic" - label="&subscribeToPageMenupopup.label;" - observes="multipleFeedsMenuState"> - <menupopup id="appmenu_subscribeToPageMenupopup" - onpopupshowing="return FeedHandler.buildFeedList(event.target);" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);"/> - </menu> - <menuseparator/> - <menu id="appmenu_bookmarksToolbar" - placesanonid="toolbar-autohide" - class="menu-iconic bookmark-item" - label="&personalbarCmd.label;" - container="true"> - <menupopup id="appmenu_bookmarksToolbarPopup" - placespopup="true" - context="placesContext" - onpopupshowing="if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=TOOLBAR');"/> - </menu> - <menuseparator/> - <!-- Bookmarks menu items --> - <menuseparator builder="end" - class="hide-if-empty-places-result"/> - <menuitem id="appmenu_unsortedBookmarks" - class="menuitem-iconic" - label="&appMenuUnsorted.label;" - oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"/> - </menupopup> - </splitmenu> - <splitmenu id="appmenu_history" - iconic="true" - label="&historyMenu.label;" - command="Browser:ShowAllHistory"> - <menupopup id="appmenu_historyMenupopup" - placespopup="true" - context="placesContext" - oncommand="this.parentNode._placesView._onCommand(event);" - onclick="checkForMiddleClick(this, event);" - onpopupshowing="if (!this.parentNode._placesView) - new HistoryMenu(event);" - tooltip="bhTooltip" - popupsinherittooltip="true"> - <menuitem id="appmenu_showAllHistory" - class="menuitem-iconic" - label="&showAllHistoryCmd2.label;" - command="Browser:ShowAllHistory" - key="showAllHistoryKb"/> - <menuseparator/> - <menuitem id="appmenu_sanitizeHistory" - class="menuitem-iconic" - label="&clearRecentHistory.label;" - key="key_sanitize" - command="Tools:Sanitize"/> - <menuseparator class="hide-if-empty-places-result"/> -#ifdef MOZ_SERVICES_SYNC - <menuitem id="appmenu_sync-tabs" - class="syncTabsMenuItem" - label="&syncTabsMenu2.label;" - oncommand="BrowserOpenSyncTabs();" - disabled="true"/> -#endif - <menuitem id="appmenu_restoreLastSession" - label="&historyRestoreLastSession.label;" - command="Browser:RestoreLastSession"/> - <menu id="appmenu_recentlyClosedTabsMenu" - class="recentlyClosedTabsMenu" - label="&historyUndoMenu.label;" - disabled="true"> - <menupopup id="appmenu_recentlyClosedTabsMenupopup" - onpopupshowing="document.getElementById('appmenu_history')._placesView.populateUndoSubmenu();"/> - </menu> - <menu id="appmenu_recentlyClosedWindowsMenu" - class="recentlyClosedWindowsMenu" - label="&historyUndoWindowMenu.label;" - disabled="true"> - <menupopup id="appmenu_recentlyClosedWindowsMenupopup" - onpopupshowing="document.getElementById('appmenu_history')._placesView.populateUndoWindowSubmenu();"/> - </menu> - <menuseparator/> - </menupopup> - </splitmenu> - <menuitem id="appmenu_downloads" - class="menuitem-tooltip" - label="&downloads.label;" - command="Tools:Downloads" - key="key_openDownloads"/> - <spacer id="appmenuSecondaryPane-spacer"/> - <menuitem id="appmenu_addons" - class="menuitem-iconic menuitem-iconic-tooltip" - label="&addons.label;" - command="Tools:Addons" - key="key_openAddons"/> - <menuitem id="appmenu_permissions" - class="menuitem-iconic" - label="&permissions.label;" - command="Tools:Permissions" - key="key_openPermissions"/> -#ifdef MOZ_SERVICES_SYNC - <!-- only one of sync-setup or sync-syncnow will be showing at once --> - <menuitem id="sync-setup-appmenu" - label="&syncSetup.label;" - observes="sync-setup-state" - oncommand="gSyncUI.openSetup()"/> - <menuitem id="sync-syncnowitem-appmenu" - label="&syncSyncNowItem.label;" - observes="sync-syncnow-state" - oncommand="gSyncUI.doSync(event);"/> -#endif - <splitmenu id="appmenu_customize" - label="&preferencesCmd2.label;" - oncommand="openPreferences();"> - <menupopup id="appmenu_customizeMenu" - onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('appmenu_toggleToolbarsSeparator'));"> - <menuitem id="appmenu_preferences" - label="&preferencesCmd2.label;" - oncommand="openPreferences();"/> - <menuseparator/> - <menuseparator id="appmenu_toggleToolbarsSeparator"/> - <menuitem id="appmenu_toggleTabsOnTop" - label="&viewTabsOnTop.label;" - type="checkbox" - command="cmd_ToggleTabsOnTop"/> - <menuitem id="appmenu_toolbarLayout" - label="&appMenuToolbarLayout.label;" - command="cmd_CustomizeToolbars"/> - </menupopup> - </splitmenu> - <splitmenu id="appmenu_help" - label="&helpMenu.label;" - oncommand="openHelpLink('firefox-help')"> - <menupopup id="appmenu_helpMenupopup"> - <menuitem id="appmenu_openHelp" - label="&helpMenu.label;" - oncommand="openHelpLink('firefox-help')" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="appmenu_troubleshootingInfo" - label="&helpTroubleshootingInfo.label;" - oncommand="openTroubleshootingPage()" - onclick="checkForMiddleClick(this,event);"/> - <menuitem id="appmenu_feedbackPage" - label="&helpFeedbackPage.label;" - oncommand="openFeedbackPage()" - onclick="checkForMiddleClick(this, event);"/> - <menuseparator/> - <menuitem id="appmenu_safeMode" - label="&appMenuSafeMode.label;" - oncommand="restart(true);"/> - <menuseparator/> - <menuitem id="appmenu_about" - label="&aboutProduct.label;" - oncommand="openAboutDialog();"/> - </menupopup> - </splitmenu> - </vbox> - </hbox> -</menupopup> diff --git a/browser/base/content/browser-charsetmenu.inc b/browser/base/content/browser-charsetmenu.inc deleted file mode 100644 index 628de1341..000000000 --- a/browser/base/content/browser-charsetmenu.inc +++ /dev/null @@ -1,62 +0,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/. - -#filter substitution - -#expand <menu id="__ID_PREFIX__charsetMenu" - label="&charsetMenu.label;" -#ifndef OMIT_ACCESSKEYS - accesskey="&charsetMenu.accesskey;" -#endif - oncommand="MultiplexHandler(event)" -#ifdef OMIT_ACCESSKEYS -#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__');" -#else -#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__', true);" -#endif - onpopupshown="UpdateMenus(event);"> - <menupopup> - <menu label="&charsetMenuAutodet.label;" -#ifndef OMIT_ACCESSKEYS - accesskey="&charsetMenuAutodet.accesskey;" -#endif - > - <menupopup> - <menuitem type="radio" - name="detectorGroup" -#expand id="__ID_PREFIX__chardet.off" - label="&charsetMenuAutodet.off.label;" -#ifndef OMIT_ACCESSKEYS - accesskey="&charsetMenuAutodet.off.accesskey;" -#endif - /> - <menuitem type="radio" - name="detectorGroup" -#expand id="__ID_PREFIX__chardet.ja_parallel_state_machine" - label="&charsetMenuAutodet.ja.label;" -#ifndef OMIT_ACCESSKEYS - accesskey="&charsetMenuAutodet.ja.accesskey;" -#endif - /> - <menuitem type="radio" - name="detectorGroup" -#expand id="__ID_PREFIX__chardet.ruprob" - label="&charsetMenuAutodet.ru.label;" -#ifndef OMIT_ACCESSKEYS - accesskey="&charsetMenuAutodet.ru.accesskey;" -#endif - /> - <menuitem type="radio" - name="detectorGroup" -#expand id="__ID_PREFIX__chardet.ukprob" - label="&charsetMenuAutodet.uk.label;" -#ifndef OMIT_ACCESSKEYS - accesskey="&charsetMenuAutodet.uk.accesskey;" -#endif - /> - </menupopup> - </menu> - <menuseparator/> - </menupopup> -</menu> diff --git a/browser/base/content/browser-context.inc b/browser/base/content/browser-context.inc deleted file mode 100644 index f672ede61..000000000 --- a/browser/base/content/browser-context.inc +++ /dev/null @@ -1,379 +0,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/. - - <menuseparator id="page-menu-separator"/> - <menuitem id="spell-no-suggestions" - disabled="true" - label="&spellNoSuggestions.label;"/> - <menuitem id="spell-add-to-dictionary" - label="&spellAddToDictionary.label;" - accesskey="&spellAddToDictionary.accesskey;" - oncommand="InlineSpellCheckerUI.addToDictionary();"/> - <menuitem id="spell-undo-add-to-dictionary" - label="&spellUndoAddToDictionary.label;" - accesskey="&spellUndoAddToDictionary.accesskey;" - oncommand="InlineSpellCheckerUI.undoAddToDictionary();" /> - <menuseparator id="spell-suggestions-separator"/> - <menuitem id="context-openlinkintab" - label="&openLinkCmdInTab.label;" - accesskey="&openLinkCmdInTab.accesskey;" - oncommand="gContextMenu.openLinkInTab();"/> - <menuitem id="context-openlink" - label="&openLinkCmd.label;" - accesskey="&openLinkCmd.accesskey;" - oncommand="gContextMenu.openLink();"/> - <menuitem id="context-openlinkprivate" - label="&openLinkInPrivateWindowCmd.label;" - accesskey="&openLinkInPrivateWindowCmd.accesskey;" - oncommand="gContextMenu.openLinkInPrivateWindow();"/> - <menuitem id="context-openlinkincurrent" - label="&openLinkCmdInCurrent.label;" - accesskey="&openLinkCmdInCurrent.accesskey;" - oncommand="gContextMenu.openLinkInCurrent();"/> - <menuseparator id="context-sep-open"/> - <menuitem id="context-bookmarklink" - label="&bookmarkThisLinkCmd.label;" - accesskey="&bookmarkThisLinkCmd.accesskey;" - oncommand="gContextMenu.bookmarkLink();"/> - <menuitem id="context-savelink" - label="&saveLinkCmd.label;" - accesskey="&saveLinkCmd.accesskey;" - oncommand="gContextMenu.saveLink();"/> - <menuitem id="context-sendlink" - label="&sendLinkCmd.label;" - accesskey="&sendLinkCmd.accesskey;" - oncommand="gContextMenu.sendLink();"/> - <menuitem id="context-copyemail" - label="©EmailCmd.label;" - accesskey="©EmailCmd.accesskey;" - oncommand="gContextMenu.copyEmail();"/> - <menuitem id="context-copylink" - label="©LinkCmd.label;" - accesskey="©LinkCmd.accesskey;" - oncommand="goDoCommand('cmd_copyLink');"/> - <menuseparator id="context-sep-copylink"/> - <menuitem id="context-media-play" - label="&mediaPlay.label;" - accesskey="&mediaPlay.accesskey;" - oncommand="gContextMenu.mediaCommand('play');"/> - <menuitem id="context-media-pause" - label="&mediaPause.label;" - accesskey="&mediaPause.accesskey;" - oncommand="gContextMenu.mediaCommand('pause');"/> - <menuitem id="context-media-mute" - label="&mediaMute.label;" - accesskey="&mediaMute.accesskey;" - oncommand="gContextMenu.mediaCommand('mute');"/> - <menuitem id="context-media-unmute" - label="&mediaUnmute.label;" - accesskey="&mediaUnmute.accesskey;" - oncommand="gContextMenu.mediaCommand('unmute');"/> - <menu id="context-media-playbackrate" label="&mediaPlaybackRate.label;" accesskey="&mediaPlaybackRate.accesskey;"> - <menupopup> - <menuitem id="context-media-playbackrate-050x" - label="&mediaPlaybackRate050x.label;" - accesskey="&mediaPlaybackRate050x.accesskey;" - type="radio" - name="playbackrate" - oncommand="gContextMenu.mediaCommand('playbackRate', 0.5);"/> - <menuitem id="context-media-playbackrate-100x" - label="&mediaPlaybackRate100x.label;" - accesskey="&mediaPlaybackRate100x.accesskey;" - type="radio" - name="playbackrate" - checked="true" - oncommand="gContextMenu.mediaCommand('playbackRate', 1.0);"/> - <menuitem id="context-media-playbackrate-150x" - label="&mediaPlaybackRate150x.label;" - accesskey="&mediaPlaybackRate150x.accesskey;" - type="radio" - name="playbackrate" - oncommand="gContextMenu.mediaCommand('playbackRate', 1.5);"/> - <menuitem id="context-media-playbackrate-200x" - label="&mediaPlaybackRate200x.label;" - accesskey="&mediaPlaybackRate200x.accesskey;" - type="radio" - name="playbackrate" - oncommand="gContextMenu.mediaCommand('playbackRate', 2.0);"/> - </menupopup> - </menu> - <menuitem id="context-media-showcontrols" - label="&mediaShowControls.label;" - accesskey="&mediaShowControls.accesskey;" - oncommand="gContextMenu.mediaCommand('showcontrols');"/> - <menuitem id="context-media-hidecontrols" - label="&mediaHideControls.label;" - accesskey="&mediaHideControls.accesskey;" - oncommand="gContextMenu.mediaCommand('hidecontrols');"/> - <menuitem id="context-video-showstats" - accesskey="&videoShowStats.accesskey;" - label="&videoShowStats.label;" - oncommand="gContextMenu.mediaCommand('showstats');"/> - <menuitem id="context-video-hidestats" - accesskey="&videoHideStats.accesskey;" - label="&videoHideStats.label;" - oncommand="gContextMenu.mediaCommand('hidestats');"/> - <menuitem id="context-video-fullscreen" - accesskey="&videoFullScreen.accesskey;" - label="&videoFullScreen.label;" - oncommand="gContextMenu.fullScreenVideo();"/> - <menuitem id="context-leave-dom-fullscreen" - accesskey="&leaveDOMFullScreen.accesskey;" - label="&leaveDOMFullScreen.label;" - oncommand="gContextMenu.leaveDOMFullScreen();"/> - <menuseparator id="context-media-sep-commands"/> - <menuitem id="context-reloadimage" - label="&reloadImageCmd.label;" - accesskey="&reloadImageCmd.accesskey;" - oncommand="gContextMenu.reloadImage();"/> - <menuitem id="context-viewimage" - label="&viewImageCmd.label;" - accesskey="&viewImageCmd.accesskey;" - oncommand="gContextMenu.viewMedia(event);" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="context-viewvideo" - label="&viewVideoCmd.label;" - accesskey="&viewVideoCmd.accesskey;" - oncommand="gContextMenu.viewMedia(event);" - onclick="checkForMiddleClick(this, event);"/> -#ifdef CONTEXT_COPY_IMAGE_CONTENTS - <menuitem id="context-copyimage-contents" - label="©ImageContentsCmd.label;" - accesskey="©ImageContentsCmd.accesskey;" - oncommand="goDoCommand('cmd_copyImage');"/> -#endif - <menuitem id="context-copyimage" - label="©ImageCmd.label;" - accesskey="©ImageCmd.accesskey;" - oncommand="gContextMenu.copyMediaLocation();"/> - <menuitem id="context-copyvideourl" - label="©VideoURLCmd.label;" - accesskey="©VideoURLCmd.accesskey;" - oncommand="gContextMenu.copyMediaLocation();"/> - <menuitem id="context-copyaudiourl" - label="©AudioURLCmd.label;" - accesskey="©AudioURLCmd.accesskey;" - oncommand="gContextMenu.copyMediaLocation();"/> - <menuseparator id="context-sep-copyimage"/> - <menuitem id="context-saveimage" - label="&saveImageCmd.label;" - accesskey="&saveImageCmd.accesskey;" - oncommand="gContextMenu.saveMedia();"/> - <menuitem id="context-sendimage" - label="&emailImageCmd.label;" - accesskey="&emailImageCmd.accesskey;" - oncommand="gContextMenu.sendMedia();"/> - <menuitem id="context-setDesktopBackground" - label="&setDesktopBackgroundCmd.label;" - accesskey="&setDesktopBackgroundCmd.accesskey;" - oncommand="gContextMenu.setDesktopBackground();"/> - <menuitem id="context-viewimageinfo" - label="&viewImageInfoCmd.label;" - accesskey="&viewImageInfoCmd.accesskey;" - oncommand="gContextMenu.viewImageInfo();"/> - <menuitem id="context-savevideo" - label="&saveVideoCmd.label;" - accesskey="&saveVideoCmd.accesskey;" - oncommand="gContextMenu.saveMedia();"/> - <menuitem id="context-saveaudio" - label="&saveAudioCmd.label;" - accesskey="&saveAudioCmd.accesskey;" - oncommand="gContextMenu.saveMedia();"/> - <menuitem id="context-video-saveimage" - accesskey="&videoSaveImage.accesskey;" - label="&videoSaveImage.label;" - oncommand="gContextMenu.saveVideoFrameAsImage();"/> - <menuitem id="context-sendvideo" - label="&emailVideoCmd.label;" - accesskey="&emailVideoCmd.accesskey;" - oncommand="gContextMenu.sendMedia();"/> - <menuitem id="context-sendaudio" - label="&emailAudioCmd.label;" - accesskey="&emailAudioCmd.accesskey;" - oncommand="gContextMenu.sendMedia();"/> - <menuitem id="context-ctp-play" - label="&playPluginCmd.label;" - accesskey="&playPluginCmd.accesskey;" - oncommand="gContextMenu.playPlugin();"/> - <menuitem id="context-ctp-hide" - label="&hidePluginCmd.label;" - accesskey="&hidePluginCmd.accesskey;" - oncommand="gContextMenu.hidePlugin();"/> - <menuseparator id="context-sep-ctp"/> - <menuitem id="context-back" - label="&backCmd.label;" - accesskey="&backCmd.accesskey;" - command="Browser:BackOrBackDuplicate" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="context-forward" - label="&forwardCmd.label;" - accesskey="&forwardCmd.accesskey;" - command="Browser:ForwardOrForwardDuplicate" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="context-reload" - label="&reloadCmd.label;" - accesskey="&reloadCmd.accesskey;" - oncommand="gContextMenu.reload(event);" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="context-stop" - label="&stopCmd.label;" - accesskey="&stopCmd.accesskey;" - command="Browser:Stop"/> - <menuseparator id="context-sep-stop"/> - <menuitem id="context-bookmarkpage" - label="&bookmarkPageCmd2.label;" - accesskey="&bookmarkPageCmd2.accesskey;" - oncommand="gContextMenu.bookmarkThisPage();"/> - <menuitem id="context-savepage" - label="&savePageCmd.label;" - accesskey="&savePageCmd.accesskey2;" - oncommand="gContextMenu.savePageAs();"/> - <menuitem id="context-sendpage" - label="&sendPageCmd.label;" - accesskey="&sendPageCmd.accesskey;" - oncommand="gContextMenu.sendPage();"/> - <menuseparator id="context-sep-viewbgimage"/> - <menuitem id="context-viewbgimage" - label="&viewBGImageCmd.label;" - accesskey="&viewBGImageCmd.accesskey;" - oncommand="gContextMenu.viewBGImage(event);" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="context-undo" - label="&undoCmd.label;" - accesskey="&undoCmd.accesskey;" - command="cmd_undo"/> - <menuseparator id="context-sep-undo"/> - <menuitem id="context-cut" - label="&cutCmd.label;" - accesskey="&cutCmd.accesskey;" - command="cmd_cut"/> - <menuitem id="context-copy" - label="©Cmd.label;" - accesskey="©Cmd.accesskey;" - command="cmd_copy"/> - <menuitem id="context-paste" - label="&pasteCmd.label;" - accesskey="&pasteCmd.accesskey;" - command="cmd_paste"/> - <menuitem id="context-delete" - label="&deleteCmd.label;" - accesskey="&deleteCmd.accesskey;" - command="cmd_delete"/> - <menuseparator id="context-sep-paste"/> - <menuitem id="context-selectall" - label="&selectAllCmd.label;" - accesskey="&selectAllCmd.accesskey;" - command="cmd_selectAll"/> - <menuseparator id="context-sep-selectall"/> - <menuitem id="context-keywordfield" - label="&keywordfield.label;" - accesskey="&keywordfield.accesskey;" - oncommand="AddKeywordForSearchField();"/> - <menuitem id="context-searchselect" - oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms);"/> - <menuseparator id="frame-sep"/> - <menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;"> - <menupopup> - <menuitem id="context-showonlythisframe" - label="&showOnlyThisFrameCmd.label;" - accesskey="&showOnlyThisFrameCmd.accesskey;" - oncommand="gContextMenu.showOnlyThisFrame();"/> - <menuitem id="context-openframeintab" - label="&openFrameCmdInTab.label;" - accesskey="&openFrameCmdInTab.accesskey;" - oncommand="gContextMenu.openFrameInTab();"/> - <menuitem id="context-openframe" - label="&openFrameCmd.label;" - accesskey="&openFrameCmd.accesskey;" - oncommand="gContextMenu.openFrame();"/> - <menuseparator id="open-frame-sep"/> - <menuitem id="context-reloadframe" - label="&reloadFrameCmd.label;" - accesskey="&reloadFrameCmd.accesskey;" - oncommand="gContextMenu.reloadFrame();"/> - <menuseparator/> - <menuitem id="context-bookmarkframe" - label="&bookmarkThisFrameCmd.label;" - accesskey="&bookmarkThisFrameCmd.accesskey;" - oncommand="gContextMenu.addBookmarkForFrame();"/> - <menuitem id="context-saveframe" - label="&saveFrameCmd.label;" - accesskey="&saveFrameCmd.accesskey;" - oncommand="gContextMenu.saveFrame();"/> - <menuseparator/> - <menuitem id="context-printframe" - label="&printFrameCmd.label;" - accesskey="&printFrameCmd.accesskey;" - oncommand="gContextMenu.printFrame();"/> - <menuseparator/> - <menuitem id="context-viewframesource" - label="&viewFrameSourceCmd.label;" - accesskey="&viewFrameSourceCmd.accesskey;" - oncommand="gContextMenu.viewFrameSource();" - observes="isFrameImage"/> - <menuitem id="context-viewframeinfo" - label="&viewFrameInfoCmd.label;" - accesskey="&viewFrameInfoCmd.accesskey;" - oncommand="gContextMenu.viewFrameInfo();"/> - </menupopup> - </menu> - <menuitem id="context-viewpartialsource-selection" - label="&viewPartialSourceForSelectionCmd.label;" - accesskey="&viewPartialSourceCmd.accesskey;" - oncommand="gContextMenu.viewPartialSource('selection');" - observes="isImage"/> - <menuitem id="context-viewpartialsource-mathml" - label="&viewPartialSourceForMathMLCmd.label;" - accesskey="&viewPartialSourceCmd.accesskey;" - oncommand="gContextMenu.viewPartialSource('mathml');" - observes="isImage"/> - <menuseparator id="context-sep-viewsource"/> - <menuitem id="context-viewsource" - label="&viewPageSourceCmd.label;" - accesskey="&viewPageSourceCmd.accesskey;" - oncommand="BrowserViewSourceOfDocument(gContextMenu.browser.contentDocument);" - observes="isImage"/> - <menuitem id="context-viewinfo" - label="&viewPageInfoCmd.label;" - accesskey="&viewPageInfoCmd.accesskey;" - oncommand="gContextMenu.viewInfo();"/> - <menuseparator id="spell-separator"/> - <menuitem id="spell-check-enabled" - label="&spellCheckToggle.label;" - type="checkbox" - accesskey="&spellCheckToggle.accesskey;" - oncommand="InlineSpellCheckerUI.toggleEnabled();"/> - <menuitem id="spell-add-dictionaries-main" - label="&spellAddDictionaries.label;" - accesskey="&spellAddDictionaries.accesskey;" - oncommand="gContextMenu.addDictionaries();"/> - <menu id="spell-dictionaries" - label="&spellDictionaries.label;" - accesskey="&spellDictionaries.accesskey;"> - <menupopup id="spell-dictionaries-menu"> - <menuseparator id="spell-language-separator"/> - <menuitem id="spell-add-dictionaries" - label="&spellAddDictionaries.label;" - accesskey="&spellAddDictionaries.accesskey;" - oncommand="gContextMenu.addDictionaries();"/> - </menupopup> - </menu> - <menuseparator hidden="true" id="context-sep-bidi"/> - <menuitem hidden="true" id="context-bidi-text-direction-toggle" - label="&bidiSwitchTextDirectionItem.label;" - accesskey="&bidiSwitchTextDirectionItem.accesskey;" - command="cmd_switchTextDirection"/> - <menuitem hidden="true" id="context-bidi-page-direction-toggle" - label="&bidiSwitchPageDirectionItem.label;" - accesskey="&bidiSwitchPageDirectionItem.accesskey;" - oncommand="gContextMenu.switchPageDirection();"/> -#ifdef MOZ_DEVTOOLS - <menuseparator id="inspect-separator" hidden="true"/> - <menuitem id="context-inspect" - hidden="true" - label="&inspectContextMenu.label;" - accesskey="&inspectContextMenu.accesskey;" - oncommand="gContextMenu.inspectNode();"/> -#endif diff --git a/browser/base/content/browser-doctype.inc b/browser/base/content/browser-doctype.inc deleted file mode 100644 index 6ee6384b6..000000000 --- a/browser/base/content/browser-doctype.inc +++ /dev/null @@ -1,19 +0,0 @@ -<!DOCTYPE window [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > -%brandDTD; -<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" > -%browserDTD; -<!ENTITY % baseMenuDTD SYSTEM "chrome://browser/locale/baseMenuOverlay.dtd" > -%baseMenuDTD; -<!ENTITY % charsetDTD SYSTEM "chrome://browser/locale/charsetMenu.dtd" > -%charsetDTD; -<!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" > -%textcontextDTD; -<!ENTITY % customizeToolbarDTD SYSTEM "chrome://global/locale/customizeToolbar.dtd"> - %customizeToolbarDTD; -<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd"> -%placesDTD; -<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd"> -%aboutHomeDTD; -]> - diff --git a/browser/base/content/browser-feeds.js b/browser/base/content/browser-feeds.js deleted file mode 100644 index c67877269..000000000 --- a/browser/base/content/browser-feeds.js +++ /dev/null @@ -1,224 +0,0 @@ -# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -# 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/. - -/** - * The Feed Handler object manages discovery of RSS/ATOM feeds in web pages - * and shows UI when they are discovered. - */ -var FeedHandler = { - - /* Pale Moon: Address Bar: Feeds - * The click handler for the Feed icon in the location bar. Opens the - * subscription page if user is not given a choice of feeds. - * (Otherwise the list of available feeds will be presented to the - * user in a popup menu.) - */ - onFeedButtonPMClick: function(event) { - event.stopPropagation(); - - if (event.target.hasAttribute("feed") && - event.eventPhase == Event.AT_TARGET && - (event.button == 0 || event.button == 1)) { - this.subscribeToFeed(null, event); - } - }, - - /** - * The click handler for the Feed icon in the toolbar. Opens the - * subscription page if user is not given a choice of feeds. - * (Otherwise the list of available feeds will be presented to the - * user in a popup menu.) - */ - onFeedButtonClick: function(event) { - event.stopPropagation(); - - let feeds = gBrowser.selectedBrowser.feeds || []; - // If there are multiple feeds, the menu will open, so no need to do - // anything. If there are no feeds, nothing to do either. - if (feeds.length != 1) - return; - - if (event.eventPhase == Event.AT_TARGET && - (event.button == 0 || event.button == 1)) { - this.subscribeToFeed(feeds[0].href, event); - } - }, - - /** Called when the user clicks on the Subscribe to This Page... menu item. - * Builds a menu of unique feeds associated with the page, and if there - * is only one, shows the feed inline in the browser window. - * @param menuPopup - * The feed list menupopup to be populated. - * @returns true if the menu should be shown, false if there was only - * one feed and the feed should be shown inline in the browser - * window (do not show the menupopup). - */ - buildFeedList: function(menuPopup) { - var feeds = gBrowser.selectedBrowser.feeds; - if (feeds == null) { - // XXX hack -- menu opening depends on setting of an "open" - // attribute, and the menu refuses to open if that attribute is - // set (because it thinks it's already open). onpopupshowing gets - // called after the attribute is unset, and it doesn't get unset - // if we return false. so we unset it here; otherwise, the menu - // refuses to work past this point. - menuPopup.parentNode.removeAttribute("open"); - return false; - } - - while (menuPopup.firstChild) - menuPopup.removeChild(menuPopup.firstChild); - - if (feeds.length == 1) { - var feedButtonPM = document.getElementById("ub-feed-button"); - if (feedButtonPM) - feedButtonPM.setAttribute("feed", feeds[0].href); - return false; - } - - if (feeds.length <= 1) - return false; - - // Build the menu showing the available feed choices for viewing. - for (let feedInfo of feeds) { - var menuItem = document.createElement("menuitem"); - var baseTitle = feedInfo.title || feedInfo.href; - var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]); - menuItem.setAttribute("class", "feed-menuitem"); - menuItem.setAttribute("label", labelStr); - menuItem.setAttribute("feed", feedInfo.href); - menuItem.setAttribute("tooltiptext", feedInfo.href); - menuItem.setAttribute("crop", "center"); - menuPopup.appendChild(menuItem); - } - return true; - }, - - /** - * Subscribe to a given feed. Called when - * 1. Page has a single feed and user clicks feed icon in location bar - * 2. Page has a single feed and user selects Subscribe menu item - * 3. Page has multiple feeds and user selects from feed icon popup - * 4. Page has multiple feeds and user selects from Subscribe submenu - * @param href - * The feed to subscribe to. May be null, in which case the - * event target's feed attribute is examined. - * @param event - * The event this method is handling. Used to decide where - * to open the preview UI. (Optional, unless href is null) - */ - subscribeToFeed: function(href, event) { - // Just load the feed in the content area to either subscribe or show the - // preview UI - if (!href) - href = event.target.getAttribute("feed"); - urlSecurityCheck(href, gBrowser.contentPrincipal, - Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); - var feedURI = makeURI(href, document.characterSet); - // Use the feed scheme so X-Moz-Is-Feed will be set - // The value doesn't matter - if (/^https?$/.test(feedURI.scheme)) - href = "feed:" + href; - this.loadFeed(href, event); - }, - - loadFeed: function(href, event) { - var feeds = gBrowser.selectedBrowser.feeds; - try { - openUILink(href, event, { ignoreAlt: true }); - } - finally { - // We might default to a livebookmarks modal dialog, - // so reset that if the user happens to click it again - gBrowser.selectedBrowser.feeds = feeds; - } - }, - - get _feedMenuitem() { - delete this._feedMenuitem; - return this._feedMenuitem = document.getElementById("singleFeedMenuitemState"); - }, - - get _feedMenupopup() { - delete this._feedMenupopup; - return this._feedMenupopup = document.getElementById("multipleFeedsMenuState"); - }, - - /** - * Update the browser UI to show whether or not feeds are available when - * a page is loaded or the user switches tabs to a page that has feeds. - */ - updateFeeds: function() { - if (this._updateFeedTimeout) - clearTimeout(this._updateFeedTimeout); - - var feeds = gBrowser.selectedBrowser.feeds; - var haveFeeds = feeds && feeds.length > 0; - - var feedButtonPM = document.getElementById("ub-feed-button"); - - var feedButton = document.getElementById("feed-button"); - - if (feedButton) - feedButton.disabled = !haveFeeds; - - if (feedButtonPM) { - if (!haveFeeds) { - feedButtonPM.collapsed = true; - feedButtonPM.removeAttribute("feed"); - } else { - feedButtonPM.collapsed = !gPrefService.getBoolPref("browser.urlbar.rss"); - } - } - - if (!haveFeeds) { - this._feedMenuitem.setAttribute("disabled", "true"); - this._feedMenuitem.removeAttribute("hidden"); - this._feedMenupopup.setAttribute("hidden", "true"); - return; - } - - if (feeds.length > 1) { - if (feedButtonPM) - feedButtonPM.removeAttribute("feed"); - this._feedMenuitem.setAttribute("hidden", "true"); - this._feedMenupopup.removeAttribute("hidden"); - } else { - if (feedButtonPM) - feedButtonPM.setAttribute("feed", feeds[0].href); - this._feedMenuitem.setAttribute("feed", feeds[0].href); - this._feedMenuitem.removeAttribute("disabled"); - this._feedMenuitem.removeAttribute("hidden"); - this._feedMenupopup.setAttribute("hidden", "true"); - } - }, - - addFeed: function(link, targetDoc) { - // find which tab this is for, and set the attribute on the browser - var browserForLink = gBrowser.getBrowserForDocument(targetDoc); - if (!browserForLink) { - // ignore feeds loaded in subframes (see bug 305472) - return; - } - - if (!browserForLink.feeds) - browserForLink.feeds = []; - - browserForLink.feeds.push({ href: link.href, title: link.title }); - - // If this addition was for the current browser, update the UI. For - // background browsers, we'll update on tab switch. - if (browserForLink == gBrowser.selectedBrowser) { - var feedButtonPM = document.getElementById("ub-feed-button"); - if (feedButtonPM) - feedButtonPM.collapsed = !gPrefService.getBoolPref("browser.urlbar.rss"); - // Batch updates to avoid updating the UI for multiple onLinkAdded events - // fired within 100ms of each other. - if (this._updateFeedTimeout) - clearTimeout(this._updateFeedTimeout); - this._updateFeedTimeout = setTimeout(this.updateFeeds.bind(this), 100); - } - } -}; diff --git a/browser/base/content/browser-fullScreen.js b/browser/base/content/browser-fullScreen.js deleted file mode 100644 index b8a29199e..000000000 --- a/browser/base/content/browser-fullScreen.js +++ /dev/null @@ -1,607 +0,0 @@ -# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -# 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/. - -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 the View:FullScreen command, which controls elements like the - // fullscreen menuitem, menubars, and the appmenu. - let fullscreenCommand = document.getElementById("View:FullScreen"); - if (enterFS) { - fullscreenCommand.setAttribute("checked", enterFS); - } else { - fullscreenCommand.removeAttribute("checked"); - } - -#ifdef XP_MACOSX - // Make sure the menu items are adjusted. - document.getElementById("enterFullScreenItem").hidden = enterFS; - document.getElementById("exitFullScreenItem").hidden = !enterFS; -#endif - - // 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 - // make sure toolbars are made visible in the case of DOM fullscreen. - if (enterFS && this.useLionFullScreen) { - if (document.mozFullScreen) { - this.showXULChrome("toolbar", false); - } - else { - gNavToolbox.setAttribute("inFullscreen", true); - document.documentElement.setAttribute("inFullscreen", true); - } - return; - } - - // show/hide menubars, toolbars (except the full screen toolbar) - 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); - // 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); - } - else { - // The user may quit fullscreen during an animation - this._cancelAnimation(); - gNavToolbox.style.marginTop = ""; - if (this._isChromeCollapsed) - this.mouseoverToggle(true); - // This is needed if they use the context menu to quit fullscreen - this._isPopupOpen = false; - - document.documentElement.removeAttribute("inDOMFullscreen"); - - this.cleanup(); - } - }, - - exitDomFullScreen : function() { - document.mozCancelFullScreen(); - }, - - handleEvent: function (event) { - switch (event.type) { - case "activate": - if (document.mozFullScreen) { - this.showWarning(this.fullscreenDoc); - } - break; - case "transitionend": - if (event.propertyName == "opacity") - this.cancelWarning(); - break; - } - }, - - enterDomFullscreen : function(event) { - if (!document.mozFullScreen) - return; - - // However, if we receive a "MozEnteredDomFullScreen" 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 - // since the "full-screen document" isn't acutally visible. - if (!event.target.defaultView.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell).isActive) { - document.mozCancelFullScreen(); - return; - } - - let focusManager = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); - if (focusManager.activeWindow != window) { - // The top-level window has lost focus since the request to enter - // full-screen was made. Cancel full-screen. - document.mozCancelFullScreen(); - return; - } - - document.documentElement.setAttribute("inDOMFullscreen", true); - - if (gFindBarInitialized) - gFindBar.close(); - - this.showWarning(event.target); - - // Exit DOM full-screen mode upon open, close, or change tab. - gBrowser.tabContainer.addEventListener("TabOpen", this.exitDomFullScreen); - gBrowser.tabContainer.addEventListener("TabClose", this.exitDomFullScreen); - gBrowser.tabContainer.addEventListener("TabSelect", this.exitDomFullScreen); - - // Add listener to detect when the fullscreen window is re-focused. - // If a fullscreen window loses focus, we show a warning when the - // fullscreen window is refocused. - if (!this.useLionFullScreen) { - window.addEventListener("activate", this); - } - - // 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); - }, - - cleanup: function () { - if (window.fullScreen) { - gBrowser.mPanelContainer.removeEventListener("mousemove", - this._collapseCallback, false); - 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); - gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen); - if (!this.useLionFullScreen) - window.removeEventListener("activate", this); - this.fullscreenDoc = null; - } - }, - - observe: function(aSubject, aTopic, aData) - { - 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); - } - } - }, - - // Event callbacks - _expandCallback: function() - { - FullScreen.mouseoverToggle(true); - }, - _collapseCallback: function() - { - FullScreen.mouseoverToggle(false); - }, - _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); - } - // 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); - }, - - // Checks whether we are allowed to collapse the chrome - _isPopupOpen: false, - _isChromeCollapsed: false, - _safeToCollapse: function(forceHide) - { - if (!gPrefService.getBoolPref("browser.fullscreen.autohide")) - return false; - - // a popup menu is open in chrome: don't collapse chrome - if (!forceHide && this._isPopupOpen) - return false; - - // a textbox in chrome is focused (location bar anyone?): don't collapse chrome - if (document.commandDispatcher.focusedElement && - document.commandDispatcher.focusedElement.ownerDocument == document && - document.commandDispatcher.focusedElement.localName == "input") { - if (forceHide) - // hidden textboxes that still have focus are bad bad bad - document.commandDispatcher.focusedElement.blur(); - else - return false; - } - return true; - }, - - _setPopupOpen: function(aEvent) - { - // Popups should only veto chrome collapsing if they were opened when the chrome was not collapsed. - // Otherwise, they would not affect chrome and the user would expect the chrome to go away. - // e.g. we wouldn't want the autoscroll icon firing this event, so when the user - // toggles chrome when moving mouse to the top, it doesn't go away again. - if (aEvent.type == "popupshown" && !FullScreen._isChromeCollapsed && - aEvent.target.localName != "tooltip" && aEvent.target.localName != "window") - FullScreen._isPopupOpen = true; - else if (aEvent.type == "popuphidden" && aEvent.target.localName != "tooltip" && - aEvent.target.localName != "window") - FullScreen._isPopupOpen = false; - }, - - // Autohide helpers for the context menu item - getAutohide: function(aItem) - { - aItem.setAttribute("checked", gPrefService.getBoolPref("browser.fullscreen.autohide")); - }, - setAutohide: function() - { - gPrefService.setBoolPref("browser.fullscreen.autohide", !gPrefService.getBoolPref("browser.fullscreen.autohide")); - }, - - // 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.mozCancelAnimationFrame(this._animationHandle); - this._animationHandle = 0; - clearTimeout(this._animationTimeout); - this._isAnimating = false; - this._shouldAnimate = false; - }, - - cancelWarning: function(event) { - if (!this.warningBox) - return; - this.warningBox.removeEventListener("transitionend", this); - if (this.warningFadeOutTimeout) { - clearTimeout(this.warningFadeOutTimeout); - this.warningFadeOutTimeout = null; - } - - // Ensure focus switches away from the (now hidden) warning box. If the user - // clicked buttons in the fullscreen key authorization UI, it would have been - // focused, and any key events would be directed at the (now hidden) chrome - // document instead of the target document. - gBrowser.selectedBrowser.focus(); - - 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. - showWarning: function(targetDoc) { - if (!document.mozFullScreen || - !gPrefService.getBoolPref("full-screen-api.approval-required")) - return; - - // Set the strings on the fullscreen approval UI. - this.fullscreenDoc = targetDoc; - let uri = this.fullscreenDoc.nodePrincipal.URI; - let host = null; - try { - 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. - let utils = {}; - Cu.import("resource://gre/modules/DownloadUtils.jsm", utils); - let displayHost = utils.DownloadUtils.getURIHost(uri.spec)[0]; - let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); - - 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 - // wasn't hidden before another request was made. - if (!this.warningBox) { - this.warningBox = document.getElementById("full-screen-warning-container"); - // Add a listener to clean up state after the warning is hidden. - this.warningBox.addEventListener("transitionend", this); - this.warningBox.removeAttribute("hidden"); - } else { - if (this.warningFadeOutTimeout) { - clearTimeout(this.warningFadeOutTimeout); - this.warningFadeOutTimeout = null; - } - 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"); - } - - // 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); - }, - - 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))) - 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) - 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 { - gBrowser.mPanelContainer.removeEventListener("mousemove", - this._collapseCallback, false); - } - - // 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; - }, - - showXULChrome: function(aTag, aShow) - { - var els = document.getElementsByTagNameNS(this._XULNS, aTag); - - for (let el of els) { - // XXX don't interfere with previously collapsed toolbars - if (el.getAttribute("fullscreentoolbar") == "true") { - if (!aShow) { - - var toolbarMode = el.getAttribute("mode"); - if (toolbarMode != "text") { - el.setAttribute("saved-mode", toolbarMode); - el.setAttribute("saved-iconsize", el.getAttribute("iconsize")); - el.setAttribute("mode", "icons"); - el.setAttribute("iconsize", "small"); - } - - // Give the main nav bar and the tab bar the fullscreen context menu, - // otherwise remove context menu to prevent breakage - el.setAttribute("saved-context", el.getAttribute("context")); - if (el.id == "nav-bar" || el.id == "TabsToolbar") - el.setAttribute("context", "autohide-context"); - else - el.removeAttribute("context"); - - // Set the inFullscreen attribute to allow specific styling - // in fullscreen mode - el.setAttribute("inFullscreen", true); - } - else { - var restoreAttr = function restoreAttr(attrName) { - var savedAttr = "saved-" + attrName; - if (el.hasAttribute(savedAttr)) { - el.setAttribute(attrName, el.getAttribute(savedAttr)); - el.removeAttribute(savedAttr); - } - } - - restoreAttr("mode"); - restoreAttr("iconsize"); - restoreAttr("context"); - - el.removeAttribute("inFullscreen"); - } - } else { - // use moz-collapsed so it doesn't persist hidden/collapsed, - // so that new windows don't have missing toolbars - if (aShow) - el.removeAttribute("moz-collapsed"); - else - el.setAttribute("moz-collapsed", "true"); - } - } - - if (aShow) { - gNavToolbox.removeAttribute("inFullscreen"); - document.documentElement.removeAttribute("inFullscreen"); - } else { - gNavToolbox.setAttribute("inFullscreen", true); - document.documentElement.setAttribute("inFullscreen", true); - } - - // In tabs-on-top mode, move window controls to the tab bar, - // and in tabs-on-bottom mode, move them back to the navigation toolbar. - // When there is a chance the tab bar may be collapsed, put window - // controls on nav bar. - var fullscreenctls = document.getElementById("window-controls"); - var navbar = document.getElementById("nav-bar"); - var ctlsOnTabbar = window.toolbar.visible && - (navbar.collapsed || (TabsOnTop.enabled && - !gPrefService.getBoolPref("browser.tabs.autoHide"))); - if (fullscreenctls.parentNode == navbar && ctlsOnTabbar) { - fullscreenctls.removeAttribute("flex"); - document.getElementById("TabsToolbar").appendChild(fullscreenctls); - } - else if (fullscreenctls.parentNode.id == "TabsToolbar" && !ctlsOnTabbar) { - fullscreenctls.setAttribute("flex", "1"); - navbar.appendChild(fullscreenctls); - } - fullscreenctls.hidden = aShow; - - ToolbarIconColor.inferFromText(); - } -}; -XPCOMUtils.defineLazyGetter(FullScreen, "useLionFullScreen", function() { - // We'll only use OS X Lion full screen if we're - // * on OS X - // * on Lion or higher (Darwin 11+) - // * have fullscreenbutton="true" -#ifdef XP_MACOSX - return parseFloat(Services.sysinfo.getProperty("version")) >= 11 && - document.documentElement.getAttribute("fullscreenbutton") == "true"; -#else - return false; -#endif -}); diff --git a/browser/base/content/browser-fullZoom.js b/browser/base/content/browser-fullZoom.js deleted file mode 100644 index 0837bf7c2..000000000 --- a/browser/base/content/browser-fullZoom.js +++ /dev/null @@ -1,550 +0,0 @@ -/* -#ifdef 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 - */ - -// One of the possible values for the mousewheel.* preferences. -// From nsEventStateManager.cpp. -const MOUSE_SCROLL_ZOOM = 3; - -/** - * Controls the "full zoom" setting and its site-specific preferences. - */ -var FullZoom = { - // Identifies the setting in the content prefs database. - name: "browser.content.full-zoom", - - // browser.zoom.siteSpecific preference cache - _siteSpecificPref: undefined, - - // browser.zoom.updateBackgroundTabs preference cache - updateBackgroundTabs: undefined, - - // This maps the browser to monotonically increasing integer - // tokens. _browserTokenMap[browser] is increased each time the zoom is - // changed in the browser. See _getBrowserToken and _ignorePendingZoomAccesses. - _browserTokenMap: new WeakMap(), - - // Stores initial locations if we receive onLocationChange - // events before we're initialized. - _initialLocations: new WeakMap(), - - get siteSpecific() { - return this._siteSpecificPref; - }, - - //**************************************************************************// - // nsISupports - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, - Ci.nsIObserver, - Ci.nsIContentPrefObserver, - Ci.nsISupportsWeakReference, - Ci.nsISupports]), - - //**************************************************************************// - // Initialization & Destruction - - init: function FullZoom_init() { - // Listen for scrollwheel events so we can save scrollwheel-based changes. - window.addEventListener("DOMMouseScroll", this, false); - - // Register ourselves with the service so we know when our pref changes. - this._cps2 = Cc["@mozilla.org/content-pref/service;1"]. - getService(Ci.nsIContentPrefService2); - this._cps2.addObserverForName(this.name, this); - - this._siteSpecificPref = - gPrefService.getBoolPref("browser.zoom.siteSpecific"); - this.updateBackgroundTabs = - gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs"); - // Listen for changes to the browser.zoom branch so we can enable/disable - // updating background tabs and per-site saving and restoring of zoom levels. - gPrefService.addObserver("browser.zoom.", this, true); - - // If we received onLocationChange events for any of the current browsers - // before we were initialized we want to replay those upon initialization. - for (let browser of gBrowser.browsers) { - if (this._initialLocations.has(browser)) { - this.onLocationChange(...this._initialLocations.get(browser), browser); - } - } - - // This should be nulled after initialization. - this._initialLocations.clear(); - this._initialLocations = null; - }, - - destroy: function FullZoom_destroy() { - gPrefService.removeObserver("browser.zoom.", this); - this._cps2.removeObserverForName(this.name, this); - window.removeEventListener("DOMMouseScroll", this, false); - }, - - - //**************************************************************************// - // Event Handlers - - // nsIDOMEventListener - - handleEvent: function FullZoom_handleEvent(event) { - switch (event.type) { - case "DOMMouseScroll": - this._handleMouseScrolled(event); - break; - } - }, - - _handleMouseScrolled: function FullZoom__handleMouseScrolled(event) { - // Construct the "mousewheel action" pref key corresponding to this event. - // Based on nsEventStateManager::WheelPrefs::GetBasePrefName(). - var pref = "mousewheel."; - - var pressedModifierCount = event.shiftKey + event.ctrlKey + event.altKey + - event.metaKey + event.getModifierState("OS"); - if (pressedModifierCount != 1) { - pref += "default."; - } else if (event.shiftKey) { - pref += "with_shift."; - } else if (event.ctrlKey) { - pref += "with_control."; - } else if (event.altKey) { - pref += "with_alt."; - } else if (event.metaKey) { - pref += "with_meta."; - } else { - pref += "with_win."; - } - - pref += "action"; - - // Don't do anything if this isn't a "zoom" scroll event. - var isZoomEvent = false; - try { - isZoomEvent = (gPrefService.getIntPref(pref) == MOUSE_SCROLL_ZOOM); - } catch (e) {} - if (!isZoomEvent) - return; - - // XXX Lazily cache all the possible action prefs so we don't have to get - // them anew from the pref service for every scroll event? We'd have to - // make sure to observe them so we can update the cache when they change. - - // We have to call _applyZoomToPref in a timeout because we handle the - // event before the event state manager has a chance to apply the zoom - // during nsEventStateManager::PostHandleEvent. - let browser = gBrowser.selectedBrowser; - let token = this._getBrowserToken(browser); - window.setTimeout(function () { - if (token.isCurrent) - this._applyZoomToPref(browser); - }.bind(this), 0); - }, - - // nsIObserver - - observe: function (aSubject, aTopic, aData) { - switch (aTopic) { - case "nsPref:changed": - switch (aData) { - case "browser.zoom.siteSpecific": - this._siteSpecificPref = - gPrefService.getBoolPref("browser.zoom.siteSpecific"); - break; - case "browser.zoom.updateBackgroundTabs": - this.updateBackgroundTabs = - gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs"); - break; - } - break; - } - }, - - // nsIContentPrefObserver - - onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) { - this._onContentPrefChanged(aGroup, aValue); - }, - - onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) { - this._onContentPrefChanged(aGroup, undefined); - }, - - /** - * Appropriately updates the zoom level after a content preference has - * changed. - * - * @param aGroup The group of the changed preference. - * @param aValue The new value of the changed preference. Pass undefined to - * indicate the preference's removal. - */ - _onContentPrefChanged: function FullZoom__onContentPrefChanged(aGroup, aValue) { - if (this._isNextContentPrefChangeInternal) { - // Ignore changes that FullZoom itself makes. This works because the - // content pref service calls callbacks before notifying observers, and it - // does both in the same turn of the event loop. - delete this._isNextContentPrefChangeInternal; - return; - } - - let browser = gBrowser.selectedBrowser; - if (!browser.currentURI) - return; - - let domain = this._cps2.extractDomain(browser.currentURI.spec); - if (aGroup) { - if (aGroup == domain) - this._applyPrefToZoom(aValue, browser); - return; - } - - this._globalValue = aValue === undefined ? aValue : - this._ensureValid(aValue); - - // If the current page doesn't have a site-specific preference, then its - // zoom should be set to the new global preference now that the global - // preference has changed. - let hasPref = false; - let ctxt = this._loadContextFromBrowser(browser); - let token = this._getBrowserToken(browser); - this._cps2.getByDomainAndName(browser.currentURI.spec, this.name, ctxt, { - handleResult: function () hasPref = true, - handleCompletion: function () { - if (!hasPref && token.isCurrent) - this._applyPrefToZoom(undefined, browser); - }.bind(this) - }); - }, - - // location change observer - - /** - * Called when the location of a tab changes. - * When that happens, we need to update the current zoom level if appropriate. - * - * @param aURI - * A URI object representing the new location. - * @param aIsTabSwitch - * Whether this location change has happened because of a tab switch. - * @param aBrowser - * (optional) browser object displaying the document - */ - onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) { - let browser = aBrowser || gBrowser.selectedBrowser; - // If we haven't been initialized yet but receive an onLocationChange - // notification then let's store and replay it upon initialization. - if (this._initialLocations) { - this._initialLocations.set(browser, [aURI, aIsTabSwitch]); - return; - } - - // Ignore all pending async zoom accesses in the browser. Pending accesses - // that started before the location change will be prevented from applying - // to the new location. - this._ignorePendingZoomAccesses(browser); - - if (!aURI || (aIsTabSwitch && !this.siteSpecific)) { - this._notifyOnLocationChange(); - return; - } - - // Avoid the cps roundtrip and apply the default/global pref. - if (aURI.spec == "about:blank") { - this._applyPrefToZoom(undefined, browser, - this._notifyOnLocationChange.bind(this)); - return; - } - - // Media documents should always start at 1, and are not affected by prefs. - if (!aIsTabSwitch && browser.isSyntheticDocument) { - ZoomManager.setZoomForBrowser(browser, 1); - // _ignorePendingZoomAccesses already called above, so no need here. - this._notifyOnLocationChange(); - return; - } - - // See if the zoom pref is cached. - let ctxt = this._loadContextFromBrowser(browser); - let pref = this._cps2.getCachedByDomainAndName(aURI.spec, this.name, ctxt); - if (pref) { - this._applyPrefToZoom(pref.value, browser, - this._notifyOnLocationChange.bind(this)); - return; - } - - // It's not cached, so we have to asynchronously fetch it. - let value = undefined; - let token = this._getBrowserToken(browser); - this._cps2.getByDomainAndName(aURI.spec, this.name, ctxt, { - handleResult: function (resultPref) value = resultPref.value, - handleCompletion: function () { - if (!token.isCurrent) { - this._notifyOnLocationChange(); - return; - } - this._applyPrefToZoom(value, browser, - this._notifyOnLocationChange.bind(this)); - }.bind(this) - }); - }, - - // update state of zoom type menu item - - updateMenu: function FullZoom_updateMenu() { - var menuItem = document.getElementById("toggle_zoom"); - - menuItem.setAttribute("checked", !ZoomManager.useFullZoom); - }, - - //**************************************************************************// - // Setting & Pref Manipulation - - /** - * Reduces the zoom level of the page in the current browser. - */ - reduce: function FullZoom_reduce() { - ZoomManager.reduce(); - let browser = gBrowser.selectedBrowser; - this._ignorePendingZoomAccesses(browser); - this._applyZoomToPref(browser); - }, - - /** - * Enlarges the zoom level of the page in the current browser. - */ - enlarge: function FullZoom_enlarge() { - ZoomManager.enlarge(); - let browser = gBrowser.selectedBrowser; - this._ignorePendingZoomAccesses(browser); - this._applyZoomToPref(browser); - }, - - /** - * Sets the zoom level of the page in the current browser to the global zoom - * level. - */ - reset: function FullZoom_reset() { - let browser = gBrowser.selectedBrowser; - let token = this._getBrowserToken(browser); - this._getGlobalValue(browser, function (value) { - if (token.isCurrent) { - ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value); - this._ignorePendingZoomAccesses(browser); - } - }); - this._removePref(browser); - }, - - /** - * Set the zoom level for a given browser. - * - * Per nsPresContext::setFullZoom, we can set the zoom to its current value - * without significant impact on performance, as the setting is only applied - * if it differs from the current setting. In fact getting the zoom and then - * checking ourselves if it differs costs more. - * - * And perhaps we should always set the zoom even if it was more expensive, - * since nsDocumentViewer::SetTextZoom claims that child documents can have - * a different text zoom (although it would be unusual), and it implies that - * those child text zooms should get updated when the parent zoom gets set, - * and perhaps the same is true for full zoom - * (although nsDocumentViewer::SetFullZoom doesn't mention it). - * - * So when we apply new zoom values to the browser, we simply set the zoom. - * We don't check first to see if the new value is the same as the current - * one. - * - * @param aValue The zoom level value. - * @param aBrowser The zoom is set in this browser. Required. - * @param aCallback If given, it's asynchronously called when complete. - */ - _applyPrefToZoom: function FullZoom__applyPrefToZoom(aValue, aBrowser, aCallback) { - if (!this.siteSpecific || gInPrintPreviewMode) { - this._executeSoon(aCallback); - return; - } - - // The browser is sometimes half-destroyed because this method is called - // by content pref service callbacks, which themselves can be called at any - // time, even after browsers are closed. - if (!aBrowser.parentNode || aBrowser.isSyntheticDocument) { - this._executeSoon(aCallback); - return; - } - - if (aValue !== undefined) { - ZoomManager.setZoomForBrowser(aBrowser, this._ensureValid(aValue)); - this._ignorePendingZoomAccesses(aBrowser); - this._executeSoon(aCallback); - return; - } - - let token = this._getBrowserToken(aBrowser); - this._getGlobalValue(aBrowser, function (value) { - if (token.isCurrent) { - ZoomManager.setZoomForBrowser(aBrowser, value === undefined ? 1 : value); - this._ignorePendingZoomAccesses(aBrowser); - } - this._executeSoon(aCallback); - }); - }, - - /** - * Saves the zoom level of the page in the given browser to the content - * prefs store. - * - * @param browser The zoom of this browser will be saved. Required. - */ - _applyZoomToPref: function FullZoom__applyZoomToPref(browser) { - if (!this.siteSpecific || - gInPrintPreviewMode || - browser.isSyntheticDocument) - return; - - this._cps2.set(browser.currentURI.spec, this.name, - ZoomManager.getZoomForBrowser(browser), - this._loadContextFromBrowser(browser), { - handleCompletion: function () { - this._isNextContentPrefChangeInternal = true; - }.bind(this), - }); - }, - - /** - * Removes from the content prefs store the zoom level of the given browser. - * - * @param browser The zoom of this browser will be removed. Required. - */ - _removePref: function FullZoom__removePref(browser) { - if (browser.isSyntheticDocument) - return; - let ctxt = this._loadContextFromBrowser(browser); - this._cps2.removeByDomainAndName(browser.currentURI.spec, this.name, ctxt, { - handleCompletion: function () { - this._isNextContentPrefChangeInternal = true; - }.bind(this), - }); - }, - - //**************************************************************************// - // Utilities - - /** - * Returns the zoom change token of the given browser. Asynchronous - * operations that access the given browser's zoom should use this method to - * capture the token before starting and use token.isCurrent to determine if - * it's safe to access the zoom when done. If token.isCurrent is false, then - * after the async operation started, either the browser's zoom was changed or - * the browser was destroyed, and depending on what the operation is doing, it - * may no longer be safe to set and get its zoom. - * - * @param browser The token of this browser will be returned. - * @return An object with an "isCurrent" getter. - */ - _getBrowserToken: function FullZoom__getBrowserToken(browser) { - let map = this._browserTokenMap; - if (!map.has(browser)) - map.set(browser, 0); - return { - token: map.get(browser), - get isCurrent() { - // At this point, the browser may have been destructed and unbound but - // its outer ID not removed from the map because outer-window-destroyed - // hasn't been received yet. In that case, the browser is unusable, it - // has no properties, so return false. Check for this case by getting a - // property, say, docShell. - return map.get(browser) === this.token && browser.parentNode; - }, - }; - }, - - /** - * Increments the zoom change token for the given browser so that pending - * async operations know that it may be unsafe to access they zoom when they - * finish. - * - * @param browser Pending accesses in this browser will be ignored. - */ - _ignorePendingZoomAccesses: function FullZoom__ignorePendingZoomAccesses(browser) { - let map = this._browserTokenMap; - map.set(browser, (map.get(browser) || 0) + 1); - }, - - _ensureValid: function FullZoom__ensureValid(aValue) { - // Note that undefined is a valid value for aValue that indicates a known- - // not-to-exist value. - if (isNaN(aValue)) - return 1; - - if (aValue < ZoomManager.MIN) - return ZoomManager.MIN; - - if (aValue > ZoomManager.MAX) - return ZoomManager.MAX; - - return aValue; - }, - - /** - * Gets the global browser.content.full-zoom content preference. - * - * WARNING: callback may be called synchronously or asynchronously. The - * reason is that it's usually desirable to avoid turns of the event loop - * where possible, since they can lead to visible, jarring jumps in zoom - * level. It's not always possible to avoid them, though. As a convenience, - * then, this method takes a callback and returns nothing. - * - * @param browser The content browser pertaining to the zoom. - * @param callback Synchronously or asynchronously called when done. It's - * bound to this object (FullZoom) and called as: - * callback(prefValue) - */ - _getGlobalValue: function FullZoom__getGlobalValue(browser, callback) { - // * !("_globalValue" in this) => global value not yet cached. - // * this._globalValue === undefined => global value known not to exist. - // * Otherwise, this._globalValue is a number, the global value. - if ("_globalValue" in this) { - callback.call(this, this._globalValue, true); - return; - } - let value = undefined; - this._cps2.getGlobal(this.name, this._loadContextFromBrowser(browser), { - handleResult: function (pref) value = pref.value, - handleCompletion: function (reason) { - this._globalValue = this._ensureValid(value); - callback.call(this, this._globalValue); - }.bind(this) - }); - }, - - /** - * Gets the load context from the given content browser. - * - * @param Browser The Browser whose load context will be returned. - * @return The nsILoadContext of the given Browser. - */ - _loadContextFromBrowser: function FullZoom__loadContextFromBrowser(browser) { - return browser.loadContext; - }, - - /** - * Asynchronously broadcasts a "browser-fullZoom:locationChange" notification - * so that tests can select tabs, load pages, etc. and be notified when the - * zoom levels on those pages change. The notification is always asynchronous - * so that observers are guaranteed a consistent behavior. - */ - _notifyOnLocationChange: function FullZoom__notifyOnLocationChange() { - this._executeSoon(function () { - Services.obs.notifyObservers(null, "browser-fullZoom:locationChange", ""); - }); - }, - - _executeSoon: function FullZoom__executeSoon(callback) { - if (!callback) - return; - Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL); - }, -}; diff --git a/browser/base/content/browser-gestureSupport.js b/browser/base/content/browser-gestureSupport.js deleted file mode 100644 index d88f47c79..000000000 --- a/browser/base/content/browser-gestureSupport.js +++ /dev/null @@ -1,1059 +0,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/. - -// Simple gestures support -// -// As per bug #412486, web content must not be allowed to receive any -// simple gesture events. Multi-touch gesture APIs are in their -// infancy and we do NOT want to be forced into supporting an API that -// will probably have to change in the future. (The current Mac OS X -// API is undocumented and was reverse-engineered.) Until support is -// implemented in the event dispatcher to keep these events as -// chrome-only, we must listen for the simple gesture events during -// the capturing phase and call stopPropagation on every event. - -let gGestureSupport = { - _currentRotation: 0, - _lastRotateDelta: 0, - _rotateMomentumThreshold: .75, - - /** - * Add or remove mouse gesture event listeners - * - * @param aAddListener - * True to add/init listeners and false to remove/uninit - */ - init: function GS_init(aAddListener) { - // Bug 863514 - Make gesture support work in electrolysis - if (gMultiProcessBrowser) - return; - - const gestureEvents = ["SwipeGestureStart", - "SwipeGestureUpdate", "SwipeGestureEnd", "SwipeGesture", - "MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture", - "RotateGestureStart", "RotateGestureUpdate", "RotateGesture", - "TapGesture", "PressTapGesture"]; - - let addRemove = aAddListener ? window.addEventListener : - window.removeEventListener; - - gestureEvents.forEach(function (event) addRemove("Moz" + event, this, true), - this); - }, - - /** - * Dispatch events based on the type of mouse gesture event. For now, make - * sure to stop propagation of every gesture event so that web content cannot - * receive gesture events. - * - * @param aEvent - * The gesture event to handle - */ - handleEvent: function GS_handleEvent(aEvent) { - if (!Services.prefs.getBoolPref( - "dom.debug.propagate_gesture_events_through_content")) { - aEvent.stopPropagation(); - } - - // Create a preference object with some defaults - let def = function(aThreshold, aLatched) - ({ threshold: aThreshold, latched: !!aLatched }); - - switch (aEvent.type) { - case "MozSwipeGestureStart": - aEvent.preventDefault(); - this._setupSwipeGesture(aEvent); - break; - case "MozSwipeGestureUpdate": - aEvent.preventDefault(); - this._doUpdate(aEvent); - break; - case "MozSwipeGestureEnd": - aEvent.preventDefault(); - this._doEnd(aEvent); - break; - case "MozSwipeGesture": - aEvent.preventDefault(); - this.onSwipe(aEvent); - break; - case "MozMagnifyGestureStart": - aEvent.preventDefault(); -#ifdef XP_WIN - this._setupGesture(aEvent, "pinch", def(25, 0), "out", "in"); -#else - this._setupGesture(aEvent, "pinch", def(150, 1), "out", "in"); -#endif - break; - case "MozRotateGestureStart": - aEvent.preventDefault(); - this._setupGesture(aEvent, "twist", def(25, 0), "right", "left"); - break; - case "MozMagnifyGestureUpdate": - case "MozRotateGestureUpdate": - aEvent.preventDefault(); - this._doUpdate(aEvent); - break; - case "MozTapGesture": - aEvent.preventDefault(); - this._doAction(aEvent, ["tap"]); - break; - case "MozRotateGesture": - aEvent.preventDefault(); - this._doAction(aEvent, ["twist", "end"]); - break; - /* case "MozPressTapGesture": - break; */ - } - }, - - /** - * Called at the start of "pinch" and "twist" gestures to setup all of the - * information needed to process the gesture - * - * @param aEvent - * The continual motion start event to handle - * @param aGesture - * Name of the gesture to handle - * @param aPref - * Preference object with the names of preferences and defaults - * @param aInc - * Command to trigger for increasing motion (without gesture name) - * @param aDec - * Command to trigger for decreasing motion (without gesture name) - */ - _setupGesture: function GS__setupGesture(aEvent, aGesture, aPref, aInc, aDec) { - // Try to load user-set values from preferences - for (let [pref, def] in Iterator(aPref)) - aPref[pref] = this._getPref(aGesture + "." + pref, def); - - // Keep track of the total deltas and latching behavior - let offset = 0; - let latchDir = aEvent.delta > 0 ? 1 : -1; - let isLatched = false; - - // Create the update function here to capture closure state - this._doUpdate = function GS__doUpdate(aEvent) { - // Update the offset with new event data - offset += aEvent.delta; - - // Check if the cumulative deltas exceed the threshold - if (Math.abs(offset) > aPref["threshold"]) { - // Trigger the action if we don't care about latching; otherwise, make - // sure either we're not latched and going the same direction of the - // initial motion; or we're latched and going the opposite way - let sameDir = (latchDir ^ offset) >= 0; - if (!aPref["latched"] || (isLatched ^ sameDir)) { - this._doAction(aEvent, [aGesture, offset > 0 ? aInc : aDec]); - - // We must be getting latched or leaving it, so just toggle - isLatched = !isLatched; - } - - // Reset motion counter to prepare for more of the same gesture - offset = 0; - } - }; - - // The start event also contains deltas, so handle an update right away - this._doUpdate(aEvent); - }, - - /** - * Checks whether a swipe gesture event can navigate the browser history or - * not. - * - * @param aEvent - * The swipe gesture event. - * @return true if the swipe event may navigate the history, false othwerwise. - */ - _swipeNavigatesHistory: function GS__swipeNavigatesHistory(aEvent) { - return this._getCommand(aEvent, ["swipe", "left"]) - == "Browser:BackOrBackDuplicate" && - this._getCommand(aEvent, ["swipe", "right"]) - == "Browser:ForwardOrForwardDuplicate"; - }, - - /** - * Sets up the history swipe animations for a swipe gesture event, if enabled. - * - * @param aEvent - * The swipe gesture start event. - */ - _setupSwipeGesture: function GS__setupSwipeGesture(aEvent) { - if (!this._swipeNavigatesHistory(aEvent)) - return; - - let canGoBack = gHistorySwipeAnimation.canGoBack(); - let canGoForward = gHistorySwipeAnimation.canGoForward(); - let isLTR = gHistorySwipeAnimation.isLTR; - - if (canGoBack) - aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_LEFT : - aEvent.DIRECTION_RIGHT; - if (canGoForward) - aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_RIGHT : - aEvent.DIRECTION_LEFT; - - gHistorySwipeAnimation.startAnimation(); - - this._doUpdate = function GS__doUpdate(aEvent) { - gHistorySwipeAnimation.updateAnimation(aEvent.delta); - }; - - this._doEnd = function GS__doEnd(aEvent) { - gHistorySwipeAnimation.swipeEndEventReceived(); - - this._doUpdate = function (aEvent) {}; - this._doEnd = function (aEvent) {}; - } - }, - - /** - * Generator producing the powerset of the input array where the first result - * is the complete set and the last result (before StopIteration) is empty. - * - * @param aArray - * Source array containing any number of elements - * @yield Array that is a subset of the input array from full set to empty - */ - _power: function GS__power(aArray) { - // Create a bitmask based on the length of the array - let num = 1 << aArray.length; - while (--num >= 0) { - // Only select array elements where the current bit is set - yield aArray.reduce(function (aPrev, aCurr, aIndex) { - if (num & 1 << aIndex) - aPrev.push(aCurr); - return aPrev; - }, []); - } - }, - - /** - * Determine what action to do for the gesture based on which keys are - * pressed and which commands are set, and execute the command. - * - * @param aEvent - * The original gesture event to convert into a fake click event - * @param aGesture - * Array of gesture name parts (to be joined by periods) - * @return Name of the executed command. Returns null if no command is - * found. - */ - _doAction: function GS__doAction(aEvent, aGesture) { - let command = this._getCommand(aEvent, aGesture); - return command && this._doCommand(aEvent, command); - }, - - /** - * Determine what action to do for the gesture based on which keys are - * pressed and which commands are set - * - * @param aEvent - * The original gesture event to convert into a fake click event - * @param aGesture - * Array of gesture name parts (to be joined by periods) - */ - _getCommand: function GS__getCommand(aEvent, aGesture) { - // Create an array of pressed keys in a fixed order so that a command for - // "meta" is preferred over "ctrl" when both buttons are pressed (and a - // command for both don't exist) - let keyCombos = []; - ["shift", "alt", "ctrl", "meta"].forEach(function (key) { - if (aEvent[key + "Key"]) - keyCombos.push(key); - }); - - // Try each combination of key presses in decreasing order for commands - for (let subCombo of this._power(keyCombos)) { - // Convert a gesture and pressed keys into the corresponding command - // action where the preference has the gesture before "shift" before - // "alt" before "ctrl" before "meta" all separated by periods - let command; - try { - command = this._getPref(aGesture.concat(subCombo).join(".")); - } catch (e) {} - - if (command) - return command; - } - return null; - }, - - /** - * Execute the specified command. - * - * @param aEvent - * The original gesture event to convert into a fake click event - * @param aCommand - * Name of the command found for the event's keys and gesture. - */ - _doCommand: function GS__doCommand(aEvent, aCommand) { - let node = document.getElementById(aCommand); - if (node) { - if (node.getAttribute("disabled") != "true") { - let cmdEvent = document.createEvent("xulcommandevent"); - cmdEvent.initCommandEvent("command", true, true, window, 0, - aEvent.ctrlKey, aEvent.altKey, - aEvent.shiftKey, aEvent.metaKey, aEvent); - node.dispatchEvent(cmdEvent); - } - - } - else { - goDoCommand(aCommand); - } - }, - - /** - * Handle continual motion events. This function will be set by - * _setupGesture or _setupSwipe. - * - * @param aEvent - * The continual motion update event to handle - */ - _doUpdate: function(aEvent) {}, - - /** - * Handle gesture end events. This function will be set by _setupSwipe. - * - * @param aEvent - * The gesture end event to handle - */ - _doEnd: function(aEvent) {}, - - /** - * Convert the swipe gesture into a browser action based on the direction. - * - * @param aEvent - * The swipe event to handle - */ - onSwipe: function GS_onSwipe(aEvent) { - // Figure out which one (and only one) direction was triggered - for (let dir of ["UP", "RIGHT", "DOWN", "LEFT"]) { - if (aEvent.direction == aEvent["DIRECTION_" + dir]) { - this._coordinateSwipeEventWithAnimation(aEvent, dir); - break; - } - } - }, - - /** - * Process a swipe event based on the given direction. - * - * @param aEvent - * The swipe event to handle - * @param aDir - * The direction for the swipe event - */ - processSwipeEvent: function GS_processSwipeEvent(aEvent, aDir) { - this._doAction(aEvent, ["swipe", aDir.toLowerCase()]); - }, - - /** - * Coordinates the swipe event with the swipe animation, if any. - * If an animation is currently running, the swipe event will be - * processed once the animation stops. This will guarantee a fluid - * motion of the animation. - * - * @param aEvent - * The swipe event to handle - * @param aDir - * The direction for the swipe event - */ - _coordinateSwipeEventWithAnimation: - function GS__coordinateSwipeEventWithAnimation(aEvent, aDir) { - if ((gHistorySwipeAnimation.isAnimationRunning()) && - (aDir == "RIGHT" || aDir == "LEFT")) { - gHistorySwipeAnimation.processSwipeEvent(aEvent, aDir); - } - else { - this.processSwipeEvent(aEvent, aDir); - } - }, - - /** - * Get a gesture preference or use a default if it doesn't exist - * - * @param aPref - * Name of the preference to load under the gesture branch - * @param aDef - * Default value if the preference doesn't exist - */ - _getPref: function GS__getPref(aPref, aDef) { - // Preferences branch under which all gestures preferences are stored - const branch = "browser.gesture."; - - try { - // Determine what type of data to load based on default value's type - let type = typeof aDef; - let getFunc = "get" + (type == "boolean" ? "Bool" : - type == "number" ? "Int" : "Char") + "Pref"; - return gPrefService[getFunc](branch + aPref); - } - catch (e) { - return aDef; - } - }, - - /** - * Perform rotation for ImageDocuments - * - * @param aEvent - * The MozRotateGestureUpdate event triggering this call - */ - rotate: function(aEvent) { - if (!(content.document instanceof ImageDocument)) - return; - - let contentElement = content.document.body.firstElementChild; - if (!contentElement) - return; - // If we're currently snapping, cancel that snap - if (contentElement.classList.contains("completeRotation")) - this._clearCompleteRotation(); - - this.rotation = Math.round(this.rotation + aEvent.delta); - contentElement.style.transform = "rotate(" + this.rotation + "deg)"; - this._lastRotateDelta = aEvent.delta; - }, - - /** - * Perform a rotation end for ImageDocuments - */ - rotateEnd: function() { - if (!(content.document instanceof ImageDocument)) - return; - - let contentElement = content.document.body.firstElementChild; - if (!contentElement) - return; - - let transitionRotation = 0; - - // The reason that 360 is allowed here is because when rotating between - // 315 and 360, setting rotate(0deg) will cause it to rotate the wrong - // direction around--spinning wildly. - if (this.rotation <= 45) - transitionRotation = 0; - else if (this.rotation > 45 && this.rotation <= 135) - transitionRotation = 90; - else if (this.rotation > 135 && this.rotation <= 225) - transitionRotation = 180; - else if (this.rotation > 225 && this.rotation <= 315) - transitionRotation = 270; - else - transitionRotation = 360; - - // If we're going fast enough, and we didn't already snap ahead of rotation, - // then snap ahead of rotation to simulate momentum - if (this._lastRotateDelta > this._rotateMomentumThreshold && - this.rotation > transitionRotation) - transitionRotation += 90; - else if (this._lastRotateDelta < -1 * this._rotateMomentumThreshold && - this.rotation < transitionRotation) - transitionRotation -= 90; - - // Only add the completeRotation class if it is is necessary - if (transitionRotation != this.rotation) { - contentElement.classList.add("completeRotation"); - contentElement.addEventListener("transitionend", this._clearCompleteRotation); - } - - contentElement.style.transform = "rotate(" + transitionRotation + "deg)"; - this.rotation = transitionRotation; - }, - - /** - * Gets the current rotation for the ImageDocument - */ - get rotation() { - return this._currentRotation; - }, - - /** - * Sets the current rotation for the ImageDocument - * - * @param aVal - * The new value to take. Can be any value, but it will be bounded to - * 0 inclusive to 360 exclusive. - */ - set rotation(aVal) { - this._currentRotation = aVal % 360; - if (this._currentRotation < 0) - this._currentRotation += 360; - return this._currentRotation; - }, - - /** - * When the location/tab changes, need to reload the current rotation for the - * image - */ - restoreRotationState: function() { - // Bug 863514 - Make gesture support work in electrolysis - if (gMultiProcessBrowser) - return; - - if (!(content.document instanceof ImageDocument)) - return; - - let contentElement = content.document.body.firstElementChild; - let transformValue = content.window.getComputedStyle(contentElement, null) - .transform; - - if (transformValue == "none") { - this.rotation = 0; - return; - } - - // transformValue is a rotation matrix--split it and do mathemagic to - // obtain the real rotation value - transformValue = transformValue.split("(")[1] - .split(")")[0] - .split(","); - this.rotation = Math.round(Math.atan2(transformValue[1], transformValue[0]) * - (180 / Math.PI)); - }, - - /** - * Removes the transition rule by removing the completeRotation class - */ - _clearCompleteRotation: function() { - let contentElement = content.document && - content.document instanceof ImageDocument && - content.document.body && - content.document.body.firstElementChild; - if (!contentElement) - return; - contentElement.classList.remove("completeRotation"); - contentElement.removeEventListener("transitionend", this._clearCompleteRotation); - }, -}; - -// History Swipe Animation Support (bug 678392) -let gHistorySwipeAnimation = { - - active: false, - isLTR: false, - - /** - * Initializes the support for history swipe animations, if it is supported - * by the platform/configuration. - */ - init: function HSA_init() { - if (!this._isSupported()) - return; - - this.active = false; - this.isLTR = document.documentElement.mozMatchesSelector( - ":-moz-locale-dir(ltr)"); - this._trackedSnapshots = []; - this._historyIndex = -1; - this._boxWidth = -1; - this._maxSnapshots = this._getMaxSnapshots(); - this._lastSwipeDir = ""; - - // We only want to activate history swipe animations if we store snapshots. - // If we don't store any, we handle horizontal swipes without animations. - if (this._maxSnapshots > 0) { - this.active = true; - gBrowser.addEventListener("pagehide", this, false); - gBrowser.addEventListener("pageshow", this, false); - gBrowser.addEventListener("popstate", this, false); - gBrowser.tabContainer.addEventListener("TabClose", this, false); - } - }, - - /** - * Uninitializes the support for history swipe animations. - */ - uninit: function HSA_uninit() { - gBrowser.removeEventListener("pagehide", this, false); - gBrowser.removeEventListener("pageshow", this, false); - gBrowser.removeEventListener("popstate", this, false); - gBrowser.tabContainer.removeEventListener("TabClose", this, false); - - this.active = false; - this.isLTR = false; - }, - - /** - * Starts the swipe animation and handles fast swiping (i.e. a swipe animation - * is already in progress when a new one is initiated). - */ - startAnimation: function HSA_startAnimation() { - if (this.isAnimationRunning()) { - gBrowser.stop(); - this._lastSwipeDir = "RELOAD"; // just ensure that != "" - this._canGoBack = this.canGoBack(); - this._canGoForward = this.canGoForward(); - this._handleFastSwiping(); - } - else { - this._historyIndex = gBrowser.webNavigation.sessionHistory.index; - this._canGoBack = this.canGoBack(); - this._canGoForward = this.canGoForward(); - if (this.active) { - this._takeSnapshot(); - this._installPrevAndNextSnapshots(); - this._addBoxes(); - this._lastSwipeDir = ""; - } - } - this.updateAnimation(0); - }, - - /** - * Stops the swipe animation. - */ - stopAnimation: function HSA_stopAnimation() { - gHistorySwipeAnimation._removeBoxes(); - }, - - /** - * Updates the animation between two pages in history. - * - * @param aVal - * A floating point value that represents the progress of the - * swipe gesture. - */ - updateAnimation: function HSA_updateAnimation(aVal) { - if (!this.isAnimationRunning()) - return; - - if ((aVal >= 0 && this.isLTR) || - (aVal <= 0 && !this.isLTR)) { - if (aVal > 1) - aVal = 1; // Cap value to avoid sliding the page further than allowed. - - if (this._canGoBack) - this._prevBox.collapsed = false; - else - this._prevBox.collapsed = true; - - // The current page is pushed to the right (LTR) or left (RTL), - // the intention is to go back. - // If there is a page to go back to, it should show in the background. - this._positionBox(this._curBox, aVal); - - // The forward page should be pushed offscreen all the way to the right. - this._positionBox(this._nextBox, 1); - } - else { - if (aVal < -1) - aVal = -1; // Cap value to avoid sliding the page further than allowed. - - // The intention is to go forward. If there is a page to go forward to, - // it should slide in from the right (LTR) or left (RTL). - // Otherwise, the current page should slide to the left (LTR) or - // right (RTL) and the backdrop should appear in the background. - // For the backdrop to be visible in that case, the previous page needs - // to be hidden (if it exists). - if (this._canGoForward) { - let offset = this.isLTR ? 1 : -1; - this._positionBox(this._curBox, 0); - this._positionBox(this._nextBox, offset + aVal); // aVal is negative - } - else { - this._prevBox.collapsed = true; - this._positionBox(this._curBox, aVal); - } - } - }, - - /** - * Event handler for events relevant to the history swipe animation. - * - * @param aEvent - * An event to process. - */ - handleEvent: function HSA_handleEvent(aEvent) { - switch (aEvent.type) { - case "TabClose": - let browser = gBrowser.getBrowserForTab(aEvent.target); - this._removeTrackedSnapshot(-1, browser); - break; - case "pageshow": - case "popstate": - if (this.isAnimationRunning()) { - if (aEvent.target != gBrowser.selectedBrowser.contentDocument) - break; - this.stopAnimation(); - } - this._historyIndex = gBrowser.webNavigation.sessionHistory.index; - break; - case "pagehide": - if (aEvent.target == gBrowser.selectedBrowser.contentDocument) { - // Take a snapshot of a page whenever it's about to be navigated away - // from. - this._takeSnapshot(); - } - break; - } - }, - - /** - * Checks whether the history swipe animation is currently running or not. - * - * @return true if the animation is currently running, false otherwise. - */ - isAnimationRunning: function HSA_isAnimationRunning() { - return !!this._container; - }, - - /** - * Process a swipe event based on the given direction. - * - * @param aEvent - * The swipe event to handle - * @param aDir - * The direction for the swipe event - */ - processSwipeEvent: function HSA_processSwipeEvent(aEvent, aDir) { - if (aDir == "RIGHT") - this._historyIndex += this.isLTR ? 1 : -1; - else if (aDir == "LEFT") - this._historyIndex += this.isLTR ? -1 : 1; - else - return; - this._lastSwipeDir = aDir; - }, - - /** - * Checks if there is a page in the browser history to go back to. - * - * @return true if there is a previous page in history, false otherwise. - */ - canGoBack: function HSA_canGoBack() { - if (this.isAnimationRunning()) - return this._doesIndexExistInHistory(this._historyIndex - 1); - return gBrowser.webNavigation.canGoBack; - }, - - /** - * Checks if there is a page in the browser history to go forward to. - * - * @return true if there is a next page in history, false otherwise. - */ - canGoForward: function HSA_canGoForward() { - if (this.isAnimationRunning()) - return this._doesIndexExistInHistory(this._historyIndex + 1); - return gBrowser.webNavigation.canGoForward; - }, - - /** - * Used to notify the history swipe animation that the OS sent a swipe end - * event and that we should navigate to the page that the user swiped to, if - * any. This will also result in the animation overlay to be torn down. - */ - swipeEndEventReceived: function HSA_swipeEndEventReceived() { - if (this._lastSwipeDir != "") - this._navigateToHistoryIndex(); - else - this.stopAnimation(); - }, - - /** - * Checks whether a particular index exists in the browser history or not. - * - * @param aIndex - * The index to check for availability for in the history. - * @return true if the index exists in the browser history, false otherwise. - */ - _doesIndexExistInHistory: function HSA__doesIndexExistInHistory(aIndex) { - try { - gBrowser.webNavigation.sessionHistory.getEntryAtIndex(aIndex, false); - } - catch(ex) { - return false; - } - return true; - }, - - /** - * Navigates to the index in history that is currently being tracked by - * |this|. - */ - _navigateToHistoryIndex: function HSA__navigateToHistoryIndex() { - if (this._doesIndexExistInHistory(this._historyIndex)) { - gBrowser.webNavigation.gotoIndex(this._historyIndex); - } - }, - - /** - * Checks to see if history swipe animations are supported by this - * platform/configuration. - * - * return true if supported, false otherwise. - */ - _isSupported: function HSA__isSupported() { - return window.matchMedia("(-moz-swipe-animation-enabled)").matches; - }, - - /** - * Handle fast swiping (i.e. a swipe animation is already in - * progress when a new one is initiated). This will swap out the snapshots - * used in the previous animation with the appropriate new ones. - */ - _handleFastSwiping: function HSA__handleFastSwiping() { - this._installCurrentPageSnapshot(null); - this._installPrevAndNextSnapshots(); - }, - - /** - * Adds the boxes that contain the snapshots used during the swipe animation. - */ - _addBoxes: function HSA__addBoxes() { - let browserStack = - document.getAnonymousElementByAttribute(gBrowser.getNotificationBox(), - "class", "browserStack"); - this._container = this._createElement("historySwipeAnimationContainer", - "stack"); - browserStack.appendChild(this._container); - - this._prevBox = this._createElement("historySwipeAnimationPreviousPage", - "box"); - this._container.appendChild(this._prevBox); - - this._curBox = this._createElement("historySwipeAnimationCurrentPage", - "box"); - this._container.appendChild(this._curBox); - - this._nextBox = this._createElement("historySwipeAnimationNextPage", - "box"); - this._container.appendChild(this._nextBox); - - this._boxWidth = this._curBox.getBoundingClientRect().width; // cache width - }, - - /** - * Removes the boxes. - */ - _removeBoxes: function HSA__removeBoxes() { - this._curBox = null; - this._prevBox = null; - this._nextBox = null; - if (this._container) - this._container.parentNode.removeChild(this._container); - this._container = null; - this._boxWidth = -1; - }, - - /** - * Creates an element with a given identifier and tag name. - * - * @param aID - * An identifier to create the element with. - * @param aTagName - * The name of the tag to create the element for. - * @return the newly created element. - */ - _createElement: function HSA__createElement(aID, aTagName) { - let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let element = document.createElementNS(XULNS, aTagName); - element.id = aID; - return element; - }, - - /** - * Moves a given box to a given X coordinate position. - * - * @param aBox - * The box element to position. - * @param aPosition - * The position (in X coordinates) to move the box element to. - */ - _positionBox: function HSA__positionBox(aBox, aPosition) { - aBox.style.transform = "translateX(" + this._boxWidth * aPosition + "px)"; - }, - - /** - * Takes a snapshot of the page the browser is currently on. - */ - _takeSnapshot: function HSA__takeSnapshot() { - if ((this._maxSnapshots < 1) || - (gBrowser.webNavigation.sessionHistory.index < 0)) - return; - - let browser = gBrowser.selectedBrowser; - let r = browser.getBoundingClientRect(); - let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", - "canvas"); - canvas.mozOpaque = true; - canvas.width = r.width; - canvas.height = r.height; - let ctx = canvas.getContext("2d"); - let zoom = browser.markupDocumentViewer.fullZoom; - ctx.scale(zoom, zoom); - ctx.drawWindow(browser.contentWindow, 0, 0, r.width, r.height, "white", - ctx.DRAWWINDOW_DO_NOT_FLUSH | ctx.DRAWWINDOW_DRAW_VIEW | - ctx.DRAWWINDOW_ASYNC_DECODE_IMAGES | - ctx.DRAWWINDOW_USE_WIDGET_LAYERS); - - this._installCurrentPageSnapshot(canvas); - this._assignSnapshotToCurrentBrowser(canvas); - }, - - /** - * Retrieves the maximum number of snapshots that should be kept in memory. - * This limit is a global limit and is valid across all open tabs. - */ - _getMaxSnapshots: function HSA__getMaxSnapshots() { - return gPrefService.getIntPref("browser.snapshots.limit"); - }, - - /** - * Adds a snapshot to the list and initiates the compression of said snapshot. - * Once the compression is completed, it will replace the uncompressed - * snapshot in the list. - * - * @param aCanvas - * The snapshot to add to the list and compress. - */ - _assignSnapshotToCurrentBrowser: - function HSA__assignSnapshotToCurrentBrowser(aCanvas) { - let browser = gBrowser.selectedBrowser; - let currIndex = browser.webNavigation.sessionHistory.index; - - this._removeTrackedSnapshot(currIndex, browser); - this._addSnapshotRefToArray(currIndex, browser); - - if (!("snapshots" in browser)) - browser.snapshots = []; - let snapshots = browser.snapshots; - // Temporarily store the canvas as the compressed snapshot. - // This avoids a blank page if the user swipes quickly - // between pages before the compression could complete. - snapshots[currIndex] = aCanvas; - - // Kick off snapshot compression. - aCanvas.toBlob(function(aBlob) { - snapshots[currIndex] = aBlob; - }, "image/png" - ); - }, - - /** - * Removes a snapshot identified by the browser and index in the array of - * snapshots for that browser, if present. If no snapshot could be identified - * the method simply returns without taking any action. If aIndex is negative, - * all snapshots for a particular browser will be removed. - * - * @param aIndex - * The index in history of the new snapshot, or negative value if all - * snapshots for a browser should be removed. - * @param aBrowser - * The browser the new snapshot was taken in. - */ - _removeTrackedSnapshot: function HSA__removeTrackedSnapshot(aIndex, aBrowser) { - let arr = this._trackedSnapshots; - let requiresExactIndexMatch = aIndex >= 0; - for (let i = 0; i < arr.length; i++) { - if ((arr[i].browser == aBrowser) && - (aIndex < 0 || aIndex == arr[i].index)) { - delete aBrowser.snapshots[arr[i].index]; - arr.splice(i, 1); - if (requiresExactIndexMatch) - return; // Found and removed the only element. - i--; // Make sure to revisit the index that we just removed an - // element at. - } - } - }, - - /** - * Adds a new snapshot reference for a given index and browser to the array - * of references to tracked snapshots. - * - * @param aIndex - * The index in history of the new snapshot. - * @param aBrowser - * The browser the new snapshot was taken in. - */ - _addSnapshotRefToArray: - function HSA__addSnapshotRefToArray(aIndex, aBrowser) { - let id = { index: aIndex, - browser: aBrowser }; - let arr = this._trackedSnapshots; - arr.unshift(id); - - while (arr.length > this._maxSnapshots) { - let lastElem = arr[arr.length - 1]; - delete lastElem.browser.snapshots[lastElem.index]; - arr.splice(-1, 1); - } - }, - - /** - * Converts a compressed blob to an Image object. In some situations - * (especially during fast swiping) aBlob may still be a canvas, not a - * compressed blob. In this case, we simply return the canvas. - * - * @param aBlob - * The compressed blob to convert, or a canvas if a blob compression - * couldn't complete before this method was called. - * @return A new Image object representing the converted blob. - */ - _convertToImg: function HSA__convertToImg(aBlob) { - if (!aBlob) - return null; - - // Return aBlob if it's still a canvas and not a compressed blob yet. - if (aBlob instanceof HTMLCanvasElement) - return aBlob; - - let img = new Image(); - let url = URL.createObjectURL(aBlob); - img.onload = function() { - URL.revokeObjectURL(url); - }; - img.src = url; - return img; - }, - - /** - * Sets the snapshot of the current page to the snapshot passed as parameter, - * or to the one previously stored for the current index in history if the - * parameter is null. - * - * @param aCanvas - * The snapshot to set the current page to. If this parameter is null, - * the previously stored snapshot for this index (if any) will be used. - */ - _installCurrentPageSnapshot: - function HSA__installCurrentPageSnapshot(aCanvas) { - let currSnapshot = aCanvas; - if (!currSnapshot) { - let snapshots = gBrowser.selectedBrowser.snapshots || {}; - let currIndex = this._historyIndex; - if (currIndex in snapshots) - currSnapshot = this._convertToImg(snapshots[currIndex]); - } - document.mozSetImageElement("historySwipeAnimationCurrentPageSnapshot", - currSnapshot); - }, - - /** - * Sets the snapshots of the previous and next pages to the snapshots - * previously stored for their respective indeces. - */ - _installPrevAndNextSnapshots: - function HSA__installPrevAndNextSnapshots() { - let snapshots = gBrowser.selectedBrowser.snapshots || []; - let currIndex = this._historyIndex; - let prevIndex = currIndex - 1; - let prevSnapshot = null; - if (prevIndex in snapshots) - prevSnapshot = this._convertToImg(snapshots[prevIndex]); - document.mozSetImageElement("historySwipeAnimationPreviousPageSnapshot", - prevSnapshot); - - let nextIndex = currIndex + 1; - let nextSnapshot = null; - if (nextIndex in snapshots) - nextSnapshot = this._convertToImg(snapshots[nextIndex]); - document.mozSetImageElement("historySwipeAnimationNextPageSnapshot", - nextSnapshot); - }, -}; diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc deleted file mode 100644 index fa9d7f0f4..000000000 --- a/browser/base/content/browser-menubar.inc +++ /dev/null @@ -1,595 +0,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/. - - <menubar id="main-menubar" - onpopupshowing="if (event.target.parentNode.parentNode == this && - !('@mozilla.org/widget/nativemenuservice;1' in Cc)) - this.setAttribute('openedwithkey', - event.target.parentNode.openedWithKey);" - style="border:0px;padding:0px;margin:0px;-moz-appearance:none"> - <menu id="file-menu" label="&fileMenu.label;" - accesskey="&fileMenu.accesskey;"> - <menupopup id="menu_FilePopup"> - <menuitem id="menu_newNavigatorTab" - label="&tabCmd.label;" - command="cmd_newNavigatorTab" - key="key_newNavigatorTab" - accesskey="&tabCmd.accesskey;"/> - <menuitem id="menu_newNavigator" - label="&newNavigatorCmd.label;" - accesskey="&newNavigatorCmd.accesskey;" - key="key_newNavigator" - command="cmd_newNavigator"/> - <menuitem id="menu_newPrivateWindow" - label="&newPrivateWindow.label;" - accesskey="&newPrivateWindow.accesskey;" - command="Tools:PrivateBrowsing" - key="key_privatebrowsing"/> - <menuitem id="menu_openLocation" - class="show-only-for-keyboard" - label="&openLocationCmd.label;" - command="Browser:OpenLocation" - key="focusURLBar" - accesskey="&openLocationCmd.accesskey;"/> - <menuitem id="menu_openFile" - label="&openFileCmd.label;" - command="Browser:OpenFile" - key="openFileKb" - accesskey="&openFileCmd.accesskey;"/> - <menuitem id="menu_close" - class="show-only-for-keyboard" - label="&closeCmd.label;" - key="key_close" - accesskey="&closeCmd.accesskey;" - command="cmd_close"/> - <menuitem id="menu_closeWindow" - class="show-only-for-keyboard" - hidden="true" - command="cmd_closeWindow" - key="key_closeWindow" - label="&closeWindow.label;" - accesskey="&closeWindow.accesskey;"/> - <menuseparator/> - <menuitem id="menu_savePage" - label="&savePageCmd.label;" - accesskey="&savePageCmd.accesskey;" - key="key_savePage" - command="Browser:SavePage"/> - <menuitem id="menu_sendLink" - label="&emailPageCmd.label;" - accesskey="&emailPageCmd.accesskey;" - command="Browser:SendLink"/> - <menuseparator/> - <menuitem id="menu_printSetup" - label="&printSetupCmd.label;" - accesskey="&printSetupCmd.accesskey;" - command="cmd_pageSetup"/> -#ifndef XP_MACOSX - <menuitem id="menu_printPreview" - label="&printPreviewCmd.label;" - accesskey="&printPreviewCmd.accesskey;" - command="cmd_printPreview"/> -#endif - <menuitem id="menu_print" - label="&printCmd.label;" - accesskey="&printCmd.accesskey;" - key="printKb" - command="cmd_print"/> - <menuseparator/> - <menuitem id="goOfflineMenuitem" - label="&goOfflineCmd.label;" - accesskey="&goOfflineCmd.accesskey;" - type="checkbox" - observes="workOfflineMenuitemState" - oncommand="BrowserOffline.toggleOfflineStatus();"/> - <menuitem id="menu_restart" - label="&restartCmd.label;" - accesskey="&restartCmd.accesskey;" - command="cmd_restartApplication"/> - <menuitem id="menu_FileQuitItem" -#ifdef XP_WIN - label="&quitApplicationCmdWin.label;" - accesskey="&quitApplicationCmdWin.accesskey;" -#else -#ifdef XP_MACOSX - label="&quitApplicationCmdMac.label;" -#else - label="&quitApplicationCmd.label;" - accesskey="&quitApplicationCmd.accesskey;" -#endif -#ifdef XP_UNIX - key="key_quitApplication" -#endif -#endif - command="cmd_quitApplication"/> - </menupopup> - </menu> - - <menu id="edit-menu" label="&editMenu.label;" - accesskey="&editMenu.accesskey;"> - <menupopup id="menu_EditPopup" - onpopupshowing="updateEditUIVisibility()" - onpopuphidden="updateEditUIVisibility()"> - <menuitem id="menu_undo" - label="&undoCmd.label;" - key="key_undo" - accesskey="&undoCmd.accesskey;" - command="cmd_undo"/> - <menuitem id="menu_redo" - label="&redoCmd.label;" - key="key_redo" - accesskey="&redoCmd.accesskey;" - command="cmd_redo"/> - <menuseparator/> - <menuitem id="menu_cut" - label="&cutCmd.label;" - key="key_cut" - accesskey="&cutCmd.accesskey;" - command="cmd_cut"/> - <menuitem id="menu_copy" - label="©Cmd.label;" - key="key_copy" - accesskey="©Cmd.accesskey;" - command="cmd_copy"/> - <menuitem id="menu_paste" - label="&pasteCmd.label;" - key="key_paste" - accesskey="&pasteCmd.accesskey;" - command="cmd_paste"/> - <menuitem id="menu_delete" - label="&deleteCmd.label;" - key="key_delete" - accesskey="&deleteCmd.accesskey;" - command="cmd_delete"/> - <menuseparator/> - <menuitem id="menu_selectAll" - label="&selectAllCmd.label;" - key="key_selectAll" - accesskey="&selectAllCmd.accesskey;" - command="cmd_selectAll"/> - <menuseparator/> - <menuitem id="menu_find" - label="&findOnCmd.label;" - accesskey="&findOnCmd.accesskey;" - key="key_find" - command="cmd_find"/> - <menuitem id="menu_findAgain" - class="show-only-for-keyboard" - label="&findAgainCmd.label;" - accesskey="&findAgainCmd.accesskey;" - key="key_findAgain" - command="cmd_findAgain"/> - <menuseparator hidden="true" id="textfieldDirection-separator"/> - <menuitem id="textfieldDirection-swap" - command="cmd_switchTextDirection" - key="key_switchTextDirection" - label="&bidiSwitchTextDirectionItem.label;" - accesskey="&bidiSwitchTextDirectionItem.accesskey;" - hidden="true"/> - </menupopup> - </menu> - - <menu id="view-menu" label="&viewMenu.label;" - accesskey="&viewMenu.accesskey;"> - <menupopup id="menu_viewPopup" - onpopupshowing="updateCharacterEncodingMenuState();"> - <menu id="viewToolbarsMenu" - label="&viewToolbarsMenu.label;" - accesskey="&viewToolbarsMenu.accesskey;"> - <menupopup onpopupshowing="onViewToolbarsPopupShowing(event);"> - <menuseparator/> - <menuitem id="menu_tabsOnTop" - command="cmd_ToggleTabsOnTop" - type="checkbox" - label="&viewTabsOnTop.label;" - accesskey="&viewTabsOnTop.accesskey;"/> - <menuitem id="menu_customizeToolbars" - label="&viewCustomizeToolbar.label;" - accesskey="&viewCustomizeToolbar.accesskey;" - command="cmd_CustomizeToolbars"/> - </menupopup> - </menu> - <menu id="viewSidebarMenuMenu" - label="&viewSidebarMenu.label;" - accesskey="&viewSidebarMenu.accesskey;"> - <menupopup id="viewSidebarMenu"> - <menuitem id="menu_bookmarksSidebar" - key="viewBookmarksSidebarKb" - observes="viewBookmarksSidebar" - label="&bookmarksButton.label;"/> - <menuitem id="menu_historySidebar" - key="key_gotoHistory" - observes="viewHistorySidebar" - label="&historyButton.label;"/> - </menupopup> - </menu> - <menuseparator/> - <menuitem id="menu_stop" - class="show-only-for-keyboard" - label="&stopCmd.label;" - accesskey="&stopCmd.accesskey;" - command="Browser:Stop" -#ifdef XP_MACOSX - key="key_stop_mac"/> -#else - key="key_stop"/> -#endif - <menuitem id="menu_reload" - class="show-only-for-keyboard" - label="&reloadCmd.label;" - accesskey="&reloadCmd.accesskey;" - key="key_reload" - command="Browser:ReloadOrDuplicate" - onclick="checkForMiddleClick(this, event);"/> - <menuseparator class="show-only-for-keyboard"/> - <menu id="viewFullZoomMenu" label="&fullZoom.label;" - accesskey="&fullZoom.accesskey;" - onpopupshowing="FullZoom.updateMenu();"> - <menupopup> - <menuitem id="menu_zoomEnlarge" - key="key_fullZoomEnlarge" - label="&fullZoomEnlargeCmd.label;" - accesskey="&fullZoomEnlargeCmd.accesskey;" - command="cmd_fullZoomEnlarge"/> - <menuitem id="menu_zoomReduce" - key="key_fullZoomReduce" - label="&fullZoomReduceCmd.label;" - accesskey="&fullZoomReduceCmd.accesskey;" - command="cmd_fullZoomReduce"/> - <menuseparator/> - <menuitem id="menu_zoomReset" - key="key_fullZoomReset" - label="&fullZoomResetCmd.label;" - accesskey="&fullZoomResetCmd.accesskey;" - command="cmd_fullZoomReset"/> - <menuseparator/> - <menuitem id="toggle_zoom" - label="&fullZoomToggleCmd.label;" - accesskey="&fullZoomToggleCmd.accesskey;" - type="checkbox" - command="cmd_fullZoomToggle" - checked="false"/> - </menupopup> - </menu> - <menu id="pageStyleMenu" label="&pageStyleMenu.label;" - accesskey="&pageStyleMenu.accesskey;" observes="isImage"> - <menupopup onpopupshowing="gPageStyleMenu.fillPopup(this);"> - <menuitem id="menu_pageStyleNoStyle" - label="&pageStyleNoStyle.label;" - accesskey="&pageStyleNoStyle.accesskey;" - oncommand="gPageStyleMenu.disableStyle();" - type="radio"/> - <menuitem id="menu_pageStylePersistentOnly" - label="&pageStylePersistentOnly.label;" - accesskey="&pageStylePersistentOnly.accesskey;" - oncommand="gPageStyleMenu.switchStyleSheet('');" - type="radio" - checked="true"/> - <menuseparator/> - </menupopup> - </menu> -#include browser-charsetmenu.inc - <menuseparator/> -#ifdef XP_MACOSX - <menuitem id="enterFullScreenItem" - accesskey="&enterFullScreenCmd.accesskey;" - label="&enterFullScreenCmd.label;" - key="key_fullScreen"> - <observes element="View:FullScreen" attribute="oncommand"/> - <observes element="View:FullScreen" attribute="disabled"/> - </menuitem> - <menuitem id="exitFullScreenItem" - accesskey="&exitFullScreenCmd.accesskey;" - label="&exitFullScreenCmd.label;" - key="key_fullScreen" - hidden="true"> - <observes element="View:FullScreen" attribute="oncommand"/> - <observes element="View:FullScreen" attribute="disabled"/> - </menuitem> -#else - <menuitem id="fullScreenItem" - accesskey="&fullScreenCmd.accesskey;" - label="&fullScreenCmd.label;" - key="key_fullScreen" - type="checkbox" - observes="View:FullScreen"/> -#endif - <menuitem id="menu_showAllTabs" - hidden="true" - accesskey="&showAllTabsCmd.accesskey;" - label="&showAllTabsCmd.label;" - command="Browser:ShowAllTabs" - key="key_showAllTabs"/> - <menuseparator hidden="true" id="documentDirection-separator"/> - <menuitem id="documentDirection-swap" - hidden="true" - label="&bidiSwitchPageDirectionItem.label;" - accesskey="&bidiSwitchPageDirectionItem.accesskey;" - oncommand="SwitchDocumentDirection(window.content)"/> - </menupopup> - </menu> - - <menu id="history-menu" - label="&historyMenu.label;" - accesskey="&historyMenu.accesskey;"> - <menupopup id="goPopup" -#ifndef XP_MACOSX - placespopup="true" -#endif - context="placesContext" - oncommand="this.parentNode._placesView._onCommand(event);" - onclick="checkForMiddleClick(this, event);" - onpopupshowing="if (!this.parentNode._placesView) - new HistoryMenu(event);" - tooltip="bhTooltip" - popupsinherittooltip="true"> - <menuitem id="historyMenuBack" - class="show-only-for-keyboard" - label="&backCmd.label;" -#ifdef XP_MACOSX - key="goBackKb2" -#else - key="goBackKb" -#endif - command="Browser:BackOrBackDuplicate" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="historyMenuForward" - class="show-only-for-keyboard" - label="&forwardCmd.label;" -#ifdef XP_MACOSX - key="goForwardKb2" -#else - key="goForwardKb" -#endif - command="Browser:ForwardOrForwardDuplicate" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="historyMenuHome" - class="show-only-for-keyboard" - label="&historyHomeCmd.label;" - oncommand="BrowserGoHome(event);" - onclick="checkForMiddleClick(this, event);" - key="goHome"/> - <menuseparator id="historyMenuHomeSeparator" - class="show-only-for-keyboard"/> - <menuitem id="menu_showAllHistory" - label="&showAllHistoryCmd2.label;" -#ifndef XP_MACOSX - class="menuitem-iconic" - key="showAllHistoryKb" -#endif - command="Browser:ShowAllHistory"/> - <menuitem id="sanitizeItem" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&clearRecentHistory.label;" - key="key_sanitize" - command="Tools:Sanitize"/> - <menuseparator id="sanitizeSeparator"/> -#ifdef MOZ_SERVICES_SYNC - <menuitem id="sync-tabs-menuitem" - class="syncTabsMenuItem" - label="&syncTabsMenu2.label;" - oncommand="BrowserOpenSyncTabs();" - disabled="true"/> -#endif - <menuitem id="historyRestoreLastSession" - label="&historyRestoreLastSession.label;" - command="Browser:RestoreLastSession"/> - <menu id="historyUndoMenu" - class="recentlyClosedTabsMenu" - label="&historyUndoMenu.label;" - disabled="true"> - <menupopup id="historyUndoPopup" -#ifndef XP_MACOSX - placespopup="true" -#endif - onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoSubmenu();"/> - </menu> - <menu id="historyUndoWindowMenu" - class="recentlyClosedWindowsMenu" - label="&historyUndoWindowMenu.label;" - disabled="true"> - <menupopup id="historyUndoWindowPopup" -#ifndef XP_MACOSX - placespopup="true" -#endif - onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoWindowSubmenu();"/> - </menu> - <menuseparator id="startHistorySeparator" - class="hide-if-empty-places-result"/> - </menupopup> - </menu> - - <menu id="bookmarksMenu" - label="&bookmarksMenu.label;" - accesskey="&bookmarksMenu.accesskey;" - ondragenter="PlacesMenuDNDHandler.onDragEnter(event);" - ondragover="PlacesMenuDNDHandler.onDragOver(event);" - ondrop="PlacesMenuDNDHandler.onDrop(event);"> - <menupopup id="bookmarksMenuPopup" -#ifndef XP_MACOSX - placespopup="true" -#endif - context="placesContext" - openInTabs="children" - oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);" - onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);" - onpopupshowing="PlacesCommandHook.updateBookmarkAllTabsCommand(); - if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');" - tooltip="bhTooltip" popupsinherittooltip="true"> - <menuitem id="bookmarksShowAll" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&organizeBookmarks.label;" - command="Browser:ShowAllBookmarks" - key="manBookmarkKb"/> - <menuseparator id="organizeBookmarksSeparator"/> - <menuitem id="menu_bookmarkThisPage" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&bookmarkThisPageCmd.label;" - command="Browser:AddBookmarkAs" - key="addBookmarkAsKb"/> - <menuitem id="subscribeToPageMenuitem" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&subscribeToPageMenuitem.label;" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);" - observes="singleFeedMenuitemState"/> - <menu id="subscribeToPageMenupopup" -#ifndef XP_MACOSX - class="menu-iconic" -#endif - label="&subscribeToPageMenupopup.label;" - observes="multipleFeedsMenuState"> - <menupopup id="subscribeToPageSubmenuMenupopup" - onpopupshowing="return FeedHandler.buildFeedList(event.target);" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);"/> - </menu> - <menuitem id="menu_bookmarkAllTabs" - label="&addCurPagesCmd.label;" - class="show-only-for-keyboard" - command="Browser:BookmarkAllTabs" - key="bookmarkAllTabsKb"/> - <menuseparator id="bookmarksToolbarSeparator"/> - <menu id="bookmarksToolbarFolderMenu" - class="menu-iconic bookmark-item" - label="&personalbarCmd.label;" - container="true"> - <menupopup id="bookmarksToolbarFolderPopup" -#ifndef XP_MACOSX - placespopup="true" -#endif - context="placesContext" - onpopupshowing="if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=TOOLBAR');"/> - </menu> - <menuseparator id="bookmarksMenuItemsSeparator"/> - <!-- Bookmarks menu items --> - <menuseparator builder="end" - class="hide-if-empty-places-result"/> - <menuitem id="menu_unsortedBookmarks" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&unsortedBookmarksCmd.label;" - oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"/> - </menupopup> - </menu> - - <menu id="tools-menu" - label="&toolsMenu.label;" - accesskey="&toolsMenu.accesskey;"> - <menupopup id="menu_ToolsPopup" -#ifdef MOZ_SERVICES_SYNC - onpopupshowing="gSyncUI.updateUI();" -#endif - > - <menuitem id="menu_search" - class="show-only-for-keyboard" - label="&search.label;" - accesskey="&search.accesskey;" - key="key_search" - command="Tools:Search"/> - <menuseparator id="browserToolsSeparator" - class="show-only-for-keyboard"/> - <menuitem id="menu_openDownloads" - label="&downloads.label;" - accesskey="&downloads.accesskey;" - key="key_openDownloads" - command="Tools:Downloads"/> - <menuitem id="menu_openAddons" - label="&addons.label;" - accesskey="&addons.accesskey;" - key="key_openAddons" - command="Tools:Addons"/> - <menuitem id="menu_openPermissions" - label="&permissions.label;" - command="Tools:Permissions" - accesskey="&permissions.accesskey;"/> -#ifdef MOZ_SERVICES_SYNC - <!-- only one of sync-setup or sync-menu will be showing at once --> - <menuitem id="sync-setup" - label="&syncSetup.label;" - accesskey="&syncSetup.accesskey;" - observes="sync-setup-state" - oncommand="gSyncUI.openSetup()"/> - <menuitem id="sync-syncnowitem" - label="&syncSyncNowItem.label;" - accesskey="&syncSyncNowItem.accesskey;" - observes="sync-syncnow-state" - oncommand="gSyncUI.doSync(event);"/> -#endif - <menuseparator id="devToolsSeparator"/> - <menu id="webDeveloperMenu" - label="&webDeveloperMenu.label;" - accesskey="&webDeveloperMenu.accesskey;"> - <menupopup id="menuWebDeveloperPopup"> -#ifdef MOZ_DEVTOOLS - <menuitem id="menu_devToolbox" - observes="devtoolsMenuBroadcaster_DevToolbox" - accesskey="&devToolboxMenuItem.accesskey;"/> - <menuseparator id="menu_devtools_separator"/> - <menuitem id="menu_devToolbar" - observes="devtoolsMenuBroadcaster_DevToolbar" - accesskey="&devToolbarMenu.accesskey;"/> - <menuitem id="menu_chromeDebugger" - observes="devtoolsMenuBroadcaster_ChromeDebugger"/> - <menuitem id="menu_browserConsole" - observes="devtoolsMenuBroadcaster_BrowserConsole" - accesskey="&browserConsoleCmd.accesskey;"/> - <menuitem id="menu_responsiveUI" - observes="devtoolsMenuBroadcaster_ResponsiveUI" - accesskey="&responsiveDesignTool.accesskey;"/> - <menuitem id="menu_eyedropper" - observes="devtoolsMenuBroadcaster_Eyedropper" - accesskey="&eyedropper.accesskey;"/> - <menuitem id="menu_scratchpad" - observes="devtoolsMenuBroadcaster_Scratchpad" - accesskey="&scratchpad.accesskey;"/> -#endif - <menuitem id="menu_pageSource" - observes="devtoolsMenuBroadcaster_PageSource" - accesskey="&pageSourceCmd.accesskey;"/> - <menuitem id="javascriptConsole" - observes="devtoolsMenuBroadcaster_ErrorConsole" - accesskey="&errorConsoleCmd.accesskey;"/> -#ifdef MOZ_DEVTOOLS - <menuitem id="menu_devtools_connect" - observes="devtoolsMenuBroadcaster_connect"/> -#endif - <menuseparator id="devToolsEndSeparator"/> - <menuitem id="getMoreDevtools" - observes="devtoolsMenuBroadcaster_GetMoreTools" - accesskey="&getMoreDevtoolsCmd.accesskey;"/> - </menupopup> - </menu> - <menuitem id="menu_pageInfo" - accesskey="&pageInfoCmd.accesskey;" - label="&pageInfoCmd.label;" -#ifndef XP_WIN - key="key_viewInfo" -#endif - command="View:PageInfo"/> - <menuseparator id="prefSep"/> - <menuitem id="menu_preferences" - label="&preferencesCmd2.label;" - accesskey="&preferencesCmd2.accesskey;" - oncommand="openPreferences();"/> - </menupopup> - </menu> - -#ifdef XP_MACOSX - <menu id="windowMenu" /> -#endif - <menu id="helpMenu" /> - </menubar> diff --git a/browser/base/content/browser-menudragging.js b/browser/base/content/browser-menudragging.js deleted file mode 100644 index cf26b2ba4..000000000 --- a/browser/base/content/browser-menudragging.js +++ /dev/null @@ -1,362 +0,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/. -// -// Based on original code by alice0775 https://github.com/alice0775 - - -"use strict"; -var browserMenuDragging = { - //-- config -- - STAY_OPEN_ONDRAGEXIT: false, - DEBUG: false, - //-- config -- - - menupopup: ['bookmarksMenuPopup', - 'PlacesToolbar', - 'BMB_bookmarksPopup', - 'appmenu_bookmarksPopup', - 'BookmarksMenuToolButtonPopup', - 'UnsortedBookmarksFolderToolButtonPopup', - 'bookmarksMenuPopup-context'], - timer:[], - count:[], - - - init: function(){ - window.removeEventListener('load', this, false); - window.addEventListener('unload', this, false); - this.addPrefListener(this.PrefListener); - - window.addEventListener('aftercustomization', this, false); - - this.initPref(); - this.delayedStartup(); - }, - - uninit: function(){ - window.removeEventListener('unload', this, false); - this.removePrefListener(this.PrefListener); - - window.removeEventListener('aftercustomization', this, false); - - for (var i = 0; i < this.menupopup.length; i++){ - var menupopup = document.getElementById(this.menupopup[i]); - if (menupopup){ - menupopup.removeEventListener('popupshowing', this, false); - menupopup.removeEventListener('popuphiding', this, false); - } - } - - }, - - initPref: function(){ - this.STAY_OPEN_ONDRAGEXIT = - this.getPref('browser.menu.dragging.stayOpen', - 'bool', false); - this.DEBUG = - this.getPref('browser.menu.dragging.debug', - 'bool', false); - }, - - //delayed startup - delayedStartup: function(){ - //wait until construction of bookmarksBarContent is completed. - for (var i = 0; i < this.menupopup.length; i++){ - this.count[i] = 0; - this.timer[i] = setInterval(function(self, i){ - if(++self.count[i] > 50 || document.getElementById(self.menupopup[i])){ - clearInterval(self.timer[i]); - var menupopup = document.getElementById(self.menupopup[i]); - if (menupopup) { - menupopup.addEventListener('popupshowing', self, false); - menupopup.addEventListener('popuphiding', self, false); - } - } - }, 250, this, i); - } - }, - - handleEvent: function(event){ - switch (event.type) { - case 'popupshowing': - this.popupshowing(event); - break; - case 'popuphiding': - this.popuphiding(event); - break; - case 'aftercustomization': - setTimeout(function(self){self.delayedStartup(self);}, 0, this); - break; - case 'load': - this.init(); - break; - case 'unload': - this.uninit(); - break; - } - }, - - popuphiding: function(event) { - var menupopup = event.originalTarget; - menupopup.parentNode.parentNode.openNode = null; - - if (menupopup.parentNode.localName == 'toolbarbutton') { - // Fix for Bug 225434 - dragging bookmark from personal toolbar and releasing - // (on same bookmark or elsewhere) or clicking on bookmark menu then cancelling - // leaves button depressed/sunken when hovered - menupopup.parentNode.parentNode._openedMenuButton = null; - - if (!PlacesControllerDragHelper.getSession()) - // Clear the dragover attribute if present, if we are dragging into a - // folder in the hierachy of current opened popup we don't clear - // this attribute on clearOverFolder. See Notify for closeTimer. - if (menupopup.parentNode.hasAttribute('dragover')) - menupopup.parentNode.removeAttribute('dragover'); - } - }, - - popupshowing: function(event) { - var menupopup = event.originalTarget; - browserMenuDragging.debug("popupshowing ===============\n" + menupopup.parentNode.getAttribute('label')); - - var parentPopup = menupopup.parentNode.parentNode; - - if (!!parentPopup.openNode){ - try { - parentPopup.openNode.hidePopup(); - } catch(e){} - } - parentPopup.openNode = menupopup; - - menupopup.onDragStart = function (event) { - // Bug 555474 - While bookmark is dragged, the tooltip should not appear - browserMenuDragging.hideTooltip(); - } - - menupopup.onDragOver = function (event) { - // Bug 555474 - While bookmark is dragged, the tooltip should not appear - browserMenuDragging.hideTooltip(); - - var target = event.originalTarget; - while (target) { - if (/menupopup/.test(target.localName)) - break; - target = target.parentNode; - } - if (this != target) - return; - event.stopPropagation(); - browserMenuDragging.debug("onDragOver " + "\n" + this.parentNode.getAttribute('label')); - - PlacesControllerDragHelper.currentDropTarget = event.target; - let dt = event.dataTransfer; - - let dropPoint = this._getDropPoint(event); - - if (!dropPoint || !dropPoint.ip || - !PlacesControllerDragHelper.canDrop(dropPoint.ip, dt)) { - this._indicatorBar.hidden = true; - event.stopPropagation(); - return; - } - - // Mark this popup as being dragged over. - this.setAttribute('dragover', 'true'); - - if (dropPoint.folderElt) { - // We are dragging over a folder. - // _overFolder should take the care of opening it on a timer. - if (this._overFolder.elt && - this._overFolder.elt != dropPoint.folderElt) { - } - if (!this._overFolder.elt) { - this._overFolder.elt = dropPoint.folderElt; - // Create the timer to open this folder. - this._overFolder.openTimer = this._overFolder - .setTimer(this._overFolder.hoverTime); - } - } - else { - // We are not dragging over a folder. - } - - // Autoscroll the popup strip if we drag over the scroll buttons. - let anonid = event.originalTarget.getAttribute('anonid'); - let scrollDir = anonid == 'scrollbutton-up' ? -1 : - anonid == 'scrollbutton-down' ? 1 : 0; - if (scrollDir != 0) { - this._scrollBox.scrollByIndex(scrollDir, false); - } - - // Check if we should hide the drop indicator for this target. - if (dropPoint.folderElt || this._hideDropIndicator(event)) { - this._indicatorBar.hidden = true; - event.preventDefault(); - event.stopPropagation(); - return; - } - - // We should display the drop indicator relative to the arrowscrollbox. - let sbo = this._scrollBox.scrollBoxObject; - let newMarginTop = 0; - if (scrollDir == 0) { - let elt = this.firstChild; - while (elt && event.screenY > elt.boxObject.screenY + - elt.boxObject.height / 2) - elt = elt.nextSibling; - newMarginTop = elt ? elt.boxObject.screenY - sbo.screenY : - sbo.height; - } - else if (scrollDir == 1) - newMarginTop = sbo.height; - - // Set the new marginTop based on arrowscrollbox. - newMarginTop += sbo.y - this._scrollBox.boxObject.y; - this._indicatorBar.firstChild.style.marginTop = newMarginTop + 'px'; - this._indicatorBar.hidden = false; - - event.preventDefault(); - event.stopPropagation(); - } - - menupopup.onDragExit = function (event) { - var target = event.originalTarget; - while (target) { - if (/menupopup/.test(target.localName)) - break; - target = target.parentNode; - } - if (this != target) - return; - event.stopPropagation(); - browserMenuDragging.debug("onDragExit " + browserMenuDragging.STAY_OPEN_ONDRAGEXIT); - - PlacesControllerDragHelper.currentDropTarget = null; - this.removeAttribute('dragover'); - - // If we have not moved to a valid new target clear the drop indicator - // this happens when moving out of the popup. - target = event.relatedTarget; - if (!target) - this._indicatorBar.hidden = true; - - // Close any folder being hovered over - if (this._overFolder.elt) { - this._overFolder.closeTimer = this._overFolder - .setTimer(this._overFolder.hoverTime); - } - - // The auto-opened attribute is set when this folder was automatically - // opened after the user dragged over it. If this attribute is set, - // auto-close the folder on drag exit. - // We should also try to close this popup if the drag has started - // from here, the timer will check if we are dragging over a child. - if (this.hasAttribute('autoopened') || - !browserMenuDragging.STAY_OPEN_ONDRAGEXIT && - this.hasAttribute('dragstart')) { - this._overFolder.closeMenuTimer = this._overFolder - .setTimer(this._overFolder.hoverTime); - } - - event.stopPropagation(); - } - - menupopup.addEventListener('dragstart', menupopup.onDragStart, true); - menupopup.addEventListener('dragover', menupopup.onDragOver, true); - menupopup.addEventListener('dragleave', menupopup.onDragExit, true); - }, - - hideTooltip: function() { - ['bhTooltip', 'btTooltip2'].forEach(function(id) { - var tooltip = document.getElementById(id); - if (tooltip) - tooltip.hidePopup(); - }); - }, - - get getVer(){ - const Cc = Components.classes; - const Ci = Components.interfaces; - var info = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); - var ver = parseInt(info.version.substr(0,3) * 10,10) / 10; - return ver; - }, - - debug: function(aMsg){ - if (!browserMenuDragging.DEBUG) - return; - Components.classes["@mozilla.org/consoleservice;1"] - .getService(Components.interfaces.nsIConsoleService) - .logStringMessage(aMsg); - }, - - getPref: function(aPrefString, aPrefType, aDefault){ - var xpPref = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - try{ - switch (aPrefType){ - case 'complex': - return xpPref.getComplexValue(aPrefString, Components.interfaces.nsILocalFile); break; - case 'str': - return xpPref.getCharPref(aPrefString).toString(); break; - case 'int': - return xpPref.getIntPref(aPrefString); break; - case 'bool': - default: - return xpPref.getBoolPref(aPrefString); break; - } - }catch(e){ - } - return aDefault; - }, - - setPref: function(aPrefString, aPrefType, aValue){ - var xpPref = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - try{ - switch (aPrefType){ - case 'complex': - return xpPref.setComplexValue(aPrefString, Components.interfaces.nsILocalFile, aValue); break; - case 'str': - return xpPref.setCharPref(aPrefString, aValue); break; - case 'int': - aValue = parseInt(aValue); - return xpPref.setIntPref(aPrefString, aValue); break; - case 'bool': - default: - return xpPref.setBoolPref(aPrefString, aValue); break; - } - }catch(e){ - } - return null; - }, - - addPrefListener: function(aObserver) { - try { - var pbi = Components.classes["@mozilla.org/preferences;1"]. - getService(Components.interfaces.nsIPrefBranch2); - pbi.addObserver(aObserver.domain, aObserver, false); - } catch(e) {} - }, - - removePrefListener: function(aObserver) { - try { - var pbi = Components.classes["@mozilla.org/preferences;1"]. - getService(Components.interfaces.nsIPrefBranch2); - pbi.removeObserver(aObserver.domain, aObserver); - } catch(e) {} - }, - - PrefListener:{ - domain : 'browser.menu.dragging.stayOpen', - - observe : function(aSubject, aTopic, aPrefstring) { - if (aTopic == 'nsPref:changed') { - browserMenuDragging.initPref(); - } - } - } -} - -window.addEventListener('load', browserMenuDragging, false);
\ No newline at end of file diff --git a/browser/base/content/browser-menudragging.xul b/browser/base/content/browser-menudragging.xul deleted file mode 100644 index f5cabe5f6..000000000 --- a/browser/base/content/browser-menudragging.xul +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0"?> - - -<overlay id="menuDraggingOverlay" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<window id="main-window"> - - <script type="application/x-javascript" src="chrome://browser/content/browser-menudragging.js" /> - -</window> - -</overlay> diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js deleted file mode 100644 index cf9c28597..000000000 --- a/browser/base/content/browser-places.js +++ /dev/null @@ -1,1303 +0,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/. - -//////////////////////////////////////////////////////////////////////////////// -//// StarUI - -var StarUI = { - _itemId: -1, - uri: null, - _batching: false, - - _element: function(aID) { - return document.getElementById(aID); - }, - - // Edit-bookmark panel - get panel() { - delete this.panel; - var element = this._element("editBookmarkPanel"); - // initially the panel is hidden - // to avoid impacting startup / new window performance - element.hidden = false; - element.addEventListener("popuphidden", this, false); - element.addEventListener("keypress", this, false); - return this.panel = element; - }, - - // Array of command elements to disable when the panel is opened. - get _blockedCommands() { - delete this._blockedCommands; - return this._blockedCommands = - ["cmd_close", "cmd_closeWindow"].map(function (id) this._element(id), this); - }, - - _blockCommands: function SU__blockCommands() { - this._blockedCommands.forEach(function (elt) { - // make sure not to permanently disable this item (see bug 409155) - if (elt.hasAttribute("wasDisabled")) - return; - if (elt.getAttribute("disabled") == "true") { - elt.setAttribute("wasDisabled", "true"); - } else { - elt.setAttribute("wasDisabled", "false"); - elt.setAttribute("disabled", "true"); - } - }); - }, - - _restoreCommandsState: function SU__restoreCommandsState() { - this._blockedCommands.forEach(function (elt) { - if (elt.getAttribute("wasDisabled") != "true") - elt.removeAttribute("disabled"); - elt.removeAttribute("wasDisabled"); - }); - }, - - // nsIDOMEventListener - handleEvent: function SU_handleEvent(aEvent) { - switch (aEvent.type) { - case "popuphidden": - if (aEvent.originalTarget == this.panel) { - if (!this._element("editBookmarkPanelContent").hidden) - this.quitEditMode(); - - this._restoreCommandsState(); - this._itemId = -1; - if (this._batching) { - PlacesUtils.transactionManager.endBatch(false); - this._batching = false; - } - - switch (this._actionOnHide) { - case "cancel": { - PlacesUtils.transactionManager.undoTransaction(); - break; - } - case "remove": { - // Remove all bookmarks for the bookmark's url, this also removes - // the tags for the url. - PlacesUtils.transactionManager.beginBatch(null); - let itemIds = PlacesUtils.getBookmarksForURI(this._uriForRemoval); - for (let i = 0; i < itemIds.length; i++) { - let txn = new PlacesRemoveItemTransaction(itemIds[i]); - PlacesUtils.transactionManager.doTransaction(txn); - } - PlacesUtils.transactionManager.endBatch(false); - break; - } - } - this._actionOnHide = ""; - } - break; - case "keypress": - if (aEvent.defaultPrevented) { - // The event has already been consumed inside of the panel. - break; - } - switch (aEvent.keyCode) { - case KeyEvent.DOM_VK_ESCAPE: - if (!this._element("editBookmarkPanelContent").hidden) - this.cancelButtonOnCommand(); - break; - case KeyEvent.DOM_VK_RETURN: - if (aEvent.target.className == "expander-up" || - aEvent.target.className == "expander-down" || - aEvent.target.id == "editBMPanel_newFolderButton") { - //XXX Why is this necessary? The defaultPrevented check should - // be enough. - break; - } - this.panel.hidePopup(); - break; - } - break; - } - }, - - _overlayLoaded: false, - _overlayLoading: false, - showEditBookmarkPopup: - function SU_showEditBookmarkPopup(aItemId, aAnchorElement, aPosition) { - // Performance: load the overlay the first time the panel is opened - // (see bug 392443). - if (this._overlayLoading) - return; - - if (this._overlayLoaded) { - this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition); - return; - } - - this._overlayLoading = true; - document.loadOverlay( - "chrome://browser/content/places/editBookmarkOverlay.xul", - (function (aSubject, aTopic, aData) { - //XXX We just caused localstore.rdf to be re-applied (bug 640158) - retrieveToolbarIconsizesFromTheme(); - - // Move the header (star, title, button) into the grid, - // so that it aligns nicely with the other items (bug 484022). - let header = this._element("editBookmarkPanelHeader"); - let rows = this._element("editBookmarkPanelGrid").lastChild; - rows.insertBefore(header, rows.firstChild); - header.hidden = false; - - this._overlayLoading = false; - this._overlayLoaded = true; - this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition); - }).bind(this) - ); - }, - - _doShowEditBookmarkPanel: - function SU__doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition) { - if (this.panel.state != "closed") - return; - - this._blockCommands(); // un-done in the popuphiding handler - - // Set panel title: - // if we are batching, i.e. the bookmark has been added now, - // then show Page Bookmarked, else if the bookmark did already exist, - // we are about editing it, then use Edit This Bookmark. - this._element("editBookmarkPanelTitle").value = - this._batching ? - gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle") : - gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle"); - - // No description; show the Done, Cancel; - this._element("editBookmarkPanelDescription").textContent = ""; - this._element("editBookmarkPanelBottomButtons").hidden = false; - this._element("editBookmarkPanelContent").hidden = false; - - // The remove button is shown only if we're not already batching, i.e. - // if the cancel button/ESC does not remove the bookmark. - this._element("editBookmarkPanelRemoveButton").hidden = this._batching; - - // The label of the remove button differs if the URI is bookmarked - // multiple times. - var bookmarks = PlacesUtils.getBookmarksForURI(gBrowser.currentURI); - var forms = gNavigatorBundle.getString("editBookmark.removeBookmarks.label"); - var label = PluralForm.get(bookmarks.length, forms).replace("#1", bookmarks.length); - this._element("editBookmarkPanelRemoveButton").label = label; - - // unset the unstarred state, if set - this._element("editBookmarkPanelStarIcon").removeAttribute("unstarred"); - - this._itemId = aItemId !== undefined ? aItemId : this._itemId; - this.beginBatch(); - - this.panel.openPopup(aAnchorElement, aPosition); - - gEditItemOverlay.initPanel(this._itemId, - { hiddenRows: ["description", "location", - "loadInSidebar", "keyword"] }); - }, - - panelShown: - function SU_panelShown(aEvent) { - if (aEvent.target == this.panel) { - if (!this._element("editBookmarkPanelContent").hidden) { - let fieldToFocus = "editBMPanel_" + - gPrefService.getCharPref("browser.bookmarks.editDialog.firstEditField"); - var elt = this._element(fieldToFocus); - elt.focus(); - elt.select(); - } - else { - // Note this isn't actually used anymore, we should remove this - // once we decide not to bring back the page bookmarked notification - this.panel.focus(); - } - } - }, - - quitEditMode: function SU_quitEditMode() { - this._element("editBookmarkPanelContent").hidden = true; - this._element("editBookmarkPanelBottomButtons").hidden = true; - gEditItemOverlay.uninitPanel(true); - }, - - cancelButtonOnCommand: function SU_cancelButtonOnCommand() { - this._actionOnHide = "cancel"; - this.panel.hidePopup(); - }, - - removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() { - this._uriForRemoval = PlacesUtils.bookmarks.getBookmarkURI(this._itemId); - this._actionOnHide = "remove"; - this.panel.hidePopup(); - }, - - beginBatch: function SU_beginBatch() { - if (!this._batching) { - PlacesUtils.transactionManager.beginBatch(null); - this._batching = true; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -//// PlacesCommandHook - -var PlacesCommandHook = { - /** - * Adds a bookmark to the page loaded in the given browser. - * - * @param aBrowser - * a <browser> element. - * @param [optional] aParent - * The folder in which to create a new bookmark if the page loaded in - * aBrowser isn't bookmarked yet, defaults to the unfiled root. - * @param [optional] aShowEditUI - * whether or not to show the edit-bookmark UI for the bookmark item - */ - bookmarkPage: function PCH_bookmarkPage(aBrowser, aParent, aShowEditUI) { - var uri = aBrowser.currentURI; - var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri); - if (itemId == -1) { - // Copied over from addBookmarkForBrowser: - // Bug 52536: We obtain the URL and title from the nsIWebNavigation - // associated with a <browser/> rather than from a DOMWindow. - // This is because when a full page plugin is loaded, there is - // no DOMWindow (?) but information about the loaded document - // may still be obtained from the webNavigation. - var webNav = aBrowser.webNavigation; - var url = webNav.currentURI; - var title; - var description; - var charset; - try { - let isErrorPage = /^about:(neterror|certerror|blocked)/ - .test(webNav.document.documentURI); - title = isErrorPage ? PlacesUtils.history.getPageTitle(url) - : webNav.document.title; - title = title || url.spec; - description = PlacesUIUtils.getDescriptionFromDocument(webNav.document); - charset = webNav.document.characterSet; - } - catch (e) { } - - if (aShowEditUI) { - // If we bookmark the page here (i.e. page was not "starred" already) - // but open right into the "edit" state, start batching here, so - // "Cancel" in that state removes the bookmark. - StarUI.beginBatch(); - } - - var parent = aParent != undefined ? - aParent : PlacesUtils.unfiledBookmarksFolderId; - var descAnno = { name: PlacesUIUtils.DESCRIPTION_ANNO, value: description }; - var txn = new PlacesCreateBookmarkTransaction(uri, parent, - PlacesUtils.bookmarks.DEFAULT_INDEX, - title, null, [descAnno]); - PlacesUtils.transactionManager.doTransaction(txn); - itemId = txn.item.id; - // Set the character-set - if (charset && !PrivateBrowsingUtils.isWindowPrivate(aBrowser.contentWindow)) - PlacesUtils.setCharsetForURI(uri, charset); - } - - // Revert the contents of the location bar - if (gURLBar) - gURLBar.handleRevert(); - - // If it was not requested to open directly in "edit" mode, we are done. - if (!aShowEditUI) - return; - - // Try to dock the panel to: - // 1. the bookmarks menu button - // 2. the page-proxy-favicon - // 3. the content area - if (BookmarkingUI.anchor) { - StarUI.showEditBookmarkPopup(itemId, BookmarkingUI.anchor, - "bottomcenter topright"); - return; - } - - let pageProxyFavicon = document.getElementById("page-proxy-favicon"); - if (isElementVisible(pageProxyFavicon)) { - StarUI.showEditBookmarkPopup(itemId, pageProxyFavicon, - "bottomcenter topright"); - } else { - StarUI.showEditBookmarkPopup(itemId, aBrowser, "overlap"); - } - }, - - /** - * Adds a bookmark to the page loaded in the current tab. - */ - bookmarkCurrentPage: function PCH_bookmarkCurrentPage(aShowEditUI, aParent) { - this.bookmarkPage(gBrowser.selectedBrowser, aParent, aShowEditUI); - }, - - /** - * Adds a bookmark to the page targeted by a link. - * @param aParent - * The folder in which to create a new bookmark if aURL isn't - * bookmarked. - * @param aURL (string) - * the address of the link target - * @param aTitle - * The link text - */ - bookmarkLink: function PCH_bookmarkLink(aParent, aURL, aTitle) { - var linkURI = makeURI(aURL); - var itemId = PlacesUtils.getMostRecentBookmarkForURI(linkURI); - if (itemId == -1) { - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "bookmark" - , uri: linkURI - , title: aTitle - , hiddenRows: [ "description" - , "location" - , "loadInSidebar" - , "keyword" ] - }, window); - } - else { - PlacesUIUtils.showBookmarkDialog({ action: "edit" - , type: "bookmark" - , itemId: itemId - }, window); - } - }, - - /** - * List of nsIURI objects characterizing the tabs currently open in the - * browser, modulo pinned tabs. The URIs will be in the order in which their - * corresponding tabs appeared and duplicates are discarded. - */ - get uniqueCurrentPages() { - let uniquePages = {}; - let URIs = []; - gBrowser.visibleTabs.forEach(function (tab) { - let spec = tab.linkedBrowser.currentURI.spec; - if (!tab.pinned && !(spec in uniquePages)) { - uniquePages[spec] = null; - URIs.push(tab.linkedBrowser.currentURI); - } - }); - return URIs; - }, - - /** - * Adds a folder with bookmarks to all of the currently open tabs in this - * window. - */ - bookmarkCurrentPages: function PCH_bookmarkCurrentPages() { - let pages = this.uniqueCurrentPages; - if (pages.length > 1) { - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "folder" - , URIList: pages - , hiddenRows: [ "description" ] - }, window); - } - }, - - /** - * Updates disabled state for the "Bookmark All Tabs" command. - */ - updateBookmarkAllTabsCommand: - function PCH_updateBookmarkAllTabsCommand() { - // There's nothing to do in non-browser windows. - if (window.location.href != getBrowserURL()) - return; - - // Disable "Bookmark All Tabs" if there are less than two - // "unique current pages". - goSetCommandEnabled("Browser:BookmarkAllTabs", - this.uniqueCurrentPages.length >= 2); - }, - - /** - * Adds a Live Bookmark to a feed associated with the current page. - * @param url - * The nsIURI of the page the feed was attached to - * @title title - * The title of the feed. Optional. - * @subtitle subtitle - * A short description of the feed. Optional. - */ - addLiveBookmark: function PCH_addLiveBookmark(url, feedTitle, feedSubtitle) { - let toolbarIP = new InsertionPoint(PlacesUtils.toolbarFolderId, -1); - - let feedURI = makeURI(url); - let title = feedTitle || gBrowser.contentTitle; - let description = feedSubtitle; - if (!description) { - description = PlacesUIUtils.getDescriptionFromDocument(gBrowser.contentDocument); - } - - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "livemark" - , feedURI: feedURI - , siteURI: gBrowser.currentURI - , title: title - , description: description - , defaultInsertionPoint: toolbarIP - , hiddenRows: [ "feedLocation" - , "siteLocation" - , "description" ] - }, window); - }, - - /** - * Opens the Places Organizer. - * @param aLeftPaneRoot - * The query to select in the organizer window - options - * are: History, AllBookmarks, BookmarksMenu, BookmarksToolbar, - * UnfiledBookmarks, Tags and Downloads. - */ - showPlacesOrganizer: function PCH_showPlacesOrganizer(aLeftPaneRoot) { - var organizer = Services.wm.getMostRecentWindow("Places:Organizer"); - // Due to bug 528706, getMostRecentWindow can return closed windows. - if (!organizer || organizer.closed) { - // No currently open places window, so open one with the specified mode. - openDialog("chrome://browser/content/places/places.xul", - "", "chrome,toolbar=yes,dialog=no,resizable", aLeftPaneRoot); - } - else { - organizer.PlacesOrganizer.selectLeftPaneQuery(aLeftPaneRoot); - organizer.focus(); - } - } -}; - -//////////////////////////////////////////////////////////////////////////////// -//// HistoryMenu - -// View for the history menu. -function HistoryMenu(aPopupShowingEvent) { - // Workaround for Bug 610187. The sidebar does not include all the Places - // views definitions, and we don't need them there. - // Defining the prototype inheritance in the prototype itself would cause - // browser.js to halt on "PlacesMenu is not defined" error. - this.__proto__.__proto__ = PlacesMenu.prototype; - XPCOMUtils.defineLazyServiceGetter(this, "_ss", - "@mozilla.org/browser/sessionstore;1", - "nsISessionStore"); - PlacesMenu.call(this, aPopupShowingEvent, - "place:sort=4&maxResults=15"); -} - -HistoryMenu.prototype = { - toggleRestoreLastSession: function HM_toggleRestoreLastSession() { - let restoreItem = this._rootElt.ownerDocument.getElementById("Browser:RestoreLastSession"); - - if (this._ss.canRestoreLastSession && - !PrivateBrowsingUtils.isWindowPrivate(window)) - restoreItem.removeAttribute("disabled"); - else - restoreItem.setAttribute("disabled", true); - }, - - toggleRecentlyClosedTabs: function HM_toggleRecentlyClosedTabs() { - // enable/disable the Recently Closed Tabs sub menu - var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedTabsMenu")[0]; - - // no restorable tabs, so disable menu - if (this._ss.getClosedTabCount(window) == 0) - undoMenu.setAttribute("disabled", true); - else - undoMenu.removeAttribute("disabled"); - }, - - /** - * Re-open a closed tab and put it to the end of the tab strip. - * Used for a middle click. - * @param aEvent - * The event when the user clicks the menu item - */ - _undoCloseMiddleClick: function PHM__undoCloseMiddleClick(aEvent) { - if (aEvent.button != 1) - return; - - undoCloseTab(aEvent.originalTarget.value); - gBrowser.moveTabToEnd(); - }, - - /** - * Populate when the history menu is opened - */ - populateUndoSubmenu: function PHM_populateUndoSubmenu() { - var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedTabsMenu")[0]; - var undoPopup = undoMenu.firstChild; - - // remove existing menu items - while (undoPopup.hasChildNodes()) - undoPopup.removeChild(undoPopup.firstChild); - - // no restorable tabs, so make sure menu is disabled, and return - if (this._ss.getClosedTabCount(window) == 0) { - undoMenu.setAttribute("disabled", true); - return; - } - - // enable menu - undoMenu.removeAttribute("disabled"); - - // populate menu - var undoItems = JSON.parse(this._ss.getClosedTabData(window)); - for (var i = 0; i < undoItems.length; i++) { - var m = document.createElement("menuitem"); - m.setAttribute("label", undoItems[i].title); - if (undoItems[i].image) { - let iconURL = undoItems[i].image; - // don't initiate a connection just to fetch a favicon (see bug 467828) - if (/^https?:/.test(iconURL)) - iconURL = "moz-anno:favicon:" + iconURL; - m.setAttribute("image", iconURL); - } - m.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon"); - m.setAttribute("value", i); - m.setAttribute("oncommand", "undoCloseTab(" + i + ");"); - - // Set the targetURI attribute so it will be shown in tooltip and trigger - // onLinkHovered. SessionStore uses one-based indexes, so we need to - // normalize them. - let tabData = undoItems[i].state; - let activeIndex = (tabData.index || tabData.entries.length) - 1; - if (activeIndex >= 0 && tabData.entries[activeIndex]) - m.setAttribute("targetURI", tabData.entries[activeIndex].url); - - m.addEventListener("click", this._undoCloseMiddleClick, false); - if (i == 0) - m.setAttribute("key", "key_undoCloseTab"); - undoPopup.appendChild(m); - } - - // "Restore All Tabs" - var strings = gNavigatorBundle; - undoPopup.appendChild(document.createElement("menuseparator")); - m = undoPopup.appendChild(document.createElement("menuitem")); - m.id = "menu_restoreAllTabs"; - m.setAttribute("label", strings.getString("menuRestoreAllTabs.label")); - m.addEventListener("command", function() { - for (var i = 0; i < undoItems.length; i++) - undoCloseTab(); - }, false); - }, - - toggleRecentlyClosedWindows: function PHM_toggleRecentlyClosedWindows() { - // enable/disable the Recently Closed Windows sub menu - var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedWindowsMenu")[0]; - - // no restorable windows, so disable menu - if (this._ss.getClosedWindowCount() == 0) - undoMenu.setAttribute("disabled", true); - else - undoMenu.removeAttribute("disabled"); - }, - - /** - * Populate when the history menu is opened - */ - populateUndoWindowSubmenu: function PHM_populateUndoWindowSubmenu() { - let undoMenu = this._rootElt.getElementsByClassName("recentlyClosedWindowsMenu")[0]; - let undoPopup = undoMenu.firstChild; - let menuLabelString = gNavigatorBundle.getString("menuUndoCloseWindowLabel"); - let menuLabelStringSingleTab = - gNavigatorBundle.getString("menuUndoCloseWindowSingleTabLabel"); - - // remove existing menu items - while (undoPopup.hasChildNodes()) - undoPopup.removeChild(undoPopup.firstChild); - - // no restorable windows, so make sure menu is disabled, and return - if (this._ss.getClosedWindowCount() == 0) { - undoMenu.setAttribute("disabled", true); - return; - } - - // enable menu - undoMenu.removeAttribute("disabled"); - - // populate menu - let undoItems = JSON.parse(this._ss.getClosedWindowData()); - for (let i = 0; i < undoItems.length; i++) { - let undoItem = undoItems[i]; - let otherTabsCount = undoItem.tabs.length - 1; - let label = (otherTabsCount == 0) ? menuLabelStringSingleTab - : PluralForm.get(otherTabsCount, menuLabelString); - let menuLabel = label.replace("#1", undoItem.title) - .replace("#2", otherTabsCount); - let m = document.createElement("menuitem"); - m.setAttribute("label", menuLabel); - let selectedTab = undoItem.tabs[undoItem.selected - 1]; - if (selectedTab.image) { - let iconURL = selectedTab.image; - // don't initiate a connection just to fetch a favicon (see bug 467828) - if (/^https?:/.test(iconURL)) - iconURL = "moz-anno:favicon:" + iconURL; - m.setAttribute("image", iconURL); - } - m.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon"); - m.setAttribute("oncommand", "undoCloseWindow(" + i + ");"); - - // Set the targetURI attribute so it will be shown in tooltip. - // SessionStore uses one-based indexes, so we need to normalize them. - let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1; - if (activeIndex >= 0 && selectedTab.entries[activeIndex]) - m.setAttribute("targetURI", selectedTab.entries[activeIndex].url); - - if (i == 0) - m.setAttribute("key", "key_undoCloseWindow"); - undoPopup.appendChild(m); - } - - // "Open All in Windows" - undoPopup.appendChild(document.createElement("menuseparator")); - let m = undoPopup.appendChild(document.createElement("menuitem")); - m.id = "menu_restoreAllWindows"; - m.setAttribute("label", gNavigatorBundle.getString("menuRestoreAllWindows.label")); - m.setAttribute("oncommand", - "for (var i = 0; i < " + undoItems.length + "; i++) undoCloseWindow();"); - }, - - toggleTabsFromOtherComputers: function PHM_toggleTabsFromOtherComputers() { - // This is a no-op if MOZ_SERVICES_SYNC isn't defined -#ifdef MOZ_SERVICES_SYNC - // Enable/disable the Tabs From Other Computers menu. Some of the menus handled - // by HistoryMenu do not have this menuitem. - let menuitem = this._rootElt.getElementsByClassName("syncTabsMenuItem")[0]; - if (!menuitem) - return; - - // If Sync isn't configured yet, then don't show the menuitem. - if (Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED || - Weave.Svc.Prefs.get("firstSync", "") == "notReady") { - menuitem.setAttribute("hidden", true); - return; - } - - // The tabs engine might never be inited (if services.sync.registerEngines - // is modified), so make sure we avoid undefined errors. - let enabled = Weave.Service.isLoggedIn && - Weave.Service.engineManager.get("tabs") && - Weave.Service.engineManager.get("tabs").enabled; - menuitem.setAttribute("disabled", !enabled); - menuitem.setAttribute("hidden", false); -#endif - }, - - _onPopupShowing: function HM__onPopupShowing(aEvent) { - PlacesMenu.prototype._onPopupShowing.apply(this, arguments); - - // Don't handle events for submenus. - if (aEvent.target != aEvent.currentTarget) - return; - - this.toggleRestoreLastSession(); - this.toggleRecentlyClosedTabs(); - this.toggleRecentlyClosedWindows(); - this.toggleTabsFromOtherComputers(); - }, - - _onCommand: function HM__onCommand(aEvent) { - let placesNode = aEvent.target._placesNode; - if (placesNode) { - if (!PrivateBrowsingUtils.isWindowPrivate(window)) - PlacesUIUtils.markPageAsTyped(placesNode.uri); - openUILink(placesNode.uri, aEvent, { ignoreAlt: true }); - } - } -}; - -//////////////////////////////////////////////////////////////////////////////// -//// BookmarksEventHandler - -/** - * Functions for handling events in the Bookmarks Toolbar and menu. - */ -var BookmarksEventHandler = { - /** - * Handler for click event for an item in the bookmarks toolbar or menu. - * Menus and submenus from the folder buttons bubble up to this handler. - * Left-click is handled in the onCommand function. - * When items are middle-clicked (or clicked with modifier), open in tabs. - * If the click came through a menu, close the menu. - * @param aEvent - * DOMEvent for the click - * @param aView - * The places view which aEvent should be associated with. - */ - onClick: function BEH_onClick(aEvent, aView) { - // Only handle middle-click or left-click with modifiers. -#ifdef XP_MACOSX - var modifKey = aEvent.metaKey || aEvent.shiftKey; -#else - var modifKey = aEvent.ctrlKey || aEvent.shiftKey; -#endif - if (aEvent.button == 2 || (aEvent.button == 0 && !modifKey)) - return; - - var target = aEvent.originalTarget; - // If this event bubbled up from a menu or menuitem, close the menus. - // Do this before opening tabs, to avoid hiding the open tabs confirm-dialog. - if (target.localName == "menu" || target.localName == "menuitem") { - for (node = target.parentNode; node; node = node.parentNode) { - if (node.localName == "menupopup") - node.hidePopup(); - else if (node.localName != "menu" && - node.localName != "splitmenu" && - node.localName != "hbox" && - node.localName != "vbox" ) - break; - } - } - - if (target._placesNode && PlacesUtils.nodeIsContainer(target._placesNode)) { - // Don't open the root folder in tabs when the empty area on the toolbar - // is middle-clicked or when a non-bookmark item except for Open in Tabs) - // in a bookmarks menupopup is middle-clicked. - if (target.localName == "menu" || target.localName == "toolbarbutton") - PlacesUIUtils.openContainerNodeInTabs(target._placesNode, aEvent, aView); - } - else if (aEvent.button == 1) { - // left-clicks with modifier are already served by onCommand - this.onCommand(aEvent, aView); - } - }, - - /** - * Handler for command event for an item in the bookmarks toolbar. - * Menus and submenus from the folder buttons bubble up to this handler. - * Opens the item. - * @param aEvent - * DOMEvent for the command - * @param aView - * The places view which aEvent should be associated with. - */ - onCommand: function BEH_onCommand(aEvent, aView) { - var target = aEvent.originalTarget; - if (target._placesNode) - PlacesUIUtils.openNodeWithEvent(target._placesNode, aEvent, aView); - }, - - fillInBHTooltip: function BEH_fillInBHTooltip(aDocument, aEvent) { - var node; - var cropped = false; - var targetURI; - - if (aDocument.tooltipNode.localName == "treechildren") { - var tree = aDocument.tooltipNode.parentNode; - var tbo = tree.treeBoxObject; - var cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY); - if (cell.row == -1) - return false; - node = tree.view.nodeForTreeIndex(cell.row); - cropped = tbo.isCellCropped(cell.row, cell.col); - } - else { - // Check whether the tooltipNode is a Places node. - // In such a case use it, otherwise check for targetURI attribute. - var tooltipNode = aDocument.tooltipNode; - if (tooltipNode._placesNode) - node = tooltipNode._placesNode; - else { - // This is a static non-Places node. - targetURI = tooltipNode.getAttribute("targetURI"); - } - } - - if (!node && !targetURI) - return false; - - // Show node.label as tooltip's title for non-Places nodes. - var title = node ? node.title : tooltipNode.label; - - // Show URL only for Places URI-nodes or nodes with a targetURI attribute. - var url; - if (targetURI || PlacesUtils.nodeIsURI(node)) - url = targetURI || node.uri; - - // Show tooltip for containers only if their title is cropped. - if (!cropped && !url) - return false; - - var tooltipTitle = aDocument.getElementById("bhtTitleText"); - tooltipTitle.hidden = (!title || (title == url)); - if (!tooltipTitle.hidden) - tooltipTitle.textContent = title; - - var tooltipUrl = aDocument.getElementById("bhtUrlText"); - tooltipUrl.hidden = !url; - if (!tooltipUrl.hidden) - tooltipUrl.value = url; - - // Show tooltip. - return true; - } -}; - -//////////////////////////////////////////////////////////////////////////////// -//// PlacesMenuDNDHandler - -// Handles special drag and drop functionality for Places menus that are not -// part of a Places view (e.g. the bookmarks menu in the menubar). -var PlacesMenuDNDHandler = { - _springLoadDelay: 350, // milliseconds - _loadTimer: null, - _closerTimer: null, - - /** - * Called when the user enters the <menu> element during a drag. - * @param event - * The DragEnter event that spawned the opening. - */ - onDragEnter: function PMDH_onDragEnter(event) { - // Opening menus in a Places popup is handled by the view itself. - if (!this._isStaticContainer(event.target)) - return; - - let popup = event.target.lastChild; - if (this._loadTimer || popup.state === "showing" || popup.state === "open") - return; - - this._loadTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this._loadTimer.initWithCallback(() => { - this._loadTimer = null; - popup.setAttribute("autoopened", "true"); - popup.showPopup(popup); - }, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT); - event.preventDefault(); - event.stopPropagation(); - }, - - /** - * Handles dragleave on the <menu> element. - * @returns true if the element is a container element (menu or - * menu-toolbarbutton), false otherwise. - */ - onDragLeave: function PMDH_onDragLeave(event) { - // Handle menu-button separate targets. - if (event.relatedTarget === event.currentTarget || - event.relatedTarget.parentNode === event.currentTarget) - return; - - // Closing menus in a Places popup is handled by the view itself. - if (!this._isStaticContainer(event.target)) - return; - - let popup = event.target.lastChild; - - if (this._loadTimer) { - this._loadTimer.cancel(); - this._loadTimer = null; - } - this._closeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this._closeTimer.initWithCallback(function() { - this._closeTimer = null; - let node = PlacesControllerDragHelper.currentDropTarget; - let inHierarchy = false; - while (node && !inHierarchy) { - inHierarchy = node == event.target; - node = node.parentNode; - } - if (!inHierarchy && popup && popup.hasAttribute("autoopened")) { - popup.removeAttribute("autoopened"); - popup.hidePopup(); - } - }, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT); - }, - - /** - * Determines if a XUL element represents a static container. - * @returns true if the element is a container element (menu or - *` menu-toolbarbutton), false otherwise. - */ - _isStaticContainer: function PMDH__isContainer(node) { - let isMenu = node.localName == "menu" || - (node.localName == "toolbarbutton" && - (node.getAttribute("type") == "menu" || - node.getAttribute("type") == "menu-button")); - let isStatic = !("_placesNode" in node) && node.lastChild && - node.lastChild.hasAttribute("placespopup") && - !node.parentNode.hasAttribute("placespopup"); - return isMenu && isStatic; - }, - - /** - * Called when the user drags over the <menu> element. - * @param event - * The DragOver event. - */ - onDragOver: function PMDH_onDragOver(event) { - let ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, - PlacesUtils.bookmarks.DEFAULT_INDEX, - Ci.nsITreeView.DROP_ON); - if (ip && PlacesControllerDragHelper.canDrop(ip, event.dataTransfer)) - event.preventDefault(); - - event.stopPropagation(); - }, - - /** - * Called when the user drops on the <menu> element. - * @param event - * The Drop event. - */ - onDrop: function PMDH_onDrop(event) { - // Put the item at the end of bookmark menu. - let ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, - PlacesUtils.bookmarks.DEFAULT_INDEX, - Ci.nsITreeView.DROP_ON); - PlacesControllerDragHelper.onDrop(ip, event.dataTransfer); - event.stopPropagation(); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -//// PlacesToolbarHelper - -/** - * This object handles the initialization and uninitialization of the bookmarks - * toolbar. - */ -let PlacesToolbarHelper = { - _place: "place:folder=TOOLBAR", - - get _viewElt() { - return document.getElementById("PlacesToolbar"); - }, - - init: function PTH_init() { - let viewElt = this._viewElt; - if (!viewElt || viewElt._placesView) - return; - - // If the bookmarks toolbar item is hidden because the parent toolbar is - // collapsed or hidden (i.e. in a popup), spare the initialization. Also, - // there is no need to initialize the toolbar if customizing because - // init() will be called when the customization is done. - let toolbar = viewElt.parentNode.parentNode; - if (toolbar.collapsed || - getComputedStyle(toolbar, "").display == "none" || - this._isCustomizing) - return; - - new PlacesToolbar(this._place); - }, - - customizeStart: function PTH_customizeStart() { - let viewElt = this._viewElt; - if (viewElt && viewElt._placesView) - viewElt._placesView.uninit(); - - this._isCustomizing = true; - }, - - customizeDone: function PTH_customizeDone() { - this._isCustomizing = false; - this.init(); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -//// BookmarkingUI - -/** - * Handles the bookmarks star button in the URL bar, as well as the bookmark - * menu button. - */ - -let BookmarkingUI = { - get button() { - if (!this._button) { - this._button = document.getElementById("bookmarks-menu-button"); - } - return this._button; - }, - - get star() { - if (!this._star) { - this._star = document.getElementById("star-button"); - } - return this._star; - }, - - get anchor() { - if (this.star && isElementVisible(this.star)) { - // Anchor to the icon, so the panel looks more natural. - return this.star; - } - return null; - }, - - STATUS_UPDATING: -1, - STATUS_UNSTARRED: 0, - STATUS_STARRED: 1, - get status() { - if (this._pendingStmt) - return this.STATUS_UPDATING; - return this.star && - this.star.hasAttribute("starred") ? this.STATUS_STARRED - : this.STATUS_UNSTARRED; - }, - - get _starredTooltip() - { - delete this._starredTooltip; - return this._starredTooltip = - gNavigatorBundle.getString("starButtonOn.tooltip"); - }, - - get _unstarredTooltip() - { - delete this._unstarredTooltip; - return this._unstarredTooltip = - gNavigatorBundle.getString("starButtonOff.tooltip"); - }, - - /** - * The popup contents must be updated when the user customizes the UI, or - * changes the personal toolbar collapsed status. In such a case, any needed - * change should be handled in the popupshowing helper, for performance - * reasons. - */ - _popupNeedsUpdate: true, - onToolbarVisibilityChange: function BUI_onToolbarVisibilityChange() { - this._popupNeedsUpdate = true; - }, - - onPopupShowing: function BUI_onPopupShowing(event) { - // Don't handle events for submenus. - if (event.target != event.currentTarget) - return; - - if (!this._popupNeedsUpdate) - return; - this._popupNeedsUpdate = false; - - let popup = event.target; - let getPlacesAnonymousElement = - aAnonId => document.getAnonymousElementByAttribute(popup.parentNode, - "placesanonid", - aAnonId); - - let viewToolbarMenuitem = getPlacesAnonymousElement("view-toolbar"); - if (viewToolbarMenuitem) { - // Update View bookmarks toolbar checkbox menuitem. - let personalToolbar = document.getElementById("PersonalToolbar"); - viewToolbarMenuitem.setAttribute("checked", !personalToolbar.collapsed); - } - - let toolbarMenuitem = getPlacesAnonymousElement("toolbar-autohide"); - if (toolbarMenuitem) { - // If bookmarks items are visible, hide Bookmarks Toolbar menu and the - // separator after it. - toolbarMenuitem.collapsed = toolbarMenuitem.nextSibling.collapsed = - isElementVisible(document.getElementById("personal-bookmarks")); - } - }, - - /** - * Handles star styling based on page proxy state changes. - */ - onPageProxyStateChanged: function BUI_onPageProxyStateChanged(aState) { - if (!this.star) { - return; - } - - if (aState == "invalid") { - this.star.setAttribute("disabled", "true"); - this.star.removeAttribute("starred"); - } - else { - this.star.removeAttribute("disabled"); - } - }, - - _updateToolbarStyle: function BUI__updateToolbarStyle() { - if (!this.button) { - return; - } - - let personalToolbar = document.getElementById("PersonalToolbar"); - let onPersonalToolbar = this.button.parentNode == personalToolbar || - this.button.parentNode.parentNode == personalToolbar; - - if (onPersonalToolbar) { - this.button.classList.add("bookmark-item"); - this.button.classList.remove("toolbarbutton-1"); - } - else { - this.button.classList.remove("bookmark-item"); - this.button.classList.add("toolbarbutton-1"); - } - }, - - _uninitView: function BUI__uninitView() { - // When an element with a placesView attached is removed and re-inserted, - // XBL reapplies the binding causing any kind of issues and possible leaks, - // so kill current view and let popupshowing generate a new one. - if (this.button && this.button._placesView) { - this.button._placesView.uninit(); - } - // Also uninit the main menubar placesView, since it would have the same - // issues. - let menubar = document.getElementById("bookmarksMenu"); - if (menubar && menubar._placesView) { - menubar._placesView.uninit(); - } - }, - - customizeStart: function BUI_customizeStart() { - this._uninitView(); - }, - - customizeChange: function BUI_customizeChange() { - this._updateToolbarStyle(); - }, - - customizeDone: function BUI_customizeDone() { - delete this._button; - this.onToolbarVisibilityChange(); - this._updateToolbarStyle(); - }, - - _hasBookmarksObserver: false, - uninit: function BUI_uninit() { - this._uninitView(); - - if (this._hasBookmarksObserver) { - PlacesUtils.removeLazyBookmarkObserver(this); - } - - if (this._pendingStmt) { - this._pendingStmt.cancel(); - delete this._pendingStmt; - } - }, - - onLocationChange: function BUI_onLocationChange() { - if (this._uri && gBrowser.currentURI.equals(this._uri)) { - return; - } - this.updateStarState(); - }, - - updateStarState: function BUI_updateStarState() { - // Reset tracked values. - this._uri = gBrowser.currentURI; - this._itemIds = []; - - if (this._pendingStmt) { - this._pendingStmt.cancel(); - delete this._pendingStmt; - } - - // We can load about:blank before the actual page, but there is no point in handling that page. - if (isBlankPageURL(this._uri.spec)) { - return; - } - - this._pendingStmt = PlacesUtils.asyncGetBookmarkIds(this._uri, (aItemIds, aURI) => { - // Safety check that the bookmarked URI equals the tracked one. - if (!aURI.equals(this._uri)) { - Components.utils.reportError("BookmarkingUI did not receive current URI"); - return; - } - - // It's possible that onItemAdded gets called before the async statement - // calls back. For such an edge case, retain all unique entries from both - // arrays. - this._itemIds = this._itemIds.filter( - function (id) aItemIds.indexOf(id) == -1 - ).concat(aItemIds); - - this._updateStar(); - - // Start observing bookmarks if needed. - if (!this._hasBookmarksObserver) { - try { - PlacesUtils.addLazyBookmarkObserver(this); - this._hasBookmarksObserver = true; - } catch(ex) { - Components.utils.reportError("BookmarkingUI failed adding a bookmarks observer: " + ex); - } - } - - delete this._pendingStmt; - }, this); - }, - - _updateStar: function BUI__updateStar() { - if (!this.star) { - return; - } - - if (this._itemIds.length > 0) { - this.star.setAttribute("starred", "true"); - this.star.setAttribute("tooltiptext", this._starredTooltip); - } - else { - this.star.removeAttribute("starred"); - this.star.setAttribute("tooltiptext", this._unstarredTooltip); - } - }, - - onCommand: function BUI_onCommand(aEvent) { - if (aEvent.target != aEvent.currentTarget) { - return; - } - // Ignore clicks on the star if we are updating its state. - if (!this._pendingStmt) { - PlacesCommandHook.bookmarkCurrentPage(this._itemIds.length > 0); - } - }, - - // nsINavBookmarkObserver - onItemAdded: function BUI_onItemAdded(aItemId, aParentId, aIndex, aItemType, - aURI) { - if (aURI && aURI.equals(this._uri)) { - // If a new bookmark has been added to the tracked uri, register it. - if (this._itemIds.indexOf(aItemId) == -1) { - this._itemIds.push(aItemId); - this._updateStar(); - } - } - }, - - onItemRemoved: function BUI_onItemRemoved(aItemId) { - let index = this._itemIds.indexOf(aItemId); - // If one of the tracked bookmarks has been removed, unregister it. - if (index != -1) { - this._itemIds.splice(index, 1); - this._updateStar(); - } - }, - - onItemChanged: function BUI_onItemChanged(aItemId, aProperty, - aIsAnnotationProperty, aNewValue) { - if (aProperty == "uri") { - let index = this._itemIds.indexOf(aItemId); - // If the changed bookmark was tracked, check if it is now pointing to - // a different uri and unregister it. - if (index != -1 && aNewValue != this._uri.spec) { - this._itemIds.splice(index, 1); - this._updateStar(); - } - // If another bookmark is now pointing to the tracked uri, register it. - else if (index == -1 && aNewValue == this._uri.spec) { - this._itemIds.push(aItemId); - this._updateStar(); - } - } - }, - - onBeginUpdateBatch: function () {}, - onEndUpdateBatch: function () {}, - onBeforeItemRemoved: function () {}, - onItemVisited: function () {}, - onItemMoved: function () {}, - - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsINavBookmarkObserver - ]) -}; diff --git a/browser/base/content/browser-plugins.js b/browser/base/content/browser-plugins.js deleted file mode 100644 index 769ac6d8a..000000000 --- a/browser/base/content/browser-plugins.js +++ /dev/null @@ -1,797 +0,0 @@ -# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -# 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/. - -const kPrefSessionPersistMinutes = "plugin.sessionPermissionNow.intervalInMinutes"; -const kPrefPersistentDays = "plugin.persistentPermissionAlways.intervalInDays"; - -var gPluginHandler = { - PLUGIN_SCRIPTED_STATE_NONE: 0, - PLUGIN_SCRIPTED_STATE_FIRED: 1, - PLUGIN_SCRIPTED_STATE_DONE: 2, - - getPluginUI: function (plugin, anonid) { - return plugin.ownerDocument. - getAnonymousElementByAttribute(plugin, "anonid", anonid); - }, - - _getPluginInfo: function (pluginElement) { - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - pluginElement.QueryInterface(Ci.nsIObjectLoadingContent); - - let tagMimetype; - let pluginName = gNavigatorBundle.getString("pluginInfo.unknownPlugin"); - let pluginTag = null; - let permissionString = null; - let fallbackType = null; - let blocklistState = null; - - if (pluginElement instanceof HTMLAppletElement) { - tagMimetype = "application/x-java-vm"; - } else { - tagMimetype = pluginElement.actualType; - - if (tagMimetype == "") { - tagMimetype = pluginElement.type; - } - } - - if (gPluginHandler.isKnownPlugin(pluginElement)) { - pluginTag = pluginHost.getPluginTagForType(pluginElement.actualType); - pluginName = gPluginHandler.makeNicePluginName(pluginTag.name); - - permissionString = pluginHost.getPermissionStringForType(pluginElement.actualType); - fallbackType = pluginElement.defaultFallbackType; - blocklistState = pluginHost.getBlocklistStateForType(pluginElement.actualType); - // Make state-softblocked == state-notblocked for our purposes, - // they have the same UI. STATE_OUTDATED should not exist for plugin - // items, but let's alias it anyway, just in case. - if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED || - blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) { - blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - } - } - - return { mimetype: tagMimetype, - pluginName: pluginName, - pluginTag: pluginTag, - permissionString: permissionString, - fallbackType: fallbackType, - blocklistState: blocklistState, - }; - }, - - // Map the plugin's name to a filtered version more suitable for user UI. - makeNicePluginName : function (aName) { - if (aName == "Shockwave Flash") - return "Adobe Flash"; - - // Clean up the plugin name by stripping off any trailing version numbers - // or "plugin". EG, "Foo Bar Plugin 1.23_02" --> "Foo Bar" - // Do this by first stripping the numbers, etc. off the end, and then - // removing "Plugin" (and then trimming to get rid of any whitespace). - // (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled) - let newName = aName.replace(/[\s\d\.\-\_\(\)]+$/, "").replace(/\bplug-?in\b/i, "").trim(); - return newName; - }, - - isTooSmall : function (plugin, overlay) { - // Is the <object>'s size too small to hold what we want to show? - let pluginRect = plugin.getBoundingClientRect(); - // XXX bug 446693. The text-shadow on the submitted-report text at - // the bottom causes scrollHeight to be larger than it should be. - // Clamp width/height to properly show CTP overlay on different - // zoom levels when embedded in iframes (rounding bug). (Bug 972237) - let overflows = (overlay.scrollWidth > Math.ceil(pluginRect.width)) || - (overlay.scrollHeight - 5 > Math.ceil(pluginRect.height)); - return overflows; - }, - - addLinkClickCallback: function (linkNode, callbackName /*callbackArgs...*/) { - // XXX just doing (callback)(arg) was giving a same-origin error. bug? - let self = this; - let callbackArgs = Array.prototype.slice.call(arguments).slice(2); - linkNode.addEventListener("click", - function(evt) { - if (!evt.isTrusted) - return; - evt.preventDefault(); - if (callbackArgs.length == 0) - callbackArgs = [ evt ]; - (self[callbackName]).apply(self, callbackArgs); - }, - true); - - linkNode.addEventListener("keydown", - function(evt) { - if (!evt.isTrusted) - return; - if (evt.keyCode == evt.DOM_VK_RETURN) { - evt.preventDefault(); - if (callbackArgs.length == 0) - callbackArgs = [ evt ]; - evt.preventDefault(); - (self[callbackName]).apply(self, callbackArgs); - } - }, - true); - }, - - // Helper to get the binding handler type from a plugin object - _getBindingType : function(plugin) { - if (!(plugin instanceof Ci.nsIObjectLoadingContent)) - return null; - - switch (plugin.pluginFallbackType) { - case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED: - return "PluginNotFound"; - case Ci.nsIObjectLoadingContent.PLUGIN_DISABLED: - return "PluginDisabled"; - case Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED: - return "PluginBlocklisted"; - case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED: - return "PluginOutdated"; - case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY: - return "PluginClickToPlay"; - case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE: - return "PluginVulnerableUpdatable"; - case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE: - return "PluginVulnerableNoUpdate"; - case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW: - return "PluginPlayPreview"; - default: - // Not all states map to a handler - return null; - } - }, - - handleEvent : function(event) { - let plugin; - let doc; - - let eventType = event.type; - if (eventType === "PluginRemoved") { - doc = event.target; - } - else { - plugin = event.target; - doc = plugin.ownerDocument; - - if (!(plugin instanceof Ci.nsIObjectLoadingContent)) - return; - } - - if (eventType == "PluginBindingAttached") { - // The plugin binding fires this event when it is created. - // As an untrusted event, ensure that this object actually has a binding - // and make sure we don't handle it twice - let overlay = this.getPluginUI(plugin, "main"); - if (!overlay || overlay._bindingHandled) { - return; - } - overlay._bindingHandled = true; - - // Lookup the handler for this binding - eventType = this._getBindingType(plugin); - if (!eventType) { - // Not all bindings have handlers - return; - } - } - - let shouldShowNotification = false; - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - if (!browser) - return; - - switch (eventType) { - case "PluginCrashed": - this.pluginInstanceCrashed(plugin, event); - break; - - case "PluginNotFound": - /* No action (plugin finder obsolete) */ - break; - - case "PluginBlocklisted": - case "PluginOutdated": - shouldShowNotification = true; - break; - - case "PluginVulnerableUpdatable": - let updateLink = this.getPluginUI(plugin, "checkForUpdatesLink"); - this.addLinkClickCallback(updateLink, "openPluginUpdatePage"); - /* FALLTHRU */ - - case "PluginVulnerableNoUpdate": - case "PluginClickToPlay": - this._handleClickToPlayEvent(plugin); - let overlay = this.getPluginUI(plugin, "main"); - let pluginName = this._getPluginInfo(plugin).pluginName; - let messageString = gNavigatorBundle.getFormattedString("PluginClickToActivate", [pluginName]); - let overlayText = this.getPluginUI(plugin, "clickToPlay"); - overlayText.textContent = messageString; - if (eventType == "PluginVulnerableUpdatable" || - eventType == "PluginVulnerableNoUpdate") { - let vulnerabilityString = gNavigatorBundle.getString(eventType); - let vulnerabilityText = this.getPluginUI(plugin, "vulnerabilityStatus"); - vulnerabilityText.textContent = vulnerabilityString; - } - shouldShowNotification = true; - break; - - case "PluginPlayPreview": - this._handlePlayPreviewEvent(plugin); - break; - - case "PluginDisabled": - let manageLink = this.getPluginUI(plugin, "managePluginsLink"); - this.addLinkClickCallback(manageLink, "managePlugins"); - shouldShowNotification = true; - break; - - case "PluginInstantiated": - //Pale Moon: don't show the indicator when plugins are enabled/allowed - if (gPrefService.getBoolPref("plugins.always_show_indicator")) { - shouldShowNotification = true; - } - break; - case "PluginRemoved": - shouldShowNotification = true; - break; - } - - // Show the in-content UI if it's not too big. The crashed plugin handler already did this. - if (eventType != "PluginCrashed" && eventType != "PluginRemoved") { - let overlay = this.getPluginUI(plugin, "main"); - if (overlay != null) { - if (!this.isTooSmall(plugin, overlay)) { - overlay.style.visibility = "visible"; - } - plugin.addEventListener("overflow", function(event) { - overlay.style.visibility = "hidden"; - }); - plugin.addEventListener("underflow", function(event) { - // this is triggered if only one dimension underflows, - // the other dimension might still overflow - if (!gPluginHandler.isTooSmall(plugin, overlay)) { - overlay.style.visibility = "visible"; - } - }); - } - } - - // Only show the notification after we've done the isTooSmall check, so - // that the notification can decide whether to show the "alert" icon - if (shouldShowNotification) { - this._showClickToPlayNotification(browser); - } - }, - - isKnownPlugin: function PH_isKnownPlugin(objLoadingContent) { - return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) == - Ci.nsIObjectLoadingContent.TYPE_PLUGIN); - }, - - canActivatePlugin: function PH_canActivatePlugin(objLoadingContent) { - // if this isn't a known plugin, we can't activate it - // (this also guards pluginHost.getPermissionStringForType against - // unexpected input) - if (!gPluginHandler.isKnownPlugin(objLoadingContent)) - return false; - - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType); - let principal = objLoadingContent.ownerDocument.defaultView.top.document.nodePrincipal; - let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString); - - let isFallbackTypeValid = - objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY && - objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE; - - if (objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW) { - // checking if play preview is subject to CTP rules - let playPreviewInfo = pluginHost.getPlayPreviewInfo(objLoadingContent.actualType); - isFallbackTypeValid = !playPreviewInfo.ignoreCTP; - } - - return !objLoadingContent.activated && - pluginPermission != Ci.nsIPermissionManager.DENY_ACTION && - isFallbackTypeValid; - }, - - hideClickToPlayOverlay: function(aPlugin) { - let overlay = this.getPluginUI(aPlugin, "main"); - if (overlay) - overlay.style.visibility = "hidden"; - }, - - stopPlayPreview: function PH_stopPlayPreview(aPlugin, aPlayPlugin) { - let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent); - if (objLoadingContent.activated) - return; - - if (aPlayPlugin) - objLoadingContent.playPlugin(); - else - objLoadingContent.cancelPlayPreview(); - }, - - // Callback for user clicking on a disabled plugin - managePlugins: function (aEvent) { - BrowserOpenAddonsMgr("addons://list/plugin"); - }, - - // Callback for user clicking on the link in a click-to-play plugin - // (where the plugin has an update) - openPluginUpdatePage: function (aEvent) { - openURL(Services.urlFormatter.formatURLPref("plugins.update.url")); - }, - - // Callback for user clicking a "reload page" link - reloadPage: function (browser) { - browser.reload(); - }, - - // Callback for user clicking the help icon - openHelpPage: function () { - openHelpLink("plugin-crashed", false); - }, - - // Event listener for click-to-play plugins. - _handleClickToPlayEvent: function PH_handleClickToPlayEvent(aPlugin) { - let doc = aPlugin.ownerDocument; - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent); - // guard against giving pluginHost.getPermissionStringForType a type - // not associated with any known plugin - if (!gPluginHandler.isKnownPlugin(objLoadingContent)) - return; - let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType); - let principal = doc.defaultView.top.document.nodePrincipal; - let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString); - - let overlay = this.getPluginUI(aPlugin, "main"); - - if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION) { - if (overlay) - overlay.style.visibility = "hidden"; - return; - } - - if (overlay) { - overlay.addEventListener("click", gPluginHandler._overlayClickListener, true); - let closeIcon = gPluginHandler.getPluginUI(aPlugin, "closeIcon"); - closeIcon.addEventListener("click", function(aEvent) { - if (aEvent.button == 0 && aEvent.isTrusted) - gPluginHandler.hideClickToPlayOverlay(aPlugin); - }, true); - } - }, - - _overlayClickListener: { - handleEvent: function PH_handleOverlayClick(aEvent) { - let plugin = document.getBindingParent(aEvent.target); - let contentWindow = plugin.ownerDocument.defaultView.top; - // gBrowser.getBrowserForDocument does not exist in the case where we - // drag-and-dropped a tab from a window containing only that tab. In - // that case, the window gets destroyed. - let browser = gBrowser.getBrowserForDocument ? - gBrowser.getBrowserForDocument(contentWindow.document) : - null; - // If browser is null here, we've been drag-and-dropped from another - // window, and this is the wrong click handler. - if (!browser) { - aEvent.target.removeEventListener("click", gPluginHandler._overlayClickListener, true); - return; - } - let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); - // Have to check that the target is not the link to update the plugin - if (!(aEvent.originalTarget instanceof HTMLAnchorElement) && - (aEvent.originalTarget.getAttribute('anonid') != 'closeIcon') && - aEvent.button == 0 && aEvent.isTrusted) { - gPluginHandler._showClickToPlayNotification(browser, plugin); - aEvent.stopPropagation(); - aEvent.preventDefault(); - } - } - }, - - _handlePlayPreviewEvent: function PH_handlePlayPreviewEvent(aPlugin) { - let doc = aPlugin.ownerDocument; - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - let pluginInfo = this._getPluginInfo(aPlugin); - let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype); - - let previewContent = this.getPluginUI(aPlugin, "previewPluginContent"); - let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0]; - if (!iframe) { - // lazy initialization of the iframe - iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe"); - iframe.className = "previewPluginContentFrame"; - previewContent.appendChild(iframe); - - // Force a style flush, so that we ensure our binding is attached. - aPlugin.clientTop; - } - iframe.src = playPreviewInfo.redirectURL; - - // MozPlayPlugin event can be dispatched from the extension chrome - // code to replace the preview content with the native plugin - previewContent.addEventListener("MozPlayPlugin", function playPluginHandler(aEvent) { - if (!aEvent.isTrusted) - return; - - previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true); - - let playPlugin = !aEvent.detail; - gPluginHandler.stopPlayPreview(aPlugin, playPlugin); - - // cleaning up: removes overlay iframe from the DOM - let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0]; - if (iframe) - previewContent.removeChild(iframe); - }, true); - - if (!playPreviewInfo.ignoreCTP) { - gPluginHandler._showClickToPlayNotification(browser); - } - }, - - reshowClickToPlayNotification: function PH_reshowClickToPlayNotification() { - let browser = gBrowser.selectedBrowser; - let contentWindow = browser.contentWindow; - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - let doc = contentWindow.document; - let plugins = cwu.plugins; - for (let plugin of plugins) { - let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); - if (overlay) - overlay.removeEventListener("click", gPluginHandler._overlayClickListener, true); - let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); - if (gPluginHandler.canActivatePlugin(objLoadingContent)) - gPluginHandler._handleClickToPlayEvent(plugin); - } - gPluginHandler._showClickToPlayNotification(browser); - }, - - _clickToPlayNotificationEventCallback: function PH_ctpEventCallback(event) { - if (event == "showing") { - gPluginHandler._makeCenterActions(this); - } - else if (event == "dismissed") { - // Once the popup is dismissed, clicking the icon should show the full - // list again - this.options.primaryPlugin = null; - } - }, - - // 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(); - for (let plugin of cwu.plugins) { - plugin.QueryInterface(Ci.nsIObjectLoadingContent); - if (plugin.getContentTypeForMIMEType(plugin.actualType) != Ci.nsIObjectLoadingContent.TYPE_PLUGIN) { - continue; - } - - let pluginInfo = this._getPluginInfo(plugin); - if (pluginInfo.permissionString === null) { - Components.utils.reportError("No permission string for active plugin."); - continue; - } - if (pluginsFound.has(pluginInfo.permissionString)) { - continue; - } - pluginsFound.add(pluginInfo.permissionString); - - // Add the per-site permissions and details URLs to pluginInfo here - // because they are more expensive to compute and so we avoid it in - // the tighter loop above. - let permissionObj = Services.perms. - getPermissionObject(principal, pluginInfo.permissionString, false); - if (permissionObj) { - pluginInfo.pluginPermissionHost = permissionObj.host; - pluginInfo.pluginPermissionType = permissionObj.expireType; - } - else { - pluginInfo.pluginPermissionHost = principalHost; - pluginInfo.pluginPermissionType = undefined; - } - - let url; - // TODO: allow the blocklist to specify a better link, bug 873093 - if (pluginInfo.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) { - url = Services.urlFormatter.formatURLPref("plugins.update.url"); - } - else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) { - url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag); - } - pluginInfo.detailsLink = url; - - centerActions.push(pluginInfo); - } - centerActions.sort(function(a, b) { - return a.pluginName.localeCompare(b.pluginName); - }); - - notification.options.centerActions = centerActions; - }, - - /** - * Called from the plugin doorhanger to set the new permissions for a plugin - * and activate plugins if necessary. - * aNewState should be either "allownow" "allowalways" or "block" - */ - _updatePluginPermission: function PH_setPermissionForPlugins(aNotification, aPluginInfo, aNewState) { - let permission; - let expireType; - let expireTime; - - switch (aNewState) { - case "allownow": - permission = Ci.nsIPermissionManager.ALLOW_ACTION; - expireType = Ci.nsIPermissionManager.EXPIRE_SESSION; - expireTime = Date.now() + Services.prefs.getIntPref(kPrefSessionPersistMinutes) * 60 * 1000; - break; - - case "allowalways": - permission = Ci.nsIPermissionManager.ALLOW_ACTION; - expireType = Ci.nsIPermissionManager.EXPIRE_TIME; - expireTime = Date.now() + - Services.prefs.getIntPref(kPrefPersistentDays) * 24 * 60 * 60 * 1000; - break; - - case "block": - permission = Ci.nsIPermissionManager.PROMPT_ACTION; - expireType = Ci.nsIPermissionManager.EXPIRE_NEVER; - expireTime = 0; - break; - - // In case a plugin has already been allowed in another tab, the "continue allowing" button - // shouldn't change any permissions but should run the plugin-enablement code below. - case "continue": - break; - - default: - Cu.reportError(Error("Unexpected plugin state: " + aNewState)); - return; - } - - let browser = aNotification.browser; - let contentWindow = browser.contentWindow; - if (aNewState != "continue") { - let principal = contentWindow.document.nodePrincipal; - Services.perms.addFromPrincipal(principal, aPluginInfo.permissionString, - permission, expireType, expireTime); - - if (aNewState == "block") { - return; - } - } - - // Manually activate the plugins that would have been automatically - // activated. - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - let plugins = cwu.plugins; - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - - for (let plugin of plugins) { - plugin.QueryInterface(Ci.nsIObjectLoadingContent); - // canActivatePlugin will return false if this isn't a known plugin type, - // so the pluginHost.getPermissionStringForType call is protected - if (gPluginHandler.canActivatePlugin(plugin) && - aPluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) { - plugin.playPlugin(); - } - } - }, - - _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aPrimaryPlugin) { - let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser); - - let contentWindow = aBrowser.contentWindow; - let contentDoc = aBrowser.contentDocument; - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - // Pale Moon: cwu.plugins may contain non-plugin <object>s, filter them out - let plugins = cwu.plugins.filter(function(plugin) { - return (plugin.getContentTypeForMIMEType(plugin.actualType) == - Ci.nsIObjectLoadingContent.TYPE_PLUGIN); - }); - if (plugins.length == 0) { - if (notification) { - PopupNotifications.remove(notification); - } - return; - } - - let icon = 'plugins-notification-icon'; - for (let plugin of plugins) { - let fallbackType = plugin.pluginFallbackType; - if (fallbackType == plugin.PLUGIN_VULNERABLE_UPDATABLE || - fallbackType == plugin.PLUGIN_VULNERABLE_NO_UPDATE || - fallbackType == plugin.PLUGIN_BLOCKLISTED) { - icon = 'blocked-plugins-notification-icon'; - break; - } - if (fallbackType == plugin.PLUGIN_CLICK_TO_PLAY) { - let overlay = contentDoc.getAnonymousElementByAttribute(plugin, "anonid", "main"); - if (!overlay || overlay.style.visibility == 'hidden') { - icon = 'alert-plugins-notification-icon'; - } - } - } - - let dismissed = notification ? notification.dismissed : true; - if (aPrimaryPlugin) - dismissed = false; - - let primaryPluginPermission = null; - if (aPrimaryPlugin) { - primaryPluginPermission = this._getPluginInfo(aPrimaryPlugin).permissionString; - } - - let options = { - dismissed: dismissed, - eventCallback: this._clickToPlayNotificationEventCallback, - primaryPlugin: primaryPluginPermission - }; - PopupNotifications.show(aBrowser, "click-to-play-plugins", - "", icon, - null, null, options); - }, - - // Crashed-plugin observer. Notified once per plugin crash, before events - // are dispatched to individual plugin instances. - pluginCrashed : function(subject, topic, data) { - let propertyBag = subject; - if (!(propertyBag instanceof Ci.nsIPropertyBag2) || - !(propertyBag instanceof Ci.nsIWritablePropertyBag2)) - return; - }, - - // Crashed-plugin event listener. Called for every instance of a - // plugin in content. - pluginInstanceCrashed: function (plugin, aEvent) { - // Ensure the plugin and event are of the right type. - if (!(aEvent instanceof Ci.nsIDOMDataContainerEvent)) - return; - - let submittedReport = aEvent.getData("submittedCrashReport"); - let doPrompt = true; // XXX followup for .getData("doPrompt"); - let submitReports = true; // XXX followup for .getData("submitReports"); - let pluginName = aEvent.getData("pluginName"); - let pluginDumpID = aEvent.getData("pluginDumpID"); - let browserDumpID = aEvent.getData("browserDumpID"); - - // Remap the plugin name to a more user-presentable form. - pluginName = this.makeNicePluginName(pluginName); - - let messageString = gNavigatorBundle.getFormattedString("crashedpluginsMessage.title", [pluginName]); - - // - // Configure the crashed-plugin placeholder. - // - - // Force a layout flush so the binding is attached. - plugin.clientTop; - let doc = plugin.ownerDocument; - let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox"); - let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus"); - - let crashText = doc.getAnonymousElementByAttribute(plugin, "class", "msgCrashedText"); - crashText.textContent = messageString; - - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - - let link = doc.getAnonymousElementByAttribute(plugin, "class", "reloadLink"); - this.addLinkClickCallback(link, "reloadPage", browser); - - let notificationBox = gBrowser.getNotificationBox(browser); - - let isShowing = true; - - // Is the <object>'s size too small to hold what we want to show? - if (this.isTooSmall(plugin, overlay)) { - // First try hiding the crash report submission UI. - statusDiv.removeAttribute("status"); - - if (this.isTooSmall(plugin, overlay)) { - // Hide the overlay's contents. Use visibility style, so that it doesn't - // collapse down to 0x0. - overlay.style.visibility = "hidden"; - isShowing = false; - } - } - - if (isShowing) { - // If a previous plugin on the page was too small and resulted in adding a - // notification bar, then remove it because this plugin instance it big - // enough to serve as in-content notification. - hideNotificationBar(); - doc.mozNoPluginCrashedNotification = true; - } else { - // If another plugin on the page was large enough to show our UI, we don't - // want to show a notification bar. - if (!doc.mozNoPluginCrashedNotification) - showNotificationBar(pluginDumpID, browserDumpID); - } - - function hideNotificationBar() { - let notification = notificationBox.getNotificationWithValue("plugin-crashed"); - if (notification) - notificationBox.removeNotification(notification, true); - } - - function showNotificationBar(pluginDumpID, browserDumpID) { - // If there's already an existing notification bar, don't do anything. - let notification = notificationBox.getNotificationWithValue("plugin-crashed"); - if (notification) - return; - - // Configure the notification bar - let priority = notificationBox.PRIORITY_WARNING_MEDIUM; - let iconURL = "chrome://mozapps/skin/plugins/notifyPluginCrashed.png"; - let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label"); - let reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey"); - let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label"); - let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey"); - - let buttons = [{ - label: reloadLabel, - accessKey: reloadKey, - popup: null, - callback: function() { browser.reload(); }, - }]; - - notification = notificationBox.appendNotification(messageString, "plugin-crashed", - iconURL, priority, buttons); - - // Add the "learn more" link. - let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let link = notification.ownerDocument.createElementNS(XULNS, "label"); - link.className = "text-link"; - link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore")); - let crashurl = formatURL("app.support.baseURL", true); - crashurl += "plugin-crashed-notificationbar"; - link.href = crashurl; - - let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText"); - description.appendChild(link); - - // Remove the notfication when the page is reloaded. - doc.defaultView.top.addEventListener("unload", function() { - notificationBox.removeNotification(notification); - }, false); - } - - } -}; diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc deleted file mode 100644 index 78cfb7faa..000000000 --- a/browser/base/content/browser-sets.inc +++ /dev/null @@ -1,436 +0,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/. - -#ifdef XP_UNIX -#ifndef XP_MACOSX -#define XP_GNOME 1 -#endif -#endif - - <stringbundleset id="stringbundleset"> - <stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/> - <stringbundle id="bundle_shell" src="chrome://browser/locale/shellservice.properties"/> - <stringbundle id="bundle_preferences" src="chrome://browser/locale/preferences/preferences.properties"/> - </stringbundleset> - - <commandset id="mainCommandSet"> - <command id="cmd_newNavigator" oncommand="OpenBrowserWindow()"/> - <command id="cmd_handleBackspace" oncommand="BrowserHandleBackspace();" /> - <command id="cmd_handleShiftBackspace" oncommand="BrowserHandleShiftBackspace();" /> - - <command id="cmd_newNavigatorTab" oncommand="BrowserOpenTab();"/> - <command id="Browser:OpenFile" oncommand="BrowserOpenFileWindow();"/> - <command id="Browser:SavePage" oncommand="saveDocument(window.content.document);"/> - - <command id="Browser:SendLink" - oncommand="MailIntegration.sendLinkForWindow(window.content);"/> - - <command id="cmd_pageSetup" oncommand="PrintUtils.showPageSetup();"/> - <command id="cmd_print" oncommand="PrintUtils.print();"/> - <command id="cmd_printPreview" oncommand="PrintUtils.printPreview(PrintPreviewListener);"/> - <command id="cmd_close" oncommand="BrowserCloseTabOrWindow()"/> - <command id="cmd_closeWindow" oncommand="BrowserTryToCloseWindow()"/> - <command id="cmd_ToggleTabsOnTop" oncommand="TabsOnTop.toggle()"/> - <command id="cmd_CustomizeToolbars" oncommand="BrowserCustomizeToolbar()"/> - <command id="cmd_restartApplication" oncommand="restart(false);"/> - <command id="cmd_quitApplication" oncommand="goQuitApplication()"/> - - - <commandset id="editMenuCommands"/> - - <command id="View:PageSource" oncommand="BrowserViewSourceOfDocument(content.document);" observes="isImage"/> - <command id="View:PageInfo" oncommand="BrowserPageInfo();"/> - <command id="View:FullScreen" oncommand="BrowserFullScreen();"/> - <command id="cmd_find" - oncommand="gFindBar.onFindCommand();" - observes="isImage"/> - <command id="cmd_findAgain" - oncommand="gFindBar.onFindAgainCommand(false);" - observes="isImage"/> - <command id="cmd_findPrevious" - oncommand="gFindBar.onFindAgainCommand(true);" - observes="isImage"/> - <!-- work-around bug 392512 --> - <command id="Browser:AddBookmarkAs" - oncommand="PlacesCommandHook.bookmarkCurrentPage(true, PlacesUtils.bookmarksMenuFolderId);"/> - <!-- The command disabled state must be manually updated through - PlacesCommandHook.updateBookmarkAllTabsCommand() --> - <command id="Browser:BookmarkAllTabs" - oncommand="PlacesCommandHook.bookmarkCurrentPages();"/> - <command id="Browser:Home" oncommand="BrowserHome();"/> - <command id="Browser:Back" oncommand="BrowserBack();" disabled="true"/> - <command id="Browser:BackOrBackDuplicate" oncommand="BrowserBack(event);" disabled="true"> - <observes element="Browser:Back" attribute="disabled"/> - </command> - <command id="Browser:Forward" oncommand="BrowserForward();" disabled="true"/> - <command id="Browser:ForwardOrForwardDuplicate" oncommand="BrowserForward(event);" disabled="true"> - <observes element="Browser:Forward" attribute="disabled"/> - </command> - <command id="Browser:Stop" oncommand="BrowserStop();" disabled="true"/> - <command id="Browser:Reload" oncommand="if (event.shiftKey) BrowserReloadSkipCache(); else BrowserReload()" disabled="true"/> - <command id="Browser:ReloadOrDuplicate" oncommand="BrowserReloadOrDuplicate(event)" disabled="true"> - <observes element="Browser:Reload" attribute="disabled"/> - </command> - <command id="Browser:ReloadSkipCache" oncommand="BrowserReloadSkipCache()" disabled="true"> - <observes element="Browser:Reload" attribute="disabled"/> - </command> - <command id="Browser:NextTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(1, true);"/> - <command id="Browser:PrevTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(-1, true);"/> - <command id="Browser:ShowAllTabs" oncommand="allTabs.open();"/> - <command id="Browser:FocusNextFrame" oncommand="focusNextFrame(event);"/> - <command id="cmd_fullZoomReduce" oncommand="FullZoom.reduce()"/> - <command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/> - <command id="cmd_fullZoomReset" oncommand="FullZoom.reset()"/> - <command id="cmd_fullZoomToggle" oncommand="ZoomManager.toggleZoom();"/> - <command id="cmd_gestureRotateLeft" oncommand="gGestureSupport.rotate(event.sourceEvent)"/> - <command id="cmd_gestureRotateRight" oncommand="gGestureSupport.rotate(event.sourceEvent)"/> - <command id="cmd_gestureRotateEnd" oncommand="gGestureSupport.rotateEnd()"/> - <command id="Browser:OpenLocation" oncommand="openLocation();"/> - <command id="Browser:RestoreLastSession" oncommand="restoreLastSession();" disabled="true"/> - - <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/> - <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/> -#ifdef MOZ_DEVTOOLS - <command id="Tools:DevToolbox" oncommand="gDevToolsBrowser.toggleToolboxCommand(gBrowser);"/> - <command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/> - <command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/> - <command id="Tools:DevAppMgr" oncommand="gDevToolsBrowser.openAppManager(gBrowser);" disabled="true" hidden="true"/> - <command id="Tools:WebIDE" oncommand="gDevToolsBrowser.openWebIDE();" disabled="true" hidden="true"/> - <command id="Tools:ChromeDebugger" oncommand="BrowserToolboxProcess.init();" disabled="true" hidden="true"/> - <command id="Tools:BrowserConsole" oncommand="HUDService.openBrowserConsoleOrFocus();"/> - <command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true" hidden="true"/> - <command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/> - <command id="Tools:Eyedropper" oncommand="openEyedropper();"/> -#endif - <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/> - <command id="Tools:Permissions" oncommand="BrowserOpenPermissionsMgr();"/> - <command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/> -#ifdef MOZ_DEVTOOLS - <command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)" disabled="true" hidden="true"/> -#endif - <command id="Tools:Sanitize" - oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/> - <command id="Tools:PrivateBrowsing" - oncommand="OpenBrowserWindow({private: true});"/> - <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/> - <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/> - <command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/> - </commandset> - - <commandset id="placesCommands"> - <command id="Browser:ShowAllBookmarks" - oncommand="PlacesCommandHook.showPlacesOrganizer('AllBookmarks');"/> - <command id="Browser:ShowAllHistory" - oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/> - </commandset> - - <broadcasterset id="mainBroadcasterSet"> - <broadcaster id="viewBookmarksSidebar" autoCheck="false" sidebartitle="&bookmarksButton.label;" - type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/bookmarks/bookmarksPanel.xul" - oncommand="toggleSidebar('viewBookmarksSidebar');"/> - - <!-- for both places and non-places, the sidebar lives at - chrome://browser/content/history/history-panel.xul so there are no - problems when switching between versions --> - <broadcaster id="viewHistorySidebar" autoCheck="false" sidebartitle="&historyButton.label;" - type="checkbox" group="sidebar" - sidebarurl="chrome://browser/content/history/history-panel.xul" - oncommand="toggleSidebar('viewHistorySidebar');"/> - - <broadcaster id="viewWebPanelsSidebar" autoCheck="false" - type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/web-panels.xul" - oncommand="toggleSidebar('viewWebPanelsSidebar');"/> - - <!-- popup blocking menu items --> - <broadcaster id="blockedPopupAllowSite" - accesskey="&allowPopups.accesskey;" - oncommand="gPopupBlockerObserver.toggleAllowPopupsForSite(event);"/> - <broadcaster id="blockedPopupEditSettings" -#ifdef XP_WIN - label="&editPopupSettings.label;" -#else - label="&editPopupSettingsUnix.label;" -#endif - accesskey="&editPopupSettings.accesskey;" - oncommand="gPopupBlockerObserver.editPopupSettings();"/> - <broadcaster id="blockedPopupDontShowMessage" - accesskey="&dontShowMessage.accesskey;" - type="checkbox" - oncommand="gPopupBlockerObserver.dontShowMessage();"/> - <broadcaster id="blockedPopupsSeparator"/> - <broadcaster id="isImage"/> - <broadcaster id="isFrameImage"/> - <broadcaster id="singleFeedMenuitemState" disabled="true"/> - <broadcaster id="multipleFeedsMenuState" hidden="true"/> -#ifdef MOZ_SERVICES_SYNC - <broadcaster id="sync-setup-state"/> - <broadcaster id="sync-syncnow-state"/> -#endif - <broadcaster id="workOfflineMenuitemState"/> - -#ifdef MOZ_DEVTOOLS - <!-- DevTools broadcasters --> - <broadcaster id="devtoolsMenuBroadcaster_DevToolbox" - label="&devToolboxMenuItem.label;" - type="checkbox" autocheck="false" - command="Tools:DevToolbox" - key="key_devToolbox"/> - <broadcaster id="devtoolsMenuBroadcaster_DevToolbar" - label="&devToolbarMenu.label;" - type="checkbox" autocheck="false" - command="Tools:DevToolbar" - key="key_devToolbar"/> - <broadcaster id="devtoolsMenuBroadcaster_DevAppMgr" - label="&devAppMgrMenu.label;" - command="Tools:DevAppMgr"/> - <broadcaster id="devtoolsMenuBroadcaster_webide" - label="&webide.label;" - command="Tools:WebIDE" - key="key_webide"/> - <broadcaster id="devtoolsMenuBroadcaster_ChromeDebugger" - label="&chromeDebuggerMenu.label;" - command="Tools:ChromeDebugger"/> - <broadcaster id="devtoolsMenuBroadcaster_BrowserConsole" - label="&browserConsoleCmd.label;" - key="key_browserConsole" - command="Tools:BrowserConsole"/> - <broadcaster id="devtoolsMenuBroadcaster_Scratchpad" - label="&scratchpad.label;" - command="Tools:Scratchpad" - key="key_scratchpad"/> - <broadcaster id="devtoolsMenuBroadcaster_ResponsiveUI" - label="&responsiveDesignTool.label;" - type="checkbox" autocheck="false" - command="Tools:ResponsiveUI" - key="key_responsiveUI"/> - <broadcaster id="devtoolsMenuBroadcaster_Eyedropper" - label="&eyedropper.label;" - type="checkbox" autocheck="false" - command="Tools:Eyedropper"/> -#endif - <broadcaster id="devtoolsMenuBroadcaster_PageSource" - label="&pageSourceCmd.label;" - key="key_viewSource" - command="View:PageSource"/> - <broadcaster id="devtoolsMenuBroadcaster_ErrorConsole" - label="&errorConsoleCmd.label;" - command="Tools:ErrorConsole"/> - <broadcaster id="devtoolsMenuBroadcaster_GetMoreTools" - label="&getMoreDevtoolsCmd.label;" - oncommand="openUILinkIn(gPrefService.getCharPref('browser.getdevtools.url'), 'tab');"/> -#ifdef MOZ_DEVTOOLS - <broadcaster id="devtoolsMenuBroadcaster_connect" - label="&devtoolsConnect.label;" - command="Tools:DevToolsConnect"/> -#endif - </broadcasterset> - - <keyset id="mainKeyset"> - <key id="key_newNavigator" - key="&newNavigatorCmd.key;" - command="cmd_newNavigator" - modifiers="accel"/> - <key id="key_newNavigatorTab" key="&tabCmd.commandkey;" modifiers="accel" command="cmd_newNavigatorTab"/> - <key id="focusURLBar" key="&openCmd.commandkey;" command="Browser:OpenLocation" - modifiers="accel"/> -#ifndef XP_MACOSX - <key id="focusURLBar2" key="&urlbar.accesskey;" command="Browser:OpenLocation" - modifiers="alt"/> -#endif - -# -# Search Command Key Logic works like this: -# -# Unix: Ctrl+K (cross platform binding) -# Ctrl+J (in case of emacs Ctrl-K conflict) -# Mac: Cmd+K (cross platform binding) -# Cmd+Opt+F (platform convention) -# Win: Ctrl+K (cross platform binding) -# Ctrl+E (IE compat) -# -# We support Ctrl+K on all platforms now and advertise it in the menu since it is -# our standard - it is a "safe" choice since it is near no harmful keys like "W" as -# "E" is. People mourning the loss of Ctrl+K for emacs compat can switch their GTK -# system setting to use emacs emulation, and we should respect it. Focus-Search-Box -# is a fundamental keybinding and we are maintaining a XP binding so that it is easy -# for people to switch to Linux. -# - <key id="key_search" key="&searchFocus.commandkey;" command="Tools:Search" modifiers="accel"/> -#ifdef XP_MACOSX - <key id="key_search2" key="&findOnCmd.commandkey;" command="Tools:Search" modifiers="accel,alt"/> -#endif -#ifdef XP_WIN - <key id="key_search2" key="&searchFocus.commandkey2;" command="Tools:Search" modifiers="accel"/> -#endif -#ifdef XP_GNOME - <key id="key_search2" key="&searchFocusUnix.commandkey;" command="Tools:Search" modifiers="accel"/> - <key id="key_openDownloads" key="&downloadsUnix.commandkey;" command="Tools:Downloads" modifiers="accel,shift"/> -#else - <key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/> -#endif - <key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/> -#ifdef MOZ_DEVTOOLS - <key id="key_browserConsole" key="&browserConsoleCmd.commandkey;" command="Tools:BrowserConsole" modifiers="accel,shift"/> - <key id="key_devToolbox" keycode="VK_F12" keytext="F12" command="Tools:DevToolbox"/> - <key id="key_devToolbar" keycode="&devToolbar.keycode;" modifiers="shift" - keytext="&devToolbar.keytext;" command="Tools:DevToolbarFocus"/> - <key id="key_responsiveUI" key="&responsiveDesignTool.commandkey;" command="Tools:ResponsiveUI" -#ifdef XP_MACOSX - modifiers="accel,alt" -#else - modifiers="accel,shift" -#endif - /> - <key id="key_scratchpad" keycode="&scratchpad.keycode;" modifiers="shift" - keytext="&scratchpad.keytext;" command="Tools:Scratchpad"/> -#endif - <key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile" modifiers="accel"/> - <key id="key_savePage" key="&savePageCmd.commandkey;" command="Browser:SavePage" modifiers="accel"/> - <key id="printKb" key="&printCmd.commandkey;" command="cmd_print" modifiers="accel"/> - <key id="key_close" key="&closeCmd.key;" command="cmd_close" modifiers="accel"/> - <key id="key_closeWindow" key="&closeCmd.key;" command="cmd_closeWindow" modifiers="accel,shift"/> - <key id="key_undo" - key="&undoCmd.key;" - modifiers="accel"/> -#ifdef XP_UNIX - <key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift"/> -#else - <key id="key_redo" key="&redoCmd.key;" modifiers="accel"/> -#endif - <key id="key_cut" - key="&cutCmd.key;" - modifiers="accel"/> - <key id="key_copy" - key="©Cmd.key;" - modifiers="accel"/> - <key id="key_paste" - key="&pasteCmd.key;" - modifiers="accel"/> - <key id="key_delete" keycode="VK_DELETE" command="cmd_delete"/> - <key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/> - - <key keycode="VK_BACK" command="cmd_handleBackspace"/> - <key keycode="VK_BACK" command="cmd_handleShiftBackspace" modifiers="shift"/> -#ifndef XP_MACOSX - <key id="goBackKb" keycode="VK_LEFT" command="Browser:Back" modifiers="alt"/> - <key id="goForwardKb" keycode="VK_RIGHT" command="Browser:Forward" modifiers="alt"/> -#else - <key id="goBackKb" keycode="VK_LEFT" command="Browser:Back" modifiers="accel" /> - <key id="goForwardKb" keycode="VK_RIGHT" command="Browser:Forward" modifiers="accel" /> -#endif -#ifdef XP_UNIX - <key id="goBackKb2" key="&goBackCmd.commandKey;" command="Browser:Back" modifiers="accel"/> - <key id="goForwardKb2" key="&goForwardCmd.commandKey;" command="Browser:Forward" modifiers="accel"/> -#endif - <key id="goHome" keycode="VK_HOME" command="Browser:Home" modifiers="alt"/> - <key keycode="VK_F5" command="Browser:Reload"/> -#ifndef XP_MACOSX - <key id="showAllHistoryKb" key="&showAllHistoryCmd.commandkey;" command="Browser:ShowAllHistory" modifiers="accel,shift"/> - <key keycode="VK_F5" command="Browser:ReloadSkipCache" modifiers="accel"/> - <key keycode="VK_F6" command="Browser:FocusNextFrame"/> - <key keycode="VK_F6" command="Browser:FocusNextFrame" modifiers="shift"/> - <key id="key_fullScreen" keycode="VK_F11" command="View:FullScreen"/> -#else - <key id="key_fullScreen" key="&fullScreenCmd.macCommandKey;" command="View:FullScreen" modifiers="accel,control"/> - <key id="key_fullScreen_old" key="&fullScreenCmd.macCommandKey;" command="View:FullScreen" modifiers="accel,shift"/> - <key keycode="VK_F11" command="View:FullScreen"/> -#endif - <key key="&reloadCmd.commandkey;" command="Browser:Reload" modifiers="accel" id="key_reload"/> - <key key="&reloadCmd.commandkey;" command="Browser:ReloadSkipCache" modifiers="accel,shift"/> - <key id="key_viewSource" key="&pageSourceCmd.commandkey;" command="View:PageSource" modifiers="accel"/> -#ifndef XP_WIN - <key id="key_viewInfo" key="&pageInfoCmd.commandkey;" command="View:PageInfo" modifiers="accel"/> -#endif - <key id="key_find" key="&findOnCmd.commandkey;" command="cmd_find" modifiers="accel"/> - <key id="key_findAgain" key="&findAgainCmd.commandkey;" command="cmd_findAgain" modifiers="accel"/> - <key id="key_findPrevious" key="&findAgainCmd.commandkey;" command="cmd_findPrevious" modifiers="accel,shift"/> - <key keycode="&findAgainCmd.commandkey2;" command="cmd_findAgain"/> - <key keycode="&findAgainCmd.commandkey2;" command="cmd_findPrevious" modifiers="shift"/> - - <key id="addBookmarkAsKb" key="&bookmarkThisPageCmd.commandkey;" command="Browser:AddBookmarkAs" modifiers="accel"/> -# Accel+Shift+A-F are reserved on GTK -#ifndef MOZ_WIDGET_GTK - <key id="bookmarkAllTabsKb" key="&bookmarkThisPageCmd.commandkey;" oncommand="PlacesCommandHook.bookmarkCurrentPages();" modifiers="accel,shift"/> - <key id="manBookmarkKb" key="&bookmarksCmd.commandkey;" command="Browser:ShowAllBookmarks" modifiers="accel,shift"/> -#else - <key id="manBookmarkKb" key="&bookmarksGtkCmd.commandkey;" command="Browser:ShowAllBookmarks" modifiers="accel,shift"/> -#endif - <key id="viewBookmarksSidebarKb" key="&bookmarksCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/> -#ifdef XP_WIN -# Cmd+I is conventially mapped to Info on MacOS X, thus it should not be -# overridden for other purposes there. - <key id="viewBookmarksSidebarWinKb" key="&bookmarksWinCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/> -#endif - -# Navigation cancel keys: Esc performs a cancel on loading (i.e.: stop button equivalent) -# Shift-Esc (and similar Shift-modified stop on Mac) performs a "superstop": this halts all -# networking requests, XHR, animated gifs, etc. - <key id="key_stop" keycode="VK_ESCAPE" command="Browser:Stop"/> - <key id="key_stop_all" keycode="VK_ESCAPE" modifiers="shift" oncommand="BrowserStop();"/> -#ifdef XP_MACOSX - <key id="key_stop_mac" modifiers="accel" key="&stopCmd.macCommandKey;" command="Browser:Stop"/> - <key id="key_stop_all_mac" modifiers="accel,shift" key="&stopCmd.macCommandKey;" oncommand="BrowserStop();"/> -#endif - - <key id="key_gotoHistory" - key="&historySidebarCmd.commandKey;" -#ifdef XP_MACOSX - modifiers="accel,shift" -#else - modifiers="accel" -#endif - command="viewHistorySidebar"/> - - <key id="key_fullZoomReduce" key="&fullZoomReduceCmd.commandkey;" command="cmd_fullZoomReduce" modifiers="accel"/> - <key key="&fullZoomReduceCmd.commandkey2;" command="cmd_fullZoomReduce" modifiers="accel"/> - <key id="key_fullZoomEnlarge" key="&fullZoomEnlargeCmd.commandkey;" command="cmd_fullZoomEnlarge" modifiers="accel"/> - <key key="&fullZoomEnlargeCmd.commandkey2;" command="cmd_fullZoomEnlarge" modifiers="accel"/> - <key key="&fullZoomEnlargeCmd.commandkey3;" command="cmd_fullZoomEnlarge" modifiers="accel"/> - <key id="key_fullZoomReset" key="&fullZoomResetCmd.commandkey;" command="cmd_fullZoomReset" modifiers="accel"/> - <key key="&fullZoomResetCmd.commandkey2;" command="cmd_fullZoomReset" modifiers="accel"/> - - <key id="key_showAllTabs" command="Browser:ShowAllTabs" keycode="VK_TAB" modifiers="control,shift"/> - - <key id="key_switchTextDirection" key="&bidiSwitchTextDirectionItem.commandkey;" command="cmd_switchTextDirection" modifiers="accel,shift" /> - - <key id="key_privatebrowsing" command="Tools:PrivateBrowsing" key="&privateBrowsingCmd.commandkey;" modifiers="accel,shift"/> - <key id="key_sanitize" command="Tools:Sanitize" keycode="VK_DELETE" modifiers="accel,shift"/> -#ifdef XP_MACOSX - <key id="key_sanitize_mac" command="Tools:Sanitize" keycode="VK_BACK" modifiers="accel,shift"/> -#endif -#ifdef XP_UNIX - <key id="key_quitApplication" key="&quitApplicationCmdUnix.key;" command="cmd_quitApplication" modifiers="accel"/> -#endif - -#ifdef FULL_BROWSER_WINDOW - <key id="key_undoCloseTab" command="History:UndoCloseTab" key="&tabCmd.commandkey;" modifiers="accel,shift"/> -#endif - <key id="key_undoCloseWindow" command="History:UndoCloseWindow" key="&newNavigatorCmd.key;" modifiers="accel,shift"/> - -#ifdef XP_GNOME -#define NUM_SELECT_TAB_MODIFIER alt -#else -#define NUM_SELECT_TAB_MODIFIER accel -#endif - -#expand <key id="key_selectTab1" oncommand="gBrowser.selectTabAtIndex(0, event);" key="1" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectTab2" oncommand="gBrowser.selectTabAtIndex(1, event);" key="2" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectTab3" oncommand="gBrowser.selectTabAtIndex(2, event);" key="3" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectTab4" oncommand="gBrowser.selectTabAtIndex(3, event);" key="4" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectTab5" oncommand="gBrowser.selectTabAtIndex(4, event);" key="5" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectTab6" oncommand="gBrowser.selectTabAtIndex(5, event);" key="6" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectTab7" oncommand="gBrowser.selectTabAtIndex(6, event);" key="7" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectTab8" oncommand="gBrowser.selectTabAtIndex(7, event);" key="8" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> -#expand <key id="key_selectLastTab" oncommand="gBrowser.selectTabAtIndex(-1, event);" key="9" modifiers="__NUM_SELECT_TAB_MODIFIER__"/> - - <key id="key_toggleAddonBar" command="Browser:ToggleAddonBar" key="&toggleAddonBarCmd.key;" modifiers="accel"/> - - </keyset> - -# Used by baseMenuOverlay -#ifdef XP_MACOSX - <commandset id="baseMenuCommandSet" /> -#endif - <keyset id="baseMenuKeyset" /> diff --git a/browser/base/content/browser-syncui.js b/browser/base/content/browser-syncui.js deleted file mode 100644 index fc8c7f016..000000000 --- a/browser/base/content/browser-syncui.js +++ /dev/null @@ -1,470 +0,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/. - -// gSyncUI handles updating the tools menu -let gSyncUI = { - _obs: ["weave:service:sync:start", - "weave:service:sync:delayed", - "weave:service:quota:remaining", - "weave:service:setup-complete", - "weave:service:login:start", - "weave:service:login:finish", - "weave:service:logout:finish", - "weave:service:start-over", - "weave:ui:login:error", - "weave:ui:sync:error", - "weave:ui:sync:finish", - "weave:ui:clear-error", - ], - - _unloaded: false, - - init: function SUI_init() { - // Proceed to set up the UI if Sync has already started up. - // Otherwise we'll do it when Sync is firing up. - let xps = Components.classes["@mozilla.org/weave/service;1"] - .getService(Components.interfaces.nsISupports) - .wrappedJSObject; - if (xps.ready) { - this.initUI(); - return; - } - - Services.obs.addObserver(this, "weave:service:ready", true); - - // Remove the observer if the window is closed before the observer - // was triggered. - window.addEventListener("unload", function onUnload() { - gSyncUI._unloaded = true; - window.removeEventListener("unload", onUnload, false); - Services.obs.removeObserver(gSyncUI, "weave:service:ready"); - - if (Weave.Status.ready) { - gSyncUI._obs.forEach(function(topic) { - Services.obs.removeObserver(gSyncUI, topic); - }); - } - }, false); - }, - - initUI: function SUI_initUI() { - // If this is a browser window? - if (gBrowser) { - this._obs.push("weave:notification:added"); - } - - this._obs.forEach(function(topic) { - Services.obs.addObserver(this, topic, true); - }, this); - - if (gBrowser && Weave.Notifications.notifications.length) { - this.initNotifications(); - } - this.updateUI(); - }, - - initNotifications: function SUI_initNotifications() { - const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let notificationbox = document.createElementNS(XULNS, "notificationbox"); - notificationbox.id = "sync-notifications"; - notificationbox.setAttribute("flex", "1"); - - let bottombox = document.getElementById("browser-bottombox"); - bottombox.insertBefore(notificationbox, bottombox.firstChild); - - // Force a style flush to ensure that our binding is attached. - notificationbox.clientTop; - - // notificationbox will listen to observers from now on. - Services.obs.removeObserver(this, "weave:notification:added"); - }, - - _wasDelayed: false, - - _needsSetup: function SUI__needsSetup() { - let firstSync = ""; - try { - firstSync = Services.prefs.getCharPref("services.sync.firstSync"); - } catch (e) { } - return Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED || - firstSync == "notReady"; - }, - - updateUI: function SUI_updateUI() { - let needsSetup = this._needsSetup(); - document.getElementById("sync-setup-state").hidden = !needsSetup; - document.getElementById("sync-syncnow-state").hidden = needsSetup; - - if (!gBrowser) - return; - - let button = document.getElementById("sync-button"); - if (!button) - return; - - button.removeAttribute("status"); - this._updateLastSyncTime(); - if (needsSetup) - button.removeAttribute("tooltiptext"); - }, - - - // Functions called by observers - onActivityStart: function SUI_onActivityStart() { - if (!gBrowser) - return; - - let button = document.getElementById("sync-button"); - if (!button) - return; - - button.setAttribute("status", "active"); - }, - - onSyncDelay: function SUI_onSyncDelay() { - // basically, we want to just inform users that stuff is going to take a while - let title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title"); - let description = this._stringBundle.GetStringFromName("error.sync.no_node_found"); - let buttons = [new Weave.NotificationButton( - this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"), - this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"), - function() { gSyncUI.openServerStatus(); return true; } - )]; - let notification = new Weave.Notification( - title, description, null, Weave.Notifications.PRIORITY_INFO, buttons); - Weave.Notifications.replaceTitle(notification); - this._wasDelayed = true; - }, - - onLoginFinish: function SUI_onLoginFinish() { - // Clear out any login failure notifications - let title = this._stringBundle.GetStringFromName("error.login.title"); - this.clearError(title); - }, - - onSetupComplete: function SUI_onSetupComplete() { - this.onLoginFinish(); - }, - - onLoginError: function SUI_onLoginError() { - // if login fails, any other notifications are essentially moot - Weave.Notifications.removeAll(); - - // if we haven't set up the client, don't show errors - if (this._needsSetup()) { - this.updateUI(); - return; - } - - let title = this._stringBundle.GetStringFromName("error.login.title"); - - let description; - if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) { - // Convert to days - let lastSync = - Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400; - description = - this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1); - } else { - let reason = Weave.Utils.getErrorString(Weave.Status.login); - description = - this._stringBundle.formatStringFromName("error.sync.description", [reason], 1); - } - - let buttons = []; - buttons.push(new Weave.NotificationButton( - this._stringBundle.GetStringFromName("error.login.prefs.label"), - this._stringBundle.GetStringFromName("error.login.prefs.accesskey"), - function() { gSyncUI.openPrefs(); return true; } - )); - - let notification = new Weave.Notification(title, description, null, - Weave.Notifications.PRIORITY_WARNING, buttons); - Weave.Notifications.replaceTitle(notification); - this.updateUI(); - }, - - onLogout: function SUI_onLogout() { - this.updateUI(); - }, - - onStartOver: function SUI_onStartOver() { - this.clearError(); - }, - - onQuotaNotice: function onQuotaNotice(subject, data) { - let title = this._stringBundle.GetStringFromName("warning.sync.quota.label"); - let description = this._stringBundle.GetStringFromName("warning.sync.quota.description"); - let buttons = []; - buttons.push(new Weave.NotificationButton( - this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.label"), - this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.accesskey"), - function() { gSyncUI.openQuotaDialog(); return true; } - )); - - let notification = new Weave.Notification( - title, description, null, Weave.Notifications.PRIORITY_WARNING, buttons); - Weave.Notifications.replaceTitle(notification); - }, - - openServerStatus: function () { - let statusURL = Services.prefs.getCharPref("services.sync.statusURL"); - window.openUILinkIn(statusURL, "tab"); - }, - - // Commands - doSync: function SUI_doSync() { - setTimeout(function() Weave.Service.errorHandler.syncAndReportErrors(), 0); - }, - - handleToolbarButton: function SUI_handleStatusbarButton() { - if (this._needsSetup()) - this.openSetup(); - else - this.doSync(); - }, - - //XXXzpao should be part of syncCommon.js - which we might want to make a module... - // To be fixed in a followup (bug 583366) - - /** - * Invoke the Sync setup wizard. - * - * @param wizardType - * Indicates type of wizard to launch: - * null -- regular set up wizard - * "pair" -- pair a device first - * "reset" -- reset sync - */ - - openSetup: function SUI_openSetup(wizardType) { - let win = Services.wm.getMostRecentWindow("Weave:AccountSetup"); - if (win) - win.focus(); - else { - window.openDialog("chrome://browser/content/sync/setup.xul", - "weaveSetup", "centerscreen,chrome,resizable=no", - wizardType); - } - }, - - openAddDevice: function () { - if (!Weave.Utils.ensureMPUnlocked()) - return; - - let win = Services.wm.getMostRecentWindow("Sync:AddDevice"); - if (win) - win.focus(); - else - window.openDialog("chrome://browser/content/sync/addDevice.xul", - "syncAddDevice", "centerscreen,chrome,resizable=no"); - }, - - openQuotaDialog: function SUI_openQuotaDialog() { - let win = Services.wm.getMostRecentWindow("Sync:ViewQuota"); - if (win) - win.focus(); - else - Services.ww.activeWindow.openDialog( - "chrome://browser/content/sync/quota.xul", "", - "centerscreen,chrome,dialog,modal"); - }, - - openPrefs: function SUI_openPrefs() { - openPreferences("paneSync"); - }, - - - // Helpers - _updateLastSyncTime: function SUI__updateLastSyncTime() { - if (!gBrowser) - return; - - let syncButton = document.getElementById("sync-button"); - if (!syncButton) - return; - - let lastSync; - try { - lastSync = Services.prefs.getCharPref("services.sync.lastSync"); - } - catch (e) { }; - if (!lastSync || this._needsSetup()) { - syncButton.removeAttribute("tooltiptext"); - return; - } - - // Show the day-of-week and time (HH:MM) of last sync - let lastSyncDate = new Date(lastSync).toLocaleFormat("%a %H:%M"); - let lastSyncLabel = - this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDate], 1); - - syncButton.setAttribute("tooltiptext", lastSyncLabel); - }, - - clearError: function SUI_clearError(errorString) { - Weave.Notifications.removeAll(errorString); - this.updateUI(); - }, - - onSyncFinish: function SUI_onSyncFinish() { - let title = this._stringBundle.GetStringFromName("error.sync.title"); - - // Clear out sync failures on a successful sync - this.clearError(title); - - if (this._wasDelayed && Weave.Status.sync != Weave.NO_SYNC_NODE_FOUND) { - title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title"); - this.clearError(title); - this._wasDelayed = false; - } - }, - - onSyncError: function SUI_onSyncError() { - let title = this._stringBundle.GetStringFromName("error.sync.title"); - - if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) { - this.onLoginError(); - return; - } - - let description; - if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) { - // Convert to days - let lastSync = - Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400; - description = - this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1); - } else { - let error = Weave.Utils.getErrorString(Weave.Status.sync); - description = - this._stringBundle.formatStringFromName("error.sync.description", [error], 1); - } - let priority = Weave.Notifications.PRIORITY_WARNING; - let buttons = []; - - // Check if the client is outdated in some way - let outdated = Weave.Status.sync == Weave.VERSION_OUT_OF_DATE; - for (let [engine, reason] in Iterator(Weave.Status.engines)) - outdated = outdated || reason == Weave.VERSION_OUT_OF_DATE; - - if (outdated) { - description = this._stringBundle.GetStringFromName( - "error.sync.needUpdate.description"); - buttons.push(new Weave.NotificationButton( - this._stringBundle.GetStringFromName("error.sync.needUpdate.label"), - this._stringBundle.GetStringFromName("error.sync.needUpdate.accesskey"), - function() { - window.openUILinkIn(Services.prefs.getCharPref("services.sync.outdated.url"), "tab"); - return true; - } - )); - } - else if (Weave.Status.sync == Weave.OVER_QUOTA) { - description = this._stringBundle.GetStringFromName( - "error.sync.quota.description"); - buttons.push(new Weave.NotificationButton( - this._stringBundle.GetStringFromName( - "error.sync.viewQuotaButton.label"), - this._stringBundle.GetStringFromName( - "error.sync.viewQuotaButton.accesskey"), - function() { gSyncUI.openQuotaDialog(); return true; } ) - ); - } - else if (Weave.Status.enforceBackoff) { - priority = Weave.Notifications.PRIORITY_INFO; - buttons.push(new Weave.NotificationButton( - this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"), - this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"), - function() { gSyncUI.openServerStatus(); return true; } - )); - } - else { - priority = Weave.Notifications.PRIORITY_INFO; - buttons.push(new Weave.NotificationButton( - this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"), - this._stringBundle.GetStringFromName("error.sync.tryAgainButton.accesskey"), - function() { gSyncUI.doSync(); return true; } - )); - } - - let notification = - new Weave.Notification(title, description, null, priority, buttons); - Weave.Notifications.replaceTitle(notification); - - if (this._wasDelayed && Weave.Status.sync != Weave.NO_SYNC_NODE_FOUND) { - title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title"); - Weave.Notifications.removeAll(title); - this._wasDelayed = false; - } - - this.updateUI(); - }, - - observe: function SUI_observe(subject, topic, data) { - if (this._unloaded) { - Cu.reportError("SyncUI observer called after unload: " + topic); - return; - } - - switch (topic) { - case "weave:service:sync:start": - this.onActivityStart(); - break; - case "weave:ui:sync:finish": - this.onSyncFinish(); - break; - case "weave:ui:sync:error": - this.onSyncError(); - break; - case "weave:service:sync:delayed": - this.onSyncDelay(); - break; - case "weave:service:quota:remaining": - this.onQuotaNotice(); - break; - case "weave:service:setup-complete": - this.onSetupComplete(); - break; - case "weave:service:login:start": - this.onActivityStart(); - break; - case "weave:service:login:finish": - this.onLoginFinish(); - break; - case "weave:ui:login:error": - this.onLoginError(); - break; - case "weave:service:logout:finish": - this.onLogout(); - break; - case "weave:service:start-over": - this.onStartOver(); - break; - case "weave:service:ready": - this.initUI(); - break; - case "weave:notification:added": - this.initNotifications(); - break; - case "weave:ui:clear-error": - this.clearError(); - break; - } - }, - - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIObserver, - Ci.nsISupportsWeakReference - ]) -}; - -XPCOMUtils.defineLazyGetter(gSyncUI, "_stringBundle", function() { - //XXXzpao these strings should probably be moved from /services to /browser... (bug 583381) - // but for now just make it work - return Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService). - createBundle("chrome://weave/locale/services/sync.properties"); -}); - diff --git a/browser/base/content/browser-tabPreviews.js b/browser/base/content/browser-tabPreviews.js deleted file mode 100644 index eaae78ba8..000000000 --- a/browser/base/content/browser-tabPreviews.js +++ /dev/null @@ -1,1051 +0,0 @@ -/* -#ifdef 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 - */ - -/** - * Tab previews utility, produces thumbnails - */ -var tabPreviews = { - aspectRatio: 0.5625, // 16:9 - - get width() { - delete this.width; - return this.width = Math.ceil(screen.availWidth / 5.75); - }, - - get height() { - delete this.height; - return this.height = Math.round(this.width * this.aspectRatio); - }, - - init: function tabPreviews_init() { - if (this._selectedTab) - return; - this._selectedTab = gBrowser.selectedTab; - - gBrowser.tabContainer.addEventListener("TabSelect", this, false); - gBrowser.tabContainer.addEventListener("SSTabRestored", this, false); - }, - - get: function tabPreviews_get(aTab) { - let uri = aTab.linkedBrowser.currentURI.spec; - - if (aTab.__thumbnail_lastURI && - aTab.__thumbnail_lastURI != uri) { - aTab.__thumbnail = null; - aTab.__thumbnail_lastURI = null; - } - - if (aTab.__thumbnail) - return aTab.__thumbnail; - - if (aTab.getAttribute("pending") == "true") { - let img = new Image; - img.src = PageThumbs.getThumbnailURL(uri); - return img; - } - - return this.capture(aTab, !aTab.hasAttribute("busy")); - }, - - capture: function tabPreviews_capture(aTab, aStore) { - var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); - thumbnail.mozOpaque = true; - thumbnail.height = this.height; - thumbnail.width = this.width; - - var ctx = thumbnail.getContext("2d"); - var win = aTab.linkedBrowser.contentWindow; - var snippetWidth = win.innerWidth * .6; - var scale = this.width / snippetWidth; - ctx.scale(scale, scale); - ctx.drawWindow(win, win.scrollX, win.scrollY, - snippetWidth, snippetWidth * this.aspectRatio, "rgb(255,255,255)"); - - if (aStore && - aTab.linkedBrowser /* bug 795608: the tab may got removed while drawing the thumbnail */) { - aTab.__thumbnail = thumbnail; - aTab.__thumbnail_lastURI = aTab.linkedBrowser.currentURI.spec; - } - - return thumbnail; - }, - - handleEvent: function tabPreviews_handleEvent(event) { - switch (event.type) { - case "TabSelect": - if (this._selectedTab && - this._selectedTab.parentNode && - !this._pendingUpdate) { - // Generate a thumbnail for the tab that was selected. - // The timeout keeps the UI snappy and prevents us from generating thumbnails - // for tabs that will be closed. During that timeout, don't generate other - // thumbnails in case multiple TabSelect events occur fast in succession. - this._pendingUpdate = true; - setTimeout(function (self, aTab) { - self._pendingUpdate = false; - if (aTab.parentNode && - !aTab.hasAttribute("busy") && - !aTab.hasAttribute("pending")) - self.capture(aTab, true); - }, 2000, this, this._selectedTab); - } - this._selectedTab = event.target; - break; - case "SSTabRestored": - this.capture(event.target, true); - break; - } - } -}; - -var tabPreviewPanelHelper = { - opening: function (host) { - host.panel.hidden = false; - - var handler = this._generateHandler(host); - host.panel.addEventListener("popupshown", handler, false); - host.panel.addEventListener("popuphiding", handler, false); - - host._prevFocus = document.commandDispatcher.focusedElement; - }, - _generateHandler: function (host) { - var self = this; - return function (event) { - if (event.target == host.panel) { - host.panel.removeEventListener(event.type, arguments.callee, false); - self["_" + event.type](host); - } - }; - }, - _popupshown: function (host) { - if ("setupGUI" in host) - host.setupGUI(); - }, - _popuphiding: function (host) { - if ("suspendGUI" in host) - host.suspendGUI(); - - if (host._prevFocus) { - Cc["@mozilla.org/focus-manager;1"] - .getService(Ci.nsIFocusManager) - .setFocus(host._prevFocus, Ci.nsIFocusManager.FLAG_NOSCROLL); - host._prevFocus = null; - } else - gBrowser.selectedBrowser.focus(); - - if (host.tabToSelect) { - gBrowser.selectedTab = host.tabToSelect; - host.tabToSelect = null; - } - } -}; - -/** - * Ctrl-Tab panel - */ -var ctrlTab = { - get panel () { - delete this.panel; - return this.panel = document.getElementById("ctrlTab-panel"); - }, - get showAllButton () { - delete this.showAllButton; - return this.showAllButton = document.getElementById("ctrlTab-showAll"); - }, - get previews () { - delete this.previews; - return this.previews = this.panel.getElementsByClassName("ctrlTab-preview"); - }, - get recentlyUsedLimit () { - delete this.recentlyUsedLimit; - return this.recentlyUsedLimit = gPrefService.getIntPref("browser.ctrlTab.recentlyUsedLimit"); - }, - get keys () { - var keys = {}; - ["close", "find", "selectAll"].forEach(function (key) { - keys[key] = document.getElementById("key_" + key) - .getAttribute("key") - .toLocaleLowerCase().charCodeAt(0); - }); - delete this.keys; - return this.keys = keys; - }, - _selectedIndex: 0, - get selected () this._selectedIndex < 0 ? - document.activeElement : - this.previews.item(this._selectedIndex), - get isOpen () this.panel.state == "open" || this.panel.state == "showing" || this._timer, - get tabCount () this.tabList.length, - get tabPreviewCount () Math.min(this.previews.length - 1, this.tabCount), - get canvasWidth () Math.min(tabPreviews.width, - Math.ceil(screen.availWidth * .85 / this.tabPreviewCount)), - get canvasHeight () Math.round(this.canvasWidth * tabPreviews.aspectRatio), - - get tabList () { - if (this._tabList) - return this._tabList; - - // Using gBrowser.tabs instead of gBrowser.visibleTabs, as the latter - // exlcudes closing tabs, breaking the following loop in case the the - // selected tab is closing. - let list = Array.filter(gBrowser.tabs, function (tab) !tab.hidden); - - // Rotate the list until the selected tab is first - while (!list[0].selected) - list.push(list.shift()); - - list = list.filter(function (tab) !tab.closing); - - if (this.recentlyUsedLimit != 0) { - let recentlyUsedTabs = []; - for (let tab of this._recentlyUsedTabs) { - if (!tab.hidden && !tab.closing) { - recentlyUsedTabs.push(tab); - if (this.recentlyUsedLimit > 0 && recentlyUsedTabs.length >= this.recentlyUsedLimit) - break; - } - } - for (let i = recentlyUsedTabs.length - 1; i >= 0; i--) { - list.splice(list.indexOf(recentlyUsedTabs[i]), 1); - list.unshift(recentlyUsedTabs[i]); - } - } - - return this._tabList = list; - }, - - init: function ctrlTab_init() { - if (!this._recentlyUsedTabs) { - tabPreviews.init(); - - this._recentlyUsedTabs = [gBrowser.selectedTab]; - this._init(true); - } - }, - - uninit: function ctrlTab_uninit() { - this._recentlyUsedTabs = null; - this._init(false); - }, - - prefName: "browser.ctrlTab.previews", - readPref: function ctrlTab_readPref() { - var enable = - gPrefService.getBoolPref(this.prefName) && - (!gPrefService.prefHasUserValue("browser.ctrlTab.disallowForScreenReaders") || - !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders")); - - if (enable) - this.init(); - else - this.uninit(); - }, - observe: function (aSubject, aTopic, aPrefName) { - this.readPref(); - }, - - updatePreviews: function ctrlTab_updatePreviews() { - for (let i = 0; i < this.previews.length; i++) - this.updatePreview(this.previews[i], this.tabList[i]); - - var showAllLabel = gNavigatorBundle.getString("ctrlTab.showAll.label"); - this.showAllButton.label = - PluralForm.get(this.tabCount, showAllLabel).replace("#1", this.tabCount); - }, - - updatePreview: function ctrlTab_updatePreview(aPreview, aTab) { - if (aPreview == this.showAllButton) - return; - - aPreview._tab = aTab; - - if (aPreview.firstChild) - aPreview.removeChild(aPreview.firstChild); - if (aTab) { - let canvasWidth = this.canvasWidth; - let canvasHeight = this.canvasHeight; - aPreview.appendChild(tabPreviews.get(aTab)); - aPreview.setAttribute("label", aTab.label); - aPreview.setAttribute("tooltiptext", aTab.label); - aPreview.setAttribute("crop", aTab.crop); - aPreview.setAttribute("canvaswidth", canvasWidth); - aPreview.setAttribute("canvasstyle", - "max-width:" + canvasWidth + "px;" + - "min-width:" + canvasWidth + "px;" + - "max-height:" + canvasHeight + "px;" + - "min-height:" + canvasHeight + "px;"); - if (aTab.image) - aPreview.setAttribute("image", aTab.image); - else - aPreview.removeAttribute("image"); - aPreview.hidden = false; - } else { - aPreview.hidden = true; - aPreview.removeAttribute("label"); - aPreview.removeAttribute("tooltiptext"); - aPreview.removeAttribute("image"); - } - }, - - advanceFocus: function ctrlTab_advanceFocus(aForward) { - let selectedIndex = Array.indexOf(this.previews, this.selected); - do { - selectedIndex += aForward ? 1 : -1; - if (selectedIndex < 0) - selectedIndex = this.previews.length - 1; - else if (selectedIndex >= this.previews.length) - selectedIndex = 0; - } while (this.previews[selectedIndex].hidden); - - if (this._selectedIndex == -1) { - // Focus is already in the panel. - this.previews[selectedIndex].focus(); - } else { - this._selectedIndex = selectedIndex; - } - - if (this._timer) { - clearTimeout(this._timer); - this._timer = null; - this._openPanel(); - } - }, - - _mouseOverFocus: function ctrlTab_mouseOverFocus(aPreview) { - if (this._trackMouseOver) - aPreview.focus(); - }, - - pick: function ctrlTab_pick(aPreview) { - if (!this.tabCount) - return; - - var select = (aPreview || this.selected); - - if (select == this.showAllButton) - this.showAllTabs(); - else - this.close(select._tab); - }, - - showAllTabs: function ctrlTab_showAllTabs(aPreview) { - this.close(); - document.getElementById("Browser:ShowAllTabs").doCommand(); - }, - - remove: function ctrlTab_remove(aPreview) { - if (aPreview._tab) - gBrowser.removeTab(aPreview._tab); - }, - - attachTab: function ctrlTab_attachTab(aTab, aPos) { - if (aPos == 0) - this._recentlyUsedTabs.unshift(aTab); - else if (aPos) - this._recentlyUsedTabs.splice(aPos, 0, aTab); - else - this._recentlyUsedTabs.push(aTab); - }, - detachTab: function ctrlTab_detachTab(aTab) { - var i = this._recentlyUsedTabs.indexOf(aTab); - if (i >= 0) - this._recentlyUsedTabs.splice(i, 1); - }, - - open: function ctrlTab_open() { - if (this.isOpen) - return; - - allTabs.close(); - - document.addEventListener("keyup", this, true); - - this.updatePreviews(); - this._selectedIndex = 1; - - // Add a slight delay before showing the UI, so that a quick - // "ctrl-tab" keypress just flips back to the MRU tab. - this._timer = setTimeout(function (self) { - self._timer = null; - self._openPanel(); - }, 200, this); - }, - - _openPanel: function ctrlTab_openPanel() { - tabPreviewPanelHelper.opening(this); - - this.panel.width = Math.min(screen.availWidth * .99, - this.canvasWidth * 1.25 * this.tabPreviewCount); - var estimateHeight = this.canvasHeight * 1.25 + 75; - this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this.panel.width) / 2, - screen.availTop + (screen.availHeight - estimateHeight) / 2, - false); - }, - - close: function ctrlTab_close(aTabToSelect) { - if (!this.isOpen) - return; - - if (this._timer) { - clearTimeout(this._timer); - this._timer = null; - this.suspendGUI(); - if (aTabToSelect) - gBrowser.selectedTab = aTabToSelect; - return; - } - - this.tabToSelect = aTabToSelect; - this.panel.hidePopup(); - }, - - setupGUI: function ctrlTab_setupGUI() { - this.selected.focus(); - this._selectedIndex = -1; - - // Track mouse movement after a brief delay so that the item that happens - // to be under the mouse pointer initially won't be selected unintentionally. - this._trackMouseOver = false; - setTimeout(function (self) { - if (self.isOpen) - self._trackMouseOver = true; - }, 0, this); - }, - - suspendGUI: function ctrlTab_suspendGUI() { - document.removeEventListener("keyup", this, true); - - Array.forEach(this.previews, function (preview) { - this.updatePreview(preview, null); - }, this); - - this._tabList = null; - }, - - onKeyPress: function ctrlTab_onKeyPress(event) { - var isOpen = this.isOpen; - - if (isOpen) { - event.preventDefault(); - event.stopPropagation(); - } - - switch (event.keyCode) { - case event.DOM_VK_TAB: - if (event.ctrlKey && !event.altKey && !event.metaKey) { - if (isOpen) { - this.advanceFocus(!event.shiftKey); - } else if (!event.shiftKey) { - event.preventDefault(); - event.stopPropagation(); - let tabs = gBrowser.visibleTabs; - if (tabs.length > 2) { - this.open(); - } else if (tabs.length == 2) { - let index = tabs[0].selected ? 1 : 0; - gBrowser.selectedTab = tabs[index]; - } - } - } - break; - default: - if (isOpen && event.ctrlKey) { - if (event.keyCode == event.DOM_VK_DELETE) { - this.remove(this.selected); - break; - } - switch (event.charCode) { - case this.keys.close: - this.remove(this.selected); - break; - case this.keys.find: - case this.keys.selectAll: - this.showAllTabs(); - break; - } - } - } - }, - - removeClosingTabFromUI: function ctrlTab_removeClosingTabFromUI(aTab) { - if (this.tabCount == 2) { - this.close(); - return; - } - - this._tabList = null; - this.updatePreviews(); - - if (this.selected.hidden) - this.advanceFocus(false); - if (this.selected == this.showAllButton) - this.advanceFocus(false); - - // If the current tab is removed, another tab can steal our focus. - if (aTab.selected && this.panel.state == "open") { - setTimeout(function (selected) { - selected.focus(); - }, 0, this.selected); - } - }, - - handleEvent: function ctrlTab_handleEvent(event) { - switch (event.type) { - case "TabAttrModified": - // tab attribute modified (e.g. label, crop, busy, image, selected) - for (let i = this.previews.length - 1; i >= 0; i--) { - if (this.previews[i]._tab && this.previews[i]._tab == event.target) { - this.updatePreview(this.previews[i], event.target); - break; - } - } - break; - case "TabSelect": - this.detachTab(event.target); - this.attachTab(event.target, 0); - break; - case "TabOpen": - this.attachTab(event.target, 1); - break; - case "TabClose": - this.detachTab(event.target); - if (this.isOpen) - this.removeClosingTabFromUI(event.target); - break; - case "keypress": - this.onKeyPress(event); - break; - case "keyup": - if (event.keyCode == event.DOM_VK_CONTROL) - this.pick(); - break; - } - }, - - _init: function ctrlTab__init(enable) { - var toggleEventListener = enable ? "addEventListener" : "removeEventListener"; - - var tabContainer = gBrowser.tabContainer; - tabContainer[toggleEventListener]("TabOpen", this, false); - tabContainer[toggleEventListener]("TabAttrModified", this, false); - tabContainer[toggleEventListener]("TabSelect", this, false); - tabContainer[toggleEventListener]("TabClose", this, false); - - document[toggleEventListener]("keypress", this, false); - gBrowser.mTabBox.handleCtrlTab = !enable; - - // If we're not running, hide the "Show All Tabs" menu item, - // as Shift+Ctrl+Tab will be handled by the tab bar. - document.getElementById("menu_showAllTabs").hidden = !enable; - - // Also disable the <key> to ensure Shift+Ctrl+Tab never triggers - // Show All Tabs. - var key_showAllTabs = document.getElementById("key_showAllTabs"); - if (enable) - key_showAllTabs.removeAttribute("disabled"); - else - key_showAllTabs.setAttribute("disabled", "true"); - } -}; - - -/** - * All Tabs panel - */ -var allTabs = { - get panel () { - delete this.panel; - return this.panel = document.getElementById("allTabs-panel"); - }, - get filterField () { - delete this.filterField; - return this.filterField = document.getElementById("allTabs-filter"); - }, - get container () { - delete this.container; - return this.container = document.getElementById("allTabs-container"); - }, - get tabCloseButton () { - delete this.tabCloseButton; - return this.tabCloseButton = document.getElementById("allTabs-tab-close-button"); - }, - get toolbarButton() document.getElementById("alltabs-button"), - get previews () this.container.getElementsByClassName("allTabs-preview"), - get isOpen () this.panel.state == "open" || this.panel.state == "showing", - - init: function allTabs_init() { - if (this._initiated) - return; - this._initiated = true; - - tabPreviews.init(); - - Array.forEach(gBrowser.tabs, function (tab) { - this._addPreview(tab); - }, this); - - gBrowser.tabContainer.addEventListener("TabOpen", this, false); - gBrowser.tabContainer.addEventListener("TabAttrModified", this, false); - gBrowser.tabContainer.addEventListener("TabMove", this, false); - gBrowser.tabContainer.addEventListener("TabClose", this, false); - }, - - uninit: function allTabs_uninit() { - if (!this._initiated) - return; - - gBrowser.tabContainer.removeEventListener("TabOpen", this, false); - gBrowser.tabContainer.removeEventListener("TabAttrModified", this, false); - gBrowser.tabContainer.removeEventListener("TabMove", this, false); - gBrowser.tabContainer.removeEventListener("TabClose", this, false); - - while (this.container.hasChildNodes()) - this.container.removeChild(this.container.firstChild); - - this._initiated = false; - }, - - prefName: "browser.allTabs.previews", - readPref: function allTabs_readPref() { - var allTabsButton = this.toolbarButton; - if (!allTabsButton) - return; - - if (gPrefService.getBoolPref(this.prefName)) { - allTabsButton.removeAttribute("type"); - allTabsButton.setAttribute("command", "Browser:ShowAllTabs"); - } else { - allTabsButton.setAttribute("type", "menu"); - allTabsButton.removeAttribute("command"); - allTabsButton.removeAttribute("oncommand"); - } - }, - observe: function (aSubject, aTopic, aPrefName) { - this.readPref(); - }, - - pick: function allTabs_pick(aPreview) { - if (!aPreview) - aPreview = this._firstVisiblePreview; - if (aPreview) - this.tabToSelect = aPreview._tab; - - this.close(); - }, - - closeTab: function allTabs_closeTab(event) { - this.filterField.focus(); - gBrowser.removeTab(event.currentTarget._targetPreview._tab); - }, - - filter: function allTabs_filter() { - if (this._currentFilter == this.filterField.value) - return; - - this._currentFilter = this.filterField.value; - - var filter = this._currentFilter.split(/\s+/g); - this._visible = 0; - Array.forEach(this.previews, function (preview) { - var tab = preview._tab; - var matches = 0; - if (filter.length && !tab.hidden) { - let tabstring = tab.linkedBrowser.currentURI.spec; - try { - tabstring = decodeURI(tabstring); - } catch (e) {} - tabstring = tab.label + " " + tab.label.toLocaleLowerCase() + " " + tabstring; - for (let i = 0; i < filter.length; i++) - matches += tabstring.includes(filter[i]); - } - if (matches < filter.length || tab.hidden) { - preview.hidden = true; - } - else { - this._visible++; - this._updatePreview(preview); - preview.hidden = false; - } - }, this); - - this._reflow(); - }, - - open: function allTabs_open() { - var allTabsButton = this.toolbarButton; - if (allTabsButton && - allTabsButton.getAttribute("type") == "menu") { - // Without setTimeout, the menupopup won't stay open when invoking - // "View > Show All Tabs" and the menu bar auto-hides. - setTimeout(function () { - allTabsButton.open = true; - }, 0); - return; - } - - this.init(); - - if (this.isOpen) - return; - - this._maxPanelHeight = Math.max(gBrowser.clientHeight, screen.availHeight / 2); - this._maxPanelWidth = Math.max(gBrowser.clientWidth, screen.availWidth / 2); - - this.filter(); - - tabPreviewPanelHelper.opening(this); - - this.panel.popupBoxObject.setConsumeRollupEvent(PopupBoxObject.ROLLUP_NO_CONSUME); - this.panel.openPopup(gBrowser, "overlap", 0, 0, false, true); - }, - - close: function allTabs_close() { - this.panel.hidePopup(); - }, - - setupGUI: function allTabs_setupGUI() { - this.filterField.focus(); - this.filterField.placeholder = this.filterField.tooltipText; - - this.panel.addEventListener("keypress", this, false); - this.panel.addEventListener("keypress", this, true); - this._browserCommandSet.addEventListener("command", this, false); - - // When the panel is open, a second click on the all tabs button should - // close the panel but not re-open it. - document.getElementById("Browser:ShowAllTabs").setAttribute("disabled", "true"); - }, - - suspendGUI: function allTabs_suspendGUI() { - this.filterField.placeholder = ""; - this.filterField.value = ""; - this._currentFilter = null; - - this._updateTabCloseButton(); - - this.panel.removeEventListener("keypress", this, false); - this.panel.removeEventListener("keypress", this, true); - this._browserCommandSet.removeEventListener("command", this, false); - - setTimeout(function () { - document.getElementById("Browser:ShowAllTabs").removeAttribute("disabled"); - }, 300); - }, - - handleEvent: function allTabs_handleEvent(event) { - if (event.type.startsWith("Tab")) { - var tab = event.target; - if (event.type != "TabOpen") - var preview = this._getPreview(tab); - } - switch (event.type) { - case "TabAttrModified": - // tab attribute modified (e.g. label, crop, busy, image) - if (!preview.hidden) - this._updatePreview(preview); - break; - case "TabOpen": - if (this.isOpen) - this.close(); - this._addPreview(tab); - break; - case "TabMove": - let siblingPreview = tab.nextSibling && - this._getPreview(tab.nextSibling); - if (siblingPreview) - siblingPreview.parentNode.insertBefore(preview, siblingPreview); - else - this.container.lastChild.appendChild(preview); - if (this.isOpen && !preview.hidden) { - this._reflow(); - preview.focus(); - } - break; - case "TabClose": - this._removePreview(preview); - break; - case "keypress": - this._onKeyPress(event); - break; - case "command": - if (event.target.id != "Browser:ShowAllTabs") { - // Close the panel when there's a browser command executing in the background. - this.close(); - } - break; - } - }, - - _visible: 0, - _currentFilter: null, - get _stack () { - delete this._stack; - return this._stack = document.getElementById("allTabs-stack"); - }, - get _browserCommandSet () { - delete this._browserCommandSet; - return this._browserCommandSet = document.getElementById("mainCommandSet"); - }, - get _previewLabelHeight () { - delete this._previewLabelHeight; - return this._previewLabelHeight = parseInt(getComputedStyle(this.previews[0], "").lineHeight); - }, - - get _visiblePreviews () - Array.filter(this.previews, function (preview) !preview.hidden), - - get _firstVisiblePreview () { - if (this._visible == 0) - return null; - var previews = this.previews; - for (let i = 0; i < previews.length; i++) { - if (!previews[i].hidden) - return previews[i]; - } - return null; - }, - - _reflow: function allTabs_reflow() { - this._updateTabCloseButton(); - - const CONTAINER_MAX_WIDTH = this._maxPanelWidth * .95; - const CONTAINER_MAX_HEIGHT = this._maxPanelHeight - 35; - // the size of the whole preview relative to the thumbnail - const REL_PREVIEW_THUMBNAIL = 1.2; - const REL_PREVIEW_HEIGHT_WIDTH = tabPreviews.height / tabPreviews.width; - const PREVIEW_MAX_WIDTH = tabPreviews.width * REL_PREVIEW_THUMBNAIL; - - var rows, previewHeight, previewWidth, outerHeight; - this._columns = Math.floor(CONTAINER_MAX_WIDTH / PREVIEW_MAX_WIDTH); - do { - rows = Math.ceil(this._visible / this._columns); - previewWidth = Math.min(PREVIEW_MAX_WIDTH, - Math.round(CONTAINER_MAX_WIDTH / this._columns)); - previewHeight = Math.round(previewWidth * REL_PREVIEW_HEIGHT_WIDTH); - outerHeight = previewHeight + this._previewLabelHeight; - } while (rows * outerHeight > CONTAINER_MAX_HEIGHT && ++this._columns); - - var outerWidth = previewWidth; - { - let innerWidth = Math.ceil(previewWidth / REL_PREVIEW_THUMBNAIL); - let innerHeight = Math.ceil(previewHeight / REL_PREVIEW_THUMBNAIL); - var canvasStyle = "max-width:" + innerWidth + "px;" + - "min-width:" + innerWidth + "px;" + - "max-height:" + innerHeight + "px;" + - "min-height:" + innerHeight + "px;"; - } - - var previews = Array.slice(this.previews); - - while (this.container.hasChildNodes()) - this.container.removeChild(this.container.firstChild); - for (let i = rows || 1; i > 0; i--) - this.container.appendChild(document.createElement("hbox")); - - var row = this.container.firstChild; - var colCount = 0; - previews.forEach(function (preview) { - if (!preview.hidden && - ++colCount > this._columns) { - row = row.nextSibling; - colCount = 1; - } - preview.setAttribute("minwidth", outerWidth); - preview.setAttribute("height", outerHeight); - preview.setAttribute("canvasstyle", canvasStyle); - preview.removeAttribute("closebuttonhover"); - row.appendChild(preview); - }, this); - - this._stack.width = this._maxPanelWidth; - this.container.width = Math.ceil(outerWidth * Math.min(this._columns, this._visible)); - this.container.left = Math.round((this._maxPanelWidth - this.container.width) / 2); - this.container.maxWidth = this._maxPanelWidth - this.container.left; - this.container.maxHeight = rows * outerHeight; - }, - - _addPreview: function allTabs_addPreview(aTab) { - var preview = document.createElement("button"); - preview.className = "allTabs-preview"; - preview._tab = aTab; - this.container.lastChild.appendChild(preview); - }, - - _removePreview: function allTabs_removePreview(aPreview) { - var updateUI = (this.isOpen && !aPreview.hidden); - aPreview._tab = null; - aPreview.parentNode.removeChild(aPreview); - if (updateUI) { - this._visible--; - this._reflow(); - this.filterField.focus(); - } - }, - - _getPreview: function allTabs_getPreview(aTab) { - var previews = this.previews; - for (let i = 0; i < previews.length; i++) - if (previews[i]._tab == aTab) - return previews[i]; - return null; - }, - - _updateTabCloseButton: function allTabs_updateTabCloseButton(event) { - if (event && event.target == this.tabCloseButton) - return; - - if (this.tabCloseButton._targetPreview) { - if (event && event.target == this.tabCloseButton._targetPreview) - return; - - this.tabCloseButton._targetPreview.removeAttribute("closebuttonhover"); - } - - if (event && - event.target.parentNode.parentNode == this.container && - (event.target._tab.previousSibling || event.target._tab.nextSibling)) { - let canvas = event.target.firstChild.getBoundingClientRect(); - let container = this.container.getBoundingClientRect(); - let tabCloseButton = this.tabCloseButton.getBoundingClientRect(); - let alignLeft = getComputedStyle(this.panel, "").direction == "rtl"; -#ifdef XP_MACOSX - alignLeft = !alignLeft; -#endif - this.tabCloseButton.left = canvas.left - - container.left + - parseInt(this.container.left) + - (alignLeft ? 0 : - canvas.width - tabCloseButton.width); - this.tabCloseButton.top = canvas.top - container.top; - this.tabCloseButton._targetPreview = event.target; - this.tabCloseButton.style.visibility = "visible"; - event.target.setAttribute("closebuttonhover", "true"); - } else { - this.tabCloseButton.style.visibility = "hidden"; - this.tabCloseButton.left = this.tabCloseButton.top = 0; - this.tabCloseButton._targetPreview = null; - } - }, - - _updatePreview: function allTabs_updatePreview(aPreview) { - aPreview.setAttribute("label", aPreview._tab.label); - aPreview.setAttribute("tooltiptext", aPreview._tab.label); - aPreview.setAttribute("crop", aPreview._tab.crop); - if (aPreview._tab.image) - aPreview.setAttribute("image", aPreview._tab.image); - else - aPreview.removeAttribute("image"); - - var thumbnail = tabPreviews.get(aPreview._tab); - if (aPreview.firstChild) { - if (aPreview.firstChild == thumbnail) - return; - aPreview.removeChild(aPreview.firstChild); - } - aPreview.appendChild(thumbnail); - }, - - _onKeyPress: function allTabs_onKeyPress(event) { - if (event.eventPhase == event.CAPTURING_PHASE) { - this._onCapturingKeyPress(event); - return; - } - - if (event.keyCode == event.DOM_VK_ESCAPE) { - this.close(); - event.preventDefault(); - event.stopPropagation(); - return; - } - - if (event.target == this.filterField) { - switch (event.keyCode) { - case event.DOM_VK_UP: - if (this._visible) { - let previews = this._visiblePreviews; - let columns = Math.min(previews.length, this._columns); - previews[Math.floor(previews.length / columns) * columns - 1].focus(); - event.preventDefault(); - event.stopPropagation(); - } - break; - case event.DOM_VK_DOWN: - if (this._visible) { - this._firstVisiblePreview.focus(); - event.preventDefault(); - event.stopPropagation(); - } - break; - } - } - }, - - _onCapturingKeyPress: function allTabs_onCapturingKeyPress(event) { - switch (event.keyCode) { - case event.DOM_VK_UP: - case event.DOM_VK_DOWN: - if (event.target != this.filterField) - this._advanceFocusVertically(event); - break; - case event.DOM_VK_RETURN: - if (event.target == this.filterField) { - this.filter(); - this.pick(); - event.preventDefault(); - event.stopPropagation(); - } - break; - } - }, - - _advanceFocusVertically: function allTabs_advanceFocusVertically(event) { - var preview = document.activeElement; - if (!preview || preview.parentNode.parentNode != this.container) - return; - - event.stopPropagation(); - - var up = (event.keyCode == event.DOM_VK_UP); - var previews = this._visiblePreviews; - - if (up && preview == previews[0]) { - this.filterField.focus(); - return; - } - - var i = previews.indexOf(preview); - var columns = Math.min(previews.length, this._columns); - var column = i % columns; - var row = Math.floor(i / columns); - - function newIndex() row * columns + column; - function outOfBounds() newIndex() >= previews.length; - - if (up) { - row--; - if (row < 0) { - let rows = Math.ceil(previews.length / columns); - row = rows - 1; - column--; - if (outOfBounds()) - row--; - } - } else { - row++; - if (outOfBounds()) { - if (column == columns - 1) { - this.filterField.focus(); - return; - } - row = 0; - column++; - } - } - previews[newIndex()].focus(); - } -}; diff --git a/browser/base/content/browser-tabPreviews.xml b/browser/base/content/browser-tabPreviews.xml deleted file mode 100644 index e957649e7..000000000 --- a/browser/base/content/browser-tabPreviews.xml +++ /dev/null @@ -1,75 +0,0 @@ -<?xml version="1.0"?> - -# -*- Mode: HTML -*- -# 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/. - -<bindings id="tabPreviews" - xmlns="http://www.mozilla.org/xbl" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:xbl="http://www.mozilla.org/xbl"> - <binding id="ctrlTab-preview" extends="chrome://global/content/bindings/button.xml#button-base"> - <content pack="center"> - <xul:stack> - <xul:vbox class="ctrlTab-preview-inner" align="center" pack="center" - xbl:inherits="width=canvaswidth"> - <xul:hbox class="tabPreview-canvas" xbl:inherits="style=canvasstyle"> - <children/> - </xul:hbox> - <xul:label xbl:inherits="value=label,crop" class="plain"/> - </xul:vbox> - <xul:hbox class="ctrlTab-favicon-container" xbl:inherits="hidden=noicon"> - <xul:image class="ctrlTab-favicon" xbl:inherits="src=image"/> - </xul:hbox> - </xul:stack> - </content> - <handlers> - <handler event="mouseover" action="ctrlTab._mouseOverFocus(this);"/> - <handler event="command" action="ctrlTab.pick(this);"/> - <handler event="click" button="1" action="ctrlTab.remove(this);"/> -#ifdef XP_MACOSX -# Control+click is a right click on OS X - <handler event="click" button="2" action="ctrlTab.pick(this);"/> -#endif - </handlers> - </binding> - - <binding id="allTabs-preview" extends="chrome://global/content/bindings/button.xml#button-base"> - <content pack="center" align="center"> - <xul:stack> - <xul:vbox class="allTabs-preview-inner" align="center" pack="center"> - <xul:hbox class="tabPreview-canvas" xbl:inherits="style=canvasstyle"> - <children/> - </xul:hbox> - <xul:label flex="1" xbl:inherits="value=label,crop" class="allTabs-preview-label plain"/> - </xul:vbox> - <xul:hbox class="allTabs-favicon-container"> - <xul:image class="allTabs-favicon" xbl:inherits="src=image"/> - </xul:hbox> - </xul:stack> - </content> - <handlers> - <handler event="command" action="allTabs.pick(this);"/> - <handler event="click" button="1" action="gBrowser.removeTab(this._tab);"/> - - <handler event="dragstart"><![CDATA[ - event.dataTransfer.mozSetDataAt("application/x-moz-node", this._tab, 0); - ]]></handler> - - <handler event="dragover"><![CDATA[ - let tab = event.dataTransfer.mozGetDataAt("application/x-moz-node", 0); - if (tab && tab.parentNode == gBrowser.tabContainer) - event.preventDefault(); - ]]></handler> - - <handler event="drop"><![CDATA[ - let tab = event.dataTransfer.mozGetDataAt("application/x-moz-node", 0); - if (tab && tab.parentNode == gBrowser.tabContainer) { - let newIndex = Array.indexOf(gBrowser.tabs, this._tab); - gBrowser.moveTabTo(tab, newIndex); - } - ]]></handler> - </handlers> - </binding> -</bindings> diff --git a/browser/base/content/browser-thumbnails.js b/browser/base/content/browser-thumbnails.js deleted file mode 100644 index dbe33e3ed..000000000 --- a/browser/base/content/browser-thumbnails.js +++ /dev/null @@ -1,198 +0,0 @@ -#ifdef 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 - -/** - * Keeps thumbnails of open web pages up-to-date. - */ -let gBrowserThumbnails = { - /** - * Pref that controls whether we can store SSL content on disk - */ - PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl", - - _captureDelayMS: 1000, - - /** - * Used to keep track of disk_cache_ssl preference - */ - _sslDiskCacheEnabled: null, - - /** - * Map of capture() timeouts assigned to their browsers. - */ - _timeouts: null, - - /** - * List of tab events we want to listen for. - */ - _tabEvents: ["TabClose", "TabSelect"], - - init: function Thumbnails_init() { - // Bug 863512 - Make page thumbnails work in electrolysis - if (gMultiProcessBrowser) - return; - - try { - if (Services.prefs.getBoolPref("browser.pagethumbnails.capturing_disabled")) - return; - } catch (e) {} - - PageThumbs.addExpirationFilter(this); - gBrowser.addTabsProgressListener(this); - Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false); - - this._sslDiskCacheEnabled = - Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL); - - this._tabEvents.forEach(function (aEvent) { - gBrowser.tabContainer.addEventListener(aEvent, this, false); - }, this); - - this._timeouts = new WeakMap(); - }, - - uninit: function Thumbnails_uninit() { - // Bug 863512 - Make page thumbnails work in electrolysis - if (gMultiProcessBrowser) - return; - - PageThumbs.removeExpirationFilter(this); - gBrowser.removeTabsProgressListener(this); - Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this); - - this._tabEvents.forEach(function (aEvent) { - gBrowser.tabContainer.removeEventListener(aEvent, this, false); - }, this); - }, - - handleEvent: function Thumbnails_handleEvent(aEvent) { - switch (aEvent.type) { - case "scroll": - let browser = aEvent.currentTarget; - if (this._timeouts.has(browser)) - this._delayedCapture(browser); - break; - case "TabSelect": - this._delayedCapture(aEvent.target.linkedBrowser); - break; - case "TabClose": { - this._clearTimeout(aEvent.target.linkedBrowser); - break; - } - } - }, - - observe: function Thumbnails_observe() { - this._sslDiskCacheEnabled = - Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL); - }, - - filterForThumbnailExpiration: - function Thumbnails_filterForThumbnailExpiration(aCallback) { - aCallback([browser.currentURI.spec for (browser of gBrowser.browsers)]); - }, - - /** - * State change progress listener for all tabs. - */ - onStateChange: function Thumbnails_onStateChange(aBrowser, aWebProgress, - aRequest, aStateFlags, aStatus) { - if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && - aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) - this._delayedCapture(aBrowser); - }, - - _capture: function Thumbnails_capture(aBrowser) { - if (this._shouldCapture(aBrowser)) - PageThumbs.captureAndStore(aBrowser); - }, - - _delayedCapture: function Thumbnails_delayedCapture(aBrowser) { - if (this._timeouts.has(aBrowser)) - clearTimeout(this._timeouts.get(aBrowser)); - else - aBrowser.addEventListener("scroll", this, true); - - let timeout = setTimeout(function () { - this._clearTimeout(aBrowser); - this._capture(aBrowser); - }.bind(this), this._captureDelayMS); - - this._timeouts.set(aBrowser, timeout); - }, - - _shouldCapture: function Thumbnails_shouldCapture(aBrowser) { - // Capture only if it's the currently selected tab. - if (aBrowser != gBrowser.selectedBrowser) - return false; - - // Don't capture in per-window private browsing mode. - if (PrivateBrowsingUtils.isWindowPrivate(window)) - return false; - - let doc = aBrowser.contentDocument; - - // FIXME Bug 720575 - Don't capture thumbnails for SVG or XML documents as - // that currently regresses Talos SVG tests. - if (doc instanceof SVGDocument || doc instanceof XMLDocument) - return false; - - // There's no point in taking screenshot of loading pages. - if (aBrowser.docShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE) - return false; - - // Don't take screenshots of about: pages. - if (aBrowser.currentURI.schemeIs("about")) - return false; - - let channel = aBrowser.docShell.currentDocumentChannel; - - // No valid document channel. We shouldn't take a screenshot. - if (!channel) - return false; - - // Don't take screenshots of internally redirecting about: pages. - // This includes error pages. - let uri = channel.originalURI; - if (uri.schemeIs("about")) - return false; - - let httpChannel; - try { - httpChannel = channel.QueryInterface(Ci.nsIHttpChannel); - } catch (e) { /* Not an HTTP channel. */ } - - if (httpChannel) { - // Continue only if we have a 2xx status code. - try { - if (Math.floor(httpChannel.responseStatus / 100) != 2) - return false; - } catch (e) { - // Can't get response information from the httpChannel - // because mResponseHead is not available. - return false; - } - - // Cache-Control: no-store. - if (httpChannel.isNoStoreResponse()) - return false; - - // Don't capture HTTPS pages unless the user explicitly enabled it. - if (uri.schemeIs("https") && !this._sslDiskCacheEnabled) - return false; - } - - return true; - }, - - _clearTimeout: function Thumbnails_clearTimeout(aBrowser) { - if (this._timeouts.has(aBrowser)) { - aBrowser.removeEventListener("scroll", this, false); - clearTimeout(this._timeouts.get(aBrowser)); - this._timeouts.delete(aBrowser); - } - } -}; diff --git a/browser/base/content/browser-title.css b/browser/base/content/browser-title.css deleted file mode 100644 index 66b5e6731..000000000 --- a/browser/base/content/browser-title.css +++ /dev/null @@ -1,204 +0,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/. */ - -#main-window::after { - content: attr(title); - line-height: 50px; - max-height: 50px; - overflow: -moz-hidden-unscrollable; - pointer-events: none; - position: fixed; - word-wrap: break-word; - -moz-hyphens: auto; - color: CaptionText; - font-weight: bold; - text-align: left; -} - -#main-window:-moz-window-inactive::after { - color: InactiveCaptionText; -} - -/* Win10 doesn't respond to inactive caption, so dim it instead */ -@media (-moz-os-version: windows-win10) { - #main-window:-moz-window-inactive::after { - opacity: 0.5; - } -} - -/* Hide in fullscreen/TiT mode */ -#main-window[inFullscreen="true"]::after, -#main-window[sizemode="maximized"][tabsintitlebar="true"]::after, -#main-window:not([chromemargin])::after { - opacity: 0 !important; -} - - -#main-window::after { - padding: 0 132px; /* AppMenu button/wincontrols width offset */ - left: 0; - right: 0; -} - -#main-window[privatebrowsingmode=temporary]::after { - padding: 0px 132px 0px 152px; /* AppMenu button width offset for PB mode */ -} - -#main-window[sizemode="normal"]::after { - left: -12px; - right: -12px; -} - -/* Lightweight Themes */ - -#main-window:-moz-lwtheme::after { - color: inherit; - text-shadow: inherit; -} - -/* Windows Classic theme */ - -@media all and (-moz-windows-classic) { - - #main-window::after { - top: -13px; - text-shadow: none !important; - background-position: 2px 18px; - } - -} - - -/* Windows Aero (Vista, non-glass 7/8) */ - -@media all and (-moz-windows-theme: aero) { - - #main-window::after { - top: -11px; - font-weight: normal; - text-shadow: none; - background-position: 2px 17px; - } - - #main-window[sizemode="maximized"]::after { - top: -7px; - } - -} - - -/* Windows Aero Glass */ - -@media (-moz-windows-glass) { - - #main-window::after { - top: -13px; - color: black; - text-shadow: rgba(255,255,255,.6) 7px -1px 12px, - rgba(255,255,255,.6) 6px -1px 13px, - rgba(255,255,255,.9) 5px -1px 14px, - rgba(255,255,255,.6) -7px -1px 12px, - rgba(255,255,255,.6) -6px -1px 13px, - rgba(255,255,255,.9) -5px -1px 14px; - z-index: -99999; - background-position: 2px 18px; - font-weight: bold; - } - - #main-window[sizemode="maximized"]::after { - top: -7px; - } - - #main-window:-moz-window-inactive::after { - opacity: .9; - color: black; - text-shadow: rgba(255,255,255,.7) 7px -1px 12px, - rgba(255,255,255,.5) 6px -1px 13px, - rgba(255,255,255,.5) 5px -1px 14px, - rgba(255,255,255,.7) -7px -1px 12px, - rgba(255,255,255,.5) -6px -1px 13px, - rgba(255,255,255,.5) -5px -1px 14px; - } - -} - - -/* Generic other themes */ - -@media all and (-moz-windows-theme: generic) { - - #main-window::after { - font-family: trebuchet MS; - font-size: 13px; - text-shadow: 1px 1px rgba(0, 0, 0, .2); - top: -9px; - background-position: 2px 16px; - } - - #main-window:-moz-window-inactive::after { - text-shadow: none; - } - -} - - -/* Compositor style for Win 8/10 */ - -@media all and (-moz-windows-compositor) { - @media not all and (-moz-windows-glass) { - - #main-window::after { - background-position: 4px 17px; - top: -13px; - } - - @media (-moz-os-version: windows-win8) { - #main-window::after { - font-size: 15px; - text-align: center; - } - - #main-window[darkwindowframe="true"]:not(:-moz-window-inactive):not(:-moz-lwtheme)::after { - /* Dark window frame/accent color on Win 8 */ - color: white; - } - } - - @media (-moz-os-version: windows-win10) { - #main-window::after { - text-align: left; - } - - @media (-moz-windows-accent-color-applies: 0) { - #main-window:not(:-moz-window-inactive):not(:-moz-lwtheme)::after { - /* Default Windows 10 styling is white - apply black text styling */ - color: black; - } - } - - @media (-moz-windows-accent-color-applies) { - #main-window:not(:-moz-window-inactive):not(:-moz-lwtheme)::after { - /* Accent color is applied - use the associated text styling */ - color: -moz-win-accentcolortext; - } - } - } - - #main-window[sizemode="maximized"]::after { - top: -5px; - } - } - -} - - -/* Hide for small windows */ - -@media not all and (min-width: 320px) { - - #main-window::after { - opacity: 0 !important; - } - -}
\ No newline at end of file diff --git a/browser/base/content/browser-webrtcUI.js b/browser/base/content/browser-webrtcUI.js deleted file mode 100644 index a6c9008ca..000000000 --- a/browser/base/content/browser-webrtcUI.js +++ /dev/null @@ -1,55 +0,0 @@ -# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -# 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/. - -let WebrtcIndicator = { - init: function () { - let temp = {}; - Cu.import("resource:///modules/webrtcUI.jsm", temp); - this.UIModule = temp.webrtcUI; - - this.updateButton(); - }, - - get button() { - delete this.button; - return this.button = document.getElementById("webrtc-status-button"); - }, - - updateButton: function () { - this.button.hidden = !this.UIModule.showGlobalIndicator; - }, - - fillPopup: function (aPopup) { - this._menuitemData = new WeakMap; - for (let streamData of this.UIModule.activeStreams) { - let menuitem = document.createElement("menuitem"); - menuitem.setAttribute("label", streamData.uri); - menuitem.setAttribute("tooltiptext", streamData.uri); - - this._menuitemData.set(menuitem, streamData); - - aPopup.appendChild(menuitem); - } - }, - - clearPopup: function (aPopup) { - while (aPopup.lastChild) - aPopup.removeChild(aPopup.lastChild); - }, - - menuCommand: function (aMenuitem) { - let streamData = this._menuitemData.get(aMenuitem); - if (!streamData) - return; - - let browserWindow = streamData.browser.ownerDocument.defaultView; - if (streamData.tab) { - browserWindow.gBrowser.selectedTab = streamData.tab; - } else { - streamData.browser.focus(); - } - browserWindow.focus(); - } -} diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css deleted file mode 100644 index 2c8ba3e69..000000000 --- a/browser/base/content/browser.css +++ /dev/null @@ -1,693 +0,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/. */ - -@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); -@namespace html url("http://www.w3.org/1999/xhtml"); - -searchbar { - -moz-binding: url("chrome://browser/content/search/search.xml#searchbar"); -} - -browser[remote="true"] { - -moz-binding: url("chrome://global/content/bindings/remote-browser.xml#remote-browser"); -} - -tabbrowser { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser"); -} - -.tabbrowser-tabs { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs"); -} - -#tabbrowser-tabs:not([overflow="true"]) ~ #alltabs-button, -#tabbrowser-tabs:not([overflow="true"]) + #new-tab-button, -#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button, -#TabsToolbar[currentset]:not([currentset*="tabbrowser-tabs,new-tab-button"]) > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button, -#TabsToolbar[customizing="true"] > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button { - visibility: collapse; -} - -#alltabs-button { /* Pale Moon: Always show this button! (less jumpy UI) */ - visibility: visible !important; -} - -#tabbrowser-tabs:not([overflow="true"])[using-closing-tabs-spacer] ~ #alltabs-button { - visibility: hidden; /* temporary space to keep a tab's close button under the cursor */ -} - -.tabbrowser-tab { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab"); -} - -.tabbrowser-tab:not([pinned]) { - -moz-box-flex: 100; - max-width: 250px; - min-width: 100px; - width: 0; - transition: min-width 175ms ease-out, - max-width 200ms ease-out, - opacity 80ms ease-out 20ms /* hide the tab for the first 20ms of the max-width transition */; -} - -.tabbrowser-tab:not([pinned]):not([fadein]) { - max-width: 0.1px; - min-width: 0.1px; - opacity: 0 !important; - transition: min-width 175ms ease-out, - max-width 200ms ease-out, - opacity 80ms ease-out 180ms /* hide the tab for the last 20ms of the max-width transition */; -} - -.tab-throbber:not([fadein]):not([pinned]), -.tab-label:not([fadein]):not([pinned]), -.tab-icon-image:not([fadein]):not([pinned]), -.tab-close-button:not([fadein]):not([pinned]) { - display: none; -} - -.tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] { - position: fixed !important; - display: block; /* position:fixed already does this (bug 579776), but let's be explicit */ -} - -.tabbrowser-tabs[movingtab] > .tabbrowser-tab[selected] { - position: relative; - z-index: 2; - pointer-events: none; /* avoid blocking dragover events on scroll buttons */ -} - -.tabbrowser-tabs[movingtab] > .tabbrowser-tab[fadein]:not([selected]) { - transition: transform 200ms ease-out; -} - -#alltabs-popup { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup"); -} - -toolbar[printpreview="true"] { - -moz-binding: url("chrome://global/content/printPreviewBindings.xml#printpreviewtoolbar"); -} - -#toolbar-menubar { - -moz-box-ordinal-group: 5; -} - -#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) { - -moz-box-ordinal-group: 50; -} - -#TabsToolbar { - -moz-box-ordinal-group: 100; -} - -#TabsToolbar[tabsontop="true"] { - -moz-box-ordinal-group: 10; -} - -%ifdef CAN_DRAW_IN_TITLEBAR -#main-window[inFullscreen] > #titlebar, -#main-window[inFullscreen] .titlebar-placeholder, -#main-window:not([tabsintitlebar]) .titlebar-placeholder { - display: none; -} - -#titlebar { - -moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox"); -} - -#titlebar-spacer { - pointer-events: none; -} - -#main-window[tabsintitlebar] #appmenu-button-container, -#main-window[tabsintitlebar] #titlebar-buttonbox { - position: relative; -} -%endif - -#main-window[inDOMFullscreen] #sidebar-box, -#main-window[inDOMFullscreen] #sidebar-splitter { - visibility: collapse; -} - -.bookmarks-toolbar-customize, -#wrapper-personal-bookmarks > #personal-bookmarks > #PlacesToolbar > hbox > #PlacesToolbarItems { - display: none; -} - -#wrapper-personal-bookmarks[place="toolbar"] > #personal-bookmarks > #PlacesToolbar > .bookmarks-toolbar-customize { - display: -moz-box; -} - -#main-window[disablechrome] #navigator-toolbox[tabsontop="true"] > toolbar:not(#toolbar-menubar):not(#TabsToolbar) { - visibility: collapse; -} - -#wrapper-urlbar-container #urlbar-container > #urlbar > toolbarbutton, -#urlbar-container:not([combined]) > #urlbar > toolbarbutton, -#urlbar-container[combined] + #reload-button + #stop-button, -#urlbar-container[combined] + #reload-button, -toolbar:not([mode="icons"]) > #urlbar-container > #urlbar > toolbarbutton, -toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button:not([displaystop]) + #urlbar-stop-button, -toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button[displaystop], -toolbar[mode="icons"] > #reload-button:not([displaystop]) + #stop-button, -toolbar[mode="icons"] > #reload-button[displaystop] { - visibility: collapse; -} - -#feed-button > .toolbarbutton-menu-dropmarker { - display: none; -} - -#feed-menu > .feed-menuitem:-moz-locale-dir(rtl) { - direction: rtl; -} - -#main-window:-moz-lwtheme { - background-repeat: no-repeat; - background-position: top right; -} - -%ifdef XP_MACOSX -#main-window[inFullscreen="true"] { - padding-top: 0; /* override drawintitlebar="true" */ -} -%endif - -#browser-bottombox[lwthemefooter="true"] { - background-repeat: no-repeat; - background-position: bottom left; -} - -splitmenu { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#splitmenu"); -} - -.splitmenu-menuitem { - -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem"); - list-style-image: inherit; - -moz-image-region: inherit; -} - -.splitmenu-menuitem[iconic="true"] { - -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic"); -} - -.splitmenu-menu > .menu-text, -:-moz-any(.splitmenu-menu, .splitmenu-menuitem) > .menu-accel-container, -#appmenu-editmenu > .menu-text, -#appmenu-editmenu > .menu-accel-container { - display: none; -} - -.menuitem-tooltip { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-tooltip"); -} - -.menuitem-iconic-tooltip, -.menuitem-tooltip[type="checkbox"], -.menuitem-tooltip[type="radio"] { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-iconic-tooltip"); -} - -%ifdef MENUBAR_CAN_AUTOHIDE -%ifndef CAN_DRAW_IN_TITLEBAR -#appmenu-toolbar-button > .toolbarbutton-text { - display: -moz-box; -} -%endif - -#appmenu_offlineModeRecovery:not([checked=true]) { - display: none; -} -%endif - -/* Hide menu elements intended for keyboard access support */ -#main-menubar[openedwithkey=false] .show-only-for-keyboard { - display: none; -} - -/* ::::: location bar ::::: */ -#urlbar { - -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar); -} - -.ac-url-text:-moz-locale-dir(rtl), -.ac-title:-moz-locale-dir(rtl) > description { - direction: ltr !important; -} - -/* For results that are actions, their description text is shown instead of - the URL - this needs to follow the locale's direction, unlike URLs. */ -panel:not([noactions]) > richlistbox > richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box { - direction: rtl; -} - -panel[noactions] > richlistbox > richlistitem[type~="action"] > .ac-url-box > .ac-url > .ac-action-text, -panel[noactions] > richlistbox > richlistitem[type~="action"] > .ac-url-box > .ac-action-icon { - visibility: collapse; -} - -panel[noactions] > richlistbox > richlistitem[type~="action"] > .ac-url-box > .ac-url > .ac-url-text { - visibility: visible; -} - -#urlbar:not([actiontype]) > #urlbar-display-box { - display: none; -} - -#wrapper-urlbar-container > #urlbar-container > #urlbar { - -moz-user-input: disabled; - cursor: -moz-grab; -} - -#PopupAutoComplete { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup"); -} - -#PopupAutoCompleteRichResult { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup"); -} - -/* Pale Moon: Address bar: Feeds */ -#ub-feed-button > .button-box > .box-inherit > .button-text, -#ub-feed-button > .button-box > .button-menu-dropmarker { - display: none; -} - -#ub-feed-menu > .feed-menuitem:-moz-locale-dir(rtl) { - direction: rtl; -} - - -#urlbar-container[combined] > #urlbar > #urlbar-icons > #go-button, -#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button), -#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button, -#urlbar[pageproxystate="invalid"][focused="true"] > #urlbar-go-button ~ toolbarbutton, -#urlbar[pageproxystate="valid"] > #urlbar-go-button, -#urlbar:not([focused="true"]) > #urlbar-go-button { - visibility: collapse; -} - -#urlbar[pageproxystate="invalid"] > #identity-box > #identity-icon-labels { - visibility: collapse; -} - -#urlbar[pageproxystate="invalid"] > #identity-box { - pointer-events: none; -} - -#identity-icon-labels { - max-width: 18em; -} - -#identity-icon-country-label { - direction: ltr; -} - -#identity-box.verifiedIdentity > #identity-icon-labels > #identity-icon-label { - -moz-margin-end: 0.25em !important; -} - -#wrapper-search-container > #search-container > #searchbar > .searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input { - visibility: hidden; -} - -/* ::::: Unified Back-/Forward Button ::::: */ -#back-button > .toolbarbutton-menu-dropmarker, -#forward-button > .toolbarbutton-menu-dropmarker { - display: none; -} -.unified-nav-current { - font-weight: bold; -} - -toolbarbutton.bookmark-item { - max-width: 13em; -} - -%ifdef MENUBAR_CAN_AUTOHIDE -#toolbar-menubar:not([autohide="true"]) ~ toolbar > #bookmarks-menu-button, -#toolbar-menubar:not([autohide="true"]) > #bookmarks-menu-button, -#toolbar-menubar:not([autohide="true"]) ~ toolbar > #history-menu-button, -#toolbar-menubar:not([autohide="true"]) > #history-menu-button { - display: none; -} -%endif - -#editBMPanel_tagsSelector { - /* override default listbox width from xul.css */ - width: auto; -} - -menupopup[emptyplacesresult="true"] > .hide-if-empty-places-result { - display: none; -} - -menuitem.spell-suggestion { - font-weight: bold; -} - -#sidebar-header > .tabs-closebutton { - -moz-user-focus: normal; -} - -/* apply Fitts' law to the notification bar's close button */ -window[sizemode="maximized"] #content .notification-inner { - border-right: 0px !important; -} - -/* Hide extension toolbars that neglected to set the proper class */ -window[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar), -window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(#nav-bar):not(#TabsToolbar):not(#print-preview-toolbar):not(.chromeclass-menubar) { - display: none; -} - -#navigator-toolbox , -#status-bar , -#mainPopupSet { - min-width: 1px; -} - -%ifdef MOZ_SERVICES_SYNC -/* Sync notification UI */ -#sync-notifications { - -moz-binding: url("chrome://browser/content/sync/notification.xml#notificationbox"); - overflow-y: visible !important; -} - -#sync-notifications notification { - -moz-binding: url("chrome://browser/content/sync/notification.xml#notification"); -} -%endif - -/* History Swipe Animation */ - -#historySwipeAnimationContainer { - overflow: hidden; -} - -#historySwipeAnimationPreviousPage, -#historySwipeAnimationCurrentPage, -#historySwipeAnimationNextPage { - background: none top left no-repeat white; -} - -#historySwipeAnimationPreviousPage { - background-image: -moz-element(#historySwipeAnimationPreviousPageSnapshot); -} - -#historySwipeAnimationCurrentPage { - background-image: -moz-element(#historySwipeAnimationCurrentPageSnapshot); -} - -#historySwipeAnimationNextPage { - background-image: -moz-element(#historySwipeAnimationNextPageSnapshot); -} - -/* Identity UI */ -#identity-popup-content-box.unknownIdentity > #identity-popup-connectedToLabel , -#identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel , -#identity-popup-content-box.unknownIdentity > #identity-popup-content-host , -#identity-popup-content-box.unknownIdentity > #identity-popup-content-owner , -#identity-popup-content-box.verifiedIdentity > #identity-popup-connectedToLabel2 , -#identity-popup-content-box.verifiedDomain > #identity-popup-connectedToLabel2 { - display: none; -} - -/* Full Screen UI */ - -#fullscr-toggler { - height: 1px; - background: black; -} - -#full-screen-warning-container { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 2147483647 !important; -} - -#full-screen-warning-container[fade-warning-out] { - transition-property: opacity !important; - transition-duration: 500ms !important; - 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 { - word-wrap: break-word; - /* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */ - min-width: 1px; -} - -#nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-icon { - display: -moz-box; -} - -#nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text { - display: none; -} - -/* ::::: Keyboard UI Panel ::::: */ -.KUI-panel-closebutton { - -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image"); -} - -:-moz-any(.ctrlTab-preview, .allTabs-preview) > html|img, -:-moz-any(.ctrlTab-preview, .allTabs-preview) > html|canvas { - min-width: inherit; - max-width: inherit; - min-height: inherit; - max-height: inherit; -} - -.ctrlTab-favicon-container, -.allTabs-favicon-container { - -moz-box-align: start; -%ifdef XP_MACOSX - -moz-box-pack: end; -%else - -moz-box-pack: start; -%endif -} - -.ctrlTab-favicon, -.allTabs-favicon { - width: 16px; - height: 16px; -} - -/* ::::: Ctrl-Tab Panel ::::: */ -.ctrlTab-preview { - -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#ctrlTab-preview"); -} - -/* ::::: All Tabs Panel ::::: */ -.allTabs-preview { - -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#allTabs-preview"); -} - -#allTabs-tab-close-button { - -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image"); - margin: 0; -} - - -/* notification anchors should only be visible when their associated - notifications are */ -.notification-anchor-icon { - -moz-user-focus: normal; -} - -.notification-anchor-icon:not([showing]) { - display: none; -} - -/* This was added with the identity toolkit, does it have any other purpose? */ -#notification-popup .text-link.custom-link { - -moz-binding: url("chrome://global/content/bindings/text.xml#text-label"); - text-decoration: none; -} - -#invalid-form-popup > description { - max-width: 280px; -} - -.form-validation-anchor { - /* should occupy space but not be visible */ - opacity: 0; - visibility: hidden; - pointer-events: none; -} - -#addon-progress-notification { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification"); -} - -#click-to-play-plugins-notification { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification"); -} - -.plugin-popupnotification-centeritem { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#plugin-popupnotification-center-item"); -} - -/* override hidden="true" for the status bar compatibility shim - in case it was persisted for the real status bar */ -#status-bar { - display: -moz-box; -} - -/* Remove the resizer from the statusbar compatibility shim */ -#status-bar[hideresizer] > .statusbar-resizerpanel { - display: none; -} - -browser[tabmodalPromptShowing] { - -moz-user-focus: none !important; -} - -/* Status panel */ - -statuspanel { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#statuspanel"); - position: fixed; - margin-top: -3em; - left: 0; - max-width: calc(100% - 5px); - pointer-events: none; -} - -statuspanel:-moz-locale-dir(ltr)[mirror], -statuspanel:-moz-locale-dir(rtl):not([mirror]) { - left: auto; - right: 0; -} - -statuspanel[sizelimit] { - max-width: 50%; -} - -statuspanel[type=status] { - min-width: 23em; -} - -@media all and (max-width: 800px) { - statuspanel[type=status] { - min-width: 33%; - } -} - -statuspanel[type=overLink] { - transition: opacity 120ms ease-out; - direction: ltr; -} - -statuspanel[inactive] { - transition: none; - opacity: 0; -} - -statuspanel[inactive][previoustype=overLink] { - transition: opacity 200ms ease-out; -} - -.statuspanel-inner { - height: 3em; - width: 100%; - -moz-box-align: end; -} - -.panel-inner-arrowcontentfooter[footertype="promobox"] { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#promobox"); -} - -/* highlighter */ -%include highlighter.css - -/* gcli */ - -html|*#gcli-tooltip-frame, -html|*#gcli-output-frame, -#gcli-output, -#gcli-tooltip { - overflow-x: hidden; -} - -.gclitoolbar-input-node, -.gclitoolbar-complete-node { - direction: ltr; -} - -#developer-toolbar-toolbox-button[error-count] > .toolbarbutton-icon { - display: none; -} - -#developer-toolbar-toolbox-button[error-count]:before { - content: attr(error-count); - display: -moz-box; - -moz-box-pack: center; -} - -/* Responsive Mode */ - -.browserContainer[responsivemode] { - overflow: auto; -} - -.devtools-responsiveui-toolbar:-moz-locale-dir(rtl) { - -moz-box-pack: end; -} - -.browserStack[responsivemode] { - transition-duration: 200ms; - transition-timing-function: linear; -} - -.browserStack[responsivemode] { - transition-property: min-width, max-width, min-height, max-height; -} - -.browserStack[responsivemode][notransition] { - transition: none; -} - -.toolbarbutton-badge[badge]:not([badge=""])::after { - content: attr(badge); -} - -toolbarbutton[type="badged"] { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#toolbarbutton-badged"); -} - -/* Strict icon size for PMkit 'ui/button' */ -toolbarbutton[pmkit-button="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon { - width: 16px; - height: 16px; -} - -/* Remove white bar at the bottom of the screen when watching HTML5 video in fullscreen */ -#main-window[inFullscreen] #global-notificationbox, -#main-window[inFullscreen] #high-priority-global-notificationbox { - visibility: collapse; -} diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js deleted file mode 100644 index 5a832c077..000000000 --- a/browser/base/content/browser.js +++ /dev/null @@ -1,7217 +0,0 @@ -# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -# 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/. - -let Ci = Components.interfaces; -let Cu = Components.utils; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource:///modules/RecentWindow.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu", - "resource:///modules/CharsetMenu.jsm"); - -const nsIWebNavigation = Ci.nsIWebNavigation; -const gToolbarInfoSeparators = ["|", "-"]; - -var gLastBrowserCharset = null; -var gPrevCharset = null; -var gProxyFavIcon = null; -var gLastValidURLStr = ""; -var gInPrintPreviewMode = false; -var gContextMenu = null; // nsContextMenu instance -var gMultiProcessBrowser = false; - -#ifndef XP_MACOSX -var gEditUIVisible = true; -#endif - -[ - ["gBrowser", "content"], - ["gNavToolbox", "navigator-toolbox"], - ["gURLBar", "urlbar"], - ["gNavigatorBundle", "bundle_browser"] -].forEach(function (elementGlobal) { - var [name, id] = elementGlobal; - window.__defineGetter__(name, function () { - var element = document.getElementById(id); - if (!element) - return null; - delete window[name]; - return window[name] = element; - }); - window.__defineSetter__(name, function (val) { - delete window[name]; - return window[name] = val; - }); -}); - -// Smart getter for the findbar. If you don't wish to force the creation of -// the findbar, check gFindBarInitialized first. -var gFindBarInitialized = false; -XPCOMUtils.defineLazyGetter(window, "gFindBar", function() { - let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let findbar = document.createElementNS(XULNS, "findbar"); - findbar.id = "FindToolbar"; - - let browserBottomBox = document.getElementById("browser-bottombox"); - browserBottomBox.insertBefore(findbar, browserBottomBox.firstChild); - - // Force a style flush to ensure that our binding is attached. - findbar.clientTop; - findbar.browser = gBrowser; - window.gFindBarInitialized = true; - return findbar; -}); - -XPCOMUtils.defineLazyGetter(this, "gPrefService", function() { - return Services.prefs; -}); - -this.__defineGetter__("AddonManager", function() { - let tmp = {}; - Cu.import("resource://gre/modules/AddonManager.jsm", tmp); - return this.AddonManager = tmp.AddonManager; -}); -this.__defineSetter__("AddonManager", function (val) { - delete this.AddonManager; - 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, "AboutHomeUtils", - "resource:///modules/AboutHomeUtils.jsm"); - -#ifdef MOZ_SERVICES_SYNC -XPCOMUtils.defineLazyModuleGetter(this, "Weave", - "resource://services-sync/main.js"); -#endif - -XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () { - let tmp = {}; - Cu.import("resource:///modules/PopupNotifications.jsm", tmp); - try { - return new tmp.PopupNotifications(gBrowser, - document.getElementById("notification-popup"), - document.getElementById("notification-popup-box")); - } catch (ex) { - Cu.reportError(ex); - return null; - } -}); - -#ifdef MOZ_DEVTOOLS -XPCOMUtils.defineLazyGetter(this, "DeveloperToolbar", function() { - let tmp = {}; - Cu.import("resource://gre/modules/devtools/DeveloperToolbar.jsm", tmp); - return new tmp.DeveloperToolbar(window, document.getElementById("developer-toolbar")); -}); - -XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function() { - let tmp = {}; - Cu.import("resource://gre/modules/devtools/ToolboxProcess.jsm", tmp); - return tmp.BrowserToolboxProcess; -}); -#endif - -XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs", - "resource://gre/modules/PageThumbs.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "gBrowserNewTabPreloader", - "resource:///modules/BrowserNewTabPreloader.jsm", "BrowserNewTabPreloader"); - -XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", - "resource://gre/modules/PrivateBrowsingUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "FormValidationHandler", - "resource:///modules/FormValidationHandler.jsm"); - -let gInitialPages = [ - "about:blank", - "about:newtab", - "about:home", - "about:privatebrowsing", - "about:sessionrestore", - "about:logopage" -]; - -#include browser-addons.js -#include browser-feeds.js -#include browser-fullScreen.js -#include browser-fullZoom.js -#include browser-places.js -#include browser-plugins.js -#include browser-tabPreviews.js -#include browser-thumbnails.js -#include browser-webrtcUI.js -#include browser-gestureSupport.js - -#ifdef MOZ_SERVICES_SYNC -#include browser-syncui.js -#endif - -XPCOMUtils.defineLazyGetter(this, "Win7Features", function () { -#ifdef XP_WIN - const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1"; - if (WINTASKBAR_CONTRACTID in Cc && - Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) { - let AeroPeek = Cu.import("resource:///modules/WindowsPreviewPerTab.jsm", {}).AeroPeek; - return { - onOpenWindow: function () { - AeroPeek.onOpenWindow(window); - }, - onCloseWindow: function () { - AeroPeek.onCloseWindow(window); - } - }; - } -#endif - return null; -}); - -XPCOMUtils.defineLazyGetter(this, "PageMenu", function() { - let tmp = {}; - Cu.import("resource:///modules/PageMenu.jsm", tmp); - return new tmp.PageMenu(); -}); - -/** -* We can avoid adding multiple load event listeners and save some time by adding -* one listener that calls all real handlers. -*/ -function pageShowEventHandlers(persisted) { - charsetLoadListener(); - XULBrowserWindow.asyncUpdateUI(); - - // The PluginClickToPlay events are not fired when navigating using the - // BF cache. |persisted| is true when the page is loaded from the - // BF cache, so this code reshows the notification if necessary. - if (persisted) - gPluginHandler.reshowClickToPlayNotification(); -} - -function UpdateBackForwardCommands(aWebNavigation) { - var backBroadcaster = document.getElementById("Browser:Back"); - var forwardBroadcaster = document.getElementById("Browser:Forward"); - - // Avoid setting attributes on broadcasters if the value hasn't changed! - // Remember, guys, setting attributes on elements is expensive! They - // get inherited into anonymous content, broadcast to other widgets, etc.! - // Don't do it if the value hasn't changed! - dwh - - var backDisabled = backBroadcaster.hasAttribute("disabled"); - var forwardDisabled = forwardBroadcaster.hasAttribute("disabled"); - if (backDisabled == aWebNavigation.canGoBack) { - if (backDisabled) - backBroadcaster.removeAttribute("disabled"); - else - backBroadcaster.setAttribute("disabled", true); - } - - if (forwardDisabled == aWebNavigation.canGoForward) { - if (forwardDisabled) - forwardBroadcaster.removeAttribute("disabled"); - else - forwardBroadcaster.setAttribute("disabled", true); - } -} - -/** - * Click-and-Hold implementation for the Back and Forward buttons - * XXXmano: should this live in toolbarbutton.xml? - */ -function SetClickAndHoldHandlers() { - var timer; - - function openMenu(aButton) { - cancelHold(aButton); - aButton.firstChild.hidden = false; - aButton.open = true; - } - - function mousedownHandler(aEvent) { - if (aEvent.button != 0 || - aEvent.currentTarget.open || - aEvent.currentTarget.disabled) - return; - - // Prevent the menupopup from opening immediately - aEvent.currentTarget.firstChild.hidden = true; - - aEvent.currentTarget.addEventListener("mouseout", mouseoutHandler, false); - aEvent.currentTarget.addEventListener("mouseup", mouseupHandler, false); - timer = setTimeout(openMenu, 500, aEvent.currentTarget); - } - - function mouseoutHandler(aEvent) { - let buttonRect = aEvent.currentTarget.getBoundingClientRect(); - if (aEvent.clientX >= buttonRect.left && - aEvent.clientX <= buttonRect.right && - aEvent.clientY >= buttonRect.bottom) - openMenu(aEvent.currentTarget); - else - cancelHold(aEvent.currentTarget); - } - - function mouseupHandler(aEvent) { - cancelHold(aEvent.currentTarget); - } - - function cancelHold(aButton) { - clearTimeout(timer); - aButton.removeEventListener("mouseout", mouseoutHandler, false); - aButton.removeEventListener("mouseup", mouseupHandler, false); - } - - function clickHandler(aEvent) { - if (aEvent.button == 0 && - aEvent.target == aEvent.currentTarget && - !aEvent.currentTarget.open && - !aEvent.currentTarget.disabled) { - let cmdEvent = document.createEvent("xulcommandevent"); - cmdEvent.initCommandEvent("command", true, true, window, 0, - aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey, - aEvent.metaKey, null); - aEvent.currentTarget.dispatchEvent(cmdEvent); - } - } - - function _addClickAndHoldListenersOnElement(aElm) { - aElm.addEventListener("mousedown", mousedownHandler, true); - aElm.addEventListener("click", clickHandler, true); - } - - // Bug 414797: Clone unified-back-forward-button's context menu into both the - // back and the forward buttons. - var unifiedButton = document.getElementById("unified-back-forward-button"); - if (unifiedButton && !unifiedButton._clickHandlersAttached) { - unifiedButton._clickHandlersAttached = true; - - let popup = document.getElementById("backForwardMenu").cloneNode(true); - popup.removeAttribute("id"); - // Prevent the context attribute on unified-back-forward-button from being - // inherited. - popup.setAttribute("context", ""); - - let backButton = document.getElementById("back-button"); - backButton.setAttribute("type", "menu"); - backButton.appendChild(popup); - _addClickAndHoldListenersOnElement(backButton); - - let forwardButton = document.getElementById("forward-button"); - popup = popup.cloneNode(true); - forwardButton.setAttribute("type", "menu"); - forwardButton.appendChild(popup); - _addClickAndHoldListenersOnElement(forwardButton); - } -} - -const gSessionHistoryObserver = { - observe: function(subject, topic, data) - { - if (topic != "browser:purge-session-history") - return; - - var backCommand = document.getElementById("Browser:Back"); - backCommand.setAttribute("disabled", "true"); - var fwdCommand = document.getElementById("Browser:Forward"); - fwdCommand.setAttribute("disabled", "true"); - - // Hide session restore button on about:home - window.messageManager.broadcastAsyncMessage("Browser:HideSessionRestoreButton"); - - if (gURLBar) { - // Clear undo history of the URL bar - gURLBar.editor.transactionManager.clear() - } - } -}; - -var gURLBarSettings = { - prefSuggest: "browser.urlbar.suggest.", - /* - For searching in the source code: - browser.urlbar.suggest.bookmark - browser.urlbar.suggest.history - browser.urlbar.suggest.openpage - */ - prefSuggests: [ - "bookmark", - "history", - "openpage" - ], - prefKeyword: "keyword.enabled", - - observe: function(aSubject, aTopic, aData) { - if (aTopic != "nsPref:changed") - return; - - this.writePlaceholder(); - }, - - writePlaceholder: function() { - let attribute = "placeholder"; - let prefs = this.prefSuggests.map(pref => { - return this.prefSuggest + pref; - }); - prefs.push(this.prefKeyword); - let placeholderDefault = prefs.some(pref => { - return gPrefService.getBoolPref(pref); - }); - - if (placeholderDefault) { - gURLBar.setAttribute( - attribute, gNavigatorBundle.getString("urlbar.placeholder")); - } else { - gURLBar.setAttribute( - attribute, gNavigatorBundle.getString("urlbar.placeholderURLOnly")); - } - } -}; - -/** - * Given a starting docshell and a URI to look up, find the docshell the URI - * is loaded in. - * @param aDocument - * A document to find instead of using just a URI - this is more specific. - * @param aDocShell - * The doc shell to start at - * @param aSoughtURI - * The URI that we're looking for - * @returns The doc shell that the sought URI is loaded in. Can be in - * subframes. - */ -function findChildShell(aDocument, aDocShell, aSoughtURI) { - aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation); - aDocShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor); - var doc = aDocShell.getInterface(Components.interfaces.nsIDOMDocument); - if ((aDocument && doc == aDocument) || - (aSoughtURI && aSoughtURI.spec == aDocShell.currentURI.spec)) - return aDocShell; - - var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeItem); - for (var i = 0; i < node.childCount; ++i) { - var docShell = node.getChildAt(i); - docShell = findChildShell(aDocument, docShell, aSoughtURI); - if (docShell) - return docShell; - } - return null; -} - -var gPopupBlockerObserver = { - _reportButton: null, - - onReportButtonClick: function (aEvent) - { - if (aEvent.button != 0 || aEvent.target != this._reportButton) - return; - - document.getElementById("blockedPopupOptions") - .openPopup(this._reportButton, "after_end", 0, 2, false, false, aEvent); - }, - - handleEvent: function (aEvent) - { - if (aEvent.originalTarget != gBrowser.selectedBrowser) - return; - - if (!this._reportButton && gURLBar) - this._reportButton = document.getElementById("page-report-button"); - - if (!gBrowser.selectedBrowser.blockedPopups) { - // Hide the icon in the location bar (if the location bar exists) - if (gURLBar) - this._reportButton.hidden = true; - return; - } - - if (gURLBar) - this._reportButton.hidden = false; - - // Only show the notification again if we've not already shown it. Since - // notifications are per-browser, we don't need to worry about re-adding - // it. - if (!gBrowser.selectedBrowser.blockedPopups.reported) { - if (gPrefService.getBoolPref("privacy.popups.showBrowserMessage")) { - var brandBundle = document.getElementById("bundle_brand"); - var brandShortName = brandBundle.getString("brandShortName"); - var popupCount = gBrowser.selectedBrowser.blockedPopups.length; - var popupButtonText = gNavigatorBundle.getString("popupWarningButton"); - var popupButtonAccesskey = gNavigatorBundle.getString("popupWarningButton.accesskey"); - var messageBase = gNavigatorBundle.getString("popupWarning.message"); - var message = PluralForm.get(popupCount, messageBase) - .replace("#1", brandShortName) - .replace("#2", popupCount); - - var notificationBox = gBrowser.getNotificationBox(); - var notification = notificationBox.getNotificationWithValue("popup-blocked"); - if (notification) { - notification.label = message; - } - else { - var buttons = [{ - label: popupButtonText, - accessKey: popupButtonAccesskey, - popup: "blockedPopupOptions", - callback: null - }]; - - const priority = notificationBox.PRIORITY_WARNING_MEDIUM; - notificationBox.appendNotification(message, "popup-blocked", - "chrome://browser/skin/Info.png", - priority, buttons); - } - } - - // Record the fact that we've reported this blocked popup, so we don't - // show it again. - gBrowser.selectedBrowser.blockedPopups.reported = true; - } - }, - - toggleAllowPopupsForSite: function (aEvent) - { - var pm = Services.perms; - var shouldBlock = aEvent.target.getAttribute("block") == "true"; - var perm = shouldBlock ? pm.DENY_ACTION : pm.ALLOW_ACTION; - pm.add(gBrowser.currentURI, "popup", perm); - - gBrowser.getNotificationBox().removeCurrentNotification(); - }, - - fillPopupList: function (aEvent) - { - // XXXben - rather than using |currentURI| here, which breaks down on multi-framed sites - // we should really walk the blockedPopups and create a list of "allow for <host>" - // menuitems for the common subset of hosts present in the report, this will - // make us frame-safe. - // - // XXXjst - Note that when this is fixed to work with multi-framed sites, - // also back out the fix for bug 343772 where - // nsGlobalWindow::CheckOpenAllow() was changed to also - // check if the top window's location is whitelisted. - let browser = gBrowser.selectedBrowser; - var uri = browser.currentURI; - var blockedPopupAllowSite = document.getElementById("blockedPopupAllowSite"); - try { - blockedPopupAllowSite.removeAttribute("hidden"); - - var pm = Services.perms; - if (pm.testPermission(uri, "popup") == pm.ALLOW_ACTION) { - // Offer an item to block popups for this site, if a whitelist entry exists - // already for it. - let blockString = gNavigatorBundle.getFormattedString("popupBlock", [uri.host || uri.spec]); - blockedPopupAllowSite.setAttribute("label", blockString); - blockedPopupAllowSite.setAttribute("block", "true"); - } - else { - // Offer an item to allow popups for this site - let allowString = gNavigatorBundle.getFormattedString("popupAllow", [uri.host || uri.spec]); - blockedPopupAllowSite.setAttribute("label", allowString); - blockedPopupAllowSite.removeAttribute("block"); - } - } - catch (e) { - blockedPopupAllowSite.setAttribute("hidden", "true"); - } - - if (PrivateBrowsingUtils.isWindowPrivate(window)) - blockedPopupAllowSite.setAttribute("disabled", "true"); - else - blockedPopupAllowSite.removeAttribute("disabled"); - - var foundUsablePopupURI = false; - var blockedPopups = browser.blockedPopups; - if (blockedPopups) { - for (let i = 0; i < blockedPopups.length; i++) { - let blockedPopup = blockedPopups[i]; - - // popupWindowURI will be null if the file picker popup is blocked. - // xxxdz this should make the option say "Show file picker" and do it (Bug 590306) - if (!blockedPopup.popupWindowURI) - continue; - var popupURIspec = blockedPopup.popupWindowURI.spec; - - // Sometimes the popup URI that we get back from the blockedPopup - // isn't useful (for instance, netscape.com's popup URI ends up - // being "http://www.netscape.com", which isn't really the URI of - // the popup they're trying to show). This isn't going to be - // useful to the user, so we won't create a menu item for it. - if (popupURIspec == "" || popupURIspec == "about:blank" || - popupURIspec == uri.spec) - continue; - - // Because of the short-circuit above, we may end up in a situation - // in which we don't have any usable popup addresses to show in - // the menu, and therefore we shouldn't show the separator. However, - // since we got past the short-circuit, we must've found at least - // one usable popup URI and thus we'll turn on the separator later. - foundUsablePopupURI = true; - - var menuitem = document.createElement("menuitem"); - var label = gNavigatorBundle.getFormattedString("popupShowPopupPrefix", - [popupURIspec]); - menuitem.setAttribute("label", label); - menuitem.setAttribute("popupWindowURI", popupURIspec); - menuitem.setAttribute("popupWindowFeatures", blockedPopup.popupWindowFeatures); - menuitem.setAttribute("popupWindowName", blockedPopup.popupWindowName); - menuitem.setAttribute("oncommand", "gPopupBlockerObserver.showBlockedPopup(event);"); - menuitem.setAttribute("popupReportIndex", i); - menuitem.popupReportBrowser = browser; - aEvent.target.appendChild(menuitem); - } - } - - // Show or hide the separator, depending on whether we added any - // showable popup addresses to the menu. - var blockedPopupsSeparator = - document.getElementById("blockedPopupsSeparator"); - if (foundUsablePopupURI) - blockedPopupsSeparator.removeAttribute("hidden"); - else - blockedPopupsSeparator.setAttribute("hidden", true); - - var blockedPopupDontShowMessage = document.getElementById("blockedPopupDontShowMessage"); - var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage"); - blockedPopupDontShowMessage.setAttribute("checked", !showMessage); - if (aEvent.target.anchorNode.id == "page-report-button") { - aEvent.target.anchorNode.setAttribute("open", "true"); - blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromLocationbar")); - } else - blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromMessage")); - }, - - onPopupHiding: function (aEvent) { - if (aEvent.target.anchorNode.id == "page-report-button") - aEvent.target.anchorNode.removeAttribute("open"); - - let item = aEvent.target.lastChild; - while (item && item.getAttribute("observes") != "blockedPopupsSeparator") { - let next = item.previousSibling; - item.parentNode.removeChild(item); - item = next; - } - }, - - showBlockedPopup: function (aEvent) - { - var target = aEvent.target; - var popupReportIndex = target.getAttribute("popupReportIndex"); - let browser = target.popupReportBrowser; - browser.unblockPopup(popupReportIndex); - }, - - editPopupSettings: function () - { - var host = ""; - try { - host = gBrowser.currentURI.host; - } - catch (e) { } - - var bundlePreferences = document.getElementById("bundle_preferences"); - var params = { blockVisible : false, - sessionVisible : false, - allowVisible : true, - prefilledHost : host, - permissionType : "popup", - windowTitle : bundlePreferences.getString("popuppermissionstitle"), - introText : bundlePreferences.getString("popuppermissionstext") }; - var existingWindow = Services.wm.getMostRecentWindow("Browser:Permissions"); - if (existingWindow) { - existingWindow.initWithParams(params); - existingWindow.focus(); - } - else - window.openDialog("chrome://browser/content/preferences/permissions.xul", - "_blank", "resizable,dialog=no,centerscreen", params); - }, - - dontShowMessage: function () - { - var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage"); - gPrefService.setBoolPref("privacy.popups.showBrowserMessage", !showMessage); - gBrowser.getNotificationBox().removeCurrentNotification(); - } -}; - -const gXSSObserver = { - - observe: function (aSubject, aTopic, aData) - { - - // Don't do anything if the notification is disabled. - if (!gPrefService.getBoolPref("security.xssfilter.displayWarning")) - return; - - // Parse incoming XSS array - aSubject.QueryInterface(Ci.nsIArray); - var policy = aSubject.queryElementAt(0, Ci.nsISupportsString).data; - var content = aSubject.queryElementAt(1, Ci.nsISupportsString).data; - var domain = aSubject.queryElementAt(2, Ci.nsISupportsString).data; - var url = aSubject.queryElementAt(3, Ci.nsISupportsCString).data; - var blockMode = aSubject.queryElementAt(4, Ci.nsISupportsPRBool).data; - - // If it is a block mode event, do not display the infobar - if (blockMode) - return; - - var nb = gBrowser.getNotificationBox(); - const priority = nb.PRIORITY_WARNING_MEDIUM; - - var buttons = [{ - label: 'View Unsafe Content', - accessKey: 'V', - popup: null, - callback: function () { - alert(content); - } - }]; - - if (domain !== "") - buttons.push({ - label: 'Add Domain Exception', - accessKey: 'A', - popup: null, - callback: function () { - let whitelist = gPrefService.getCharPref("security.xssfilter.whitelist"); - if (whitelist != "") { - whitelist = whitelist + "," + domain; - } else { - whitelist = domain; - } - // Write the updated whitelist. Since this is observed by the XSS filter, - // it will automatically sync to the back-end and update immediately. - gPrefService.setCharPref("security.xssfilter.whitelist", whitelist); - // After setting this, we automatically reload the page. - BrowserReloadSkipCache(); - } - }); - - nb.appendNotification("The XSS Filter has detected a potential XSS attack. Type: " + - policy, 'popup-blocked', 'chrome://browser/skin/Info.png', - priority, buttons); - } -}; - -var gBrowserInit = { - onLoad: function() { - gMultiProcessBrowser = gPrefService.getBoolPref("browser.tabs.remote"); - - var mustLoadSidebar = false; - - Cc["@mozilla.org/eventlistenerservice;1"] - .getService(Ci.nsIEventListenerService) - .addSystemEventListener(gBrowser, "click", contentAreaClick, true); - - gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false); - - // Note that the XBL binding is untrusted - gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true); - gBrowser.addEventListener("PluginCrashed", gPluginHandler, true); - gBrowser.addEventListener("PluginOutdated", gPluginHandler, true); - gBrowser.addEventListener("PluginInstantiated", gPluginHandler, true); - gBrowser.addEventListener("PluginRemoved", gPluginHandler, true); - - Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false); - - window.addEventListener("AppCommand", HandleAppCommandEvent, true); - - messageManager.loadFrameScript("chrome://browser/content/content.js", true); - messageManager.loadFrameScript("chrome://browser/content/content-sessionStore.js", true); - - // initialize observers and listeners - // and give C++ access to gBrowser - XULBrowserWindow.init(); - window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIXULWindow) - .XULBrowserWindow = window.XULBrowserWindow; - window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = - new nsBrowserAccess(); - - // set default character set if provided - // window.arguments[1]: character set (string) - if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) { - if (window.arguments[1].startsWith("charset=")) { - var arrayArgComponents = window.arguments[1].split("="); - if (arrayArgComponents) { - //we should "inherit" the charset menu setting in a new window - //TFE FIXME: this is now a wrappednative and can't be set this way. - //getMarkupDocumentViewer().defaultCharacterSet = arrayArgComponents[1]; - } - } - } - - // Manually hook up session and global history for the first browser - // so that we don't have to load global history before bringing up a - // window. - // Wire up session and global history before any possible - // progress notifications for back/forward button updating - gBrowser.webNavigation.sessionHistory = Cc["@mozilla.org/browser/shistory;1"]. - createInstance(Ci.nsISHistory); - Services.obs.addObserver(gBrowser.browsers[0], "browser:purge-session-history", false); - - // remove the disablehistory attribute so the browser cleans up, as - // though it had done this work itself - gBrowser.browsers[0].removeAttribute("disablehistory"); - - // enable global history - try { - if (!gMultiProcessBrowser) - gBrowser.docShell.useGlobalHistory = true; - } catch(ex) { - Cu.reportError("Places database may be locked: " + ex); - } - - // hook up UI through progress listener - gBrowser.addProgressListener(window.XULBrowserWindow); - gBrowser.addTabsProgressListener(window.TabsProgressListener); - - // setup our common DOMLinkAdded listener - gBrowser.addEventListener("DOMLinkAdded", DOMLinkHandler, false); - - // setup our MozApplicationManifest listener - gBrowser.addEventListener("MozApplicationManifest", - OfflineApps, false); - - // setup simple gestures support - gGestureSupport.init(true); - - // setup history swipe animation - gHistorySwipeAnimation.init(); - - if (window.opener && !window.opener.closed) { - let openerSidebarBox = window.opener.document.getElementById("sidebar-box"); - // If the opener had a sidebar, open the same sidebar in our window. - // The opener can be the hidden window too, if we're coming from the state - // where no windows are open, and the hidden window has no sidebar box. - if (openerSidebarBox && !openerSidebarBox.hidden) { - let sidebarCmd = openerSidebarBox.getAttribute("sidebarcommand"); - let sidebarCmdElem = document.getElementById(sidebarCmd); - - // dynamically generated sidebars will fail this check. - if (sidebarCmdElem) { - let sidebarBox = document.getElementById("sidebar-box"); - let sidebarTitle = document.getElementById("sidebar-title"); - - sidebarTitle.setAttribute( - "value", window.opener.document.getElementById("sidebar-title").getAttribute("value")); - sidebarBox.setAttribute("width", openerSidebarBox.boxObject.width); - - sidebarBox.setAttribute("sidebarcommand", sidebarCmd); - // Note: we're setting 'src' on sidebarBox, which is a <vbox>, not on - // the <browser id="sidebar">. This lets us delay the actual load until - // delayedStartup(). - sidebarBox.setAttribute( - "src", window.opener.document.getElementById("sidebar").getAttribute("src")); - mustLoadSidebar = true; - - sidebarBox.hidden = false; - document.getElementById("sidebar-splitter").hidden = false; - sidebarCmdElem.setAttribute("checked", "true"); - } - } - } - else { - let box = document.getElementById("sidebar-box"); - if (box.hasAttribute("sidebarcommand")) { - let commandID = box.getAttribute("sidebarcommand"); - if (commandID) { - let command = document.getElementById(commandID); - if (command) { - mustLoadSidebar = true; - box.hidden = false; - document.getElementById("sidebar-splitter").hidden = false; - command.setAttribute("checked", "true"); - } - else { - // Remove the |sidebarcommand| attribute, because the element it - // refers to no longer exists, so we should assume this sidebar - // panel has been uninstalled. (249883) - box.removeAttribute("sidebarcommand"); - } - } - } - } - - // Certain kinds of automigration rely on this notification to complete their - // tasks BEFORE the browser window is shown. - Services.obs.notifyObservers(null, "browser-window-before-show", ""); - - // Set a sane starting width/height for all resolutions on new profiles. - if (!document.documentElement.hasAttribute("width")) { - let defaultWidth; - let defaultHeight; - - // Very small: maximize the window - // Portrait : use about full width and 3/4 height, to view entire pages - // at once (without being obnoxiously tall) - // Widescreen: use about half width, to suggest side-by-side page view - // Otherwise : use 3/4 height and width - if (screen.availHeight <= 600) { - document.documentElement.setAttribute("sizemode", "maximized"); - defaultWidth = 610; - defaultHeight = 450; - } - else { - if (screen.availWidth <= screen.availHeight) { - defaultWidth = screen.availWidth * .9; - defaultHeight = screen.availHeight * .75; - } - else if (screen.availWidth >= 2048) { - defaultWidth = (screen.availWidth / 2) - 20; - defaultHeight = screen.availHeight - 10; - } - else { - defaultWidth = screen.availWidth * .75; - defaultHeight = screen.availHeight * .75; - } - -#ifdef MOZ_WIDGET_GTK2 - // On X, we're not currently able to account for the size of the window - // border. Use 28px as a guess (titlebar + bottom window border) - defaultHeight -= 28; -#endif - } - document.documentElement.setAttribute("width", defaultWidth); - document.documentElement.setAttribute("height", defaultHeight); - } - - if (!gShowPageResizers) - document.getElementById("status-bar").setAttribute("hideresizer", "true"); - - if (!window.toolbar.visible) { - // adjust browser UI for popups - if (gURLBar) { - gURLBar.setAttribute("readonly", "true"); - gURLBar.setAttribute("enablehistory", "false"); - } - goSetCommandEnabled("cmd_newNavigatorTab", false); - } - -#ifdef MENUBAR_CAN_AUTOHIDE - updateAppButtonDisplay(); -#endif - - // Misc. inits. - CombinedStopReload.init(); - allTabs.readPref(); - TabsOnTop.init(); - gPrivateBrowsingUI.init(); - TabsInTitlebar.init(); - retrieveToolbarIconsizesFromTheme(); - ToolbarIconColor.init(); - -#ifdef XP_WIN - if (window.matchMedia("(-moz-os-version: windows-win8)").matches && - window.matchMedia("(-moz-windows-default-theme)").matches) { - let windows8WindowFrameColor = Cu.import("resource:///modules/Windows8WindowFrameColor.jsm", {}).Windows8WindowFrameColor; - - var windowFrameColor; - windowFrameColor = windows8WindowFrameColor.get_win8(); - - // Formula from Microsoft's UWP guideline. - let backgroundLuminance = (windowFrameColor[0] * 2 + - windowFrameColor[1] * 5 + - windowFrameColor[2]) / 8; - if (backgroundLuminance <= 128) { - document.documentElement.setAttribute("darkwindowframe", "true"); - } - } -#endif - - // Wait until chrome is painted before executing code not critical to making the window visible - this._boundDelayedStartup = this._delayedStartup.bind(this, mustLoadSidebar); - window.addEventListener("MozAfterPaint", this._boundDelayedStartup); - - this._loadHandled = true; - }, - - _cancelDelayedStartup: function () { - window.removeEventListener("MozAfterPaint", this._boundDelayedStartup); - this._boundDelayedStartup = null; - }, - - _delayedStartup: function(mustLoadSidebar) { - let tmp = {}; - - this._cancelDelayedStartup(); - - let uriToLoad = this._getUriToLoad(); - var isLoadingBlank = isBlankPageURL(uriToLoad); - - // This pageshow listener needs to be registered before we may call - // swapBrowsersAndCloseOther() to receive pageshow events fired by that. - gBrowser.addEventListener("pageshow", function(event) { - // Filter out events that are not about the document load we are interested in - if (content && event.target == content.document) - setTimeout(pageShowEventHandlers, 0, event.persisted); - }, true); - - if (uriToLoad && uriToLoad != "about:blank") { - if (uriToLoad instanceof Ci.nsISupportsArray) { - let count = uriToLoad.Count(); - let specs = []; - for (let i = 0; i < count; i++) { - let urisstring = uriToLoad.GetElementAt(i).QueryInterface(Ci.nsISupportsString); - specs.push(urisstring.data); - } - - // This function throws for certain malformed URIs, so use exception handling - // so that we don't disrupt startup - try { - gBrowser.loadTabs(specs, false, true); - } catch (e) {} - } - else if (uriToLoad instanceof XULElement) { - // swap the given tab with the default about:blank tab and then close - // the original tab in the other window. - - // Stop the about:blank load - gBrowser.stop(); - // make sure it has a docshell - gBrowser.docShell; - - gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, uriToLoad); - } - // window.arguments[2]: referrer (nsIURI) - // [3]: postData (nsIInputStream) - // [4]: allowThirdPartyFixup (bool) - else if (window.arguments.length >= 3) { - loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null, - window.arguments[4] || false); - window.focus(); - } - // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3. - // Such callers expect that window.arguments[0] is handled as a single URI. - else - loadOneOrMoreURIs(uriToLoad); - } - - Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false); - Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled", false); - Services.obs.addObserver(gXPInstallObserver, "addon-install-started", false); - Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false); - Services.obs.addObserver(gXPInstallObserver, "addon-install-origin-blocked", false); - Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false); - Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false); - Services.obs.addObserver(gXSSObserver, "xss-on-violate-policy", false); - - gPrefService.addObserver(gURLBarSettings.prefSuggest, gURLBarSettings, false); - gPrefService.addObserver(gURLBarSettings.prefKeyword, gURLBarSettings, false); - - gURLBarSettings.writePlaceholder(); - - BrowserOffline.init(); - OfflineApps.init(); - IndexedDBPromptHelper.init(); - AddonManager.addAddonListener(AddonsMgrListener); - WebrtcIndicator.init(); - - // Ensure login manager is up and running. - Services.logins; - - if (mustLoadSidebar) { - let sidebar = document.getElementById("sidebar"); - let sidebarBox = document.getElementById("sidebar-box"); - sidebar.setAttribute("src", sidebarBox.getAttribute("src")); - } - - UpdateUrlbarSearchSplitterState(); - - if (!isLoadingBlank || !focusAndSelectUrlBar()) - gBrowser.selectedBrowser.focus(); - - gNavToolbox.customizeDone = BrowserToolboxCustomizeDone; - gNavToolbox.customizeChange = BrowserToolboxCustomizeChange; - - // Set up Sanitize Item - this._initializeSanitizer(); - - // Enable/Disable auto-hide tabbar - gBrowser.tabContainer.updateVisibility(); - - gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton, false); - - var homeButton = document.getElementById("home-button"); - gHomeButton.updateTooltip(homeButton); - gHomeButton.updatePersonalToolbarStyle(homeButton); - - // BiDi UI - gBidiUI = isBidiEnabled(); - if (gBidiUI) { - document.getElementById("documentDirection-separator").hidden = false; - document.getElementById("documentDirection-swap").hidden = false; - document.getElementById("textfieldDirection-separator").hidden = false; - document.getElementById("textfieldDirection-swap").hidden = false; - } - - // Setup click-and-hold gestures access to the session history - // menus if global click-and-hold isn't turned on - if (!getBoolPref("ui.click_hold_context_menus", false)) - SetClickAndHoldHandlers(); - - // Initialize the full zoom setting. - // We do this before the session restore service gets initialized so we can - // apply full zoom settings to tabs restored by the session restore service. - FullZoom.init(); - - // Bug 666804 - NetworkPrioritizer support for e10s - if (!gMultiProcessBrowser) { - let NP = {}; - Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP); - NP.trackBrowserWindow(window); - } - - // initialize the session-restore service (in case it's not already running) - let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - let ssPromise = ss.init(window); - - PlacesToolbarHelper.init(); - - ctrlTab.readPref(); - gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false); - gPrefService.addObserver(allTabs.prefName, allTabs, false); - - // Initialize the download manager some time after the app starts so that - // auto-resume downloads begin (such as after crashing or quitting with - // active downloads) and speeds up the first-load of the download manager UI. - // If the user manually opens the download manager before the timeout, the - // downloads will start right away, and getting the service again won't hurt. - setTimeout(function() { - try { - Cu.import("resource:///modules/DownloadsCommon.jsm", {}) - .DownloadsCommon.initializeAllDataLinks(); - Cu.import("resource:///modules/DownloadsTaskbar.jsm", {}) - .DownloadsTaskbar.registerIndicator(window); - } catch(ex) { - Cu.reportError(ex); - } - }, 10000); - - // Load the Login Manager data from disk off the main thread, some time - // after startup. If the data is required before the timeout, for example - // because a restored page contains a password field, it will be loaded on - // the main thread, and this initialization request will be ignored. - setTimeout(function() { - try { - Services.logins; - } catch (ex) { - Cu.reportError(ex); - } - }, 3000); - - // The object handling the downloads indicator is also initialized here in the - // delayed startup function, but the actual indicator element is not loaded - // unless there are downloads to be displayed. - DownloadsButton.initializeIndicator(); - -#ifndef XP_MACOSX - updateEditUIVisibility(); - let placesContext = document.getElementById("placesContext"); - placesContext.addEventListener("popupshowing", updateEditUIVisibility, false); - placesContext.addEventListener("popuphiding", updateEditUIVisibility, false); -#endif - - gBrowser.mPanelContainer.addEventListener("InstallBrowserTheme", LightWeightThemeWebInstaller, false, true); - gBrowser.mPanelContainer.addEventListener("PreviewBrowserTheme", LightWeightThemeWebInstaller, false, true); - gBrowser.mPanelContainer.addEventListener("ResetBrowserThemePreview", LightWeightThemeWebInstaller, false, true); - - // Bug 666808 - AeroPeek support for e10s - if (!gMultiProcessBrowser) { - if (Win7Features) - Win7Features.onOpenWindow(); - } - - // called when we go into full screen, even if initiated by a web page script - window.addEventListener("fullscreen", onFullScreen, true); - - // 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); - - if (window.fullScreen) - onFullScreen(); - if (document.mozFullScreen) - onMozEnteredDomFullscreen(); - -#ifdef MOZ_SERVICES_SYNC - // initialize the sync UI - gSyncUI.init(); -#endif - - gBrowserThumbnails.init(); - - setUrlAndSearchBarWidthForConditionalForwardButton(); - window.addEventListener("resize", function resizeHandler(event) { - if (event.target == window) - setUrlAndSearchBarWidthForConditionalForwardButton(); - }); - -#ifdef MOZ_DEVTOOLS - // Enable Chrome Debugger? - let chromeEnabled = gPrefService.getBoolPref("devtools.chrome.enabled"); - let remoteEnabled = chromeEnabled && - gPrefService.getBoolPref("devtools.debugger.chrome-enabled") && - gPrefService.getBoolPref("devtools.debugger.remote-enabled"); - if (remoteEnabled) { - let cmd = document.getElementById("Tools:ChromeDebugger"); - cmd.removeAttribute("disabled"); - cmd.removeAttribute("hidden"); - } - - // Enable Scratchpad in the UI, if the preference allows this. - let scratchpadEnabled = gPrefService.getBoolPref(Scratchpad.prefEnabledName); - if (scratchpadEnabled) { - let cmd = document.getElementById("Tools:Scratchpad"); - cmd.removeAttribute("disabled"); - cmd.removeAttribute("hidden"); - } -#endif - - // Enable Error Console? - let consoleEnabled = gPrefService.getBoolPref("devtools.errorconsole.enabled"); - if (consoleEnabled) { - let cmd = document.getElementById("Tools:ErrorConsole"); - cmd.removeAttribute("disabled"); - cmd.removeAttribute("hidden"); - } - -#ifdef MENUBAR_CAN_AUTOHIDE - // If the user (or the locale) hasn't enabled the top-level "Character - // Encoding" menu via the "browser.menu.showCharacterEncoding" preference, - // hide it. - if ("true" != gPrefService.getComplexValue("browser.menu.showCharacterEncoding", - Ci.nsIPrefLocalizedString).data) - document.getElementById("appmenu_charsetMenu").hidden = true; -#endif - -#ifdef MOZ_DEVTOOLS - // Enable Responsive UI? - let responsiveUIEnabled = gPrefService.getBoolPref("devtools.responsiveUI.enabled"); - if (responsiveUIEnabled) { - let cmd = document.getElementById("Tools:ResponsiveUI"); - cmd.removeAttribute("disabled"); - cmd.removeAttribute("hidden"); - } - - // Add Devtools menuitems and listeners - gDevToolsBrowser.registerBrowserWindow(window); -#endif - - let appMenuButton = document.getElementById("appmenu-button"); - let appMenuPopup = document.getElementById("appmenu-popup"); - if (appMenuButton && appMenuPopup) { - let appMenuOpening = null; - appMenuButton.addEventListener("mousedown", function(event) { - if (event.button == 0) - appMenuOpening = new Date(); - }, false); - appMenuPopup.addEventListener("popupshown", function(event) { - if (event.target != appMenuPopup || !appMenuOpening) - return; - let duration = new Date() - appMenuOpening; - appMenuOpening = null; - }, false); - } - - window.addEventListener("mousemove", MousePosTracker, false); - window.addEventListener("dragover", MousePosTracker, false); - - // End startup crash tracking after a delay to catch crashes while restoring - // tabs and to postpone saving the pref to disk. - try { - const startupCrashEndDelay = 30 * 1000; - setTimeout(Services.startup.trackStartupCrashEnd, startupCrashEndDelay); - } catch (ex) { - Cu.reportError("Could not end startup crash tracking: " + ex); - } - - ssPromise.then(() =>{ - // Bail out if the window has been closed in the meantime. - if (window.closed) { - return; - } - if ("TabView" in window) { - TabView.init(); - } - // XXX: do we still need this?... - setTimeout(function () { BrowserChromeTest.markAsReady(); }, 0); - }); - - Services.obs.notifyObservers(window, "browser-delayed-startup-finished", ""); - }, - - // Returns the URI(s) to load at startup. - _getUriToLoad: function () { - // window.arguments[0]: URI to load (string), or an nsISupportsArray of - // nsISupportsStrings to load, or a xul:tab of - // a tabbrowser, which will be replaced by this - // window (for this case, all other arguments are - // ignored). - if (!window.arguments || !window.arguments[0]) - return null; - - let uri = window.arguments[0]; - let sessionStartup = Cc["@mozilla.org/browser/sessionstartup;1"] - .getService(Ci.nsISessionStartup); - let defaultArgs = Cc["@mozilla.org/browser/clh;1"] - .getService(Ci.nsIBrowserHandler) - .defaultArgs; - - // If the given URI matches defaultArgs (the default homepage) we want - // to block its load if we're going to restore a session anyway. - if (uri == defaultArgs && sessionStartup.willOverrideHomepage) - return null; - - return uri; - }, - - onUnload: function() { - // In certain scenarios it's possible for unload to be fired before onload, - // (e.g. if the window is being closed after browser.js loads but before the - // load completes). In that case, there's nothing to do here. - if (!this._loadHandled) - return; - -#ifdef MOZ_DEVTOOLS - gDevToolsBrowser.forgetBrowserWindow(window); - - let desc = Object.getOwnPropertyDescriptor(window, "DeveloperToolbar"); - if (desc && !desc.get) { - DeveloperToolbar.destroy(); - } -#endif - - // First clean up services initialized in gBrowserInit.onLoad (or those whose - // uninit methods don't depend on the services having been initialized). - - allTabs.uninit(); - - CombinedStopReload.uninit(); - - gGestureSupport.init(false); - - gHistorySwipeAnimation.uninit(); - - FullScreen.cleanup(); - - Services.obs.removeObserver(gPluginHandler.pluginCrashed, "plugin-crashed"); - - try { - gBrowser.removeProgressListener(window.XULBrowserWindow); - gBrowser.removeTabsProgressListener(window.TabsProgressListener); - } catch (ex) { - } - - BookmarkingUI.uninit(); - - TabsOnTop.uninit(); - - TabsInTitlebar.uninit(); - - ToolbarIconColor.uninit(); - - var enumerator = Services.wm.getEnumerator(null); - enumerator.getNext(); - if (!enumerator.hasMoreElements()) { - document.persist("sidebar-box", "sidebarcommand"); - document.persist("sidebar-box", "width"); - document.persist("sidebar-box", "src"); - document.persist("sidebar-title", "value"); - } - - // Now either cancel delayedStartup, or clean up the services initialized from - // it. - if (this._boundDelayedStartup) { - this._cancelDelayedStartup(); - } else { - if (Win7Features) - Win7Features.onCloseWindow(); - - gPrefService.removeObserver(ctrlTab.prefName, ctrlTab); - gPrefService.removeObserver(allTabs.prefName, allTabs); - ctrlTab.uninit(); - if ("TabView" in window) { - TabView.uninit(); - } - gBrowserThumbnails.uninit(); - FullZoom.destroy(); - - Services.obs.removeObserver(gSessionHistoryObserver, "browser:purge-session-history"); - Services.obs.removeObserver(gXPInstallObserver, "addon-install-disabled"); - Services.obs.removeObserver(gXPInstallObserver, "addon-install-started"); - Services.obs.removeObserver(gXPInstallObserver, "addon-install-blocked"); - Services.obs.removeObserver(gXPInstallObserver, "addon-install-origin-blocked"); - Services.obs.removeObserver(gXPInstallObserver, "addon-install-failed"); - Services.obs.removeObserver(gXPInstallObserver, "addon-install-complete"); - Services.obs.removeObserver(gXSSObserver, "xss-on-violate-policy"); - - try { - gPrefService.removeObserver(gURLBarSettings.prefSuggest, gURLBarSettings); - gPrefService.removeObserver(gURLBarSettings.prefKeyword, gURLBarSettings); - } catch (ex) { - Cu.reportError(ex); - } - - try { - gPrefService.removeObserver(gHomeButton.prefDomain, gHomeButton); - } catch (ex) { - Cu.reportError(ex); - } - - BrowserOffline.uninit(); - OfflineApps.uninit(); - IndexedDBPromptHelper.uninit(); - AddonManager.removeAddonListener(AddonsMgrListener); - } - - // Final window teardown, do this last. - window.XULBrowserWindow.destroy(); - window.XULBrowserWindow = null; - window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIXULWindow) - .XULBrowserWindow = null; - window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = null; - }, - -#ifdef XP_MACOSX - // nonBrowserWindowStartup(), nonBrowserWindowDelayedStartup(), and - // nonBrowserWindowShutdown() are used for non-browser windows in - // macBrowserOverlay - nonBrowserWindowStartup: function() { - // Disable inappropriate commands / submenus - var disabledItems = ['Browser:SavePage', - 'Browser:SendLink', 'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain', - 'viewToolbarsMenu', 'viewSidebarMenuMenu', 'Browser:Reload', - 'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen', - 'viewHistorySidebar', 'Browser:AddBookmarkAs', 'Browser:BookmarkAllTabs', - 'View:PageInfo', 'Browser:ToggleAddonBar']; - var element; - - for (let disabledItem of disabledItems) { - element = document.getElementById(disabledItem); - if (element) - element.setAttribute("disabled", "true"); - } - - // If no windows are active (i.e. we're the hidden window), disable the close, minimize - // and zoom menu commands as well - if (window.location.href == "chrome://browser/content/hiddenWindow.xul") { - var hiddenWindowDisabledItems = ['cmd_close', 'minimizeWindow', 'zoomWindow']; - for (let hiddenWindowDisabledItem of hiddenWindowDisabledItems) { - element = document.getElementById(hiddenWindowDisabledItem); - if (element) - element.setAttribute("disabled", "true"); - } - - // also hide the window-list separator - element = document.getElementById("sep-window-list"); - element.setAttribute("hidden", "true"); - - // Setup the dock menu. - let dockMenuElement = document.getElementById("menu_mac_dockmenu"); - if (dockMenuElement != null) { - let nativeMenu = Cc["@mozilla.org/widget/standalonenativemenu;1"] - .createInstance(Ci.nsIStandaloneNativeMenu); - - try { - nativeMenu.init(dockMenuElement); - - let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"] - .getService(Ci.nsIMacDockSupport); - dockSupport.dockMenu = nativeMenu; - } - catch (e) { - } - } - } - - if (PrivateBrowsingUtils.permanentPrivateBrowsing) { - document.getElementById("macDockMenuNewWindow").hidden = true; - } - - this._delayedStartupTimeoutId = setTimeout(this.nonBrowserWindowDelayedStartup.bind(this), 0); - }, - - nonBrowserWindowDelayedStartup: function() { - this._delayedStartupTimeoutId = null; - - // initialise the offline listener - BrowserOffline.init(); - - // Set up Sanitize Item - this._initializeSanitizer(); - - // initialize the private browsing UI - gPrivateBrowsingUI.init(); - -#ifdef MOZ_SERVICES_SYNC - // initialize the sync UI - gSyncUI.init(); -#endif - }, - - nonBrowserWindowShutdown: function() { - // If nonBrowserWindowDelayedStartup hasn't run yet, we have no work to do - - // just cancel the pending timeout and return; - if (this._delayedStartupTimeoutId) { - clearTimeout(this._delayedStartupTimeoutId); - return; - } - - BrowserOffline.uninit(); - }, -#endif - - _initializeSanitizer: function() { - const kDidSanitizeDomain = "privacy.sanitize.didShutdownSanitize"; - if (gPrefService.prefHasUserValue(kDidSanitizeDomain)) { - gPrefService.clearUserPref(kDidSanitizeDomain); - // We need to persist this preference change, since we want to - // check it at next app start even if the browser exits abruptly - gPrefService.savePrefFile(null); - } - - /** - * Migrate Firefox 3.0 privacy.item prefs under one of these conditions: - * - * a) User has customized any privacy.item prefs - * b) privacy.sanitize.sanitizeOnShutdown is set - */ - if (!gPrefService.getBoolPref("privacy.sanitize.migrateFx3Prefs")) { - let itemBranch = gPrefService.getBranch("privacy.item."); - let itemArray = itemBranch.getChildList(""); - - // See if any privacy.item prefs are set - let doMigrate = itemArray.some(function (name) itemBranch.prefHasUserValue(name)); - // Or if sanitizeOnShutdown is set - if (!doMigrate) - doMigrate = gPrefService.getBoolPref("privacy.sanitize.sanitizeOnShutdown"); - - if (doMigrate) { - let cpdBranch = gPrefService.getBranch("privacy.cpd."); - let clearOnShutdownBranch = gPrefService.getBranch("privacy.clearOnShutdown."); - for (let name of itemArray) { - try { - // don't migrate password or offlineApps clearing in the CRH dialog since - // there's no UI for those anymore. They default to false. bug 497656 - if (name != "passwords" && name != "offlineApps") - cpdBranch.setBoolPref(name, itemBranch.getBoolPref(name)); - clearOnShutdownBranch.setBoolPref(name, itemBranch.getBoolPref(name)); - } - catch(e) { - Cu.reportError("Exception thrown during privacy pref migration: " + e); - } - } - } - - gPrefService.setBoolPref("privacy.sanitize.migrateFx3Prefs", true); - } - }, -} - - -/* Legacy global init functions */ -var BrowserStartup = gBrowserInit.onLoad.bind(gBrowserInit); -var BrowserShutdown = gBrowserInit.onUnload.bind(gBrowserInit); -#ifdef XP_MACOSX -var nonBrowserWindowStartup = gBrowserInit.nonBrowserWindowStartup.bind(gBrowserInit); -var nonBrowserWindowDelayedStartup = gBrowserInit.nonBrowserWindowDelayedStartup.bind(gBrowserInit); -var nonBrowserWindowShutdown = gBrowserInit.nonBrowserWindowShutdown.bind(gBrowserInit); -#endif - -function HandleAppCommandEvent(evt) { - switch (evt.command) { - case "Back": - BrowserBack(); - break; - case "Forward": - BrowserForward(); - break; - case "Reload": - BrowserReloadSkipCache(); - break; - case "Stop": - if (XULBrowserWindow.stopCommand.getAttribute("disabled") != "true") - BrowserStop(); - break; - case "Search": - BrowserSearch.webSearch(); - break; - case "Bookmarks": - toggleSidebar('viewBookmarksSidebar'); - break; - case "Home": - BrowserHome(); - break; - case "New": - BrowserOpenTab(); - break; - case "Close": - BrowserCloseTabOrWindow(); - break; - case "Find": - gFindBar.onFindCommand(); - break; - case "Help": - openHelpLink('firefox-help'); - break; - case "Open": - BrowserOpenFileWindow(); - break; - case "Print": - PrintUtils.print(); - break; - case "Save": - saveDocument(window.content.document); - break; - case "SendMail": - MailIntegration.sendLinkForWindow(window.content); - break; - default: - return; - } - evt.stopPropagation(); - evt.preventDefault(); -} - -function gotoHistoryIndex(aEvent) { - let index = aEvent.target.getAttribute("index"); - if (!index) - return false; - - let where = whereToOpenLink(aEvent); - - if (where == "current") { - // Normal click. Go there in the current tab and update session history. - - try { - gBrowser.gotoIndex(index); - } - catch(ex) { - return false; - } - return true; - } - // Modified click. Go there in a new tab/window. - - duplicateTabIn(gBrowser.selectedTab, where, index - gBrowser.sessionHistory.index); - return true; -} - -function BrowserForward(aEvent) { - let where = whereToOpenLink(aEvent, false, true); - - if (where == "current") { - try { - gBrowser.goForward(); - } - catch(ex) { - } - } - else { - duplicateTabIn(gBrowser.selectedTab, where, 1); - } -} - -function BrowserBack(aEvent) { - let where = whereToOpenLink(aEvent, false, true); - - if (where == "current") { - try { - gBrowser.goBack(); - } - catch(ex) { - } - } - else { - duplicateTabIn(gBrowser.selectedTab, where, -1); - } -} - -function BrowserHandleBackspace() -{ - switch (gPrefService.getIntPref("browser.backspace_action")) { - case 0: - BrowserBack(); - break; - case 1: - goDoCommand("cmd_scrollPageUp"); - break; - } -} - -function BrowserHandleShiftBackspace() -{ - switch (gPrefService.getIntPref("browser.backspace_action")) { - case 0: - BrowserForward(); - break; - case 1: - goDoCommand("cmd_scrollPageDown"); - break; - } -} - -function BrowserStop() { - const stopFlags = nsIWebNavigation.STOP_ALL; - gBrowser.webNavigation.stop(stopFlags); -} - -function BrowserReloadOrDuplicate(aEvent) { - var backgroundTabModifier = aEvent.button == 1 || -#ifdef XP_MACOSX - aEvent.metaKey; -#else - aEvent.ctrlKey; -#endif - if (aEvent.shiftKey && !backgroundTabModifier) { - BrowserReloadSkipCache(); - return; - } - - let where = whereToOpenLink(aEvent, false, true); - if (where == "current") - BrowserReload(); - else - duplicateTabIn(gBrowser.selectedTab, where); -} - -function BrowserReload() { - const reloadFlags = nsIWebNavigation.LOAD_FLAGS_NONE; - BrowserReloadWithFlags(reloadFlags); -} - -function BrowserReloadSkipCache() { - // Bypass proxy and cache. - const reloadFlags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE; - BrowserReloadWithFlags(reloadFlags); -} - -var BrowserHome = BrowserGoHome; -function BrowserGoHome(aEvent) { - if (aEvent && "button" in aEvent && - aEvent.button == 2) // right-click: do nothing - return; - - var homePage = gHomeButton.getHomePage(); - var where = whereToOpenLink(aEvent, false, true); - var urls; - - // Home page should open in a new tab when current tab is an app tab - if (where == "current" && - gBrowser && - gBrowser.selectedTab.pinned) - where = "tab"; - - // openUILinkIn in utilityOverlay.js doesn't handle loading multiple pages - switch (where) { - case "current": - loadOneOrMoreURIs(homePage); - break; - case "tabshifted": - case "tab": - urls = homePage.split("|"); - var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground", false); - gBrowser.loadTabs(urls, loadInBackground); - break; - case "window": - OpenBrowserWindow(); - break; - } -} - -function loadOneOrMoreURIs(aURIString) -{ -#ifdef XP_MACOSX - // we're not a browser window, pass the URI string to a new browser window - if (window.location.href != getBrowserURL()) - { - window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", aURIString); - return; - } -#endif - // This function throws for certain malformed URIs, so use exception handling - // so that we don't disrupt startup - try { - gBrowser.loadTabs(aURIString.split("|"), false, true); - } - catch (e) { - } -} - -function focusAndSelectUrlBar() { - if (gURLBar) { - if (window.fullScreen) - FullScreen.mouseoverToggle(true); - - gURLBar.select(); - if (document.activeElement == gURLBar.inputField) - return true; - } - return false; -} - -function openLocation() { - if (focusAndSelectUrlBar()) - return; - -#ifdef XP_MACOSX - if (window.location.href != getBrowserURL()) { - var win = getTopWin(); - if (win) { - // If there's an open browser window, it should handle this command - win.focus() - win.openLocation(); - } - else { - // If there are no open browser windows, open a new one - win = window.openDialog("chrome://browser/content/", "_blank", - "chrome,all,dialog=no", BROWSER_NEW_TAB_URL); - win.addEventListener("load", openLocationCallback, false); - } - return; - } -#endif - openDialog("chrome://browser/content/openLocation.xul", "_blank", - "chrome,modal,titlebar", window); -} - -function openLocationCallback() -{ - // make sure the DOM is ready - setTimeout(function() { this.openLocation(); }, 0); -} - -function BrowserOpenTab() -{ - openUILinkIn(BROWSER_NEW_TAB_URL, "tab"); -} - -/* Called from the openLocation dialog. This allows that dialog to instruct - its opener to open a new window and then step completely out of the way. - Anything less byzantine is causing horrible crashes, rather believably, - though oddly only on Linux. */ -function delayedOpenWindow(chrome, flags, href, postData) -{ - // The other way to use setTimeout, - // setTimeout(openDialog, 10, chrome, "_blank", flags, url), - // doesn't work here. The extra "magic" extra argument setTimeout adds to - // the callback function would confuse gBrowserInit.onLoad() by making - // window.arguments[1] be an integer instead of null. - setTimeout(function() { openDialog(chrome, "_blank", flags, href, null, null, postData); }, 10); -} - -/* Required because the tab needs time to set up its content viewers and get the load of - the URI kicked off before becoming the active content area. */ -function delayedOpenTab(aUrl, aReferrer, aCharset, aPostData, aAllowThirdPartyFixup) -{ - gBrowser.loadOneTab(aUrl, { - referrerURI: aReferrer, - charset: aCharset, - postData: aPostData, - inBackground: false, - allowThirdPartyFixup: aAllowThirdPartyFixup}); -} - -var gLastOpenDirectory = { - _lastDir: null, - get path() { - if (!this._lastDir || !this._lastDir.exists()) { - try { - this._lastDir = gPrefService.getComplexValue("browser.open.lastDir", - Ci.nsILocalFile); - if (!this._lastDir.exists()) - this._lastDir = null; - } - catch(e) {} - } - return this._lastDir; - }, - set path(val) { - try { - if (!val || !val.isDirectory()) - return; - } catch(e) { - return; - } - this._lastDir = val.clone(); - - // Don't save the last open directory pref inside the Private Browsing mode - if (!PrivateBrowsingUtils.isWindowPrivate(window)) - gPrefService.setComplexValue("browser.open.lastDir", Ci.nsILocalFile, - this._lastDir); - }, - reset: function() { - this._lastDir = null; - } -}; - -function BrowserOpenFileWindow() -{ - // Get filepicker component. - try { - const nsIFilePicker = Ci.nsIFilePicker; - let fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); - let fpCallback = function fpCallback_done(aResult) { - if (aResult == nsIFilePicker.returnOK) { - try { - if (fp.file) { - gLastOpenDirectory.path = - fp.file.parent.QueryInterface(Ci.nsILocalFile); - } - } catch (ex) { - } - openUILinkIn(fp.fileURL.spec, "current"); - } - }; - - fp.init(window, gNavigatorBundle.getString("openFile"), - nsIFilePicker.modeOpen); - fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText | - nsIFilePicker.filterImages | nsIFilePicker.filterXML | - nsIFilePicker.filterHTML); - fp.displayDirectory = gLastOpenDirectory.path; - fp.open(fpCallback); - } catch (ex) { - } -} - -function BrowserCloseTabOrWindow() { -#ifdef XP_MACOSX - // If we're not a browser window, just close the window - if (window.location.href != getBrowserURL()) { - closeWindow(true); - return; - } -#endif - - // If the current tab is the last one, this will close the window. - gBrowser.removeCurrentTab({animate: true}); -} - -function BrowserTryToCloseWindow() -{ - if (WindowIsClosing()) - window.close(); // WindowIsClosing does all the necessary checks -} - -function loadURI(uri, referrer, postData, allowThirdPartyFixup) { - if (postData === undefined) - postData = null; - - var flags = nsIWebNavigation.LOAD_FLAGS_NONE; - if (allowThirdPartyFixup) { - flags |= nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; - flags |= nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - } - - try { - gBrowser.loadURIWithFlags(uri, flags, referrer, null, postData); - } catch (e) {} -} - -function getShortcutOrURI(aURL, aPostDataRef, aMayInheritPrincipal) { - // Initialize outparam to false - if (aMayInheritPrincipal) - aMayInheritPrincipal.value = false; - - var shortcutURL = null; - var keyword = aURL; - var param = ""; - - var offset = aURL.indexOf(" "); - if (offset > 0) { - keyword = aURL.substr(0, offset); - param = aURL.substr(offset + 1); - } - - if (!aPostDataRef) - aPostDataRef = {}; - - var engine = Services.search.getEngineByAlias(keyword); - if (engine) { - var submission = engine.getSubmission(param); - aPostDataRef.value = submission.postData; - return submission.uri.spec; - } - - [shortcutURL, aPostDataRef.value] = - PlacesUtils.getURLAndPostDataForKeyword(keyword); - - if (!shortcutURL) - return aURL; - - var postData = ""; - if (aPostDataRef.value) - postData = unescape(aPostDataRef.value); - - 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) {} - } - - // 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); - - 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; - - return aURL; - } - - // 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 shortcutURL; -} - -function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) { - var dataStream = Cc["@mozilla.org/io/string-input-stream;1"]. - createInstance(Ci.nsIStringInputStream); - aStringData = aStringData.replace(/%s/g, aEncKeyword).replace(/%S/g, aKeyword); - dataStream.data = aStringData; - - var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"]. - createInstance(Ci.nsIMIMEInputStream); - mimeStream.addHeader("Content-Type", aType); - mimeStream.addContentLength = true; - mimeStream.setData(dataStream); - return mimeStream.QueryInterface(Ci.nsIInputStream); -} - -function getLoadContext() { - return window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsILoadContext); -} - -function readFromClipboard() -{ - var url; - - try { - // Create transferable that will transfer the text. - var trans = Components.classes["@mozilla.org/widget/transferable;1"] - .createInstance(Components.interfaces.nsITransferable); - trans.init(getLoadContext()); - - trans.addDataFlavor("text/unicode"); - - // If available, use selection clipboard, otherwise global one - if (Services.clipboard.supportsSelectionClipboard()) - Services.clipboard.getData(trans, Services.clipboard.kSelectionClipboard); - else - Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard); - - var data = {}; - var dataLen = {}; - trans.getTransferData("text/unicode", data, dataLen); - - if (data) { - data = data.value.QueryInterface(Components.interfaces.nsISupportsString); - url = data.data.substring(0, dataLen.value / 2); - } - } catch (ex) { - } - - return url; -} - -function BrowserViewSourceOfDocument(aDocument) -{ - var pageCookie; - var webNav; - - // Get the document charset - var docCharset = "charset=" + aDocument.characterSet; - - // Get the nsIWebNavigation associated with the document - try { - var win; - var ifRequestor; - - // Get the DOMWindow for the requested document. If the DOMWindow - // cannot be found, then just use the content window... - // - // XXX: This is a bit of a hack... - win = aDocument.defaultView; - if (win == window) { - win = content; - } - ifRequestor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor); - - webNav = ifRequestor.getInterface(nsIWebNavigation); - } catch(err) { - // If nsIWebNavigation cannot be found, just get the one for the whole - // window... - webNav = gBrowser.webNavigation; - } - // - // Get the 'PageDescriptor' for the current document. This allows the - // view-source to access the cached copy of the content rather than - // refetching it from the network... - // - try{ - var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor); - - pageCookie = PageLoader.currentDescriptor; - } catch(err) { - // If no page descriptor is available, just use the view-source URL... - } - - top.gViewSourceUtils.viewSource(webNav.currentURI.spec, pageCookie, aDocument); -} - -// doc - document to use for source, or null for this window's document -// initialTab - name of the initial tab to display, or null for the first tab -// imageElement - image to load in the Media Tab of the Page Info window; can be null/omitted -function BrowserPageInfo(doc, initialTab, imageElement) { - var args = {doc: doc, initialTab: initialTab, imageElement: imageElement}; - var windows = Services.wm.getEnumerator("Browser:page-info"); - - var documentURL = doc ? doc.location : window.content.document.location; - - // Check for windows matching the url - while (windows.hasMoreElements()) { - var currentWindow = windows.getNext(); - if (currentWindow.document.documentElement.getAttribute("relatedUrl") == documentURL) { - currentWindow.focus(); - currentWindow.resetPageInfo(args); - return currentWindow; - } - } - - // We didn't find a matching window, so open a new one. - return openDialog("chrome://browser/content/pageinfo/pageInfo.xul", "", - "chrome,toolbar,dialog=no,resizable", args); -} - -function URLBarSetURI(aURI) { - var value = gBrowser.userTypedValue; - var valid = false; - - if (value == null) { - let uri = aURI || gBrowser.currentURI; - // Strip off "wyciwyg://" and passwords for the location bar - try { - uri = Services.uriFixup.createExposableURI(uri); - } catch (e) {} - - // Replace initial page URIs with an empty string - // only if there's no opener (bug 370555). - // Bug 863515 - Make content.opener checks work in electrolysis. - if (gInitialPages.indexOf(uri.spec) != -1) - value = !gMultiProcessBrowser && content.opener ? uri.spec : ""; - else - value = losslessDecodeURI(uri); - - valid = !isBlankPageURL(uri.spec); - } - - let isDifferentValidValue = valid && value != gURLBar.value; - gURLBar.value = value; - gURLBar.valueIsTyped = !valid; - if (isDifferentValidValue) { - gURLBar.selectionStart = gURLBar.selectionEnd = 0; - } - - SetPageProxyState(valid ? "valid" : "invalid"); -} - -function losslessDecodeURI(aURI) { - let scheme = aURI.scheme; - let decodeASCIIOnly = !(/(https|http|file|ftp)/i.test(scheme)); - - var value = aURI.spec; - - // Try to decode as UTF-8 if there's no encoding sequence that we would break. - if (!/%25(?:3B|2F|3F|3A|40|26|3D|2B|24|2C|23)/i.test(value)) { - if (decodeASCIIOnly) { - // This only decodes ASCII characters (hex) 20-7e, except 25 (%). - // This avoids both cases stipulated below (%-related issues, and \r, \n - // and \t, which would be %0d, %0a and %09, respectively) as well as any - // non-US-ascii characters. - value = value.replace(/%(2[0-4]|2[6-9a-f]|[3-6][0-9a-f]|7[0-9a-e])/g, decodeURI); - } else { - try { - value = decodeURI(value) - // 1. decodeURI decodes %25 to %, which creates unintended - // encoding sequences. Re-encode it, unless it's part of - // a sequence that survived decodeURI, i.e. one for: - // ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#' - // (RFC 3987 section 3.2) - // 2. Re-encode whitespace so that it doesn't get eaten away - // by the location bar (bug 410726). - .replace(/%(?!3B|2F|3F|3A|40|26|3D|2B|24|2C|23)|[\r\n\t]/ig, - encodeURIComponent); - } catch (e) {} - } - } - - // Encode invisible characters (C0/C1 control characters, U+007F [DEL], - // U+00A0 [no-break space], line and paragraph separator, - // object replacement character) (bug 452979, bug 909264) - value = value.replace(/[\u0000-\u001f\u007f-\u00a0\u2028\u2029\ufffc]/g, - encodeURIComponent); - - // Encode default ignorable characters (bug 546013) - // except ZWNJ (U+200C) and ZWJ (U+200D) (bug 582186). - // This includes all bidirectional formatting characters. - // (RFC 3987 sections 3.2 and 4.1 paragraph 6) - value = value.replace(/[\u00ad\u034f\u115f-\u1160\u17b4-\u17b5\u180b-\u180d\u200b\u200e-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufe00-\ufe0f\ufeff\uffa0\ufff0-\ufff8]|\ud834[\udd73-\udd7a]|[\udb40-\udb43][\udc00-\udfff]/g, - encodeURIComponent); - return value; -} - -function UpdateUrlbarSearchSplitterState() -{ - var splitter = document.getElementById("urlbar-search-splitter"); - var urlbar = document.getElementById("urlbar-container"); - var searchbar = document.getElementById("search-container"); - var stop = document.getElementById("stop-button"); - - var ibefore = null; - if (urlbar && searchbar) { - if (urlbar.nextSibling == searchbar || - urlbar.getAttribute("combined") && - stop && stop.nextSibling == searchbar) - ibefore = searchbar; - else if (searchbar.nextSibling == urlbar) - ibefore = urlbar; - } - - if (ibefore) { - if (!splitter) { - splitter = document.createElement("splitter"); - splitter.id = "urlbar-search-splitter"; - splitter.setAttribute("resizebefore", "flex"); - splitter.setAttribute("resizeafter", "flex"); - splitter.setAttribute("skipintoolbarset", "true"); - splitter.className = "chromeclass-toolbar-additional"; - } - urlbar.parentNode.insertBefore(splitter, ibefore); - } else if (splitter) - splitter.parentNode.removeChild(splitter); -} - -function setUrlAndSearchBarWidthForConditionalForwardButton() { - // Workaround for bug 694084: Showing/hiding the conditional forward button resizes - // the search bar when the url/search bar splitter hasn't been used. - var urlbarContainer = document.getElementById("urlbar-container"); - var searchbarContainer = document.getElementById("search-container"); - if (!urlbarContainer || - !searchbarContainer || - urlbarContainer.hasAttribute("width") || - searchbarContainer.hasAttribute("width") || - urlbarContainer.parentNode != searchbarContainer.parentNode) - return; - urlbarContainer.style.width = searchbarContainer.style.width = ""; - var urlbarWidth = urlbarContainer.clientWidth; - var searchbarWidth = searchbarContainer.clientWidth; - urlbarContainer.style.width = urlbarWidth + "px"; - searchbarContainer.style.width = searchbarWidth + "px"; -} - -function UpdatePageProxyState() -{ - if (gURLBar && gURLBar.value != gLastValidURLStr) - SetPageProxyState("invalid"); -} - -function SetPageProxyState(aState) -{ - BookmarkingUI.onPageProxyStateChanged(aState); - - if (!gURLBar) - return; - - if (!gProxyFavIcon) - gProxyFavIcon = document.getElementById("page-proxy-favicon"); - - gURLBar.setAttribute("pageproxystate", aState); - gProxyFavIcon.setAttribute("pageproxystate", aState); - - // the page proxy state is set to valid via OnLocationChange, which - // gets called when we switch tabs. - if (aState == "valid") { - gLastValidURLStr = gURLBar.value; - gURLBar.addEventListener("input", UpdatePageProxyState, false); - PageProxySetIcon(gBrowser.getIcon()); - } else if (aState == "invalid") { - gURLBar.removeEventListener("input", UpdatePageProxyState, false); - PageProxyClearIcon(); - } -} - -function PageProxySetIcon (aURL) -{ - if (!gProxyFavIcon) - return; - - if (gBrowser.selectedBrowser.contentDocument instanceof ImageDocument) { - // PageProxyClearIcon(); - gProxyFavIcon.setAttribute("src", "chrome://browser/skin/imagedocument.png"); - return; - } - - if (!aURL) - PageProxyClearIcon(); - else if (gProxyFavIcon.getAttribute("src") != aURL) - gProxyFavIcon.setAttribute("src", aURL); -} - -function PageProxyClearIcon () -{ - gProxyFavIcon.removeAttribute("src"); -} - - -function PageProxyClickHandler(aEvent) -{ - if (aEvent.button == 1 && gPrefService.getBoolPref("middlemouse.paste")) - middleMousePaste(aEvent); -} - -/** - * Handle load of some pages (about:*) so that we can make modifications - * to the DOM for unprivileged pages. - */ -function BrowserOnAboutPageLoad(doc) { - if (doc.documentURI.toLowerCase() == "about:home") { - let ss = Components.classes["@mozilla.org/browser/sessionstore;1"]. - getService(Components.interfaces.nsISessionStore); - if (ss.canRestoreLastSession && - !PrivateBrowsingUtils.isWindowPrivate(window)) - doc.getElementById("launcher").setAttribute("session", "true"); - - // Inject search engine and snippets URL. - let docElt = doc.documentElement; - // set the following attributes BEFORE searchEngineURL, which triggers to - // show the snippets when it's set. - docElt.setAttribute("snippetsURL", AboutHomeUtils.snippetsURL); - if (AboutHomeUtils.showKnowYourRights) { - docElt.setAttribute("showKnowYourRights", "true"); - // Set pref to indicate we've shown the notification. - let currentVersion = Services.prefs.getIntPref("browser.rights.version"); - Services.prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true); - } - docElt.setAttribute("snippetsVersion", AboutHomeUtils.snippetsVersion); - - function updateSearchEngine() { - let engine = AboutHomeUtils.defaultSearchEngine; - docElt.setAttribute("searchEngineName", engine.name); - docElt.setAttribute("searchEnginePostData", engine.postDataString || ""); - docElt.setAttribute("searchEngineURL", engine.searchURL); - } - updateSearchEngine(); - - // Listen for the event that's triggered when the user changes search engine. - // At this point we simply reload about:home to reflect the change. - Services.obs.addObserver(updateSearchEngine, "browser-search-engine-modified", false); - - // Remove the observer when the page is reloaded or closed. - doc.defaultView.addEventListener("pagehide", function removeObserver() { - doc.defaultView.removeEventListener("pagehide", removeObserver); - Services.obs.removeObserver(updateSearchEngine, "browser-search-engine-modified"); - }, false); - } -} - -/** - * Handle command events bubbling up from error page content - */ -let BrowserOnClick = { - handleEvent: function BrowserOnClick_handleEvent(aEvent) { - if (!aEvent.isTrusted || // Don't trust synthetic events - aEvent.button == 2 || aEvent.target.localName != "button") { - return; - } - - let originalTarget = aEvent.originalTarget; - let ownerDoc = originalTarget.ownerDocument; - - // If the event came from an ssl error page, it is probably either the "Add - // Exception…" or "Get me out of here!" button - if (ownerDoc.documentURI.startsWith("about:certerror")) { - this.onAboutCertError(originalTarget, ownerDoc); - } - else if (ownerDoc.documentURI.startsWith("about:neterror")) { - this.onAboutNetError(originalTarget, ownerDoc); - } - else if (ownerDoc.documentURI.toLowerCase() == "about:home") { - this.onAboutHome(originalTarget, ownerDoc); - } - }, - - onAboutCertError: function BrowserOnClick_onAboutCertError(aTargetElm, aOwnerDoc) { - let elmId = aTargetElm.getAttribute("id"); - let isTopFrame = (aOwnerDoc.defaultView.parent === aOwnerDoc.defaultView); - - switch (elmId) { - case "exceptionDialogButton": - let params = { exceptionAdded : false }; - - try { - switch (Services.prefs.getIntPref("browser.ssl_override_behavior")) { - case 2 : // Pre-fetch & pre-populate - params.prefetchCert = true; - case 1 : // Pre-populate - params.location = aOwnerDoc.location.href; - } - } catch (e) { - Components.utils.reportError("Couldn't get ssl_override pref: " + e); - } - - window.openDialog('chrome://pippki/content/exceptionDialog.xul', - '','chrome,centerscreen,modal', params); - - // If the user added the exception cert, attempt to reload the page - if (params.exceptionAdded) { - aOwnerDoc.location.reload(); - } - break; - - case "getMeOutOfHereButton": - getMeOutOfHere(); - break; - - case "technicalContent": - break; - - case "expertContent": - break; - - } - }, - - onAboutNetError: function BrowserOnClick_onAboutNetError(aTargetElm, aOwnerDoc) { - let elmId = aTargetElm.getAttribute("id"); - if (elmId != "errorTryAgain" || !/e=netOffline/.test(aOwnerDoc.documentURI)) - return; - Services.io.offline = false; - }, - - onAboutHome: function BrowserOnClick_onAboutHome(aTargetElm, aOwnerDoc) { - let elmId = aTargetElm.getAttribute("id"); - - switch (elmId) { - case "restorePreviousSession": - let ss = Cc["@mozilla.org/browser/sessionstore;1"]. - getService(Ci.nsISessionStore); - if (ss.canRestoreLastSession) { - ss.restoreLastSession(); - } - aOwnerDoc.getElementById("launcher").removeAttribute("session"); - break; - - case "downloads": - BrowserDownloadsUI(); - break; - - case "bookmarks": - PlacesCommandHook.showPlacesOrganizer("AllBookmarks"); - break; - - case "history": - PlacesCommandHook.showPlacesOrganizer("History"); - break; - - case "addons": - BrowserOpenAddonsMgr(); - break; - - case "sync": - openPreferences("paneSync"); - break; - - case "settings": - openPreferences(); - break; - } - }, -}; - -/** - * Re-direct the browser to a known-safe page. This function is - * used when, for example, the user browses to a known malware page - * and is presented with about:blocked. The "Get me out of here!" - * button should take the user to the default start page so that even - * when their own homepage is infected, we can get them somewhere safe. - */ -function getMeOutOfHere() { - try { - let toBlank = Services.prefs.getBoolPref("browser.escape_to_blank"); - if (toBlank) { - content.location = "about:logopage"; - return; - } - } catch(e) { - Components.utils.reportError("Couldn't get escape pref: " + e); - } - // Get the start page from the *default* pref branch, not the user's - var prefs = Services.prefs.getDefaultBranch(null); - var url = BROWSER_NEW_TAB_URL; - try { - url = prefs.getComplexValue("browser.startup.homepage", - Ci.nsIPrefLocalizedString).data; - // If url is a pipe-delimited set of pages, just take the first one. - if (url.includes("|")) - url = url.split("|")[0]; - } catch(e) { - Components.utils.reportError("Couldn't get homepage pref: " + e); - } - content.location = url; -} - -function BrowserFullScreen() -{ - window.fullScreen = !window.fullScreen; -} - -function onFullScreen(event) { - FullScreen.toggle(event); -} - -function onMozEnteredDomFullscreen(event) { - FullScreen.enterDomFullscreen(event); -} - -function getWebNavigation() -{ - return gBrowser.webNavigation; -} - -function BrowserReloadWithFlags(reloadFlags) { - /* First, we'll try to use the session history object to reload so - * that framesets are handled properly. If we're in a special - * window (such as view-source) that has no session history, fall - * back on using the web navigation's reload method. - */ - - var webNav = gBrowser.webNavigation; - try { - var sh = webNav.sessionHistory; - if (sh) - webNav = sh.QueryInterface(nsIWebNavigation); - } catch (e) { - } - - try { - webNav.reload(reloadFlags); - } catch (e) { - } -} - -var PrintPreviewListener = { - _printPreviewTab: null, - _tabBeforePrintPreview: null, - - getPrintPreviewBrowser: function () { - if (!this._printPreviewTab) { - this._tabBeforePrintPreview = gBrowser.selectedTab; - this._printPreviewTab = gBrowser.loadOneTab("about:blank", - { inBackground: false }); - gBrowser.selectedTab = this._printPreviewTab; - } - return gBrowser.getBrowserForTab(this._printPreviewTab); - }, - getSourceBrowser: function () { - return this._tabBeforePrintPreview ? - this._tabBeforePrintPreview.linkedBrowser : gBrowser.selectedBrowser; - }, - getNavToolbox: function () { - return gNavToolbox; - }, - onEnter: function () { - // We might have accidentally switched tabs since the user invoked print - // preview - if (gBrowser.selectedTab != this._printPreviewTab) { - gBrowser.selectedTab = this._printPreviewTab; - } - gInPrintPreviewMode = true; - this._toggleAffectedChrome(); - }, - onExit: function () { - gBrowser.selectedTab = this._tabBeforePrintPreview; - this._tabBeforePrintPreview = null; - gInPrintPreviewMode = false; - this._toggleAffectedChrome(); - gBrowser.removeTab(this._printPreviewTab); - this._printPreviewTab = null; - }, - _toggleAffectedChrome: function () { - gNavToolbox.collapsed = gInPrintPreviewMode; - - if (gInPrintPreviewMode) - this._hideChrome(); - else - this._showChrome(); - - if (this._chromeState.sidebarOpen) - toggleSidebar(this._sidebarCommand); - -#ifdef MENUBAR_CAN_AUTOHIDE - updateAppButtonDisplay(); -#endif - }, - _hideChrome: function () { - this._chromeState = {}; - - var sidebar = document.getElementById("sidebar-box"); - this._chromeState.sidebarOpen = !sidebar.hidden; - this._sidebarCommand = sidebar.getAttribute("sidebarcommand"); - - var notificationBox = gBrowser.getNotificationBox(); - this._chromeState.notificationsOpen = !notificationBox.notificationsHidden; - notificationBox.notificationsHidden = true; - - document.getElementById("sidebar").setAttribute("src", "about:blank"); - var addonBar = document.getElementById("addon-bar"); - this._chromeState.addonBarOpen = !addonBar.collapsed; - addonBar.collapsed = true; - gBrowser.updateWindowResizers(); - - this._chromeState.findOpen = gFindBarInitialized && !gFindBar.hidden; - if (gFindBarInitialized) - gFindBar.close(); - - var globalNotificationBox = document.getElementById("global-notificationbox"); - this._chromeState.globalNotificationsOpen = !globalNotificationBox.notificationsHidden; - globalNotificationBox.notificationsHidden = true; - - this._chromeState.syncNotificationsOpen = false; - var syncNotifications = document.getElementById("sync-notifications"); - if (syncNotifications) { - this._chromeState.syncNotificationsOpen = !syncNotifications.notificationsHidden; - syncNotifications.notificationsHidden = true; - } - }, - _showChrome: function () { - if (this._chromeState.notificationsOpen) - gBrowser.getNotificationBox().notificationsHidden = false; - - if (this._chromeState.addonBarOpen) { - document.getElementById("addon-bar").collapsed = false; - gBrowser.updateWindowResizers(); - } - - if (this._chromeState.findOpen) - gFindBar.open(); - - if (this._chromeState.globalNotificationsOpen) - document.getElementById("global-notificationbox").notificationsHidden = false; - - if (this._chromeState.syncNotificationsOpen) - document.getElementById("sync-notifications").notificationsHidden = false; - } -} - -function getMarkupDocumentViewer() -{ - return gBrowser.markupDocumentViewer; -} - -// This function is obsolete. Newer code should use <tooltip page="true"/> instead. -function FillInHTMLTooltip(tipElement) -{ - document.getElementById("aHTMLTooltip").fillInPageTooltip(tipElement); -} - -var browserDragAndDrop = { - canDropLink: function (aEvent) Services.droppedLinkHandler.canDropLink(aEvent, true), - - dragOver: function (aEvent) - { - if (this.canDropLink(aEvent)) { - aEvent.preventDefault(); - } - }, - - drop: function (aEvent, aName, aDisallowInherit) { - return Services.droppedLinkHandler.dropLink(aEvent, aName, aDisallowInherit); - } -}; - -var homeButtonObserver = { - onDrop: function (aEvent) - { - // disallow setting home pages that inherit the principal - let url = browserDragAndDrop.drop(aEvent, {}, true); - setTimeout(openHomeDialog, 0, url); - }, - - onDragOver: function (aEvent) - { - browserDragAndDrop.dragOver(aEvent); - aEvent.dropEffect = "link"; - }, - onDragExit: function (aEvent) - { - } -} - -function openHomeDialog(aURL) -{ - var promptTitle = gNavigatorBundle.getString("droponhometitle"); - var 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; - gPrefService.setComplexValue("browser.startup.homepage", - Components.interfaces.nsISupportsString, str); - } catch (ex) { - dump("Failed to set the home page.\n"+ex+"\n"); - } - } -} - -var bookmarksButtonObserver = { - onDrop: function (aEvent) - { - let name = { }; - let url = browserDragAndDrop.drop(aEvent, name); - try { - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "bookmark" - , uri: makeURI(url) - , title: name - , hiddenRows: [ "description" - , "location" - , "loadInSidebar" - , "keyword" ] - }, window); - } catch(ex) { } - }, - - onDragOver: function (aEvent) - { - browserDragAndDrop.dragOver(aEvent); - aEvent.dropEffect = "link"; - }, - - onDragExit: function (aEvent) - { - } -} - -var newTabButtonObserver = { - onDragOver: function (aEvent) - { - browserDragAndDrop.dragOver(aEvent); - }, - - onDragExit: function (aEvent) - { - }, - - 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); - } - } -} - -var newWindowButtonObserver = { - onDragOver: function (aEvent) - { - browserDragAndDrop.dragOver(aEvent); - }, - onDragExit: function (aEvent) - { - }, - 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); - } - } -} - -const DOMLinkHandler = { - handleEvent: function (event) { - switch (event.type) { - case "DOMLinkAdded": - this.onLinkAdded(event); - break; - } - }, - getLinkIconURI: function(aLink) { - let targetDoc = aLink.ownerDocument; - var uri = makeURI(aLink.href, targetDoc.characterSet); - - // Verify that the load of this icon is legal. - // Some error or special pages can load their favicon. - // To be on the safe side, only allow chrome:// favicons. - var isAllowedPage = [ - /^about:neterror\?/, - /^about:blocked\?/, - /^about:certerror\?/, - /^about:home$/, - ].some(function (re) re.test(targetDoc.documentURI)); - - if (!isAllowedPage || !uri.schemeIs("chrome")) { - var ssm = Services.scriptSecurityManager; - try { - ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri, - Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); - } catch(e) { - return null; - } - } - - try { - var contentPolicy = Cc["@mozilla.org/layout/content-policy;1"]. - getService(Ci.nsIContentPolicy); - } catch(e) { - return null; // Refuse to load if we can't do a security check. - } - - // Security says okay, now ask content policy - if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE, - uri, targetDoc.documentURIObject, - aLink, aLink.type, null) - != Ci.nsIContentPolicy.ACCEPT) - return null; - - try { - uri.userPass = ""; - } catch(e) { - // some URIs are immutable - } - return uri; - }, - onLinkAdded: function (event) { - var link = event.originalTarget; - var rel = link.rel && link.rel.toLowerCase(); - if (!link || !link.ownerDocument || !rel || !link.href) - return; - - var feedAdded = false; - var iconAdded = false; - var searchAdded = false; - var rels = {}; - for (let relString of rel.split(/\s+/)) - rels[relString] = true; - - for (let relVal in rels) { - switch (relVal) { - case "feed": - case "alternate": - if (!feedAdded) { - if (!rels.feed && rels.alternate && rels.stylesheet) - break; - - if (isValidFeed(link, link.ownerDocument.nodePrincipal, "feed" in rels)) { - FeedHandler.addFeed(link, link.ownerDocument); - feedAdded = true; - } - } - break; - case "icon": - if (!iconAdded) { - if (!gPrefService.getBoolPref("browser.chrome.site_icons")) - break; - - var uri = this.getLinkIconURI(link); - if (!uri) - break; - - if (gBrowser.isFailedIcon(uri)) - break; - - var browserIndex = gBrowser.getBrowserIndexForDocument(link.ownerDocument); - // no browser? no favicon. - if (browserIndex == -1) - break; - - let tab = gBrowser.tabs[browserIndex]; - gBrowser.setIcon(tab, uri.spec); - iconAdded = true; - } - break; - case "search": - if (!searchAdded) { - var type = link.type && link.type.toLowerCase(); - type = type.replace(/^\s+|\s*(?:;.*)?$/g, ""); - - if (type == "application/opensearchdescription+xml" && link.title && - /^(?:https?|ftp):/i.test(link.href) && - !PrivateBrowsingUtils.isWindowPrivate(window)) { - var engine = { title: link.title, href: link.href }; - BrowserSearch.addEngine(engine, link.ownerDocument); - searchAdded = true; - } - } - break; - } - } - } -} - -const BrowserSearch = { - addEngine: function(engine, targetDoc) { - if (!this.searchBar) - return; - - var browser = gBrowser.getBrowserForDocument(targetDoc); - // ignore search engines from subframes (see bug 479408) - if (!browser) - return; - - // Check to see whether we've already added an engine with this title - if (browser.engines) { - if (browser.engines.some(function (e) e.title == engine.title)) - return; - } - - // Append the URI and an appropriate title to the browser data. - // Use documentURIObject in the check for shouldLoadFavIcon so that we - // do the right thing with about:-style error pages. Bug 453442 - var iconURL = null; - if (gBrowser.shouldLoadFavIcon(targetDoc.documentURIObject)) - iconURL = targetDoc.documentURIObject.prePath + "/favicon.ico"; - - var hidden = false; - // If this engine (identified by title) is already in the list, add it - // to the list of hidden engines rather than to the main list. - // XXX This will need to be changed when engines are identified by URL; - // see bug 335102. - if (Services.search.getEngineByName(engine.title)) - hidden = true; - - var engines = (hidden ? browser.hiddenEngines : browser.engines) || []; - - engines.push({ uri: engine.href, - title: engine.title, - icon: iconURL }); - - if (hidden) - browser.hiddenEngines = engines; - else - browser.engines = engines; - }, - - /** - * Gives focus to the search bar, if it is present on the toolbar, or loads - * the default engine's search form otherwise. For Mac, opens a new window - * or focuses an existing window, if necessary. - */ - webSearch: function BrowserSearch_webSearch() { -#ifdef XP_MACOSX - if (window.location.href != getBrowserURL()) { - var win = getTopWin(); - if (win) { - // If there's an open browser window, it should handle this command - win.focus(); - win.BrowserSearch.webSearch(); - } else { - // If there are no open browser windows, open a new one - var observer = function observer(subject, topic, data) { - if (subject == win) { - BrowserSearch.webSearch(); - Services.obs.removeObserver(observer, "browser-delayed-startup-finished"); - } - } - win = window.openDialog(getBrowserURL(), "_blank", - "chrome,all,dialog=no", "about:blank"); - Services.obs.addObserver(observer, "browser-delayed-startup-finished", false); - } - return; - } -#endif - var searchBar = this.searchBar; - if (searchBar && window.fullScreen) - FullScreen.mouseoverToggle(true); - if (searchBar) - searchBar.select(); - if (!searchBar || document.activeElement != searchBar.textbox.inputField) - openUILinkIn(Services.search.defaultEngine.searchForm, "current"); - }, - - /** - * Loads a search results page, given a set of search terms. Uses the current - * engine if the search bar is visible, or the default engine otherwise. - * - * @param searchText - * The search terms to use for the search. - * - * @param useNewTab - * Boolean indicating whether or not the search should load in a new - * tab. - * - * @param purpose [optional] - * A string meant to indicate the context of the search request. This - * allows the search service to provide a different nsISearchSubmission - * depending on e.g. where the search is triggered in the UI. - * - * @return string Name of the search engine used to perform a search or null - * if a search was not performed. - */ - loadSearch: function BrowserSearch_search(searchText, useNewTab, purpose) { - var engine; - - // If the search bar is visible, use the current engine, otherwise, fall - // back to the default engine. - if (isElementVisible(this.searchBar)) - engine = Services.search.currentEngine; - else - engine = Services.search.defaultEngine; - - var submission = engine.getSubmission(searchText, null, purpose); // HTML response - - // getSubmission can return null if the engine doesn't have a URL - // with a text/html response type. This is unlikely (since - // SearchService._addEngineToStore() should fail for such an engine), - // but let's be on the safe side. - if (!submission) { - return null; - } - - let inBackground = Services.prefs.getBoolPref("browser.search.context.loadInBackground"); - openLinkIn(submission.uri.spec, - useNewTab ? "tab" : "current", - { postData: submission.postData, - inBackground: inBackground, - relatedToCurrent: true }); - - return engine.name; - }, - - /** - * Perform a search initiated from the context menu. - * - * This should only be called from the context menu. See - * BrowserSearch.loadSearch for the preferred API. - */ - loadSearchFromContext: function (terms) { - let engine = BrowserSearch.loadSearch(terms, true, "contextmenu"); - }, - - /** - * Returns the search bar element if it is present in the toolbar, null otherwise. - */ - get searchBar() { - return document.getElementById("searchbar"); - }, - - loadAddEngines: function BrowserSearch_loadAddEngines() { - var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow"); - var where = newWindowPref == 3 ? "tab" : "window"; - var searchEnginesURL = formatURL("browser.search.searchEnginesURL", true); - openUILinkIn(searchEnginesURL, where); - }, -}; - -function FillHistoryMenu(aParent) { - // Lazily add the hover listeners on first showing and never remove them - if (!aParent.hasStatusListener) { - // Show history item's uri in the status bar when hovering, and clear on exit - aParent.addEventListener("DOMMenuItemActive", function(aEvent) { - // Only the current page should have the checked attribute, so skip it - if (!aEvent.target.hasAttribute("checked")) - XULBrowserWindow.setOverLink(aEvent.target.getAttribute("uri")); - }, false); - aParent.addEventListener("DOMMenuItemInactive", function() { - XULBrowserWindow.setOverLink(""); - }, false); - - aParent.hasStatusListener = true; - } - - // Remove old entries if any - var children = aParent.childNodes; - for (var i = children.length - 1; i >= 0; --i) { - if (children[i].hasAttribute("index")) - aParent.removeChild(children[i]); - } - - var webNav = gBrowser.webNavigation; - var sessionHistory = webNav.sessionHistory; - - var count = sessionHistory.count; - if (count <= 1) // don't display the popup for a single item - return false; - - const MAX_HISTORY_MENU_ITEMS = 15; - var index = sessionHistory.index; - var half_length = Math.floor(MAX_HISTORY_MENU_ITEMS / 2); - var start = Math.max(index - half_length, 0); - var end = Math.min(start == 0 ? MAX_HISTORY_MENU_ITEMS : index + half_length + 1, count); - if (end == count) - start = Math.max(count - MAX_HISTORY_MENU_ITEMS, 0); - - var tooltipBack = gNavigatorBundle.getString("tabHistory.goBack"); - var tooltipCurrent = gNavigatorBundle.getString("tabHistory.current"); - var tooltipForward = gNavigatorBundle.getString("tabHistory.goForward"); - - for (var j = end - 1; j >= start; j--) { - let item = document.createElement("menuitem"); - let entry = sessionHistory.getEntryAtIndex(j, false); - let uri = entry.URI.spec; - - item.setAttribute("uri", uri); - item.setAttribute("label", entry.title || uri); - item.setAttribute("index", j); - - if (j != index) { - PlacesUtils.favicons.getFaviconURLForPage(entry.URI, function (aURI) { - if (aURI) { - let iconURL = PlacesUtils.favicons.getFaviconLinkForIcon(aURI).spec; - item.style.listStyleImage = "url(" + iconURL + ")"; - } - }); - } - - if (j < index) { - item.className = "unified-nav-back menuitem-iconic menuitem-with-favicon"; - item.setAttribute("tooltiptext", tooltipBack); - } else if (j == index) { - item.setAttribute("type", "radio"); - item.setAttribute("checked", "true"); - item.className = "unified-nav-current"; - item.setAttribute("tooltiptext", tooltipCurrent); - } else { - item.className = "unified-nav-forward menuitem-iconic menuitem-with-favicon"; - item.setAttribute("tooltiptext", tooltipForward); - } - - aParent.appendChild(item); - } - return true; -} - -function addToUrlbarHistory(aUrlToAdd) { - if (!PrivateBrowsingUtils.isWindowPrivate(window) && - aUrlToAdd && - !aUrlToAdd.includes(" ") && - !/[\x00-\x1F]/.test(aUrlToAdd)) - PlacesUIUtils.markPageAsTyped(aUrlToAdd); -} - -function toJavaScriptConsole() -{ - toOpenWindowByType("global:console", "chrome://global/content/console.xul"); -} - -function BrowserDownloadsUI() -{ - if (PrivateBrowsingUtils.isWindowPrivate(window)) { - openUILinkIn("about:downloads", "tab"); - } else { - PlacesCommandHook.showPlacesOrganizer("Downloads"); - } -} - -function toOpenWindowByType(inType, uri, features) -{ - var topWindow = Services.wm.getMostRecentWindow(inType); - - if (topWindow) - topWindow.focus(); - else if (features) - window.open(uri, "_blank", features); - else - window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar"); -} - -function OpenBrowserWindow(options) -{ - function newDocumentShown(doc, topic, data) { - if (topic == "document-shown" && - doc != document && - doc.defaultView == win) { - Services.obs.removeObserver(newDocumentShown, "document-shown"); - } - }; - Services.obs.addObserver(newDocumentShown, "document-shown", false); - - var charsetArg = new String(); - var handler = Components.classes["@mozilla.org/browser/clh;1"] - .getService(Components.interfaces.nsIBrowserHandler); - var defaultArgs = handler.defaultArgs; - var wintype = document.documentElement.getAttribute('windowtype'); - - var extraFeatures = ""; - if (options && options.private) { - extraFeatures = ",private"; - if (!PrivateBrowsingUtils.permanentPrivateBrowsing) { - // Force the new window to load about:privatebrowsing instead of the default home page - defaultArgs = "about:privatebrowsing"; - } - } else { - extraFeatures = ",non-private"; - } - - // if and only if the current window is a browser window and it has a document with a character - // set, then extract the current charset menu setting from the current document and use it to - // initialize the new browser window... - var win; - if (window && (wintype == "navigator:browser") && window.content && window.content.document) - { - var DocCharset = window.content.document.characterSet; - charsetArg = "charset="+DocCharset; - - //we should "inherit" the charset menu setting in a new window - win = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no" + extraFeatures, defaultArgs, charsetArg); - } - else // forget about the charset information. - { - win = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no" + extraFeatures, defaultArgs); - } - - return win; -} - -var gCustomizeSheet = false; -function BrowserCustomizeToolbar() { - // Disable the toolbar context menu items - var menubar = document.getElementById("main-menubar"); - for (let childNode of menubar.childNodes) - childNode.setAttribute("disabled", true); - - var cmd = document.getElementById("cmd_CustomizeToolbars"); - cmd.setAttribute("disabled", "true"); - - var splitter = document.getElementById("urlbar-search-splitter"); - if (splitter) - splitter.parentNode.removeChild(splitter); - - CombinedStopReload.uninit(); - - PlacesToolbarHelper.customizeStart(); - BookmarkingUI.customizeStart(); - DownloadsButton.customizeStart(); - - TabsInTitlebar.allowedBy("customizing-toolbars", false); - - var customizeURL = "chrome://global/content/customizeToolbar.xul"; - gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false); - - if (gCustomizeSheet) { - let sheetFrame = document.createElement("iframe"); - let panel = document.getElementById("customizeToolbarSheetPopup"); - sheetFrame.id = "customizeToolbarSheetIFrame"; - sheetFrame.toolbox = gNavToolbox; - sheetFrame.panel = panel; - sheetFrame.setAttribute("style", panel.getAttribute("sheetstyle")); - panel.appendChild(sheetFrame); - - // Open the panel, but make it invisible until the iframe has loaded so - // that the user doesn't see a white flash. - panel.style.visibility = "hidden"; - gNavToolbox.addEventListener("beforecustomization", function onBeforeCustomization() { - gNavToolbox.removeEventListener("beforecustomization", onBeforeCustomization, false); - panel.style.removeProperty("visibility"); - }, false); - - sheetFrame.setAttribute("src", customizeURL); - - panel.openPopup(gNavToolbox, "after_start", 0, 0); - } else { - window.openDialog(customizeURL, - "CustomizeToolbar", - "chrome,titlebar,toolbar,location,resizable,dependent", - gNavToolbox); - } -} - -function BrowserToolboxCustomizeDone(aToolboxChanged) { - if (gCustomizeSheet) { - document.getElementById("customizeToolbarSheetPopup").hidePopup(); - let iframe = document.getElementById("customizeToolbarSheetIFrame"); - iframe.parentNode.removeChild(iframe); - } - - // Update global UI elements that may have been added or removed - if (aToolboxChanged) { - gURLBar = document.getElementById("urlbar"); - - gProxyFavIcon = document.getElementById("page-proxy-favicon"); - gHomeButton.updateTooltip(); - gIdentityHandler._cacheElements(); - window.XULBrowserWindow.init(); - -#ifndef XP_MACOSX - updateEditUIVisibility(); -#endif - - // Hacky: update the PopupNotifications' object's reference to the iconBox, - // if it already exists, since it may have changed if the URL bar was - // added/removed. - if (!window.__lookupGetter__("PopupNotifications")) - PopupNotifications.iconBox = document.getElementById("notification-popup-box"); - } - - PlacesToolbarHelper.customizeDone(); - BookmarkingUI.customizeDone(); - DownloadsButton.customizeDone(); - - // The url bar splitter state is dependent on whether stop/reload - // and the location bar are combined, so we need this ordering - CombinedStopReload.init(); - UpdateUrlbarSearchSplitterState(); - setUrlAndSearchBarWidthForConditionalForwardButton(); - - // Update the urlbar - if (gURLBar) { - URLBarSetURI(); - XULBrowserWindow.asyncUpdateUI(); - BookmarkingUI.updateStarState(); - } - - TabsInTitlebar.allowedBy("customizing-toolbars", true); - - // Re-enable parts of the UI we disabled during the dialog - var menubar = document.getElementById("main-menubar"); - for (let childNode of menubar.childNodes) - childNode.setAttribute("disabled", false); - var cmd = document.getElementById("cmd_CustomizeToolbars"); - cmd.removeAttribute("disabled"); - - // make sure to re-enable click-and-hold - if (!getBoolPref("ui.click_hold_context_menus", false)) - SetClickAndHoldHandlers(); - - gBrowser.selectedBrowser.focus(); -} - -function BrowserToolboxCustomizeChange(aType) { - switch (aType) { - case "iconsize": - case "mode": - retrieveToolbarIconsizesFromTheme(); - break; - default: - gHomeButton.updatePersonalToolbarStyle(); - BookmarkingUI.customizeChange(); - allTabs.readPref(); - } -} - -/** - * Allows themes to override the "iconsize" attribute on toolbars. - */ -function retrieveToolbarIconsizesFromTheme() { - function retrieveToolbarIconsize(aToolbar) { - if (aToolbar.localName != "toolbar") - return; - - // The theme indicates that it wants to override the "iconsize" attribute - // by specifying a special value for the "counter-reset" property on the - // toolbar. A custom property cannot be used because getComputedStyle can - // only return the values of standard CSS properties. - let counterReset = getComputedStyle(aToolbar).counterReset; - if (counterReset == "smallicons 0") - aToolbar.setAttribute("iconsize", "small"); - else if (counterReset == "largeicons 0") - aToolbar.setAttribute("iconsize", "large"); - } - - Array.forEach(gNavToolbox.childNodes, retrieveToolbarIconsize); - gNavToolbox.externalToolbars.forEach(retrieveToolbarIconsize); -} - -/** - * Update the global flag that tracks whether or not any edit UI (the Edit menu, - * edit-related items in the context menu, and edit-related toolbar buttons - * is visible, then update the edit commands' enabled state accordingly. We use - * this flag to skip updating the edit commands on focus or selection changes - * when no UI is visible to improve performance (including pageload performance, - * since focus changes when you load a new page). - * - * If UI is visible, we use goUpdateGlobalEditMenuItems to set the commands' - * enabled state so the UI will reflect it appropriately. - * - * If the UI isn't visible, we enable all edit commands so keyboard shortcuts - * still work and just lazily disable them as needed when the user presses a - * shortcut. - * - * This doesn't work on Mac, since Mac menus flash when users press their - * keyboard shortcuts, so edit UI is essentially always visible on the Mac, - * and we need to always update the edit commands. Thus on Mac this function - * is a no op. - */ -function updateEditUIVisibility() -{ -#ifndef XP_MACOSX - let editMenuPopupState = document.getElementById("menu_EditPopup").state; - let contextMenuPopupState = document.getElementById("contentAreaContextMenu").state; - let placesContextMenuPopupState = document.getElementById("placesContext").state; -#ifdef MENUBAR_CAN_AUTOHIDE - let appMenuPopupState = document.getElementById("appmenu-popup").state; -#endif - - // The UI is visible if the Edit menu is opening or open, if the context menu - // is open, or if the toolbar has been customized to include the Cut, Copy, - // or Paste toolbar buttons. - gEditUIVisible = editMenuPopupState == "showing" || - editMenuPopupState == "open" || - contextMenuPopupState == "showing" || - contextMenuPopupState == "open" || - placesContextMenuPopupState == "showing" || - placesContextMenuPopupState == "open" || -#ifdef MENUBAR_CAN_AUTOHIDE - appMenuPopupState == "showing" || - appMenuPopupState == "open" || -#endif - document.getElementById("cut-button") || - document.getElementById("copy-button") || - document.getElementById("paste-button") ? true : false; - - // If UI is visible, update the edit commands' enabled state to reflect - // whether or not they are actually enabled for the current focus/selection. - if (gEditUIVisible) - goUpdateGlobalEditMenuItems(); - - // Otherwise, enable all commands, so that keyboard shortcuts still work, - // then lazily determine their actual enabled state when the user presses - // a keyboard shortcut. - else { - goSetCommandEnabled("cmd_undo", true); - goSetCommandEnabled("cmd_redo", true); - goSetCommandEnabled("cmd_cut", true); - goSetCommandEnabled("cmd_copy", true); - goSetCommandEnabled("cmd_paste", true); - goSetCommandEnabled("cmd_selectAll", true); - goSetCommandEnabled("cmd_delete", true); - goSetCommandEnabled("cmd_switchTextDirection", true); - } -#endif -} - -/** - * Makes the Character Encoding menu enabled or disabled as appropriate. - * To be called when the View menu or the app menu is opened. - */ -function updateCharacterEncodingMenuState() -{ - let charsetMenu = document.getElementById("charsetMenu"); - let appCharsetMenu = document.getElementById("appmenu_charsetMenu"); - let appDevCharsetMenu = - document.getElementById("appmenu_developer_charsetMenu"); - // gBrowser is null on Mac when the menubar shows in the context of - // non-browser windows. The above elements may be null depending on - // what parts of the menubar are present. E.g. no app menu on Mac. - if (gBrowser && - gBrowser.docShell && - gBrowser.docShell.mayEnableCharacterEncodingMenu) { - if (charsetMenu) { - charsetMenu.removeAttribute("disabled"); - } - if (appCharsetMenu) { - appCharsetMenu.removeAttribute("disabled"); - } - if (appDevCharsetMenu) { - appDevCharsetMenu.removeAttribute("disabled"); - } - } else { - if (charsetMenu) { - charsetMenu.setAttribute("disabled", "true"); - } - if (appCharsetMenu) { - appCharsetMenu.setAttribute("disabled", "true"); - } - if (appDevCharsetMenu) { - appDevCharsetMenu.setAttribute("disabled", "true"); - } - } -} - -/** - * Returns true if |aMimeType| is text-based, false otherwise. - * - * @param aMimeType - * The MIME type to check. - * - * If adding types to this function, please also check the similar - * function in findbar.xml - */ -function mimeTypeIsTextBased(aMimeType) -{ - return aMimeType.startsWith("text/") || - aMimeType.endsWith("+xml") || - aMimeType == "application/x-javascript" || - aMimeType == "application/javascript" || - aMimeType == "application/json" || - aMimeType == "application/xml" || - aMimeType == "mozilla.application/cached-xul"; -} - -var XULBrowserWindow = { - // Stored Status, Link and Loading values - status: "", - defaultStatus: "", - overLink: "", - startTime: 0, - statusText: "", - isBusy: false, -/* Pale Moon: Don't hide navigation controls and toolbars for "special" pages. SBaD, M! - inContentWhitelist: ["about:addons", "about:downloads", "about:permissions", - "about:sync-progress"],*/ - inContentWhitelist: [], - - QueryInterface: function (aIID) { - if (aIID.equals(Ci.nsIWebProgressListener) || - aIID.equals(Ci.nsIWebProgressListener2) || - aIID.equals(Ci.nsISupportsWeakReference) || - aIID.equals(Ci.nsIXULBrowserWindow) || - aIID.equals(Ci.nsISupports)) - return this; - throw Cr.NS_NOINTERFACE; - }, - - get stopCommand () { - delete this.stopCommand; - return this.stopCommand = document.getElementById("Browser:Stop"); - }, - get reloadCommand () { - delete this.reloadCommand; - return this.reloadCommand = document.getElementById("Browser:Reload"); - }, - get statusTextField () { - delete this.statusTextField; - return this.statusTextField = document.getElementById("statusbar-display"); - }, - get isImage () { - delete this.isImage; - return this.isImage = document.getElementById("isImage"); - }, - - init: function () { - this.throbberElement = document.getElementById("navigator-throbber"); - - // Bug 666809 - SecurityUI support for e10s - if (gMultiProcessBrowser) - return; - - // Initialize the security button's state and tooltip text. Remember to reset - // _hostChanged, otherwise onSecurityChange will short circuit. - var securityUI = gBrowser.securityUI; - this._hostChanged = true; - this.onSecurityChange(null, null, securityUI.state); - }, - - destroy: function () { - // XXXjag to avoid leaks :-/, see bug 60729 - delete this.throbberElement; - delete this.stopCommand; - delete this.reloadCommand; - delete this.statusTextField; - delete this.statusText; - }, - - setJSStatus: function () { - // unsupported - }, - - setDefaultStatus: function (status) { - this.defaultStatus = status; - this.updateStatusField(); - }, - - setOverLink: function (url, anchorElt) { - // Encode bidirectional formatting characters. - // (RFC 3987 sections 3.2 and 4.1 paragraph 6) - url = url.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g, - encodeURIComponent); - - if (gURLBar && gURLBar._mayTrimURLs /* corresponds to browser.urlbar.trimURLs */) - url = trimURL(url); - - this.overLink = url; - LinkTargetDisplay.update(); - }, - - updateStatusField: function () { - var text, type, types = ["overLink"]; - if (this._busyUI) - types.push("status"); - types.push("defaultStatus"); - for (type of types) { - text = this[type]; - if (text) - break; - } - - // check the current value so we don't trigger an attribute change - // and cause needless (slow!) UI updates - if (this.statusText != text) { - let field = this.statusTextField; - field.setAttribute("previoustype", field.getAttribute("type")); - field.setAttribute("type", type); - field.label = text; - field.setAttribute("crop", type == "overLink" ? "center" : "end"); - this.statusText = text; - } - }, - - // Called before links are navigated to to allow us to retarget them if needed. - onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) { - let target = this._onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab); - return target; - }, - - _onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) { - // Don't modify non-default targets or targets that aren't in top-level app - // tab docshells (isAppTab will be false for app tab subframes). - if (originalTarget != "" || !isAppTab) - return originalTarget; - - // External links from within app tabs should always open in new tabs - // instead of replacing the app tab's page (Bug 575561) - let linkHost; - let docHost; - try { - linkHost = linkURI.host; - docHost = linkNode.ownerDocument.documentURIObject.host; - } catch(e) { - // nsIURI.host can throw for non-nsStandardURL nsIURIs. - // If we fail to get either host, just return originalTarget. - return originalTarget; - } - - if (docHost == linkHost) - return originalTarget; - - // Special case: ignore "www" prefix if it is part of host string - let [longHost, shortHost] = - linkHost.length > docHost.length ? [linkHost, docHost] : [docHost, linkHost]; - if (longHost == "www." + shortHost) - return originalTarget; - - return "_blank"; - }, - - onLinkIconAvailable: function (aIconURL) { - if (gProxyFavIcon && gBrowser.userTypedValue === null) { - PageProxySetIcon(aIconURL); // update the favicon in the URL bar - } - }, - - onProgressChange: function (aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, - aCurTotalProgress, aMaxTotalProgress) { - // Do nothing. - }, - - onProgressChange64: function (aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, - aCurTotalProgress, aMaxTotalProgress) { - return this.onProgressChange(aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, - aMaxTotalProgress); - }, - - // This function fires only for the currently selected tab. - onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) { - const nsIWebProgressListener = Ci.nsIWebProgressListener; - const nsIChannel = Ci.nsIChannel; - - if (aStateFlags & nsIWebProgressListener.STATE_START && - aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { - - if (aRequest && aWebProgress.isTopLevel) { - // clear out feed data - gBrowser.selectedBrowser.feeds = null; - - // clear out search-engine data - gBrowser.selectedBrowser.engines = null; - } - - this.isBusy = true; - - if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) { - this._busyUI = true; - - // Turn the throbber on. - if (this.throbberElement) - this.throbberElement.setAttribute("busy", "true"); - - // XXX: This needs to be based on window activity... - this.stopCommand.removeAttribute("disabled"); - CombinedStopReload.switchToStop(); - } - } - else if (aStateFlags & nsIWebProgressListener.STATE_STOP) { - // This (thanks to the filter) is a network stop or the last - // request stop outside of loading the document, stop throbbers - // and progress bars and such - if (aRequest) { - let msg = ""; - let location; - // Get the URI either from a channel or a pseudo-object - if (aRequest instanceof nsIChannel || "URI" in aRequest) { - location = aRequest.URI; - - // For keyword URIs clear the user typed value since they will be changed into real URIs - if (location.scheme == "keyword" && aWebProgress.isTopLevel) - gBrowser.userTypedValue = null; - - if (location.spec != "about:blank") { - switch (aStatus) { - case Components.results.NS_ERROR_NET_TIMEOUT: - msg = gNavigatorBundle.getString("nv_timeout"); - break; - } - } - } - - this.status = ""; - this.setDefaultStatus(msg); - - // Disable menu entries for images, enable otherwise - if (!gMultiProcessBrowser && content.document && mimeTypeIsTextBased(content.document.contentType)) - this.isImage.removeAttribute('disabled'); - else - this.isImage.setAttribute('disabled', 'true'); - } - - this.isBusy = false; - - if (this._busyUI) { - this._busyUI = false; - - // Turn the throbber off. - if (this.throbberElement) - this.throbberElement.removeAttribute("busy"); - - this.stopCommand.setAttribute("disabled", "true"); - CombinedStopReload.switchToReload(aRequest instanceof Ci.nsIRequest); - } - } - }, - - onLocationChange: function (aWebProgress, aRequest, aLocationURI, aFlags) { - var location = aLocationURI ? aLocationURI.spec : ""; - this._hostChanged = true; - - // If displayed, hide the form validation popup. - FormValidationHandler.hidePopup(); - - let pageTooltip = document.getElementById("aHTMLTooltip"); - let tooltipNode = pageTooltip.triggerNode; - if (tooltipNode) { - // Optimise for the common case - if (aWebProgress.isTopLevel) { - pageTooltip.hidePopup(); - } - else { - for (let tooltipWindow = tooltipNode.ownerDocument.defaultView; - tooltipWindow != tooltipWindow.parent; - tooltipWindow = tooltipWindow.parent) { - if (tooltipWindow == aWebProgress.DOMWindow) { - pageTooltip.hidePopup(); - break; - } - } - } - } - - // Disable menu entries for images, enable otherwise - if (!gMultiProcessBrowser && content.document && mimeTypeIsTextBased(content.document.contentType)) - this.isImage.removeAttribute('disabled'); - else - this.isImage.setAttribute('disabled', 'true'); - - this.hideOverLinkImmediately = true; - this.setOverLink("", null); - this.hideOverLinkImmediately = false; - - // We should probably not do this if the value has changed since the user - // searched - // Update urlbar only if a new page was loaded on the primary content area - // Do not update urlbar if there was a subframe navigation - - var browser = gBrowser.selectedBrowser; - if (aWebProgress.isTopLevel) { - if ((location == "about:blank" && (gMultiProcessBrowser || !content.opener)) || - location == "") { // Second condition is for new tabs, otherwise - // reload function is enabled until tab is refreshed. - this.reloadCommand.setAttribute("disabled", "true"); - } else { - this.reloadCommand.removeAttribute("disabled"); - } - - if (gURLBar) { - URLBarSetURI(aLocationURI); - - // Update starring UI - BookmarkingUI.updateStarState(); - } - - // Show or hide browser chrome based on the whitelist - if (this.hideChromeForLocation(location)) { - document.documentElement.setAttribute("disablechrome", "true"); - } else { - let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - if (ss.getTabValue(gBrowser.selectedTab, "appOrigin")) - document.documentElement.setAttribute("disablechrome", "true"); - else - document.documentElement.removeAttribute("disablechrome"); - } - - // Utility functions for disabling find - var shouldDisableFind = function shouldDisableFind(aDocument) { - let docElt = aDocument.documentElement; - return docElt && docElt.getAttribute("disablefastfind") == "true"; - } - - var disableFindCommands = function disableFindCommands(aDisable) { - let findCommands = [document.getElementById("cmd_find"), - document.getElementById("cmd_findAgain"), - document.getElementById("cmd_findPrevious")]; - for (let elt of findCommands) { - if (aDisable) - elt.setAttribute("disabled", "true"); - else - elt.removeAttribute("disabled"); - } - if (gFindBarInitialized) { - if (!gFindBar.hidden && aDisable) { - gFindBar.hidden = true; - this._findbarTemporarilyHidden = true; - } else if (this._findbarTemporarilyHidden && !aDisable) { - gFindBar.hidden = false; - this._findbarTemporarilyHidden = false; - } - } - }.bind(this); - - var onContentRSChange = function onContentRSChange(e) { - if (e.target.readyState != "interactive" && e.target.readyState != "complete") - return; - - e.target.removeEventListener("readystatechange", onContentRSChange); - disableFindCommands(shouldDisableFind(e.target)); - } - - // Disable find commands in documents that ask for them to be disabled. - if (!gMultiProcessBrowser && aLocationURI && - (aLocationURI.schemeIs("about") || aLocationURI.schemeIs("chrome"))) { - // Don't need to re-enable/disable find commands for same-document location changes - // (e.g. the replaceStates in about:addons) - if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)) { - if (content.document.readyState == "interactive" || content.document.readyState == "complete") - disableFindCommands(shouldDisableFind(content.document)); - else { - content.document.addEventListener("readystatechange", onContentRSChange); - } - } - } else - disableFindCommands(false); - - if (gFindBarInitialized) { - if (gFindBar.findMode != gFindBar.FIND_NORMAL) { - // Close the Find toolbar if we're in old-style TAF mode - gFindBar.close(); - } - - if (!(gPrefService.getBoolPref("accessibility.typeaheadfind.highlightallremember") || - gPrefService.getBoolPref("accessibility.typeaheadfind.highlightallbydefault"))) { - // fix bug 253793 - turn off highlight when page changes - gFindBar.getElement("highlight").checked = false; - } - } - } - UpdateBackForwardCommands(gBrowser.webNavigation); - - gGestureSupport.restoreRotationState(); - - // See bug 358202, when tabs are switched during a drag operation, - // timers don't fire on windows (bug 203573) - if (aRequest) - setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0); - else - this.asyncUpdateUI(); - }, - - asyncUpdateUI: function () { - FeedHandler.updateFeeds(); - }, - - hideChromeForLocation: function(aLocation) { - aLocation = aLocation.toLowerCase(); - return this.inContentWhitelist.some(function(aSpec) { - return aSpec == aLocation; - }); - }, - - onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) { - this.status = aMessage; - this.updateStatusField(); - }, - - // Properties used to cache security state used to update the UI - _state: null, - _hostChanged: false, // onLocationChange will flip this bit - - onSecurityChange: function (aWebProgress, aRequest, aState) { - // Don't need to do anything if the data we use to update the UI hasn't - // changed - if (this._state == aState && - !this._hostChanged) { -#ifdef DEBUG - try { - var contentHost = gBrowser.contentWindow.location.host; - if (this._host !== undefined && this._host != contentHost) { - Components.utils.reportError( - "ASSERTION: browser.js host is inconsistent. Content window has " + - "<" + contentHost + "> but cached host is <" + this._host + ">.\n" - ); - } - } catch (ex) {} -#endif - return; - } - this._state = aState; - -#ifdef DEBUG - try { - this._host = gBrowser.contentWindow.location.host; - } catch(ex) { - this._host = null; - } -#endif - - this._hostChanged = false; - - // aState is defined as a bitmask that may be extended in the future. - // We filter out any unknown bits before testing for known values. - const wpl = Components.interfaces.nsIWebProgressListener; - const wpl_security_bits = wpl.STATE_IS_SECURE | - wpl.STATE_IS_BROKEN | - wpl.STATE_IS_INSECURE; - var level; - - switch (this._state & wpl_security_bits) { - case wpl.STATE_IS_SECURE: - level = "high"; - break; - case wpl.STATE_IS_BROKEN: - level = "broken"; - break; - } - - if (level) { - // We don't style the Location Bar based on the the 'level' attribute - // anymore, but still set it for third-party themes. - if (gURLBar) - gURLBar.setAttribute("level", level); - } else { - if (gURLBar) - gURLBar.removeAttribute("level"); - } - - if (gMultiProcessBrowser) - return; - - // Don't pass in the actual location object, since it can cause us to - // hold on to the window object too long. Just pass in the fields we - // care about. (bug 424829) - var location = gBrowser.contentWindow.location; - var locationObj = {}; - try { - // about:blank can be used by webpages so pretend it is http - locationObj.protocol = location == "about:blank" ? "http:" : location.protocol; - locationObj.host = location.host; - locationObj.hostname = location.hostname; - locationObj.port = location.port; - } catch (ex) { - // Can sometimes throw if the URL being visited has no host/hostname, - // e.g. about:blank. The _state for these pages means we won't need these - // properties anyways, though. - } - gIdentityHandler.checkIdentity(this._state, locationObj); - }, - - // simulate all change notifications after switching tabs - onUpdateCurrentBrowser: function XWB_onUpdateCurrentBrowser(aStateFlags, aStatus, aMessage, aTotalProgress) { - if (FullZoom.updateBackgroundTabs) - FullZoom.onLocationChange(gBrowser.currentURI, true); - var nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; - var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP; - // use a pseudo-object instead of a (potentially nonexistent) channel for getting - // a correct error message - and make sure that the UI is always either in - // loading (STATE_START) or done (STATE_STOP) mode - this.onStateChange( - gBrowser.webProgress, - { URI: gBrowser.currentURI }, - loadingDone ? nsIWebProgressListener.STATE_STOP : nsIWebProgressListener.STATE_START, - aStatus - ); - // status message and progress value are undefined if we're done with loading - if (loadingDone) - return; - this.onStatusChange(gBrowser.webProgress, null, 0, aMessage); - } -}; - -var LinkTargetDisplay = { - get DELAY_SHOW() { - delete this.DELAY_SHOW; - return this.DELAY_SHOW = Services.prefs.getIntPref("browser.overlink-delay"); - }, - - DELAY_HIDE: 250, - _timer: 0, - - get _isVisible () XULBrowserWindow.statusTextField.label != "", - - update: function () { - clearTimeout(this._timer); - window.removeEventListener("mousemove", this, true); - - if (!XULBrowserWindow.overLink) { - if (XULBrowserWindow.hideOverLinkImmediately) - this._hide(); - else - this._timer = setTimeout(this._hide.bind(this), this.DELAY_HIDE); - return; - } - - if (this._isVisible) { - XULBrowserWindow.updateStatusField(); - } else { - // Let the display appear when the mouse doesn't move within the delay - this._showDelayed(); - window.addEventListener("mousemove", this, true); - } - }, - - handleEvent: function (event) { - switch (event.type) { - case "mousemove": - // Restart the delay since the mouse was moved - clearTimeout(this._timer); - this._showDelayed(); - break; - } - }, - - _showDelayed: function () { - this._timer = setTimeout(function (self) { - XULBrowserWindow.updateStatusField(); - window.removeEventListener("mousemove", self, true); - }, this.DELAY_SHOW, this); - }, - - _hide: function () { - clearTimeout(this._timer); - - XULBrowserWindow.updateStatusField(); - } -}; - -var CombinedStopReload = { - init: function () { - if (this._initialized) - return; - - var urlbar = document.getElementById("urlbar-container"); - var reload = document.getElementById("reload-button"); - var stop = document.getElementById("stop-button"); - - if (urlbar) { - if (urlbar.parentNode.getAttribute("mode") != "icons" || - !reload || urlbar.nextSibling != reload || - !stop || reload.nextSibling != stop) - urlbar.removeAttribute("combined"); - else { - urlbar.setAttribute("combined", "true"); - reload = document.getElementById("urlbar-reload-button"); - stop = document.getElementById("urlbar-stop-button"); - } - } - if (!stop || !reload || reload.nextSibling != stop) - return; - - this._initialized = true; - if (XULBrowserWindow.stopCommand.getAttribute("disabled") != "true") - reload.setAttribute("displaystop", "true"); - stop.addEventListener("click", this, false); - this.reload = reload; - this.stop = stop; - }, - - uninit: function () { - if (!this._initialized) - return; - - this._cancelTransition(); - this._initialized = false; - this.stop.removeEventListener("click", this, false); - this.reload = null; - this.stop = null; - }, - - handleEvent: function (event) { - // the only event we listen to is "click" on the stop button - if (event.button == 0 && - !this.stop.disabled) - this._stopClicked = true; - }, - - switchToStop: function () { - if (!this._initialized) - return; - - this._cancelTransition(); - this.reload.setAttribute("displaystop", "true"); - }, - - switchToReload: function (aDelay) { - if (!this._initialized) - return; - - this.reload.removeAttribute("displaystop"); - - if (!aDelay || this._stopClicked) { - this._stopClicked = false; - this._cancelTransition(); - this.reload.disabled = XULBrowserWindow.reloadCommand - .getAttribute("disabled") == "true"; - return; - } - - if (this._timer) - return; - - // Temporarily disable the reload button to prevent the user from - // accidentally reloading the page when intending to click the stop button - this.reload.disabled = true; - this._timer = setTimeout(function (self) { - self._timer = 0; - self.reload.disabled = XULBrowserWindow.reloadCommand - .getAttribute("disabled") == "true"; - }, 650, this); - }, - - _cancelTransition: function () { - if (this._timer) { - clearTimeout(this._timer); - this._timer = 0; - } - } -}; - -var TabsProgressListener = { - onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { - - // Attach a listener to watch for "click" events bubbling up from error - // pages and other similar page. This lets us fix bugs like 401575 which - // require error page UI to do privileged things, without letting error - // pages have any privilege themselves. - // We can't look for this during onLocationChange since at that point the - // document URI is not yet the about:-uri of the error page. - - let doc = gMultiProcessBrowser ? null : aWebProgress.DOMWindow.document; - if (!gMultiProcessBrowser && - aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && - Components.isSuccessCode(aStatus) && - doc.documentURI.startsWith("about:") && - !doc.documentURI.toLowerCase().startsWith("about:blank") && - !doc.documentElement.hasAttribute("hasBrowserHandlers")) { - // STATE_STOP may be received twice for documents, thus store an - // attribute to ensure handling it just once. - doc.documentElement.setAttribute("hasBrowserHandlers", "true"); - aBrowser.addEventListener("click", BrowserOnClick, true); - aBrowser.addEventListener("pagehide", function onPageHide(event) { - if (event.target.defaultView.frameElement) - return; - aBrowser.removeEventListener("click", BrowserOnClick, true); - aBrowser.removeEventListener("pagehide", onPageHide, true); - if (event.target.documentElement) - event.target.documentElement.removeAttribute("hasBrowserHandlers"); - }, true); - - // We also want to make changes to page UI for unprivileged about pages. - BrowserOnAboutPageLoad(doc); - } - }, - - onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI, - aFlags) { - // Filter out location changes caused by anchor navigation - // or history.push/pop/replaceState. - if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) - return; - - // Only need to call locationChange if the PopupNotifications object - // for this window has already been initialized (i.e. its getter no - // longer exists) - if (!Object.getOwnPropertyDescriptor(window, "PopupNotifications").get) - PopupNotifications.locationChange(aBrowser); - - gBrowser.getNotificationBox(aBrowser).removeTransientNotifications(); - - // Filter out location changes in sub documents. - if (aWebProgress.isTopLevel) { - // Initialize the click-to-play state. - aBrowser._clickToPlayPluginsActivated = new Map(); - aBrowser._clickToPlayAllPluginsActivated = false; - aBrowser._pluginScriptedState = gPluginHandler.PLUGIN_SCRIPTED_STATE_NONE; - - FullZoom.onLocationChange(aLocationURI, false, aBrowser); - } - }, - - onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) { - if (gPrefService.getBoolPref("accessibility.blockautorefresh")) { - let brandBundle = document.getElementById("bundle_brand"); - let brandShortName = brandBundle.getString("brandShortName"); - let refreshButtonText = - gNavigatorBundle.getString("refreshBlocked.goButton"); - let refreshButtonAccesskey = - gNavigatorBundle.getString("refreshBlocked.goButton.accesskey"); - let message = - gNavigatorBundle.getFormattedString(aSameURI ? "refreshBlocked.refreshLabel" - : "refreshBlocked.redirectLabel", - [brandShortName]); - let docShell = aWebProgress.DOMWindow - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); - let notificationBox = gBrowser.getNotificationBox(aBrowser); - let notification = notificationBox.getNotificationWithValue("refresh-blocked"); - if (notification) { - notification.label = message; - notification.refreshURI = aURI; - notification.delay = aDelay; - notification.docShell = docShell; - } else { - let buttons = [{ - label: refreshButtonText, - accessKey: refreshButtonAccesskey, - callback: function (aNotification, aButton) { - var refreshURI = aNotification.docShell - .QueryInterface(Ci.nsIRefreshURI); - refreshURI.forceRefreshURI(aNotification.refreshURI, - aNotification.delay, true); - } - }]; - notification = - notificationBox.appendNotification(message, "refresh-blocked", - "chrome://browser/skin/Info.png", - notificationBox.PRIORITY_INFO_MEDIUM, - buttons); - notification.refreshURI = aURI; - notification.delay = aDelay; - notification.docShell = docShell; - } - return false; - } - return true; - } -} - -function nsBrowserAccess() { } - -nsBrowserAccess.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow, Ci.nsISupports]), - - openURI: function (aURI, aOpener, aWhere, aContext) { - var newWindow = null; - var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL); - - if (isExternal && aURI && aURI.schemeIs("chrome")) { - dump("use -chrome command-line option to load external chrome urls\n"); - return null; - } - - if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) { - if (isExternal && - gPrefService.prefHasUserValue("browser.link.open_newwindow.override.external")) - aWhere = gPrefService.getIntPref("browser.link.open_newwindow.override.external"); - else - aWhere = gPrefService.getIntPref("browser.link.open_newwindow"); - } - switch (aWhere) { - case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW : - // FIXME: Bug 408379. So how come this doesn't send the - // referrer like the other loads do? - var url = aURI ? aURI.spec : "about:blank"; - // Pass all params to openDialog to ensure that "url" isn't passed through - // loadOneOrMoreURIs, which splits based on "|" - newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, null); - break; - case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB : - let win, needToFocusWin; - - // try the current window. if we're in a popup, fall back on the most recent browser window - if (window.toolbar.visible) - win = window; - else { - let isPrivate = PrivateBrowsingUtils.isWindowPrivate(aOpener || window); - win = RecentWindow.getMostRecentBrowserWindow({private: isPrivate}); - needToFocusWin = true; - } - - if (!win) { - // we couldn't find a suitable window, a new one needs to be opened. - return null; - } - - if (isExternal && (!aURI || aURI.spec == "about:blank")) { - win.BrowserOpenTab(); // this also focuses the location bar - win.focus(); - newWindow = win.content; - break; - } - - let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground"); - let referrer = aOpener ? makeURI(aOpener.location.href) : null; - - let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", { - referrerURI: referrer, - fromExternal: isExternal, - inBackground: loadInBackground}); - let browser = win.gBrowser.getBrowserForTab(tab); - - if (gPrefService.getBoolPref("browser.tabs.noWindowActivationOnExternal")) { - isExternal = false; // this is a hack, but it works - } - - newWindow = browser.contentWindow; - if (needToFocusWin || (!loadInBackground && isExternal)) - newWindow.focus(); - break; - 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); - } - if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground")) - window.focus(); - } - return newWindow; - }, - - isTabContentWindow: function (aWindow) { - return gBrowser.browsers.some(function (browser) browser.contentWindow == aWindow); - } -} - -function onViewToolbarsPopupShowing(aEvent, aInsertPoint) { - var popup = aEvent.target; - if (popup != aEvent.currentTarget) - return; - - // Empty the menu - for (var i = popup.childNodes.length-1; i >= 0; --i) { - var deadItem = popup.childNodes[i]; - if (deadItem.hasAttribute("toolbarId")) - popup.removeChild(deadItem); - } - - var firstMenuItem = aInsertPoint || popup.firstChild; - - let toolbarNodes = Array.slice(gNavToolbox.childNodes); - toolbarNodes.push(document.getElementById("addon-bar")); - - for (let toolbar of toolbarNodes) { - let toolbarName = toolbar.getAttribute("toolbarname"); - if (toolbarName) { - let menuItem = document.createElement("menuitem"); - let hidingAttribute = toolbar.getAttribute("type") == "menubar" ? - "autohide" : "collapsed"; - menuItem.setAttribute("id", "toggle_" + toolbar.id); - menuItem.setAttribute("toolbarId", toolbar.id); - menuItem.setAttribute("type", "checkbox"); - menuItem.setAttribute("label", toolbarName); - menuItem.setAttribute("checked", toolbar.getAttribute(hidingAttribute) != "true"); - if (popup.id != "appmenu_customizeMenu") - menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey")); - if (popup.id != "toolbar-context-menu") - menuItem.setAttribute("key", toolbar.getAttribute("key")); - - popup.insertBefore(menuItem, firstMenuItem); - - menuItem.addEventListener("command", onViewToolbarCommand, false); - } - } -} - -function onViewToolbarCommand(aEvent) { - var toolbarId = aEvent.originalTarget.getAttribute("toolbarId"); - var toolbar = document.getElementById(toolbarId); - var isVisible = aEvent.originalTarget.getAttribute("checked") == "true"; - setToolbarVisibility(toolbar, isVisible); -} - -function setToolbarVisibility(toolbar, isVisible) { - var hidingAttribute = toolbar.getAttribute("type") == "menubar" ? - "autohide" : "collapsed"; - - toolbar.setAttribute(hidingAttribute, !isVisible); - document.persist(toolbar.id, hidingAttribute); - - // Customizable toolbars - persist the hiding attribute. - if (toolbar.hasAttribute("customindex")) { - var toolbox = toolbar.parentNode; - var name = toolbar.getAttribute("toolbarname"); - if (toolbox.toolbarset) { - try { - // Checking all attributes starting with "toolbar". - Array.prototype.slice.call(toolbox.toolbarset.attributes, 0) - .find(x => { - if (x.name.startsWith("toolbar")) { - var toolbarInfo = x.value; - var infoSplit = toolbarInfo.split(gToolbarInfoSeparators[0]); - if (infoSplit[0] == name) { - infoSplit[1] = [ - infoSplit[1].split(gToolbarInfoSeparators[1], 1), !isVisible - ].join(gToolbarInfoSeparators[1]); - toolbox.toolbarset.setAttribute( - x.name, infoSplit.join(gToolbarInfoSeparators[0])); - document.persist(toolbox.toolbarset.id, x.name); - } - } - }); - } catch (e) { - Components.utils.reportError( - "Customizable toolbars - persist the hiding attribute: " + e); - } - } - } - - PlacesToolbarHelper.init(); - BookmarkingUI.onToolbarVisibilityChange(); - gBrowser.updateWindowResizers(); - -#ifdef MENUBAR_CAN_AUTOHIDE - updateAppButtonDisplay(); -#endif - - if (isVisible) - ToolbarIconColor.inferFromText(); -} - -var TabsOnTop = { - init: function TabsOnTop_init() { - Services.prefs.addObserver(this._prefName, this, false); -// Pale Moon: Stop Being a Derp, Mozilla (#3) - // Only show the toggle UI if the user disabled tabs on top. -// if (Services.prefs.getBoolPref(this._prefName)) { -// for (let item of document.querySelectorAll("menuitem[command=cmd_ToggleTabsOnTop]")) -// item.parentNode.removeChild(item); -// } - }, - - uninit: function TabsOnTop_uninit() { - Services.prefs.removeObserver(this._prefName, this); - }, - - toggle: function () { - this.enabled = !Services.prefs.getBoolPref(this._prefName); - }, - - syncUI: function () { - let userEnabled = Services.prefs.getBoolPref(this._prefName); - let enabled = userEnabled && gBrowser.tabContainer.visible; - - document.getElementById("cmd_ToggleTabsOnTop") - .setAttribute("checked", userEnabled); - - document.documentElement.setAttribute("tabsontop", enabled); - document.getElementById("navigator-toolbox").setAttribute("tabsontop", enabled); - document.getElementById("TabsToolbar").setAttribute("tabsontop", enabled); - document.getElementById("nav-bar").setAttribute("tabsontop", enabled); - gBrowser.tabContainer.setAttribute("tabsontop", enabled); - TabsInTitlebar.allowedBy("tabs-on-top", enabled); - }, - - get enabled () { - return gNavToolbox.getAttribute("tabsontop") == "true"; - }, - - set enabled (val) { - Services.prefs.setBoolPref(this._prefName, !!val); - return val; - }, - - observe: function (subject, topic, data) { - if (topic == "nsPref:changed") - this.syncUI(); - }, - - _prefName: "browser.tabs.onTop" -} - -var TabsInTitlebar = { - init: function () { -#ifdef CAN_DRAW_IN_TITLEBAR - this._readPref(); - Services.prefs.addObserver(this._prefName, this, false); - - // Don't trust the initial value of the sizemode attribute; wait for - // the resize event (handled in tabbrowser.xml). - this.allowedBy("sizemode", false); - - this._initialized = true; -#endif - }, - - allowedBy: function (condition, allow) { -#ifdef CAN_DRAW_IN_TITLEBAR - if (allow) { - if (condition in this._disallowed) { - delete this._disallowed[condition]; - this._update(); - } - } else { - if (!(condition in this._disallowed)) { - this._disallowed[condition] = null; - this._update(); - } - } -#endif - }, - - get enabled() { - return document.documentElement.getAttribute("tabsintitlebar") == "true"; - }, - -#ifdef CAN_DRAW_IN_TITLEBAR - observe: function (subject, topic, data) { - if (topic == "nsPref:changed") - this._readPref(); - }, - - _initialized: false, - _disallowed: {}, - _prefName: "browser.tabs.drawInTitlebar", - - _readPref: function () { - this.allowedBy("pref", - Services.prefs.getBoolPref(this._prefName)); - }, - - _update: function () { - function $(id) document.getElementById(id); - function rect(ele) ele.getBoundingClientRect(); - - if (!this._initialized || window.fullScreen) - return; - - let allowed = true; - for (let something in this._disallowed) { - allowed = false; - break; - } - - if (allowed == this.enabled) - return; - - let titlebar = $("titlebar"); - - if (allowed) { - let tabsToolbar = $("TabsToolbar"); - -#ifdef MENUBAR_CAN_AUTOHIDE - let appmenuButtonBox = $("appmenu-button-container"); - this._sizePlaceholder("appmenu-button", rect(appmenuButtonBox).width); -#endif - let captionButtonsBox = $("titlebar-buttonbox"); - this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width); - - let tabsToolbarRect = rect(tabsToolbar); - let titlebarTop = rect($("titlebar-content")).top; - titlebar.style.marginBottom = - Math.min(tabsToolbarRect.top - titlebarTop, - tabsToolbarRect.height) + "px"; - - document.documentElement.setAttribute("tabsintitlebar", "true"); - - if (!this._draghandle) { - let tmp = {}; - Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp); - this._draghandle = new tmp.WindowDraggingElement(tabsToolbar); - this._draghandle.mouseDownCheck = function () { - return !this._dragBindingAlive && TabsInTitlebar.enabled; - }; - } - } else { - document.documentElement.removeAttribute("tabsintitlebar"); - - titlebar.style.marginBottom = ""; - } - - ToolbarIconColor.inferFromText(); - }, - - _sizePlaceholder: function (type, width) { - Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='"+ type +"']"), - function (node) { node.width = width; }); - }, -#endif - - uninit: function () { -#ifdef CAN_DRAW_IN_TITLEBAR - this._initialized = false; - Services.prefs.removeObserver(this._prefName, this); -#endif - } -}; - -#ifdef MENUBAR_CAN_AUTOHIDE -function updateAppButtonDisplay() { - var displayAppButton = - !gInPrintPreviewMode && - window.menubar.visible && - document.getElementById("toolbar-menubar").getAttribute("autohide") == "true"; - -#ifdef CAN_DRAW_IN_TITLEBAR - document.getElementById("titlebar").hidden = !displayAppButton; - - if (displayAppButton) - document.documentElement.setAttribute("chromemargin", "0,2,2,2"); - else - document.documentElement.removeAttribute("chromemargin"); - - TabsInTitlebar.allowedBy("drawing-in-titlebar", displayAppButton); -#else - document.getElementById("appmenu-toolbar-button").hidden = - !displayAppButton; -#endif -} -#endif - -#ifdef CAN_DRAW_IN_TITLEBAR -function onTitlebarMaxClick() { - if (window.windowState == window.STATE_MAXIMIZED) - window.restore(); - else - window.maximize(); -} -#endif - -function displaySecurityInfo() -{ - BrowserPageInfo(null, "securityTab"); -} - -/** - * Opens or closes the sidebar identified by commandID. - * - * @param commandID a string identifying the sidebar to toggle; see the - * note below. (Optional if a sidebar is already open.) - * @param forceOpen boolean indicating whether the sidebar should be - * opened regardless of its current state (optional). - * @note - * We expect to find a xul:broadcaster element with the specified ID. - * The following attributes on that element may be used and/or modified: - * - id (required) the string to match commandID. The convention - * is to use this naming scheme: 'view<sidebar-name>Sidebar'. - * - sidebarurl (required) specifies the URL to load in this sidebar. - * - sidebartitle or label (in that order) specify the title to - * display on the sidebar. - * - checked indicates whether the sidebar is currently displayed. - * Note that toggleSidebar updates this attribute when - * it changes the sidebar's visibility. - * - group this attribute must be set to "sidebar". - */ -function toggleSidebar(commandID, forceOpen) { - - var sidebarBox = document.getElementById("sidebar-box"); - if (!commandID) - commandID = sidebarBox.getAttribute("sidebarcommand"); - - var sidebarBroadcaster = document.getElementById(commandID); - var sidebar = document.getElementById("sidebar"); // xul:browser - var sidebarTitle = document.getElementById("sidebar-title"); - var sidebarSplitter = document.getElementById("sidebar-splitter"); - - if (sidebarBroadcaster.getAttribute("checked") == "true") { - if (!forceOpen) { - // Replace the document currently displayed in the sidebar with about:blank - // so that we can free memory by unloading the page. We need to explicitly - // create a new content viewer because the old one doesn't get destroyed - // until about:blank has loaded (which does not happen as long as the - // element is hidden). - sidebar.setAttribute("src", "about:blank"); - sidebar.docShell.createAboutBlankContentViewer(null); - - sidebarBroadcaster.removeAttribute("checked"); - sidebarBox.setAttribute("sidebarcommand", ""); - sidebarTitle.value = ""; - sidebarBox.hidden = true; - sidebarSplitter.hidden = true; - gBrowser.selectedBrowser.focus(); - } else { - fireSidebarFocusedEvent(); - } - return; - } - - // now we need to show the specified sidebar - - // ..but first update the 'checked' state of all sidebar broadcasters - var broadcasters = document.getElementsByAttribute("group", "sidebar"); - for (let broadcaster of broadcasters) { - // skip elements that observe sidebar broadcasters and random - // other elements - if (broadcaster.localName != "broadcaster") - continue; - - if (broadcaster != sidebarBroadcaster) - broadcaster.removeAttribute("checked"); - else - sidebarBroadcaster.setAttribute("checked", "true"); - } - - sidebarBox.hidden = false; - sidebarSplitter.hidden = false; - - var url = sidebarBroadcaster.getAttribute("sidebarurl"); - var title = sidebarBroadcaster.getAttribute("sidebartitle"); - if (!title) - title = sidebarBroadcaster.getAttribute("label"); - sidebar.setAttribute("src", url); // kick off async load - sidebarBox.setAttribute("sidebarcommand", sidebarBroadcaster.id); - sidebarTitle.value = title; - - // We set this attribute here in addition to setting it on the <browser> - // element itself, because the code in gBrowserInit.onUnload persists this - // attribute, not the "src" of the <browser id="sidebar">. The reason it - // does that is that we want to delay sidebar load a bit when a browser - // window opens. See delayedStartup(). - sidebarBox.setAttribute("src", url); - - if (sidebar.contentDocument.location.href != url) - sidebar.addEventListener("load", sidebarOnLoad, true); - else // older code handled this case, so we do it too - fireSidebarFocusedEvent(); -} - -function sidebarOnLoad(event) { - var sidebar = document.getElementById("sidebar"); - sidebar.removeEventListener("load", sidebarOnLoad, true); - // We're handling the 'load' event before it bubbles up to the usual - // (non-capturing) event handlers. Let it bubble up before firing the - // SidebarFocused event. - setTimeout(fireSidebarFocusedEvent, 0); -} - -/** - * Fire a "SidebarFocused" event on the sidebar's |window| to give the sidebar - * a chance to adjust focus as needed. An additional event is needed, because - * we don't want to focus the sidebar when it's opened on startup or in a new - * window, only when the user opens the sidebar. - */ -function fireSidebarFocusedEvent() { - var sidebar = document.getElementById("sidebar"); - var event = document.createEvent("Events"); - event.initEvent("SidebarFocused", true, false); - sidebar.contentWindow.dispatchEvent(event); -} - -var gHomeButton = { - prefDomain: "browser.startup.homepage", - observe: function (aSubject, aTopic, aPrefName) - { - if (aTopic != "nsPref:changed" || aPrefName != this.prefDomain) - return; - - this.updateTooltip(); - }, - - updateTooltip: function (homeButton) - { - if (!homeButton) - homeButton = document.getElementById("home-button"); - if (homeButton) { - var homePage = this.getHomePage(); - homePage = homePage.replace(/\|/g,', '); - if (homePage.toLowerCase() == "about:home") - homeButton.setAttribute("tooltiptext", homeButton.getAttribute("aboutHomeOverrideTooltip")); - else - homeButton.setAttribute("tooltiptext", homePage); - } - }, - - getHomePage: function () - { - var url; - try { - url = gPrefService.getComplexValue(this.prefDomain, - Components.interfaces.nsIPrefLocalizedString).data; - } catch (e) { - } - - // use this if we can't find the pref - if (!url) { - var configBundle = Services.strings - .createBundle("chrome://branding/locale/browserconfig.properties"); - url = configBundle.GetStringFromName(this.prefDomain); - } - - return url; - }, - - updatePersonalToolbarStyle: function (homeButton) - { - if (!homeButton) - homeButton = document.getElementById("home-button"); - if (homeButton) - homeButton.className = homeButton.parentNode.id == "PersonalToolbar" - || homeButton.parentNode.parentNode.id == "PersonalToolbar" ? - homeButton.className.replace("toolbarbutton-1", "bookmark-item") : - homeButton.className.replace("bookmark-item", "toolbarbutton-1"); - } -}; - -/** - * Gets the selected text in the active browser. Leading and trailing - * whitespace is removed, and consecutive whitespace is replaced by a single - * space. A maximum of 150 characters will be returned, regardless of the value - * of aCharLen. - * - * @param aCharLen - * The maximum number of characters to return. - */ -function getBrowserSelection(aCharLen) { - // selections of more than 150 characters aren't useful - const kMaxSelectionLen = 150; - const charLen = Math.min(aCharLen || kMaxSelectionLen, kMaxSelectionLen); - let commandDispatcher = document.commandDispatcher; - - var focusedWindow = commandDispatcher.focusedWindow; - var selection = focusedWindow.getSelection().toString(); - // try getting a selected text in text input. - if (!selection) { - let element = commandDispatcher.focusedElement; - var isOnTextInput = function isOnTextInput(elem) { - // we avoid to return a value if a selection is in password field. - // ref. bug 565717 - return elem instanceof HTMLTextAreaElement || - (elem instanceof HTMLInputElement && elem.mozIsTextField(true)); - }; - - if (isOnTextInput(element)) { - selection = element.QueryInterface(Ci.nsIDOMNSEditableElement) - .editor.selection.toString(); - } - } - - if (selection) { - if (selection.length > charLen) { - // only use the first charLen important chars. see bug 221361 - var pattern = new RegExp("^(?:\\s*.){0," + charLen + "}"); - pattern.test(selection); - selection = RegExp.lastMatch; - } - - selection = selection.trim().replace(/\s+/g, " "); - - if (selection.length > charLen) - selection = selection.substr(0, charLen); - } - return selection; -} - -var gWebPanelURI; -function openWebPanel(aTitle, aURI) -{ - // Ensure that the web panels sidebar is open. - toggleSidebar('viewWebPanelsSidebar', true); - - // Set the title of the panel. - document.getElementById("sidebar-title").value = aTitle; - - // Tell the Web Panels sidebar to load the bookmark. - var sidebar = document.getElementById("sidebar"); - if (sidebar.docShell && sidebar.contentDocument && sidebar.contentDocument.getElementById('web-panels-browser')) { - sidebar.contentWindow.loadWebPanel(aURI); - if (gWebPanelURI) { - gWebPanelURI = ""; - sidebar.removeEventListener("load", asyncOpenWebPanel, true); - } - } - else { - // The panel is still being constructed. Attach an onload handler. - if (!gWebPanelURI) - sidebar.addEventListener("load", asyncOpenWebPanel, true); - gWebPanelURI = aURI; - } -} - -function asyncOpenWebPanel(event) -{ - var sidebar = document.getElementById("sidebar"); - if (gWebPanelURI && sidebar.contentDocument && sidebar.contentDocument.getElementById('web-panels-browser')) - sidebar.contentWindow.loadWebPanel(gWebPanelURI); - gWebPanelURI = ""; - sidebar.removeEventListener("load", asyncOpenWebPanel, true); -} - -/* - * - [ Dependencies ] --------------------------------------------------------- - * utilityOverlay.js: - * - gatherTextUnder - */ - -/** - * Extracts linkNode and href for the current click target. - * - * @param event - * The click event. - * @return [href, linkNode]. - * - * @note linkNode will be null if the click wasn't on an anchor - * element (or XLink). - */ -function hrefAndLinkNodeForClickEvent(event) -{ - function isHTMLLink(aNode) - { - // Be consistent with what nsContextMenu.js does. - return ((aNode instanceof HTMLAnchorElement && aNode.href) || - (aNode instanceof HTMLAreaElement && aNode.href) || - aNode instanceof HTMLLinkElement); - } - - let node = event.target; - while (node && !isHTMLLink(node)) { - node = node.parentNode; - } - - if (node) - return [node.href, node]; - - // If there is no linkNode, try simple XLink. - let href, baseURI; - node = event.target; - while (node && !href) { - if (node.nodeType == Node.ELEMENT_NODE && - (node.localName == "a" || - node.namespaceURI == "http://www.w3.org/1998/Math/MathML")) { - href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href"); - if (href) { - baseURI = node.baseURI; - break; - } - } - node = node.parentNode; - } - - // In case of XLink, we don't return the node we got href from since - // callers expect <a>-like elements. - return [href ? makeURLAbsolute(baseURI, href) : null, null]; -} - -/** - * Called whenever the user clicks in the content area. - * - * @param event - * The click event. - * @param isPanelClick - * Whether the event comes from a web panel. - * @note default event is prevented if the click is handled. - */ -function contentAreaClick(event, isPanelClick) -{ - if (!event.isTrusted || event.defaultPrevented || event.button == 2) - return; - - let [href, linkNode] = hrefAndLinkNodeForClickEvent(event); - if (!href) { - // Not a link, handle middle mouse navigation. - if (event.button == 1 && - gPrefService.getBoolPref("middlemouse.contentLoadURL") && - !gPrefService.getBoolPref("general.autoScroll")) { - middleMousePaste(event); - event.preventDefault(); - } - return; - } - - // This code only applies if we have a linkNode (i.e. clicks on real anchor - // elements, as opposed to XLink). - if (linkNode && event.button == 0 && - !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) { - // A Web panel's links should target the main content area. Do this - // if no modifier keys are down and if there's no target or the target - // equals _main (the IE convention) or _content (the Mozilla convention). - let target = linkNode.target; - let mainTarget = !target || target == "_content" || target == "_main"; - if (isPanelClick && mainTarget) { - // javascript and data links should be executed in the current browser. - if (linkNode.getAttribute("onclick") || - href.startsWith("javascript:") || - href.startsWith("data:")) - return; - - try { - urlSecurityCheck(href, linkNode.ownerDocument.nodePrincipal); - } - catch(ex) { - // Prevent loading unsecure destinations. - event.preventDefault(); - return; - } - - loadURI(href, null, null, false); - event.preventDefault(); - return; - } - - if (linkNode.getAttribute("rel") == "sidebar") { - // This is the Opera convention for a special link that, when clicked, - // allows to add a sidebar panel. The link's title attribute contains - // the title that should be used for the sidebar panel. - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "bookmark" - , uri: makeURI(href) - , title: linkNode.getAttribute("title") - , loadBookmarkInSidebar: true - , hiddenRows: [ "description" - , "location" - , "keyword" ] - }, window); - event.preventDefault(); - return; - } - } - - handleLinkClick(event, href, linkNode); - - // Mark the page as a user followed link. This is done so that history can - // distinguish automatic embed visits from user activated ones. For example - // pages loaded in frames are embed visits and lost with the session, while - // visits across frames should be preserved. - try { - if (!PrivateBrowsingUtils.isWindowPrivate(window)) - PlacesUIUtils.markPageAsFollowedLink(href); - } catch (ex) { /* Skip invalid URIs. */ } -} - -/** - * Handles clicks on links. - * - * @return true if the click event was handled, false otherwise. - */ -function handleLinkClick(event, href, linkNode) { - if (event.button == 2) // right click - return false; - - var where = whereToOpenLink(event); - if (where == "current") - return false; - - var doc = event.target.ownerDocument; - - if (where == "save") { - saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true, - true, doc.documentURIObject, doc); - event.preventDefault(); - return true; - } - - urlSecurityCheck(href, doc.nodePrincipal); - openLinkIn(href, where, { referrerURI: doc.documentURIObject, - charset: doc.characterSet }); - event.preventDefault(); - return true; -} - -function middleMousePaste(event) { - let clipboard = readFromClipboard(); - if (!clipboard) - return; - - // Strip embedded newlines and surrounding whitespace, to match the URL - // 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; - } - - 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); - } - - openUILink(url, event, - { ignoreButton: true, - disallowInheritPrincipal: !mayInheritPrincipal.value }); - - event.stopPropagation(); -} - -function handleDroppedLink(event, url, name) -{ - let postData = { }; - let uri = getShortcutOrURI(url, postData); - if (uri) - loadURI(uri, null, postData.value, false); - - // Keep the event from being handled by the dragDrop listeners - // built-in to goanna if they happen to be above us. - event.preventDefault(); -}; - -function MultiplexHandler(event) -{ try { - var node = event.target; - var name = node.getAttribute('name'); - - if (name == 'detectorGroup') { - BrowserCharsetReload(); - SelectDetector(event, false); - } else if (name == 'charsetGroup') { - var charset = node.getAttribute('id'); - charset = charset.substring(charset.indexOf('charset.') + 'charset.'.length); - BrowserSetForcedCharacterSet(charset); - } else if (name == 'charsetCustomize') { - //do nothing - please remove this else statement, once the charset prefs moves to the pref window - } else { - BrowserSetForcedCharacterSet(node.getAttribute('id')); - } - } catch(ex) { alert(ex); } -} - -function SelectDetector(event, doReload) -{ - var uri = event.target.getAttribute("id"); - var prefvalue = uri.substring(uri.indexOf('chardet.') + 'chardet.'.length); - if ("off" == prefvalue) { // "off" is special value to turn off the detectors - prefvalue = ""; - } - - try { - var str = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - - str.data = prefvalue; - gPrefService.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str); - if (doReload) - window.content.location.reload(); - } - catch (ex) { - dump("Failed to set the intl.charset.detector preference.\n"); - } -} - -function BrowserSetForcedCharacterSet(aCharset) -{ - gBrowser.docShell.charset = aCharset; - // Save the forced character-set - if (!PrivateBrowsingUtils.isWindowPrivate(window)) - PlacesUtils.setCharsetForURI(getWebNavigation().currentURI, aCharset); - BrowserCharsetReload(); -} - -function BrowserCharsetReload() -{ - BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE); -} - -function charsetMenuGetElement(parent, id) { - return parent.getElementsByAttribute("id", id)[0]; -} - -function UpdateCurrentCharset(target) { - // extract the charset from DOM - var wnd = document.commandDispatcher.focusedWindow; - if ((window == wnd) || (wnd == null)) wnd = window.content; - - // Uncheck previous item - if (gPrevCharset) { - var pref_item = charsetMenuGetElement(target, "charset." + gPrevCharset); - if (pref_item) - pref_item.setAttribute('checked', 'false'); - } - - var menuitem = charsetMenuGetElement(target, "charset." + wnd.document.characterSet); - if (menuitem) { - menuitem.setAttribute('checked', 'true'); - } -} - -function UpdateCharsetDetector(target) { - var prefvalue; - - try { - prefvalue = gPrefService.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString).data; - } - catch (ex) {} - - if (!prefvalue) - prefvalue = "off"; - - var menuitem = charsetMenuGetElement(target, "chardet." + prefvalue); - if (menuitem) - menuitem.setAttribute("checked", "true"); -} - -function UpdateMenus(event) { - UpdateCurrentCharset(event.target); - UpdateCharsetDetector(event.target); -} - -function charsetLoadListener() { - var charset = window.content.document.characterSet; - - if (charset.length > 0 && (charset != gLastBrowserCharset)) { - gPrevCharset = gLastBrowserCharset; - gLastBrowserCharset = charset; - } -} - - -var gPageStyleMenu = { - - _getAllStyleSheets: function (frameset) { - var styleSheetsArray = Array.slice(frameset.document.styleSheets); - for (let i = 0; i < frameset.frames.length; i++) { - let frameSheets = this._getAllStyleSheets(frameset.frames[i]); - styleSheetsArray = styleSheetsArray.concat(frameSheets); - } - return styleSheetsArray; - }, - - fillPopup: function (menuPopup) { - var noStyle = menuPopup.firstChild; - var persistentOnly = noStyle.nextSibling; - var sep = persistentOnly.nextSibling; - while (sep.nextSibling) - menuPopup.removeChild(sep.nextSibling); - - var styleSheets = this._getAllStyleSheets(window.content); - var currentStyleSheets = {}; - var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled; - var haveAltSheets = false; - var altStyleSelected = false; - - for (let currentStyleSheet of styleSheets) { - if (!currentStyleSheet.title) - continue; - - // Skip any stylesheets whose media attribute doesn't match. - if (currentStyleSheet.media.length > 0) { - let mediaQueryList = currentStyleSheet.media.mediaText; - if (!window.content.matchMedia(mediaQueryList).matches) - continue; - } - - if (!currentStyleSheet.disabled) - altStyleSelected = true; - - haveAltSheets = true; - - let lastWithSameTitle = null; - if (currentStyleSheet.title in currentStyleSheets) - lastWithSameTitle = currentStyleSheets[currentStyleSheet.title]; - - if (!lastWithSameTitle) { - let menuItem = document.createElement("menuitem"); - menuItem.setAttribute("type", "radio"); - menuItem.setAttribute("label", currentStyleSheet.title); - menuItem.setAttribute("data", currentStyleSheet.title); - menuItem.setAttribute("checked", !currentStyleSheet.disabled && !styleDisabled); - menuItem.setAttribute("oncommand", "gPageStyleMenu.switchStyleSheet(this.getAttribute('data'));"); - menuPopup.appendChild(menuItem); - currentStyleSheets[currentStyleSheet.title] = menuItem; - } else if (currentStyleSheet.disabled) { - lastWithSameTitle.removeAttribute("checked"); - } - } - - noStyle.setAttribute("checked", styleDisabled); - persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled); - persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false; - sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets; - }, - - _stylesheetInFrame: function (frame, title) { - return Array.some(frame.document.styleSheets, - function (stylesheet) stylesheet.title == title); - }, - - _stylesheetSwitchFrame: function (frame, title) { - var docStyleSheets = frame.document.styleSheets; - - for (let i = 0; i < docStyleSheets.length; ++i) { - let docStyleSheet = docStyleSheets[i]; - - if (docStyleSheet.title) - docStyleSheet.disabled = (docStyleSheet.title != title); - else if (docStyleSheet.disabled) - docStyleSheet.disabled = false; - } - }, - - _stylesheetSwitchAll: function (frameset, title) { - if (!title || this._stylesheetInFrame(frameset, title)) - this._stylesheetSwitchFrame(frameset, title); - - for (let i = 0; i < frameset.frames.length; i++) - this._stylesheetSwitchAll(frameset.frames[i], title); - }, - - switchStyleSheet: function (title, contentWindow) { - getMarkupDocumentViewer().authorStyleDisabled = false; - this._stylesheetSwitchAll(contentWindow || content, title); - }, - - disableStyle: function () { - getMarkupDocumentViewer().authorStyleDisabled = true; - }, -}; - -/* Legacy global page-style functions */ -var getAllStyleSheets = gPageStyleMenu._getAllStyleSheets.bind(gPageStyleMenu); -var stylesheetFillPopup = gPageStyleMenu.fillPopup.bind(gPageStyleMenu); -function stylesheetSwitchAll(contentWindow, title) { - gPageStyleMenu.switchStyleSheet(title, contentWindow); -} -function setStyleDisabled(disabled) { - if (disabled) - gPageStyleMenu.disableStyle(); -} - - -var BrowserOffline = { - _inited: false, - - ///////////////////////////////////////////////////////////////////////////// - // BrowserOffline Public Methods - init: function () - { - if (!this._uiElement) - this._uiElement = document.getElementById("workOfflineMenuitemState"); - - Services.obs.addObserver(this, "network:offline-status-changed", false); - - this._updateOfflineUI(Services.io.offline); - - this._inited = true; - }, - - uninit: function () - { - if (this._inited) { - Services.obs.removeObserver(this, "network:offline-status-changed"); - } - }, - - toggleOfflineStatus: function () - { - var ioService = Services.io; - - // Stop automatic management of the offline status - try { - ioService.manageOfflineStatus = false; - } catch (ex) { - } - - if (!ioService.offline && !this._canGoOffline()) { - this._updateOfflineUI(false); - return; - } - - ioService.offline = !ioService.offline; - }, - - ///////////////////////////////////////////////////////////////////////////// - // nsIObserver - observe: function (aSubject, aTopic, aState) - { - if (aTopic != "network:offline-status-changed") - return; - - this._updateOfflineUI(aState == "offline"); - }, - - ///////////////////////////////////////////////////////////////////////////// - // BrowserOffline Implementation Methods - _canGoOffline: function () - { - try { - var cancelGoOffline = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); - Services.obs.notifyObservers(cancelGoOffline, "offline-requested", null); - - // Something aborted the quit process. - if (cancelGoOffline.data) - return false; - } - catch (ex) { - } - - return true; - }, - - _uiElement: null, - _updateOfflineUI: function (aOffline) - { - var offlineLocked = gPrefService.prefIsLocked("network.online"); - if (offlineLocked) - this._uiElement.setAttribute("disabled", "true"); - - this._uiElement.setAttribute("checked", aOffline); - } -}; - -var OfflineApps = { - ///////////////////////////////////////////////////////////////////////////// - // OfflineApps Public Methods - init: function () - { - Services.obs.addObserver(this, "offline-cache-update-completed", false); - }, - - uninit: function () - { - Services.obs.removeObserver(this, "offline-cache-update-completed"); - }, - - handleEvent: function(event) { - if (event.type == "MozApplicationManifest") { - this.offlineAppRequested(event.originalTarget.defaultView); - } - }, - - ///////////////////////////////////////////////////////////////////////////// - // OfflineApps Implementation Methods - - // XXX: _getBrowserWindowForContentWindow and _getBrowserForContentWindow - // were taken from browser/components/feeds/src/WebContentConverter. - _getBrowserWindowForContentWindow: function(aContentWindow) { - return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow) - .wrappedJSObject; - }, - - _getBrowserForContentWindow: function(aBrowserWindow, aContentWindow) { - // This depends on pseudo APIs of browser.js and tabbrowser.xml - aContentWindow = aContentWindow.top; - var browsers = aBrowserWindow.gBrowser.browsers; - for (let browser of browsers) { - if (browser.contentWindow == aContentWindow) - return browser; - } - // handle other browser/iframe elements that may need popupnotifications - let browser = aContentWindow - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler; - if (browser.getAttribute("popupnotificationanchor")) - return browser; - return null; - }, - - _getManifestURI: function(aWindow) { - if (!aWindow.document.documentElement) - return null; - - var attr = aWindow.document.documentElement.getAttribute("manifest"); - if (!attr) - return null; - - try { - var contentURI = makeURI(aWindow.location.href, null, null); - return makeURI(attr, aWindow.document.characterSet, contentURI); - } catch (e) { - return null; - } - }, - - // A cache update isn't tied to a specific window. Try to find - // the best browser in which to warn the user about space usage - _getBrowserForCacheUpdate: function(aCacheUpdate) { - // Prefer the current browser - var uri = this._getManifestURI(content); - if (uri && uri.equals(aCacheUpdate.manifestURI)) { - return gBrowser.selectedBrowser; - } - - var browsers = gBrowser.browsers; - for (let browser of browsers) { - uri = this._getManifestURI(browser.contentWindow); - if (uri && uri.equals(aCacheUpdate.manifestURI)) { - return browser; - } - } - - // is this from a non-tab browser/iframe? - browsers = document.querySelectorAll("iframe[popupnotificationanchor] | browser[popupnotificationanchor]"); - for (let browser of browsers) { - uri = this._getManifestURI(browser.contentWindow); - if (uri && uri.equals(aCacheUpdate.manifestURI)) { - return browser; - } - } - - return null; - }, - - _warnUsage: function(aBrowser, aURI) { - if (!aBrowser) - return; - - let mainAction = { - label: gNavigatorBundle.getString("offlineApps.manageUsage"), - accessKey: gNavigatorBundle.getString("offlineApps.manageUsageAccessKey"), - callback: OfflineApps.manage - }; - - let warnQuota = gPrefService.getIntPref("offline-apps.quota.warn"); - let message = gNavigatorBundle.getFormattedString("offlineApps.usage", - [ aURI.host, - warnQuota / 1024 ]); - - let anchorID = "indexedDB-notification-icon"; - PopupNotifications.show(aBrowser, "offline-app-usage", message, - anchorID, mainAction); - - // Now that we've warned once, prevent the warning from showing up - // again. - Services.perms.add(aURI, "offline-app", - Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN); - }, - - // XXX: duplicated in preferences/advanced.js - _getOfflineAppUsage: function (host, groups) - { - var cacheService = Cc["@mozilla.org/network/application-cache-service;1"]. - getService(Ci.nsIApplicationCacheService); - if (!groups) - groups = cacheService.getGroups(); - - var usage = 0; - for (let group of groups) { - var uri = Services.io.newURI(group, null, null); - if (uri.asciiHost == host) { - var cache = cacheService.getActiveCache(group); - usage += cache.usage; - } - } - - return usage; - }, - - _checkUsage: function(aURI) { - // if the user has already allowed excessive usage, don't bother checking - if (Services.perms.testExactPermission(aURI, "offline-app") != - Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN) { - var usage = this._getOfflineAppUsage(aURI.asciiHost); - var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn"); - if (usage >= warnQuota * 1024) { - return true; - } - } - - return false; - }, - - offlineAppRequested: function(aContentWindow) { - if (!gPrefService.getBoolPref("browser.offline-apps.notify")) { - return; - } - - let browserWindow = this._getBrowserWindowForContentWindow(aContentWindow); - let browser = this._getBrowserForContentWindow(browserWindow, - aContentWindow); - - let currentURI = aContentWindow.document.documentURIObject; - - // don't bother showing UI if the user has already made a decision - if (Services.perms.testExactPermission(currentURI, "offline-app") != Services.perms.UNKNOWN_ACTION) - return; - - try { - if (gPrefService.getBoolPref("offline-apps.allow_by_default")) { - // all pages can use offline capabilities, no need to ask the user - return; - } - } catch(e) { - // this pref isn't set by default, ignore failures - } - - let host = currentURI.asciiHost; - let notificationID = "offline-app-requested-" + host; - let notification = PopupNotifications.getNotification(notificationID, browser); - - if (notification) { - notification.options.documents.push(aContentWindow.document); - } else { - let mainAction = { - label: gNavigatorBundle.getString("offlineApps.allow"), - accessKey: gNavigatorBundle.getString("offlineApps.allowAccessKey"), - callback: function() { - for (let document of notification.options.documents) { - OfflineApps.allowSite(document); - } - } - }; - let secondaryActions = [{ - label: gNavigatorBundle.getString("offlineApps.never"), - accessKey: gNavigatorBundle.getString("offlineApps.neverAccessKey"), - callback: function() { - for (let document of notification.options.documents) { - OfflineApps.disallowSite(document); - } - } - }]; - let message = gNavigatorBundle.getFormattedString("offlineApps.available", - [ host ]); - let anchorID = "indexedDB-notification-icon"; - let options= { - documents : [ aContentWindow.document ] - }; - notification = PopupNotifications.show(browser, notificationID, message, - anchorID, mainAction, - secondaryActions, options); - } - }, - - allowSite: function(aDocument) { - Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.ALLOW_ACTION); - - // When a site is enabled while loading, manifest resources will - // start fetching immediately. This one time we need to do it - // ourselves. - this._startFetching(aDocument); - }, - - disallowSite: function(aDocument) { - Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.DENY_ACTION); - }, - - manage: function() { - openAdvancedPreferences("networkTab"); - }, - - _startFetching: function(aDocument) { - if (!aDocument.documentElement) - return; - - var manifest = aDocument.documentElement.getAttribute("manifest"); - if (!manifest) - return; - - var manifestURI = makeURI(manifest, aDocument.characterSet, - aDocument.documentURIObject); - - var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"]. - getService(Ci.nsIOfflineCacheUpdateService); - updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject, window); - }, - - ///////////////////////////////////////////////////////////////////////////// - // nsIObserver - observe: function (aSubject, aTopic, aState) - { - if (aTopic == "offline-cache-update-completed") { - var cacheUpdate = aSubject.QueryInterface(Ci.nsIOfflineCacheUpdate); - - var uri = cacheUpdate.manifestURI; - if (OfflineApps._checkUsage(uri)) { - var browser = this._getBrowserForCacheUpdate(cacheUpdate); - if (browser) { - OfflineApps._warnUsage(browser, cacheUpdate.manifestURI); - } - } - } - } -}; - -var IndexedDBPromptHelper = { - _permissionsPrompt: "indexedDB-permissions-prompt", - _permissionsResponse: "indexedDB-permissions-response", - - _quotaPrompt: "indexedDB-quota-prompt", - _quotaResponse: "indexedDB-quota-response", - _quotaCancel: "indexedDB-quota-cancel", - - _notificationIcon: "indexedDB-notification-icon", - - init: - function IndexedDBPromptHelper_init() { - Services.obs.addObserver(this, this._permissionsPrompt, false); - Services.obs.addObserver(this, this._quotaPrompt, false); - Services.obs.addObserver(this, this._quotaCancel, false); - }, - - uninit: - function IndexedDBPromptHelper_uninit() { - Services.obs.removeObserver(this, this._permissionsPrompt); - Services.obs.removeObserver(this, this._quotaPrompt); - Services.obs.removeObserver(this, this._quotaCancel); - }, - - observe: - function IndexedDBPromptHelper_observe(subject, topic, data) { - if (topic != this._permissionsPrompt && - topic != this._quotaPrompt && - topic != this._quotaCancel) { - throw new Error("Unexpected topic!"); - } - - var requestor = subject.QueryInterface(Ci.nsIInterfaceRequestor); - - var contentWindow = requestor.getInterface(Ci.nsIDOMWindow); - var contentDocument = contentWindow.document; - var browserWindow = - OfflineApps._getBrowserWindowForContentWindow(contentWindow); - - if (browserWindow != window) { - // Must belong to some other window. - return; - } - - var browser = - OfflineApps._getBrowserForContentWindow(browserWindow, contentWindow); - - var host = contentDocument.documentURIObject.asciiHost; - - var message; - var responseTopic; - if (topic == this._permissionsPrompt) { - message = gNavigatorBundle.getFormattedString("offlineApps.available", - [ host ]); - responseTopic = this._permissionsResponse; - } - else if (topic == this._quotaPrompt) { - message = gNavigatorBundle.getFormattedString("indexedDB.usage", - [ host, data ]); - responseTopic = this._quotaResponse; - } - else if (topic == this._quotaCancel) { - responseTopic = this._quotaResponse; - } - - const hiddenTimeoutDuration = 30000; // 30 seconds - const firstTimeoutDuration = 300000; // 5 minutes - - var timeoutId; - - var observer = requestor.getInterface(Ci.nsIObserver); - - var mainAction = { - label: gNavigatorBundle.getString("offlineApps.allow"), - accessKey: gNavigatorBundle.getString("offlineApps.allowAccessKey"), - callback: function() { - clearTimeout(timeoutId); - observer.observe(null, responseTopic, - Ci.nsIPermissionManager.ALLOW_ACTION); - } - }; - - var secondaryActions = [ - { - label: gNavigatorBundle.getString("offlineApps.never"), - accessKey: gNavigatorBundle.getString("offlineApps.neverAccessKey"), - callback: function() { - clearTimeout(timeoutId); - observer.observe(null, responseTopic, - Ci.nsIPermissionManager.DENY_ACTION); - } - } - ]; - - // This will be set to the result of PopupNotifications.show() below, or to - // the result of PopupNotifications.getNotification() if this is a - // quotaCancel notification. - var notification; - - function timeoutNotification() { - // Remove the notification. - if (notification) { - notification.remove(); - } - - // Clear all of our timeout stuff. We may be called directly, not just - // when the timeout actually elapses. - clearTimeout(timeoutId); - - // And tell the page that the popup timed out. - observer.observe(null, responseTopic, - Ci.nsIPermissionManager.UNKNOWN_ACTION); - } - - var options = { - eventCallback: function(state) { - // Don't do anything if the timeout has not been set yet. - if (!timeoutId) { - return; - } - - // If the popup is being dismissed start the short timeout. - if (state == "dismissed") { - clearTimeout(timeoutId); - timeoutId = setTimeout(timeoutNotification, hiddenTimeoutDuration); - return; - } - - // If the popup is being re-shown then clear the timeout allowing - // unlimited waiting. - if (state == "shown") { - clearTimeout(timeoutId); - } - } - }; - - if (topic == this._quotaCancel) { - notification = PopupNotifications.getNotification(this._quotaPrompt, - browser); - timeoutNotification(); - return; - } - - notification = PopupNotifications.show(browser, topic, message, - this._notificationIcon, mainAction, - secondaryActions, options); - - // Set the timeoutId after the popup has been created, and use the long - // timeout value. If the user doesn't notice the popup after this amount of - // time then it is most likely not visible and we want to alert the page. - timeoutId = setTimeout(timeoutNotification, firstTimeoutDuration); - } -}; - -function WindowIsClosing() -{ - let event = document.createEvent("Events"); - event.initEvent("WindowIsClosing", true, true); - if (!window.dispatchEvent(event)) - return false; - - if (!closeWindow(false, warnAboutClosingWindow)) - return false; - - for (let browser of gBrowser.browsers) { - let ds = browser.docShell; - if (ds.contentViewer && !ds.contentViewer.permitUnload()) - return false; - } - - return true; -} - -/** - * Checks if this is the last full *browser* window around. If it is, this will - * be communicated like quitting. Otherwise, we warn about closing multiple tabs. - * @returns true if closing can proceed, false if it got cancelled. - */ -function warnAboutClosingWindow() { - // Popups aren't considered full browser windows. - let isPBWindow = PrivateBrowsingUtils.isWindowPrivate(window); - if (!isPBWindow && !toolbar.visible) - return gBrowser.warnAboutClosingTabs(gBrowser.closingTabsEnum.ALL); - - // Figure out if there's at least one other browser window around. - let e = Services.wm.getEnumerator("navigator:browser"); - let otherPBWindowExists = false; - let nonPopupPresent = false; - while (e.hasMoreElements()) { - let win = e.getNext(); - if (win != window) { - if (isPBWindow && PrivateBrowsingUtils.isWindowPrivate(win)) - otherPBWindowExists = true; - if (win.toolbar.visible) - nonPopupPresent = true; - // If the current window is not in private browsing mode we don't need to - // look for other pb windows, we can leave the loop when finding the - // first non-popup window. If however the current window is in private - // browsing mode then we need at least one other pb and one non-popup - // window to break out early. - if ((!isPBWindow || otherPBWindowExists) && nonPopupPresent) - break; - } - } - - if (isPBWindow && !otherPBWindowExists) { - let exitingCanceled = Cc["@mozilla.org/supports-PRBool;1"]. - createInstance(Ci.nsISupportsPRBool); - exitingCanceled.data = false; - Services.obs.notifyObservers(exitingCanceled, - "last-pb-context-exiting", - null); - if (exitingCanceled.data) - return false; - } - - if (nonPopupPresent) { - return isPBWindow || gBrowser.warnAboutClosingTabs(gBrowser.closingTabsEnum.ALL); - } - - let os = Services.obs; - - let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"]. - createInstance(Ci.nsISupportsPRBool); - os.notifyObservers(closingCanceled, - "browser-lastwindow-close-requested", null); - if (closingCanceled.data) - return false; - - os.notifyObservers(null, "browser-lastwindow-close-granted", null); - -#ifdef XP_MACOSX - // OS X doesn't quit the application when the last window is closed, but keeps - // the session alive. Hence don't prompt users to save tabs, but warn about - // closing multiple tabs. - return isPBWindow || gBrowser.warnAboutClosingTabs(gBrowser.closingTabsEnum.ALL); -#else - return true; -#endif -} - -var MailIntegration = { - sendLinkForWindow: function (aWindow) { - this.sendMessage(aWindow.location.href, - aWindow.document.title); - }, - - sendMessage: function (aBody, aSubject) { - // generate a mailto url based on the url and the url's title - var mailtoUrl = "mailto:"; - if (aBody) { - mailtoUrl += "?body=" + encodeURIComponent(aBody); - mailtoUrl += "&subject=" + encodeURIComponent(aSubject); - } - - var uri = makeURI(mailtoUrl); - - // now pass this uri to the operating system - this._launchExternalUrl(uri); - }, - - // a generic method which can be used to pass arbitrary urls to the operating - // system. - // aURL --> a nsIURI which represents the url to launch - _launchExternalUrl: function (aURL) { - var extProtocolSvc = - Cc["@mozilla.org/uriloader/external-protocol-service;1"] - .getService(Ci.nsIExternalProtocolService); - if (extProtocolSvc) - extProtocolSvc.loadUrl(aURL); - } -}; - -function BrowserOpenAddonsMgr(aView) { - if (aView) { - let emWindow; - let browserWindow; - - var receivePong = function receivePong(aSubject, aTopic, aData) { - let browserWin = aSubject.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow); - if (!emWindow || browserWin == window /* favor the current window */) { - emWindow = aSubject; - browserWindow = browserWin; - } - } - Services.obs.addObserver(receivePong, "EM-pong", false); - Services.obs.notifyObservers(null, "EM-ping", ""); - Services.obs.removeObserver(receivePong, "EM-pong"); - - if (emWindow) { - emWindow.loadView(aView); - browserWindow.gBrowser.selectedTab = - browserWindow.gBrowser._getTabForContentWindow(emWindow); - emWindow.focus(); - return; - } - } - - var newLoad = !switchToTabHavingURI("about:addons", true); - - if (aView) { - // This must be a new load, else the ping/pong would have - // found the window above. - Services.obs.addObserver(function observer(aSubject, aTopic, aData) { - Services.obs.removeObserver(observer, aTopic); - aSubject.loadView(aView); - }, "EM-loaded", false); - } -} - -function BrowserOpenPermissionsMgr() { - switchToTabHavingURI("about:permissions", true); -} - -function AddKeywordForSearchField() { - var node = document.popupNode; - - var charset = node.ownerDocument.characterSet; - - var docURI = makeURI(node.ownerDocument.URL, - charset); - - var formURI = makeURI(node.form.getAttribute("action"), - charset, - docURI); - - var spec = formURI.spec; - - var isURLEncoded = - (node.form.method.toUpperCase() == "POST" - && (node.form.enctype == "application/x-www-form-urlencoded" || - node.form.enctype == "")); - - var title = gNavigatorBundle.getFormattedString("addKeywordTitleAutoFill", - [node.ownerDocument.title]); - var description = PlacesUIUtils.getDescriptionFromDocument(node.ownerDocument); - - var formData = []; - - function escapeNameValuePair(aName, aValue, aIsFormUrlEncoded) { - if (aIsFormUrlEncoded) - return escape(aName + "=" + aValue); - else - return escape(aName) + "=" + escape(aValue); - } - - for (let el of node.form.elements) { - if (!el.type) // happens with fieldsets - continue; - - if (el == node) { - formData.push((isURLEncoded) ? escapeNameValuePair(el.name, "%s", true) : - // Don't escape "%s", just append - escapeNameValuePair(el.name, "", false) + "%s"); - continue; - } - - let type = el.type.toLowerCase(); - - if (((el instanceof HTMLInputElement && el.mozIsTextField(true)) || - type == "hidden" || type == "textarea") || - ((type == "checkbox" || type == "radio") && el.checked)) { - formData.push(escapeNameValuePair(el.name, el.value, isURLEncoded)); - } else if (el instanceof HTMLSelectElement && el.selectedIndex >= 0) { - for (var j=0; j < el.options.length; j++) { - if (el.options[j].selected) - formData.push(escapeNameValuePair(el.name, el.options[j].value, - isURLEncoded)); - } - } - } - - var postData; - - if (isURLEncoded) - postData = formData.join("&"); - else - spec += "?" + formData.join("&"); - - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "bookmark" - , uri: makeURI(spec) - , title: title - , description: description - , keyword: "" - , postData: postData - , charSet: charset - , hiddenRows: [ "location" - , "description" - , "tags" - , "loadInSidebar" ] - }, window); -} - -function SwitchDocumentDirection(aWindow) { - // document.dir can also be "auto", in which case it won't change - if (aWindow.document.dir == "ltr" || aWindow.document.dir == "") { - aWindow.document.dir = "rtl"; - } else if (aWindow.document.dir == "rtl") { - aWindow.document.dir = "ltr"; - } - for (var run = 0; run < aWindow.frames.length; run++) - SwitchDocumentDirection(aWindow.frames[run]); -} - -function convertFromUnicode(charset, str) -{ - try { - var unicodeConverter = Components - .classes["@mozilla.org/intl/scriptableunicodeconverter"] - .createInstance(Components.interfaces.nsIScriptableUnicodeConverter); - unicodeConverter.charset = charset; - str = unicodeConverter.ConvertFromUnicode(str); - return str + unicodeConverter.Finish(); - } catch(ex) { - return null; - } -} - -/** - * Re-open a closed tab. - * @param aIndex - * The index of the tab (via nsSessionStore.getClosedTabData) - * @returns a reference to the reopened tab. - */ -function undoCloseTab(aIndex) { - // wallpaper patch to prevent an unnecessary blank tab (bug 343895) - var blankTabToRemove = null; - if (gBrowser.tabs.length == 1 && - !gPrefService.getBoolPref("browser.tabs.autoHide") && - isTabEmpty(gBrowser.selectedTab)) - blankTabToRemove = gBrowser.selectedTab; - - var tab = null; - var ss = Cc["@mozilla.org/browser/sessionstore;1"]. - getService(Ci.nsISessionStore); - if (ss.getClosedTabCount(window) > (aIndex || 0)) { - tab = ss.undoCloseTab(window, aIndex || 0); - - if (blankTabToRemove) - gBrowser.removeTab(blankTabToRemove); - } - - return tab; -} - -/** - * Re-open a closed window. - * @param aIndex - * The index of the window (via nsSessionStore.getClosedWindowData) - * @returns a reference to the reopened window. - */ -function undoCloseWindow(aIndex) { - let ss = Cc["@mozilla.org/browser/sessionstore;1"]. - getService(Ci.nsISessionStore); - let window = null; - if (ss.getClosedWindowCount() > (aIndex || 0)) - window = ss.undoCloseWindow(aIndex || 0); - - return window; -} - -/* - * Determines if a tab is "empty", usually used in the context of determining - * if it's ok to close the tab. - */ -function isTabEmpty(aTab) { - if (aTab.hasAttribute("busy")) - return false; - - let browser = aTab.linkedBrowser; - if (!isBlankPageURL(browser.currentURI.spec)) - return false; - - // Bug 863515 - Make content.opener checks work in electrolysis. - if (!gMultiProcessBrowser && browser.contentWindow.opener) - return false; - - if (browser.sessionHistory && browser.sessionHistory.count >= 2) - return false; - - return true; -} - -#ifdef MOZ_SERVICES_SYNC -function BrowserOpenSyncTabs() { - switchToTabHavingURI("about:sync-tabs", true); -} -#endif - -/** - * Format a URL - * eg: - * echo formatURL("https://addons.mozilla.org/%LOCALE%/%APP%/%VERSION%/"); - * > https://addons.mozilla.org/en-US/firefox/3.0a1/ - * - * Currently supported built-ins are LOCALE, APP, and any value from nsIXULAppInfo, uppercased. - */ -function formatURL(aFormat, aIsPref) { - var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter); - return aIsPref ? formatter.formatURLPref(aFormat) : formatter.formatURL(aFormat); -} - -/** - * Utility object to handle manipulations of the identity indicators in the UI - */ -var gIdentityHandler = { - // Mode strings used to control CSS display - IDENTITY_MODE_IDENTIFIED : "verifiedIdentity", // High-quality identity information - IDENTITY_MODE_DOMAIN_VERIFIED : "verifiedDomain", // Minimal SSL CA-signed domain verification - IDENTITY_MODE_UNKNOWN : "unknownIdentity", // No trusted identity information - IDENTITY_MODE_MIXED_CONTENT : "unknownIdentity mixedContent", // SSL with unauthenticated content - IDENTITY_MODE_MIXED_ACTIVE_CONTENT : "unknownIdentity mixedContent mixedActiveContent", // SSL with unauthenticated content - IDENTITY_MODE_CHROMEUI : "chromeUI", // Part of the product's UI - - // Cache the most recent SSLStatus and Location seen in checkIdentity - _lastStatus : null, - _lastLocation : null, - _mode : "unknownIdentity", - - // smart getters - get _encryptionLabel () { - delete this._encryptionLabel; - this._encryptionLabel = {}; - this._encryptionLabel[this.IDENTITY_MODE_DOMAIN_VERIFIED] = - gNavigatorBundle.getString("identity.encrypted"); - this._encryptionLabel[this.IDENTITY_MODE_IDENTIFIED] = - gNavigatorBundle.getString("identity.encrypted"); - this._encryptionLabel[this.IDENTITY_MODE_UNKNOWN] = - gNavigatorBundle.getString("identity.unencrypted"); - this._encryptionLabel[this.IDENTITY_MODE_MIXED_CONTENT] = - gNavigatorBundle.getString("identity.mixed_content"); - this._encryptionLabel[this.IDENTITY_MODE_MIXED_ACTIVE_CONTENT] = - gNavigatorBundle.getString("identity.mixed_content"); - return this._encryptionLabel; - }, - get _identityPopup () { - delete this._identityPopup; - return this._identityPopup = document.getElementById("identity-popup"); - }, - get _identityBox () { - delete this._identityBox; - return this._identityBox = document.getElementById("identity-box"); - }, - get _identityPopupContentBox () { - delete this._identityPopupContentBox; - return this._identityPopupContentBox = - document.getElementById("identity-popup-content-box"); - }, - get _identityPopupContentHost () { - delete this._identityPopupContentHost; - return this._identityPopupContentHost = - document.getElementById("identity-popup-content-host"); - }, - get _identityPopupContentOwner () { - delete this._identityPopupContentOwner; - return this._identityPopupContentOwner = - document.getElementById("identity-popup-content-owner"); - }, - get _identityPopupContentSupp () { - delete this._identityPopupContentSupp; - return this._identityPopupContentSupp = - document.getElementById("identity-popup-content-supplemental"); - }, - get _identityPopupContentVerif () { - delete this._identityPopupContentVerif; - return this._identityPopupContentVerif = - document.getElementById("identity-popup-content-verifier"); - }, - get _identityPopupEncLabel () { - delete this._identityPopupEncLabel; - return this._identityPopupEncLabel = - document.getElementById("identity-popup-encryption-label"); - }, - get _identityIconLabel () { - delete this._identityIconLabel; - return this._identityIconLabel = document.getElementById("identity-icon-label"); - }, - get _overrideService () { - delete this._overrideService; - return this._overrideService = Cc["@mozilla.org/security/certoverride;1"] - .getService(Ci.nsICertOverrideService); - }, - get _identityIconCountryLabel () { - delete this._identityIconCountryLabel; - return this._identityIconCountryLabel = document.getElementById("identity-icon-country-label"); - }, - get _identityIcon () { - delete this._identityIcon; - return this._identityIcon = document.getElementById("page-proxy-favicon"); - }, - - /** - * Rebuild cache of the elements that may or may not exist depending - * on whether there's a location bar. - */ - _cacheElements : function() { - delete this._identityBox; - delete this._identityIconLabel; - delete this._identityIconCountryLabel; - delete this._identityIcon; - this._identityBox = document.getElementById("identity-box"); - this._identityIconLabel = document.getElementById("identity-icon-label"); - this._identityIconCountryLabel = document.getElementById("identity-icon-country-label"); - this._identityIcon = document.getElementById("page-proxy-favicon"); - }, - - /** - * Handler for mouseclicks on the "More Information" button in the - * "identity-popup" panel. - */ - handleMoreInfoClick : function(event) { - displaySecurityInfo(); - event.stopPropagation(); - }, - - /** - * Helper to parse out the important parts of _lastStatus (of the SSL cert in - * particular) for use in constructing identity UI strings - */ - getIdentityData : function() { - var result = {}; - var status = this._lastStatus.QueryInterface(Components.interfaces.nsISSLStatus); - var cert = status.serverCert; - - // Human readable name of Subject - result.subjectOrg = cert.organization; - - // SubjectName fields, broken up for individual access - if (cert.subjectName) { - result.subjectNameFields = {}; - cert.subjectName.split(",").forEach(function(v) { - var field = v.split("="); - this[field[0]] = field[1]; - }, result.subjectNameFields); - - // Call out city, state, and country specifically - result.city = result.subjectNameFields.L; - result.state = result.subjectNameFields.ST; - result.country = result.subjectNameFields.C; - } - - // Human readable name of Certificate Authority - result.caOrg = cert.issuerOrganization || cert.issuerCommonName; - result.cert = cert; - - return result; - }, - - /** - * Determine the identity of the page being displayed by examining its SSL cert - * (if available) and, if necessary, update the UI to reflect this. Intended to - * be called by onSecurityChange - * - * @param PRUint32 state - * @param JS Object location that mirrors an nsLocation (i.e. has .host and - * .hostname and .port) - */ - checkIdentity : function(state, location) { - var currentStatus = gBrowser.securityUI - .QueryInterface(Components.interfaces.nsISSLStatusProvider) - .SSLStatus; - this._lastStatus = currentStatus; - this._lastLocation = location; - - let nsIWebProgressListener = Ci.nsIWebProgressListener; - if (location.protocol == "chrome:" || location.protocol == "about:") { - this.setMode(this.IDENTITY_MODE_CHROMEUI); - } else if (state & nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) { - this.setMode(this.IDENTITY_MODE_IDENTIFIED); - } else if (state & nsIWebProgressListener.STATE_IS_SECURE) { - this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED); - } else if (state & nsIWebProgressListener.STATE_IS_BROKEN) { - if ((state & nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) && - gPrefService.getBoolPref("security.mixed_content.block_active_content")) { - this.setMode(this.IDENTITY_MODE_MIXED_ACTIVE_CONTENT); - } else { - this.setMode(this.IDENTITY_MODE_MIXED_CONTENT); - } - } else { - this.setMode(this.IDENTITY_MODE_UNKNOWN); - } - - // Ensure the doorhanger is shown when mixed active content is blocked. - if (state & nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT) - this.showMixedContentDoorhanger(); - }, - - /** - * Display the Mixed Content Blocker doohanger, providing an option - * to the user to override mixed content blocking - */ - showMixedContentDoorhanger : function() { - // If we've already got an active notification, bail out to avoid showing it repeatedly. - if (PopupNotifications.getNotification("mixed-content-blocked", gBrowser.selectedBrowser)) - return; - - let brandBundle = document.getElementById("bundle_brand"); - let brandShortName = brandBundle.getString("brandShortName"); - let messageString = gNavigatorBundle.getFormattedString("mixedContentBlocked.message", [brandShortName]); - let action = { - label: gNavigatorBundle.getString("mixedContentBlocked.keepBlockingButton.label"), - accessKey: gNavigatorBundle.getString("mixedContentBlocked.keepBlockingButton.accesskey"), - callback: function() { /* NOP */ } - }; - let secondaryActions = [ - { - label: gNavigatorBundle.getString("mixedContentBlocked.unblock.label"), - accessKey: gNavigatorBundle.getString("mixedContentBlocked.unblock.accesskey"), - callback: function() { - // Reload the page with the content unblocked - BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT); - } - } - ]; - let options = { - dismissed: true, - learnMoreURL: Services.urlFormatter.formatURLPref("browser.mixedcontent.warning.infoURL"), - }; - PopupNotifications.show(gBrowser.selectedBrowser, "mixed-content-blocked", - messageString, "mixed-content-blocked-notification-icon", - action, secondaryActions, options); - }, - - /** - * Return the eTLD+1 version of the current hostname - */ - getEffectiveHost : function() { - try { - let baseDomain = - Services.eTLD.getBaseDomainFromHost(this._lastLocation.hostname); - return this._IDNService.convertToDisplayIDN(baseDomain, {}); - } catch (e) { - // If something goes wrong (e.g. hostname is an IP address) just fail back - // to the full domain. - return this._lastLocation.hostname; - } - }, - - /** - * Update the UI to reflect the specified mode, which should be one of the - * IDENTITY_MODE_* constants. - */ - setMode : function(newMode) { - if (!this._identityBox) { - // No identity box means the identity box is not visible, in which - // case there's nothing to do. - return; - } - - this._identityBox.className = newMode; - this.setIdentityMessages(newMode); - - // Update the popup too, if it's open - if (this._identityPopup.state == "open") - this.setPopupMessages(newMode); - - this._mode = newMode; - }, - - /** - * Set up the messages for the primary identity UI based on the specified mode, - * and the details of the SSL cert, where applicable - * - * @param newMode The newly set identity mode. Should be one of the IDENTITY_MODE_* constants. - */ - setIdentityMessages : function(newMode) { - let icon_label = ""; - let tooltip = ""; - let icon_country_label = ""; - let icon_labels_dir = "ltr"; - - if (!this._IDNService) - this._IDNService = Cc["@mozilla.org/network/idn-service;1"] - .getService(Ci.nsIIDNService); - let punyID = gPrefService.getIntPref("browser.identity.display_punycode", 1); - - switch (newMode) { - case this.IDENTITY_MODE_DOMAIN_VERIFIED: { - let iData = this.getIdentityData(); - - let label_display = ""; - - //Pale Moon: honor browser.identity.ssl_domain_display! - switch (gPrefService.getIntPref("browser.identity.ssl_domain_display")) { - case 2 : // Show full domain - label_display = this._lastLocation.hostname; - break; - case 1 : // Show eTLD. - label_display = this.getEffectiveHost(); - } - - if (punyID >= 1) { - // Display punycode version in identity panel - icon_label = this._IDNService.convertUTF8toACE(label_display); - } else { - icon_label = label_display; - } - - // Verifier is either the CA Org, for a normal cert, or a special string - // for certs that are trusted because of a security exception. - tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier", - [iData.caOrg]); - - // Check whether this site is a security exception. XPConnect does the right - // thing here in terms of converting _lastLocation.port from string to int, but - // the overrideService doesn't like undefined ports, so make sure we have - // something in the default case (bug 432241). - // .hostname can return an empty string in some exceptional cases - - // hasMatchingOverride does not handle that, so avoid calling it. - // Updating the tooltip value in those cases isn't critical. - // FIXME: Fixing bug 646690 would probably makes this check unnecessary - if (this._lastLocation.hostname && - this._overrideService.hasMatchingOverride(this._lastLocation.hostname, - (this._lastLocation.port || 443), - iData.cert, {}, {})) - tooltip = gNavigatorBundle.getString("identity.identified.verified_by_you"); - break; } - case this.IDENTITY_MODE_IDENTIFIED: { - // If it's identified, then we can populate the dialog with credentials - let iData = this.getIdentityData(); - tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier", - [iData.caOrg]); - icon_label = iData.subjectOrg; - if (iData.country) - icon_country_label = "(" + iData.country + ")"; - - // If the organization name starts with an RTL character, then - // swap the positions of the organization and country code labels. - // The Unicode ranges reflect the definition of the UCS2_CHAR_IS_BIDI - // macro in intl/unicharutil/util/nsBidiUtils.h. When bug 218823 gets - // fixed, this test should be replaced by one adhering to the - // Unicode Bidirectional Algorithm proper (at the paragraph level). - icon_labels_dir = /^[\u0590-\u08ff\ufb1d-\ufdff\ufe70-\ufefc]/.test(icon_label) ? - "rtl" : "ltr"; - break; } - case this.IDENTITY_MODE_CHROMEUI: - break; - default: - tooltip = gNavigatorBundle.getString("identity.unknown.tooltip"); - if (punyID == 2) { - // Check for IDN and display if so... - let rawHost = this._IDNService.convertUTF8toACE(this._lastLocation.hostname); - if (this._IDNService.isACE(rawHost)) { - icon_label = rawHost; - } - } - } - - // Push the appropriate strings out to the UI - this._identityBox.tooltipText = tooltip; - this._identityIconLabel.value = icon_label; - this._identityIconCountryLabel.value = icon_country_label; - // Set cropping and direction - this._identityIconLabel.crop = icon_country_label ? "end" : "center"; - this._identityIconLabel.parentNode.style.direction = icon_labels_dir; - // Hide completely if the organization label is empty - this._identityIconLabel.parentNode.collapsed = icon_label ? false : true; - }, - - /** - * Set up the title and content messages for the identity message popup, - * based on the specified mode, and the details of the SSL cert, where - * applicable - * - * @param newMode The newly set identity mode. Should be one of the IDENTITY_MODE_* constants. - */ - setPopupMessages : function(newMode) { - - this._identityPopup.className = newMode; - this._identityPopupContentBox.className = newMode; - - // Set the static strings up front - this._identityPopupEncLabel.textContent = this._encryptionLabel[newMode]; - - // Initialize the optional strings to empty values - let supplemental = ""; - let verifier = ""; - let host = ""; - let owner = ""; - - switch (newMode) { - case this.IDENTITY_MODE_DOMAIN_VERIFIED: - host = this.getEffectiveHost(); - owner = gNavigatorBundle.getString("identity.ownerUnknown2"); - verifier = this._identityBox.tooltipText; - break; - case this.IDENTITY_MODE_IDENTIFIED: { - // If it's identified, then we can populate the dialog with credentials - let iData = this.getIdentityData(); - host = this.getEffectiveHost(); - owner = iData.subjectOrg; - verifier = this._identityBox.tooltipText; - - // Build an appropriate supplemental block out of whatever location data we have - if (iData.city) - supplemental += iData.city + "\n"; - if (iData.state && iData.country) - supplemental += gNavigatorBundle.getFormattedString("identity.identified.state_and_country", - [iData.state, iData.country]); - else if (iData.state) // State only - supplemental += iData.state; - else if (iData.country) // Country only - supplemental += iData.country; - break; } - } - - // Push the appropriate strings out to the UI - this._identityPopupContentHost.textContent = host; - this._identityPopupContentOwner.textContent = owner; - this._identityPopupContentSupp.textContent = supplemental; - this._identityPopupContentVerif.textContent = verifier; - }, - - hideIdentityPopup : function() { - this._identityPopup.hidePopup(); - }, - - /** - * Click handler for the identity-box element in primary chrome. - */ - handleIdentityButtonEvent : function(event) { - event.stopPropagation(); - - if ((event.type == "click" && event.button != 0) || - (event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE && - event.keyCode != KeyEvent.DOM_VK_RETURN)) { - return; // Left click, space or enter only - } - - // Don't allow left click, space or enter if the location - // is chrome UI or the location has been modified. - if (this._mode == this.IDENTITY_MODE_CHROMEUI || - gURLBar.getAttribute("pageproxystate") != "valid") { - return; - } - - // Make sure that the display:none style we set in xul is removed now that - // the popup is actually needed - this._identityPopup.hidden = false; - - // Update the popup strings - this.setPopupMessages(this._identityBox.className); - - // Add the "open" attribute to the identity box for styling - this._identityBox.setAttribute("open", "true"); - var self = this; - this._identityPopup.addEventListener("popuphidden", function onPopupHidden(e) { - e.currentTarget.removeEventListener("popuphidden", onPopupHidden, false); - self._identityBox.removeAttribute("open"); - }, false); - - // Now open the popup, anchored off the primary chrome element - this._identityPopup.openPopup(this._identityIcon, "bottomcenter topleft"); - }, - - onPopupShown : function(event) { - document.getElementById('identity-popup-more-info-button').focus(); - }, - - onDragStart: function (event) { - if (gURLBar.getAttribute("pageproxystate") != "valid") - return; - - var value = content.location.href; - var urlString = value + "\n" + content.document.title; - var htmlString = "<a href=\"" + value + "\">" + value + "</a>"; - - var dt = event.dataTransfer; - dt.setData("text/x-moz-url", urlString); - dt.setData("text/uri-list", value); - dt.setData("text/plain", value); - dt.setData("text/html", htmlString); - dt.setDragImage(gProxyFavIcon, 16, 16); - } -}; - -function getNotificationBox(aWindow) { - var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document); - if (foundBrowser) - return gBrowser.getNotificationBox(foundBrowser) - return null; -}; - -function getTabModalPromptBox(aWindow) { - var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document); - if (foundBrowser) - return gBrowser.getTabModalPromptBox(foundBrowser); - return null; -}; - -/* DEPRECATED */ -function getBrowser() gBrowser; -function getNavToolbox() gNavToolbox; - -let gPrivateBrowsingUI = { - init: function PBUI_init() { - // Do nothing for normal windows - if (!PrivateBrowsingUtils.isWindowPrivate(window)) { - return; - } - - // Disable the Clear Recent History... menu item when in PB mode - // temporary fix until bug 463607 is fixed - document.getElementById("Tools:Sanitize").setAttribute("disabled", "true"); - - if (window.location.href == getBrowserURL()) { -#ifdef XP_MACOSX - if (!PrivateBrowsingUtils.permanentPrivateBrowsing) { - document.documentElement.setAttribute("drawintitlebar", true); - } -#endif - - // Adjust the window's title - let docElement = document.documentElement; - if (!PrivateBrowsingUtils.permanentPrivateBrowsing) { - docElement.setAttribute("title", - docElement.getAttribute("title_privatebrowsing")); - docElement.setAttribute("titlemodifier", - docElement.getAttribute("titlemodifier_privatebrowsing")); - } - docElement.setAttribute("privatebrowsingmode", - PrivateBrowsingUtils.permanentPrivateBrowsing ? "permanent" : "temporary"); - gBrowser.updateTitlebar(); - - if (PrivateBrowsingUtils.permanentPrivateBrowsing) { - // Adjust the New Window menu entries - [ - { normal: "menu_newNavigator", private: "menu_newPrivateWindow" }, - { normal: "appmenu_newNavigator", private: "appmenu_newPrivateWindow" }, - ].forEach(function(menu) { - let newWindow = document.getElementById(menu.normal); - let newPrivateWindow = document.getElementById(menu.private); - if (newWindow && newPrivateWindow) { - newPrivateWindow.hidden = true; - newWindow.label = newPrivateWindow.label; - newWindow.accessKey = newPrivateWindow.accessKey; - newWindow.command = newPrivateWindow.command; - } - }); - } - } - - if (gURLBar && - !PrivateBrowsingUtils.permanentPrivateBrowsing) { - // Disable switch to tab autocompletion for private windows - // (not for "Always use private browsing" mode) - gURLBar.setAttribute("autocompletesearchparam", ""); - } - } -}; - - -/** - * Switch to a tab that has a given URI, and focusses its browser window. - * If a matching tab is in this window, it will be switched to. Otherwise, other - * windows will be searched. - * - * @param aURI - * URI to search for - * @param aOpenNew - * True to open a new tab and switch to it, if no existing tab is found. - * If no suitable window is found, a new one will be opened. - * @return True if an existing tab was found, false otherwise - */ -function switchToTabHavingURI(aURI, aOpenNew) { - // This will switch to the tab in aWindow having aURI, if present. - function switchIfURIInWindow(aWindow) { - // Only switch to the tab if neither the source and desination window are - // private and they are not in permanent private borwsing mode - if ((PrivateBrowsingUtils.isWindowPrivate(window) || - PrivateBrowsingUtils.isWindowPrivate(aWindow)) && - !PrivateBrowsingUtils.permanentPrivateBrowsing) { - return false; - } - - let browsers = aWindow.gBrowser.browsers; - for (let i = 0; i < browsers.length; i++) { - let browser = browsers[i]; - if (browser.currentURI.equals(aURI)) { - // Focus the matching window & tab - aWindow.focus(); - aWindow.gBrowser.tabContainer.selectedIndex = i; - return true; - } - } - return false; - } - - // This can be passed either nsIURI or a string. - if (!(aURI instanceof Ci.nsIURI)) - aURI = Services.io.newURI(aURI, null, null); - - let isBrowserWindow = !!window.gBrowser; - - // Prioritise this window. - if (isBrowserWindow && switchIfURIInWindow(window)) - return true; - - let winEnum = Services.wm.getEnumerator("navigator:browser"); - while (winEnum.hasMoreElements()) { - let browserWin = winEnum.getNext(); - // Skip closed (but not yet destroyed) windows, - // and the current window (which was checked earlier). - if (browserWin.closed || browserWin == window) - continue; - if (switchIfURIInWindow(browserWin)) - return true; - } - - // No opened tab has that url. - if (aOpenNew) { - if (isBrowserWindow && isTabEmpty(gBrowser.selectedTab)) - gBrowser.selectedBrowser.loadURI(aURI.spec); - else - openUILinkIn(aURI.spec, "tab"); - } - - return false; -} - -function restoreLastSession() { - let ss = Cc["@mozilla.org/browser/sessionstore;1"]. - getService(Ci.nsISessionStore); - ss.restoreLastSession(); -} - -var TabContextMenu = { - contextTab: null, - updateContextMenu: function updateContextMenu(aPopupMenu) { - this.contextTab = aPopupMenu.triggerNode.localName == "tab" ? - aPopupMenu.triggerNode : gBrowser.selectedTab; - let disabled = gBrowser.tabs.length == 1; - - // Enable the "Close Tab" menuitem when the window doesn't close with the last tab. - document.getElementById("context_closeTab").disabled = - disabled && gBrowser.tabContainer._closeWindowWithLastTab; - - var menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple"); - for (let menuItem of menuItems) - menuItem.disabled = disabled; - - disabled = gBrowser.visibleTabs.length == 1; - menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple-visible"); - for (let menuItem of menuItems) - menuItem.disabled = disabled; - - // Session store - document.getElementById("context_undoCloseTab").disabled = - Cc["@mozilla.org/browser/sessionstore;1"]. - getService(Ci.nsISessionStore). - getClosedTabCount(window) == 0; - - // Only one of pin/unpin should be visible - document.getElementById("context_pinTab").hidden = this.contextTab.pinned; - document.getElementById("context_unpinTab").hidden = !this.contextTab.pinned; - - // Disable "Close Tabs to the Right" if there are no tabs - // following it and hide it when the user rightclicked on a pinned - // tab. - document.getElementById("context_closeTabsToTheEnd").disabled = - gBrowser.getTabsToTheEndFrom(this.contextTab).length == 0; - document.getElementById("context_closeTabsToTheEnd").hidden = this.contextTab.pinned; - - // Disable "Close other Tabs" if there is only one unpinned tab and - // hide it when the user rightclicked on a pinned tab. - let unpinnedTabs = gBrowser.visibleTabs.length - gBrowser._numPinnedTabs; - document.getElementById("context_closeOtherTabs").disabled = unpinnedTabs <= 1; - document.getElementById("context_closeOtherTabs").hidden = this.contextTab.pinned; - - // Hide "Bookmark All Tabs" for a pinned tab. Update its state if visible. - let bookmarkAllTabs = document.getElementById("context_bookmarkAllTabs"); - bookmarkAllTabs.hidden = this.contextTab.pinned; - if (!bookmarkAllTabs.hidden) - PlacesCommandHook.updateBookmarkAllTabsCommand(); - } -}; - -#ifdef MOZ_DEVTOOLS -XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", - "resource://gre/modules/devtools/gDevTools.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "gDevToolsBrowser", - "resource://gre/modules/devtools/gDevTools.jsm"); - -Object.defineProperty(this, "HUDService", { - get: function HUDService_getter() { - let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools; - return devtools.require("devtools/webconsole/hudservice").HUDService; - }, - configurable: true, - enumerable: true -}); -#endif - -// Prompt user to restart the browser in safe mode or normally -function restart(safeMode) -{ - let promptTitleString = null; - let promptMessageString = null; - let restartTextString = null; - if (safeMode) { - promptTitleString = "safeModeRestartPromptTitle"; - promptMessageString = "safeModeRestartPromptMessage"; - restartTextString = "safeModeRestartButton"; - } else { - promptTitleString = "restartPromptTitle"; - promptMessageString = "restartPromptMessage"; - restartTextString = "restartButton"; - } - - let flags = Ci.nsIAppStartup.eAttemptQuit; - - // Prompt the user to confirm - let promptTitle = gNavigatorBundle.getString(promptTitleString); - let brandBundle = document.getElementById("bundle_brand"); - let brandShortName = brandBundle.getString("brandShortName"); - let promptMessage = - gNavigatorBundle.getFormattedString(promptMessageString, [brandShortName]); - let restartText = gNavigatorBundle.getString(restartTextString); - let buttonFlags = (Services.prompt.BUTTON_POS_0 * - Services.prompt.BUTTON_TITLE_IS_STRING) + - (Services.prompt.BUTTON_POS_1 * - Services.prompt.BUTTON_TITLE_CANCEL) + - Services.prompt.BUTTON_POS_0_DEFAULT; - - let rv = Services.prompt.confirmEx(window, promptTitle, promptMessage, - buttonFlags, restartText, null, null, - null, {}); - - if (rv == 0) { - // Notify all windows that an application quit has been requested. - let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"] - .createInstance(Ci.nsISupportsPRBool); - Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart"); - - // Something aborted the quit process. - if (cancelQuit.data) { - return; - } - - if (safeMode) { - Services.startup.restartInSafeMode(flags); - } else { - Services.startup.quit(flags | Ci.nsIAppStartup.eRestart); - } - } -} - -/* duplicateTabIn duplicates tab in a place specified by the parameter |where|. - * - * |where| can be: - * "tab" new tab - * "tabshifted" same as "tab" but in background if default is to select new - * tabs, and vice versa - * "window" new window - * - * delta is the offset to the history entry that you want to load. - */ -function duplicateTabIn(aTab, where, delta) { - let newTab = Cc['@mozilla.org/browser/sessionstore;1'] - .getService(Ci.nsISessionStore) - .duplicateTab(window, aTab, delta); - - switch (where) { - case "window": - gBrowser.hideTab(newTab); - gBrowser.replaceTabWithWindow(newTab); - break; - case "tabshifted": - // A background tab has been opened, nothing else to do here. - break; - case "tab": - gBrowser.selectedTab = newTab; - break; - } -} - -function toggleAddonBar() { - let addonBar = document.getElementById("addon-bar"); - setToolbarVisibility(addonBar, addonBar.collapsed); -} - -#ifdef MOZ_DEVTOOLS -var Scratchpad = { - prefEnabledName: "devtools.scratchpad.enabled", - - openScratchpad: function SP_openScratchpad() { - return this.ScratchpadManager.openScratchpad(); - } -}; - -XPCOMUtils.defineLazyGetter(Scratchpad, "ScratchpadManager", function() { - let tmp = {}; - Cu.import("resource://gre/modules/devtools/scratchpad-manager.jsm", tmp); - return tmp.ScratchpadManager; -}); - -var ResponsiveUI = { - toggle: function RUI_toggle() { - this.ResponsiveUIManager.toggle(window, gBrowser.selectedTab); - } -}; - -XPCOMUtils.defineLazyGetter(ResponsiveUI, "ResponsiveUIManager", function() { - let tmp = {}; - Cu.import("resource://gre/modules/devtools/responsivedesign.jsm", tmp); - return tmp.ResponsiveUIManager; -}); - -function openEyedropper() { - var eyedropper = new this.Eyedropper(this, { context: "menu", - copyOnSelect: true }); - eyedropper.open(); -} - -Object.defineProperty(this, "Eyedropper", { - get: function() { - let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools; - return devtools.require("devtools/eyedropper/eyedropper").Eyedropper; - }, - configurable: true, - enumerable: true -}); -#endif - -XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () { -#ifdef XP_WIN - // Only show resizers on Windows 2000 and XP - return parseFloat(Services.sysinfo.getProperty("version")) < 6; -#else - return false; -#endif -}); - -var MousePosTracker = { - _listeners: [], - _x: 0, - _y: 0, - get _windowUtils() { - delete this._windowUtils; - return this._windowUtils = window.getInterface(Ci.nsIDOMWindowUtils); - }, - - addListener: function (listener) { - if (this._listeners.indexOf(listener) >= 0) - return; - - listener._hover = false; - this._listeners.push(listener); - - this._callListener(listener); - }, - - removeListener: function (listener) { - var index = this._listeners.indexOf(listener); - if (index < 0) - return; - - this._listeners.splice(index, 1); - }, - - handleEvent: function (event) { - var fullZoom = this._windowUtils.fullZoom; - this._x = event.screenX / fullZoom - window.mozInnerScreenX; - this._y = event.screenY / fullZoom - window.mozInnerScreenY; - - this._listeners.forEach(function (listener) { - try { - this._callListener(listener); - } catch (e) { - Cu.reportError(e); - } - }, this); - }, - - _callListener: function (listener) { - let rect = listener.getMouseTargetRect(); - let hover = this._x >= rect.left && - this._x <= rect.right && - this._y >= rect.top && - this._y <= rect.bottom; - - if (hover == listener._hover) - return; - - listener._hover = hover; - - if (hover) { - if (listener.onMouseEnter) - listener.onMouseEnter(); - } else { - if (listener.onMouseLeave) - listener.onMouseLeave(); - } - } -}; - -function focusNextFrame(event) { - let fm = Services.focus; - let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC; - let element = fm.moveFocus(window, null, dir, fm.FLAG_BYKEY); - if (element.ownerDocument == document) - focusAndSelectUrlBar(); -} -let BrowserChromeTest = { - _cb: null, - _ready: false, - markAsReady: function () { - this._ready = true; - if (this._cb) { - this._cb(); - this._cb = null; - } - }, - runWhenReady: function (cb) { - if (this._ready) - cb(); - else - this._cb = cb; - } -}; - -let ToolbarIconColor = { - init: function () { - this._initialized = true; - - window.addEventListener("activate", this); - window.addEventListener("deactivate", this); - Services.obs.addObserver(this, "lightweight-theme-styling-update", false); - gPrefService.addObserver("ui.colorChanged", this, false); - - // If the window isn't active now, we assume that it has never been active - // before and will soon become active such that inferFromText will be - // called from the initial activate event. - if (Services.focus.activeWindow == window) - this.inferFromText(); - }, - - uninit: function () { - this._initialized = false; - - window.removeEventListener("activate", this); - window.removeEventListener("deactivate", this); - Services.obs.removeObserver(this, "lightweight-theme-styling-update"); - gPrefService.removeObserver("ui.colorChanged", this); - }, - - handleEvent: function (event) { - switch (event.type) { - case "activate": - case "deactivate": - this.inferFromText(); - break; - } - }, - - observe: function (aSubject, aTopic, aData) { - switch (aTopic) { - case "lightweight-theme-styling-update": - // inferFromText needs to run after LightweightThemeConsumer.jsm's - // lightweight-theme-styling-update observer. - setTimeout(() => { this.inferFromText(); }, 0); - break; - case "nsPref:changed": - // system color change - var colorChangedPref = false; - try { - colorChangedPref = gPrefService.getBoolPref("ui.colorChanged"); - } catch(e) { } - // if pref indicates change, call inferFromText() on a small delay - if (colorChangedPref == true) - setTimeout(() => { this.inferFromText(); }, 300); - break; - default: - console.error("ToolbarIconColor: Uncaught topic " + aTopic); - } - }, - - inferFromText: function () { - if (!this._initialized) - return; - - function parseRGB(aColorString) { - let rgb = aColorString.match(/^rgba?\((\d+), (\d+), (\d+)/); - rgb.shift(); - return rgb.map(x => parseInt(x)); - } - - let toolbarSelector = "toolbar:not([collapsed=true])"; -#ifdef XP_MACOSX - toolbarSelector += ":not([type=menubar])"; -#endif - - // The getComputedStyle calls and setting the brighttext are separated in - // two loops to avoid flushing layout and making it dirty repeatedly. - - let luminances = new Map; - for (let toolbar of document.querySelectorAll(toolbarSelector)) { - let [r, g, b] = parseRGB(getComputedStyle(toolbar).color); - let luminance = (2 * r + 5 * g + b) / 8; - luminances.set(toolbar, luminance); - } - - for (let [toolbar, luminance] of luminances) { - if (luminance <= 128) - toolbar.removeAttribute("brighttext"); - else - toolbar.setAttribute("brighttext", "true"); - } - - // Clear pref if set, since we're done applying the color changes. - gPrefService.clearUserPref("ui.colorChanged"); - } -} diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul deleted file mode 100644 index 3044ce675..000000000 --- a/browser/base/content/browser.xul +++ /dev/null @@ -1,1058 +0,0 @@ -#filter substitution -<?xml version="1.0"?> -# -*- Mode: HTML -*- -# -# 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://browser/content/browser.css" type="text/css"?> - -# Restore title to AppMenu windowed use -<?xml-stylesheet href="chrome://browser/content/browser-title.css" type="text/css"?> - -<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?> -#ifdef MOZ_DEVTOOLS -<?xml-stylesheet href="chrome://global/skin/devtools/common.css" type="text/css"?> -#endif -<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?> - -<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> -<?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?> -<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?> - -# Padlock feature -<?xul-overlay href="chrome://browser/content/padlock.xul"?> -# Improve bookmark menu dragging -<?xul-overlay href="chrome://browser/content/browser-menudragging.xul"?> -# Automatic browser recovery -<?xul-overlay href="chrome://browser/content/autorecovery.xul"?> - - -# All DTD information is stored in a separate file so that it can be shared by -# hiddenWindow.xul. -#include browser-doctype.inc - -<window id="main-window" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - onload="gBrowserInit.onLoad()" onunload="gBrowserInit.onUnload()" onclose="return WindowIsClosing();" - title="&mainWindow.title;" - title_normal="&mainWindow.title;" -#ifdef XP_MACOSX - title_privatebrowsing="&mainWindow.title;&mainWindow.titlemodifiermenuseparator;&mainWindow.titlePrivateBrowsingSuffix;" - titledefault="&mainWindow.title;" - titlemodifier="" - titlemodifier_normal="" - titlemodifier_privatebrowsing="&mainWindow.titlePrivateBrowsingSuffix;" -#else - title_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;" - titlemodifier="&mainWindow.titlemodifier;" - titlemodifier_normal="&mainWindow.titlemodifier;" - titlemodifier_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;" -#endif - titlemenuseparator="&mainWindow.titlemodifiermenuseparator;" - lightweightthemes="true" - lightweightthemesfooter="browser-bottombox" - windowtype="navigator:browser" - macanimationtype="document" - screenX="4" screenY="4" - fullscreenbutton="true" - persist="screenX screenY width height sizemode"> - -# All JS files which are not content (only) dependent that browser.xul -# wishes to include *must* go into the global-scripts.inc file -# so that they can be shared by macBrowserOverlay.xul. -#include global-scripts.inc -<script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/> - -<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/> - -<script type="application/javascript" src="chrome://browser/content/places/editBookmarkOverlay.js"/> - -# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the -# browser-sets.inc file for sharing with hiddenWindow.xul. -#define FULL_BROWSER_WINDOW -#include browser-sets.inc -#undef FULL_BROWSER_WINDOW - - <popupset id="mainPopupSet"> - <menupopup id="tabContextMenu" - onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);" - onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;"> - <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;" - oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/> - <menuseparator/> - <menuitem id="context_pinTab" label="&pinTab.label;" - accesskey="&pinTab.accesskey;" - oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/> - <menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true" - accesskey="&unpinTab.accesskey;" - oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/> - <menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;" - accesskey="&moveToNewWindow.accesskey;" - tbattr="tabbrowser-multiple" - oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/> - <menuseparator/> - <menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;" - tbattr="tabbrowser-multiple-visible" - oncommand="gBrowser.reloadAllTabs();"/> - <menuitem id="context_bookmarkAllTabs" - label="&bookmarkAllTabs.label;" - accesskey="&bookmarkAllTabs.accesskey;" - command="Browser:BookmarkAllTabs"/> - <menuitem id="context_closeTabsToTheEnd" label="&closeTabsToTheEnd.label;" accesskey="&closeTabsToTheEnd.accesskey;" - oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab);"/> - <menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;" - oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/> - <menuseparator/> - <menuitem id="context_undoCloseTab" - label="&undoCloseTab.label;" - accesskey="&undoCloseTab.accesskey;" - observes="History:UndoCloseTab"/> - <menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;" - oncommand="gBrowser.removeTab(TabContextMenu.contextTab, { animate: true });"/> - </menupopup> - - <!-- bug 415444/582485: event.stopPropagation is here for the cloned version - of this menupopup --> - <menupopup id="backForwardMenu" - onpopupshowing="return FillHistoryMenu(event.target);" - oncommand="gotoHistoryIndex(event); event.stopPropagation();" - onclick="checkForMiddleClick(this, event);"/> - <tooltip id="aHTMLTooltip" page="true"/> - - <!-- for search and content formfill/pw manager --> - <panel type="autocomplete" id="PopupAutoComplete" noautofocus="true" hidden="true"/> - - <!-- for url bar autocomplete --> - <panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/> - - <!-- for invalid form error message --> - <panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent"> - <description/> - </panel> - - <panel id="editBookmarkPanel" - type="arrow" - footertype="promobox" - orient="vertical" - ignorekeys="true" - consumeoutsideclicks="true" - hidden="true" - onpopupshown="StarUI.panelShown(event);" - aria-labelledby="editBookmarkPanelTitle"> - <row id="editBookmarkPanelHeader" align="center" hidden="true"> - <vbox align="center"> - <image id="editBookmarkPanelStarIcon"/> - </vbox> - <vbox> - <label id="editBookmarkPanelTitle"/> - <description id="editBookmarkPanelDescription"/> - <hbox> - <button id="editBookmarkPanelRemoveButton" - class="editBookmarkPanelHeaderButton" - oncommand="StarUI.removeBookmarkButtonCommand();" - accesskey="&editBookmark.removeBookmark.accessKey;"/> - </hbox> - </vbox> - </row> - <vbox id="editBookmarkPanelContent" flex="1" hidden="true"/> - <hbox id="editBookmarkPanelBottomButtons" pack="end"> -#ifndef XP_UNIX - <button id="editBookmarkPanelDoneButton" - class="editBookmarkPanelBottomButton" - label="&editBookmark.done.label;" - default="true" - oncommand="StarUI.panel.hidePopup();"/> - <button id="editBookmarkPanelDeleteButton" - class="editBookmarkPanelBottomButton" - label="&editBookmark.cancel.label;" - oncommand="StarUI.cancelButtonOnCommand();"/> -#else - <button id="editBookmarkPanelDeleteButton" - class="editBookmarkPanelBottomButton" - label="&editBookmark.cancel.label;" - oncommand="StarUI.cancelButtonOnCommand();"/> - <button id="editBookmarkPanelDoneButton" - class="editBookmarkPanelBottomButton" - label="&editBookmark.done.label;" - default="true" - oncommand="StarUI.panel.hidePopup();"/> -#endif - </hbox> - </panel> - - <menupopup id="toolbar-context-menu" - onpopupshowing="onViewToolbarsPopupShowing(event);"> - <menuseparator/> - <menuitem command="cmd_ToggleTabsOnTop" - type="checkbox" - label="&viewTabsOnTop.label;" - accesskey="&viewTabsOnTop.accesskey;"/> - <menuitem command="cmd_CustomizeToolbars" - label="&viewCustomizeToolbar.label;" - accesskey="&viewCustomizeToolbar.accesskey;"/> - </menupopup> - - <menupopup id="blockedPopupOptions" - onpopupshowing="gPopupBlockerObserver.fillPopupList(event);" - onpopuphiding="gPopupBlockerObserver.onPopupHiding(event);"> - <menuitem observes="blockedPopupAllowSite"/> - <menuitem observes="blockedPopupEditSettings"/> - <menuitem observes="blockedPopupDontShowMessage"/> - <menuseparator observes="blockedPopupsSeparator"/> - </menupopup> - - <menupopup id="autohide-context" - onpopupshowing="FullScreen.getAutohide(this.firstChild);"> - <menuitem type="checkbox" label="&fullScreenAutohide.label;" - accesskey="&fullScreenAutohide.accesskey;" - oncommand="FullScreen.setAutohide();"/> - <menuseparator/> - <menuitem label="&fullScreenExit.label;" - accesskey="&fullScreenExit.accesskey;" - oncommand="BrowserFullScreen();"/> - </menupopup> - - <menupopup id="contentAreaContextMenu" pagemenu="start" - onpopupshowing="if (event.target != this) - return true; - gContextMenu = new nsContextMenu(this, event.shiftKey); - if (gContextMenu.shouldDisplay) - updateEditUIVisibility(); - return gContextMenu.shouldDisplay;" - onpopuphiding="if (event.target != this) - return; - gContextMenu.hiding(); - gContextMenu = null; - updateEditUIVisibility();"> -#include browser-context.inc - </menupopup> - - <menupopup id="placesContext"/> - - - <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top"> - <hbox> - <button class="ctrlTab-preview" flex="1"/> - <button class="ctrlTab-preview" flex="1"/> - <button class="ctrlTab-preview" flex="1"/> - <button class="ctrlTab-preview" flex="1"/> - <button class="ctrlTab-preview" flex="1"/> - <button class="ctrlTab-preview" flex="1"/> - </hbox> - <hbox pack="center"> - <button id="ctrlTab-showAll" class="ctrlTab-preview" noicon="true"/> - </hbox> - </panel> - - <panel id="allTabs-panel" hidden="true" norestorefocus="true" ignorekeys="true" - onmouseover="allTabs._updateTabCloseButton(event);"> - <hbox id="allTabs-meta" align="center"> - <spacer flex="1"/> - <textbox id="allTabs-filter" - tooltiptext="&allTabs.filter.emptyText;" - type="search" - oncommand="allTabs.filter();"/> - <spacer flex="1"/> - <toolbarbutton class="KUI-panel-closebutton" - oncommand="allTabs.close()" - tooltiptext="&closeCmd.label;"/> - </hbox> - <stack id="allTabs-stack"> - <vbox id="allTabs-container"><hbox/></vbox> - <toolbarbutton id="allTabs-tab-close-button" - class="tabs-closebutton close-icon" - oncommand="allTabs.closeTab(event);" - tooltiptext="&closeCmd.label;" - style="visibility:hidden"/> - </stack> - </panel> - - <!-- Bookmarks and history tooltip --> - <tooltip id="bhTooltip"/> - - <panel id="customizeToolbarSheetPopup" - noautohide="true" - sheetstyle="&dialog.dimensions;"/> - - <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/> - - <tooltip id="back-button-tooltip"> - <label class="tooltip-label" value="&backButton.tooltip;"/> -#ifdef XP_MACOSX - <label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/> -#else - <label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/> -#endif - </tooltip> - - <tooltip id="forward-button-tooltip"> - <label class="tooltip-label" value="&forwardButton.tooltip;"/> -#ifdef XP_MACOSX - <label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/> -#else - <label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/> -#endif - </tooltip> - -#include popup-notifications.inc - - </popupset> - -#ifdef CAN_DRAW_IN_TITLEBAR -<vbox id="titlebar"> - <hbox id="titlebar-content"> -#ifdef MENUBAR_CAN_AUTOHIDE - <hbox id="appmenu-button-container"> - <button id="appmenu-button" - type="menu" - label="&brandShortName;" - tooltiptext="&appMenuButton.tooltip;" - style="-moz-user-focus: ignore;"> -#include browser-appmenu.inc - </button> - </hbox> -#endif - <spacer id="titlebar-spacer" flex="1"/> - <hbox id="titlebar-buttonbox-container" align="start"> - <hbox id="titlebar-buttonbox"> - <toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/> - <toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/> - <toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/> - </hbox> - </hbox> - </hbox> -</vbox> -#endif - -<deck flex="1" id="tab-view-deck"> -<vbox flex="1" id="browser-panel"> - - <toolbox id="navigator-toolbox" - defaultmode="icons" mode="icons" - iconsize="large"> - <!-- Menu --> - <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true" - defaultset="menubar-items" - mode="icons" iconsize="small" defaulticonsize="small" - lockiconsize="true" -#ifdef MENUBAR_CAN_AUTOHIDE - toolbarname="&menubarCmd.label;" - accesskey="&menubarCmd.accesskey;" -#endif - context="toolbar-context-menu"> - <toolbaritem id="menubar-items" align="center"> -# The entire main menubar is placed into browser-menubar.inc, so that it can be shared by -# hiddenWindow.xul. -#include browser-menubar.inc - </toolbaritem> - -#ifdef CAN_DRAW_IN_TITLEBAR - <hbox class="titlebar-placeholder" type="appmenu-button" ordinal="0"/> - <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"/> -#endif - </toolbar> - - <toolbar id="nav-bar" class="toolbar-primary chromeclass-toolbar" - toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;" - fullscreentoolbar="true" mode="icons" customizable="true" - iconsize="large" - defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container,bookmarks-menu-button,history-menu-button,downloads-button,window-controls" - context="toolbar-context-menu"> - - <toolbaritem id="unified-back-forward-button" class="chromeclass-toolbar-additional" - context="backForwardMenu" removable="true" - forwarddisabled="true" - title="&backForwardItem.title;"> - <toolbarbutton id="back-button" class="toolbarbutton-1" - label="&backCmd.label;" - command="Browser:BackOrBackDuplicate" - onclick="checkForMiddleClick(this, event);" - tooltip="back-button-tooltip"/> - <toolbarbutton id="forward-button" class="toolbarbutton-1" - label="&forwardCmd.label;" - command="Browser:ForwardOrForwardDuplicate" - onclick="checkForMiddleClick(this, event);" - tooltip="forward-button-tooltip"/> - <dummyobservertarget hidden="true" - onbroadcast="if (this.getAttribute('disabled') == 'true') - this.parentNode.setAttribute('forwarddisabled', 'true'); - else - this.parentNode.removeAttribute('forwarddisabled');"> - <observes element="Browser:ForwardOrForwardDuplicate" attribute="disabled"/> - </dummyobservertarget> - </toolbaritem> - - <toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&reloadCmd.label;" removable="true" - command="Browser:ReloadOrDuplicate" - onclick="checkForMiddleClick(this, event);" - tooltiptext="&reloadButton.tooltip;"/> - - <toolbarbutton id="stop-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&stopCmd.label;" removable="true" - command="Browser:Stop" - tooltiptext="&stopButton.tooltip;"/> - - <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - persist="class" removable="true" - label="&homeButton.label;" - ondragover="homeButtonObserver.onDragOver(event)" - ondragenter="homeButtonObserver.onDragOver(event)" - ondrop="homeButtonObserver.onDrop(event)" - ondragexit="homeButtonObserver.onDragExit(event)" - onclick="BrowserGoHome(event);" - aboutHomeOverrideTooltip="&abouthome.pageTitle;"/> - - <toolbaritem id="urlbar-container" align="center" flex="400" persist="width" combined="true" - title="&locationItem.title;" class="chromeclass-location" removable="true"> - <textbox id="urlbar" flex="1" - placeholder="" - type="autocomplete" - autocompletesearch="urlinline history" - autocompletesearchparam="enable-actions" - autocompletepopup="PopupAutoCompleteRichResult" - completeselectedindex="true" - tabscrolling="true" - showcommentcolumn="true" - showimagecolumn="true" - enablehistory="true" - maxrows="6" - newlines="stripsurroundingwhitespace" - oninput="gBrowser.userTypedValue = this.value;" - ontextentered="this.handleCommand(param);" - ontextreverted="return this.handleRevert();" - pageproxystate="invalid" - onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'" - onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);"> - <box id="notification-popup-box" hidden="true" align="center"> - <image id="default-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="password-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="alert-plugins-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="pointerLock-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="servicesInstall-notification-icon" class="notification-anchor-icon" role="button"/> - </box> - <!-- Use onclick instead of normal popup= syntax since the popup - code fires onmousedown, and hence eats our favicon drag events. - We only add the identity-box button to the tab order when the location bar - has focus, otherwise pressing F6 focuses it instead of the location bar --> - <box id="identity-box" role="button" - align="center" - onclick="gIdentityHandler.handleIdentityButtonEvent(event);" - onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);" - ondragstart="gIdentityHandler.onDragStart(event);"> - <image id="page-proxy-favicon" - onclick="PageProxyClickHandler(event);" - pageproxystate="invalid"/> - <hbox id="identity-icon-labels"> - <label id="identity-icon-label" class="plain" flex="1"/> - <label id="identity-icon-country-label" class="plain"/> - </hbox> - </box> - <box id="urlbar-display-box" align="center"> - <label id="urlbar-display" value="&urlbar.switchToTab.label;"/> - </box> - <hbox id="urlbar-icons"> - <image id="page-report-button" - class="urlbar-icon" - hidden="true" - tooltiptext="&pageReportIcon.tooltip;" - onclick="gPopupBlockerObserver.onReportButtonClick(event);"/> - <button type="menu" - style="-moz-user-focus: none" - class="plain urlbar-icon" - id="ub-feed-button" - collapsed="true" - tooltiptext="&feedButton.tooltip;" - onclick="return FeedHandler.onFeedButtonPMClick(event);"> - <menupopup position="after_end" - id="ub-feed-menu" - onpopupshowing="return FeedHandler.buildFeedList(this);" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);"/> - </button> - <image id="star-button" - class="urlbar-icon" - onclick="BookmarkingUI.onCommand(event);"/> - <image id="go-button" - class="urlbar-icon" - tooltiptext="&goEndCap.tooltip;" - onclick="gURLBar.handleCommand(event);"/> - </hbox> - <toolbarbutton id="urlbar-go-button" - class="chromeclass-toolbar-additional" - onclick="gURLBar.handleCommand(event);" - tooltiptext="&goEndCap.tooltip;"/> - <toolbarbutton id="urlbar-reload-button" - class="chromeclass-toolbar-additional" - command="Browser:ReloadOrDuplicate" - onclick="checkForMiddleClick(this, event);" - tooltiptext="&reloadButton.tooltip;"/> - <toolbarbutton id="urlbar-stop-button" - class="chromeclass-toolbar-additional" - command="Browser:Stop" - tooltiptext="&stopButton.tooltip;"/> - </textbox> - </toolbaritem> - - <toolbaritem id="search-container" title="&searchItem.title;" - align="center" class="chromeclass-toolbar-additional" - flex="100" persist="width" removable="true"> - <searchbar id="searchbar" flex="1"/> - </toolbaritem> - - <toolbarbutton id="webrtc-status-button" - class="toolbarbutton-1 chromeclass-toolbar-additional" - type="menu" - hidden="true" - orient="horizontal" - label="&webrtcIndicatorButton.label;" - tooltiptext="&webrtcIndicatorButton.tooltip;"> - <menupopup onpopupshowing="WebrtcIndicator.fillPopup(this);" - onpopuphiding="WebrtcIndicator.clearPopup(this);" - oncommand="WebrtcIndicator.menuCommand(event.target);"/> - </toolbarbutton> - - <toolbarbutton id="bookmarks-menu-button" - class="toolbarbutton-1 chromeclass-toolbar-additional" - persist="class" - removable="true" - type="menu" - label="&bookmarksMenuButton.label;" - tooltiptext="&bookmarksMenuButton.tooltip;" - onclick="if (event.button == 1) - toggleSidebar('viewBookmarksSidebar');" - ondragenter="PlacesMenuDNDHandler.onDragEnter(event);" - ondragover="PlacesMenuDNDHandler.onDragOver(event);" - ondragleave="PlacesMenuDNDHandler.onDragLeave(event);" - ondrop="PlacesMenuDNDHandler.onDrop(event);"> - <menupopup id="BMB_bookmarksPopup" - placespopup="true" - context="placesContext" - openInTabs="children" - oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);" - onclick="event.stopPropagation(); - BookmarksEventHandler.onClick(event, this.parentNode._placesView);" - onpopupshowing="BookmarkingUI.onPopupShowing(event); - if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');" - tooltip="bhTooltip" popupsinherittooltip="true"> - <menuitem id="BMB_viewBookmarksToolbar" - placesanonid="view-toolbar" - toolbarId="PersonalToolbar" - type="checkbox" - oncommand="onViewToolbarCommand(event)" - label="&viewBookmarksToolbar.label;"/> - <menuseparator/> - <menuitem id="BMB_bookmarksShowAll" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&organizeBookmarks.label;" - command="Browser:ShowAllBookmarks" - key="manBookmarkKb"/> - <menuseparator/> - <menuitem id="BMB_bookmarkThisPage" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&bookmarkThisPageCmd.label;" - command="Browser:AddBookmarkAs" - key="addBookmarkAsKb"/> - <menuitem id="BMB_subscribeToPageMenuitem" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&subscribeToPageMenuitem.label;" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);" - observes="singleFeedMenuitemState"/> - <menu id="BMB_subscribeToPageMenupopup" -#ifndef XP_MACOSX - class="menu-iconic" -#endif - label="&subscribeToPageMenupopup.label;" - observes="multipleFeedsMenuState"> - <menupopup id="BMB_subscribeToPageSubmenuMenupopup" - onpopupshowing="return FeedHandler.buildFeedList(event.target);" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);"/> - </menu> - <menuseparator/> - <menu id="BMB_bookmarksToolbar" - placesanonid="toolbar-autohide" - class="menu-iconic bookmark-item" - label="&personalbarCmd.label;" - container="true"> - <menupopup id="BMB_bookmarksToolbarPopup" - placespopup="true" - context="placesContext" - onpopupshowing="if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=TOOLBAR');"/> - </menu> - <menuseparator/> - <!-- Bookmarks menu items --> - <menuseparator builder="end" - class="hide-if-empty-places-result"/> - <menuitem id="BMB_unsortedBookmarks" - class="menuitem-iconic" - label="&bookmarksMenuButton.unsorted.label;" - oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"/> - </menupopup> - </toolbarbutton> - - <toolbarbutton id="history-menu-button" - class="toolbarbutton-1 chromeclass-toolbar-additional" - persist="class" - removable="true" - type="menu" - label="&historyButton.label;" - tooltiptext="&historyButton.tooltip;" - onclick="if (event.button == 1) - toggleSidebar('viewHistorySidebar');"> - <menupopup id="HMB_historyPopup" - placespopup="true" - context="placesContext" - oncommand="this.parentNode._placesView._onCommand(event);" - onclick="event.stopPropagation(); - checkForMiddleClick(this, event);" - onpopupshowing="if (!this.parentNode._placesView) - new HistoryMenu(event);" - tooltip="bhTooltip" - popupsinherittooltip="true"> - <menuitem id="HMB_showAllHistory" - label="&showAllHistoryCmd2.label;" -#ifndef XP_MACOSX - class="menuitem-iconic" - key="showAllHistoryKb" -#endif - command="Browser:ShowAllHistory"/> - <menuitem id="HMB_sanitizeItem" -#ifndef XP_MACOSX - class="menuitem-iconic" -#endif - label="&clearRecentHistory.label;" - key="key_sanitize" - command="Tools:Sanitize"/> - <menuseparator id="HMB_sanitizeSeparator"/> -#ifdef MOZ_SERVICES_SYNC - <menuitem id="HMB_sync-tabs-menuitem" - class="syncTabsMenuItem" - label="&syncTabsMenu2.label;" - oncommand="BrowserOpenSyncTabs();" - disabled="true"/> -#endif - <menuitem id="HMB_historyRestoreLastSession" - label="&historyRestoreLastSession.label;" - command="Browser:RestoreLastSession"/> - <menu id="HMB_historyUndoMenu" - class="recentlyClosedTabsMenu" - label="&historyUndoMenu.label;" - disabled="true"> - <menupopup id="HMB_historyUndoPopup" - placespopup="true" - onpopupshowing="document.getElementById('history-menu-button')._placesView.populateUndoSubmenu();"/> - </menu> - <menu id="HMB_historyUndoWindowMenu" - class="recentlyClosedWindowsMenu" - label="&historyUndoWindowMenu.label;" - disabled="true"> - <menupopup id="HMB_historyUndoWindowPopup" - placespopup="true" - onpopupshowing="document.getElementById('history-menu-button')._placesView.populateUndoWindowSubmenu();"/> - </menu> - <menuseparator id="HMB_startHistorySeparator" - class="hide-if-empty-places-result"/> - <!-- History menu items --> - </menupopup> - </toolbarbutton> - - <hbox id="window-controls" hidden="true" pack="end"> - <toolbarbutton id="minimize-button" - tooltiptext="&fullScreenMinimize.tooltip;" - oncommand="window.minimize();"/> - - <toolbarbutton id="restore-button" - tooltiptext="&fullScreenRestore.tooltip;" - oncommand="BrowserFullScreen();"/> - - <toolbarbutton id="close-button" - tooltiptext="&fullScreenClose.tooltip;" - oncommand="BrowserTryToCloseWindow();"/> - </hbox> - </toolbar> - - <toolbarset id="customToolbars" context="toolbar-context-menu"/> - - <toolbar id="PersonalToolbar" - mode="icons" iconsize="small" defaulticonsize="small" - lockiconsize="true" - class="chromeclass-directories" - context="toolbar-context-menu" - defaultset="personal-bookmarks" - toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;" - collapsed="false" - customizable="true"> - <toolbaritem flex="1" id="personal-bookmarks" title="&bookmarksItem.title;" - removable="true"> - <hbox flex="1" - id="PlacesToolbar" - context="placesContext" - onclick="BookmarksEventHandler.onClick(event, this._placesView);" - oncommand="BookmarksEventHandler.onCommand(event, this._placesView);" - tooltip="bhTooltip" - popupsinherittooltip="true"> - <toolbarbutton class="bookmark-item bookmarks-toolbar-customize" - mousethrough="never" - label="&bookmarksToolbarItem.label;"/> - <hbox flex="1"> - <hbox align="center"> - <image id="PlacesToolbarDropIndicator" - mousethrough="always" - collapsed="true"/> - </hbox> - <scrollbox orient="horizontal" - id="PlacesToolbarItems" - flex="1"/> - <toolbarbutton type="menu" - id="PlacesChevron" - class="chevron" - mousethrough="never" - collapsed="true" - tooltiptext="&bookmarksToolbarChevron.tooltip;" - onpopupshowing="document.getElementById('PlacesToolbar') - ._placesView._onChevronPopupShowing(event);"> - <menupopup id="PlacesChevronPopup" - placespopup="true" - tooltip="bhTooltip" popupsinherittooltip="true" - context="placesContext"/> - </toolbarbutton> - </hbox> - </hbox> - </toolbaritem> - </toolbar> - -#ifdef MENUBAR_CAN_AUTOHIDE -#ifndef CAN_DRAW_IN_TITLEBAR -#define APPMENU_ON_TABBAR -#endif -#endif - - - <toolbar id="TabsToolbar" - class="toolbar-primary" - fullscreentoolbar="true" - customizable="true" - mode="icons" lockmode="true" - iconsize="small" defaulticonsize="small" lockiconsize="true" - aria-label="&tabsToolbar.label;" - context="toolbar-context-menu" -#ifdef APPMENU_ON_TABBAR - defaultset="appmenu-toolbar-button,tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton" -#else - defaultset="tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton" -#endif - collapsed="true"> - -#ifdef APPMENU_ON_TABBAR - <toolbarbutton id="appmenu-toolbar-button" - class="chromeclass-toolbar-additional" - type="menu" - label="&brandShortName;" - tooltiptext="&appMenuButton.tooltip;"> -#include browser-appmenu.inc - </toolbarbutton> -#endif - - <tabs id="tabbrowser-tabs" - class="tabbrowser-tabs" - tabbrowser="content" - flex="1" - setfocus="false" - tooltip="tabbrowser-tab-tooltip"> - <tab class="tabbrowser-tab" selected="true" fadein="true"/> - </tabs> - - <toolbarbutton id="new-tab-button" - class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&tabCmd.label;" - command="cmd_newNavigatorTab" - onclick="checkForMiddleClick(this, event);" - tooltiptext="&newTabButton.tooltip;" - ondrop="newTabButtonObserver.onDrop(event)" - ondragover="newTabButtonObserver.onDragOver(event)" - ondragenter="newTabButtonObserver.onDragOver(event)" - ondragexit="newTabButtonObserver.onDragExit(event)" - removable="true"/> - - <toolbarbutton id="alltabs-button" - class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button" - type="menu" - label="&listAllTabs.label;" - tooltiptext="&listAllTabs.label;" - removable="true"> - <menupopup id="alltabs-popup" position="after_end"/> - </toolbarbutton> - - <toolbarbutton id="tabs-closebutton" - class="close-button tabs-closebutton close-icon" - command="cmd_close" - label="&closeTab.label;" - tooltiptext="&closeTab.label;"/> - -#ifdef CAN_DRAW_IN_TITLEBAR - <hbox class="titlebar-placeholder" type="appmenu-button" ordinal="0"/> - <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"/> -#endif - </toolbar> - - <toolbarpalette id="BrowserToolbarPalette"> - -# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding -# or removing default items with the toolbarbutton-1 class. - - <toolbarbutton id="print-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&printButton.label;" command="cmd_print" - tooltiptext="&printButton.tooltip;"/> - - <!-- This is a placeholder for the Downloads Indicator. It is visible - during the customization of the toolbar, in the palette, and before - the Downloads Indicator overlay is loaded. --> - <toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - oncommand="DownloadsIndicatorView.onCommand(event);" - ondrop="DownloadsIndicatorView.onDrop(event);" - ondragover="DownloadsIndicatorView.onDragOver(event);" - ondragenter="DownloadsIndicatorView.onDragOver(event);" - label="&downloads.label;" - tooltiptext="&downloads.tooltip;"/> - - <toolbarbutton id="history-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - observes="viewHistorySidebar" label="&historyButton.label;" - tooltiptext="&historyButton.tooltip;"/> - - <toolbarbutton id="bookmarks-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - observes="viewBookmarksSidebar" label="&bookmarksButton.label;" - tooltiptext="&bookmarksButton.tooltip;" - ondrop="bookmarksButtonObserver.onDrop(event)" - ondragover="bookmarksButtonObserver.onDragOver(event)" - ondragenter="bookmarksButtonObserver.onDragOver(event)" - ondragexit="bookmarksButtonObserver.onDragExit(event)"/> - - <toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&newNavigatorCmd.label;" - command="key_newNavigator" - tooltiptext="&newWindowButton.tooltip;" - ondrop="newWindowButtonObserver.onDrop(event)" - ondragover="newWindowButtonObserver.onDragOver(event)" - ondragenter="newWindowButtonObserver.onDragOver(event)" - ondragexit="newWindowButtonObserver.onDragExit(event)"/> - - <toolbarbutton id="fullscreen-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - observes="View:FullScreen" - type="checkbox" - label="&fullScreenCmd.label;" - tooltiptext="&fullScreenButton.tooltip;"/> - - <toolbaritem id="zoom-controls" class="chromeclass-toolbar-additional" - title="&zoomControls.label;"> - <toolbarbutton id="zoom-out-button" class="toolbarbutton-1" - label="&fullZoomReduceCmd.label;" - command="cmd_fullZoomReduce" - tooltiptext="&zoomOutButton.tooltip;"/> - <toolbarbutton id="zoom-in-button" class="toolbarbutton-1" - label="&fullZoomEnlargeCmd.label;" - command="cmd_fullZoomEnlarge" - tooltiptext="&zoomInButton.tooltip;"/> - </toolbaritem> - - <toolbarbutton id="feed-button" - type="menu" - class="toolbarbutton-1 chromeclass-toolbar-additional" - disabled="true" - label="&feedButton.label;" - tooltiptext="&feedButton.tooltip;" - onclick="return FeedHandler.onFeedButtonClick(event);"> - <menupopup position="after_end" - id="feed-menu" - onpopupshowing="return FeedHandler.buildFeedList(this);" - oncommand="return FeedHandler.subscribeToFeed(null, event);" - onclick="checkForMiddleClick(this, event);"/> - </toolbarbutton> - - <toolbarbutton id="cut-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&cutCmd.label;" - command="cmd_cut" - tooltiptext="&cutButton.tooltip;"/> - - <toolbarbutton id="copy-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="©Cmd.label;" - command="cmd_copy" - tooltiptext="©Button.tooltip;"/> - - <toolbarbutton id="paste-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&pasteCmd.label;" - command="cmd_paste" - tooltiptext="&pasteButton.tooltip;"/> - -#ifdef MOZ_SERVICES_SYNC - <toolbarbutton id="sync-button" - class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&syncToolbarButton.label;" - oncommand="gSyncUI.handleToolbarButton()"/> -#endif - - <toolbaritem id="navigator-throbber" title="&throbberItem.title;" align="center" pack="center" - mousethrough="always"> - <image/> - </toolbaritem> - </toolbarpalette> - </toolbox> - - <hbox id="fullscr-toggler" collapsed="true"/> - - <hbox flex="1" id="browser"> - <vbox id="browser-border-start" hidden="true" layer="true"/> - <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome"> - <sidebarheader id="sidebar-header" align="center"> - <label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/> - <image id="sidebar-throbber"/> - <toolbarbutton class="tabs-closebutton close-icon" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="toggleSidebar();"/> - </sidebarheader> - <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true" - style="min-width: 14em; width: 18em; max-width: 36em;"/> - </vbox> - - <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/> - <vbox id="appcontent" flex="1"> - <tabbrowser id="content" disablehistory="true" - flex="1" contenttooltip="aHTMLTooltip" - tabcontainer="tabbrowser-tabs" - contentcontextmenu="contentAreaContextMenu" - autocompletepopup="PopupAutoComplete"/> - <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/> - <statuspanel id="statusbar-display" inactive="true"/> - </vbox> - <vbox id="browser-border-end" hidden="true" layer="true"/> - </hbox> - - <hbox id="full-screen-warning-container" hidden="true" fadeout="true"> - <hbox style="width: 100%;" pack="center"> <!-- Inner hbox needed due to bug 579776. --> - <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> - - <vbox id="browser-bottombox" layer="true"> - <notificationbox id="global-notificationbox"/> -#ifdef MOZ_DEVTOOLS - <toolbar id="developer-toolbar" - class="devtools-toolbar" - hidden="true"> -#ifdef XP_MACOSX - <toolbarbutton id="developer-toolbar-closebutton" - class="devtools-closebutton" - oncommand="DeveloperToolbar.hide();" - tooltiptext="&devToolbarCloseButton.tooltiptext;"/> -#endif - <stack class="gclitoolbar-stack-node" flex="1"> - <textbox class="gclitoolbar-input-node" rows="1"/> - <hbox class="gclitoolbar-complete-node"/> - </stack> - <toolbarbutton id="developer-toolbar-toolbox-button" - class="developer-toolbar-button" - observes="devtoolsMenuBroadcaster_DevToolbox" - tooltiptext="&devToolbarToolsButton.tooltip;"/> -#ifndef XP_MACOSX - <toolbarbutton id="developer-toolbar-closebutton" - class="devtools-closebutton" - oncommand="DeveloperToolbar.hide();" - tooltiptext="&devToolbarCloseButton.tooltiptext;"/> -#endif - </toolbar> -#endif - - <toolbar id="addon-bar" - toolbarname="&statusBar.label;" accesskey="&statusBar.accesskey;" - collapsed="true" - class="toolbar-primary chromeclass-toolbar" - context="toolbar-context-menu" toolboxid="navigator-toolbox" - mode="icons" iconsize="small" defaulticonsize="small" - lockiconsize="true" - defaultset="addonbar-closebutton,spring,status-bar" - customizable="true" - key="key_toggleAddonBar"> - <toolbarbutton id="addonbar-closebutton" - class="close-icon" - tooltiptext="&addonBarCloseButton.tooltip;" - oncommand="setToolbarVisibility(this.parentNode, false);"/> - <statusbar id="status-bar" ordinal="1000"/> - </toolbar> - </vbox> - -#ifndef XP_UNIX - <svg:svg height="0"> - <svg:clipPath id="windows-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox"> - <svg:path d="M 0,0 C 0.16,0.11 0.28,0.29 0.28,0.5 0.28,0.71 0.16,0.89 0,1 L 1,1 1,0 0,0 z"/> - </svg:clipPath> - <svg:clipPath id="windows-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="M 0,0 0,7.8 C 2.5,11 4,14 4,18 4,22 2.5,25 0,28 l 0,22 10000,0 0,-50 L 0,0 z"/> - </svg:clipPath> - </svg:svg> -#endif -#ifdef XP_MACOSX - <svg:svg height="0"> - <svg:clipPath id="osx-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox"> - <svg:path d="M 0,0 C 0.15,0.12 0.25,0.3 0.25,0.5 0.25,0.7 0.15,0.88 0,1 L 1,1 1,0 0,0 z"/> - </svg:clipPath> - <svg:clipPath id="osx-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="m 0,-5 0,4.03 C 3.6,1.8 6,6.1 6,11 6,16 3.6,20 0,23 l 0,27 10000,0 0,-55 L 0,-5 z"/> - </svg:clipPath> - <svg:clipPath id="osx-tab-ontop-left-curve-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="M 9,0 C 7.3,0 6,1.3 6,3 l 0,14 c 0,3 -2.2,5 -5,5 l -1,0 0,1 12,0 0,-1 0,-19 0,-3 -3,0 z"/> - </svg:clipPath> - <svg:clipPath id="osx-tab-ontop-right-curve-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="m 0,0 0,3 0,19 0,1 12,0 0,-1 -1,0 C 8.2,22 6,20 6,17 L 6,3 C 6,1.3 4.7,0 3,0 L 0,0 z"/> - </svg:clipPath> - <svg:clipPath id="osx-tab-onbottom-left-curve-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="m 0,0 0,1 1,0 c 2.8,0 5,2.2 5,5 l 0,14 c 0,2 1.3,3 3,3 l 3,0 0,-3 L 12,1 12,0 0,0 z"/> - </svg:clipPath> - <svg:clipPath id="osx-tab-onbottom-right-curve-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="m 0,0 0,1 0,19 0,3 3,0 c 1.7,0 3,-1 3,-3 L 6,6 C 6,3.2 8.2,1 11,1 L 12,1 12,0 0,0 z"/> - </svg:clipPath> - </svg:svg> -#endif - -</vbox> -# <iframe id="tab-view"> is dynamically appended as the 2nd child of #tab-view-deck. -# Introducing the iframe dynamically, as needed, was found to be better than -# starting with an empty iframe here in browser.xul from a Ts standpoint. -</deck> - -</window> diff --git a/browser/base/content/browserMountPoints.inc b/browser/base/content/browserMountPoints.inc deleted file mode 100644 index e4315b04a..000000000 --- a/browser/base/content/browserMountPoints.inc +++ /dev/null @@ -1,12 +0,0 @@ -<stringbundleset id="stringbundleset"/> - -<commandset id="mainCommandSet"/> -<commandset id="baseMenuCommandSet"/> -<commandset id="placesCommands"/> - -<broadcasterset id="mainBroadcasterSet"/> - -<keyset id="mainKeyset"/> -<keyset id="baseMenuKeyset"/> - -<menubar id="main-menubar"/>
\ No newline at end of file diff --git a/browser/base/content/content.js b/browser/base/content/content.js deleted file mode 100644 index 3587bbeef..000000000 --- a/browser/base/content/content.js +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -let Cc = Components.classes; -let Ci = Components.interfaces; -let Cu = Components.utils; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils", - "resource://gre/modules/BrowserUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent", - "resource://gre/modules/LoginManagerContent.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils", - "resource://gre/modules/InsecurePasswordUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FormSubmitObserver", - "resource:///modules/FormSubmitObserver.jsm"); - -// Bug 671101 - directly using webNavigation in this context -// causes docshells to leak -this.__defineGetter__("webNavigation", function () { - return docShell.QueryInterface(Ci.nsIWebNavigation); -}); - -addMessageListener("WebNavigation:LoadURI", function (message) { - let flags = message.json.flags || webNavigation.LOAD_FLAGS_NONE; - - webNavigation.loadURI(message.json.uri, flags, null, null, null); -}); - -// TabChildGlobal -var global = this; - -// Load the form validation popup handler -var formSubmitObserver = new FormSubmitObserver(content, this); - -addMessageListener("Browser:HideSessionRestoreButton", function (message) { - // Hide session restore button on about:home - let doc = content.document; - let container; - if (doc.documentURI.toLowerCase() == "about:home" && - (container = doc.getElementById("sessionRestoreContainer"))){ - container.hidden = true; - } -}); - -addEventListener("DOMFormHasPassword", function(event) { - InsecurePasswordUtils.checkForInsecurePasswords(event.target); - LoginManagerContent.onFormPassword(event); -}); -addEventListener("DOMAutoComplete", function(event) { - LoginManagerContent.onUsernameInput(event); -}); -addEventListener("blur", function(event) { - LoginManagerContent.onUsernameInput(event); -}); - -// Lazily load the finder code -addMessageListener("Finder:Initialize", function () { - let {RemoteFinderListener} = Cu.import("resource://gre/modules/RemoteFinder.jsm", {}); - new RemoteFinderListener(global); -}); - -addEventListener("DOMWebNotificationClicked", function(event) { - sendAsyncMessage("DOMWebNotificationClicked", {}); -}, false); diff --git a/browser/base/content/downloadManagerOverlay.xul b/browser/base/content/downloadManagerOverlay.xul deleted file mode 100644 index 9987820cb..000000000 --- a/browser/base/content/downloadManagerOverlay.xul +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0"?> -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?> - -<overlay id="downloadManagerOverlay" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<window id="downloadManager"> - -#include browserMountPoints.inc - -<script type="application/javascript"><![CDATA[ - window.addEventListener("load", function(event) { - // Bug 405696: Map Edit -> Find command to the download manager's command - var findMenuItem = document.getElementById("menu_find"); - findMenuItem.setAttribute("command", "cmd_findDownload"); - findMenuItem.setAttribute("key", "key_findDownload"); - - // Bug 429614: Map Edit -> Select All command to download manager's command - let selectAllMenuItem = document.getElementById("menu_selectAll"); - selectAllMenuItem.setAttribute("command", "cmd_selectAllDownloads"); - selectAllMenuItem.setAttribute("key", "key_selectAllDownloads"); - }, false); -]]></script> - -</window> - -</overlay> diff --git a/browser/base/content/global-scripts.inc b/browser/base/content/global-scripts.inc deleted file mode 100644 index b4de574ae..000000000 --- a/browser/base/content/global-scripts.inc +++ /dev/null @@ -1,13 +0,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/. - -<script type="application/javascript" src="chrome://global/content/printUtils.js"/> -<script type="application/javascript" src="chrome://global/content/viewZoomOverlay.js"/> -<script type="application/javascript" src="chrome://browser/content/places/browserPlacesViews.js"/> -<script type="application/javascript" src="chrome://browser/content/browser.js"/> -<script type="application/javascript" src="chrome://browser/content/downloads/downloads.js"/> -<script type="application/javascript" src="chrome://browser/content/downloads/indicator.js"/> -<script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/> -<script type="application/javascript" src="chrome://global/content/viewSourceUtils.js"/> diff --git a/browser/base/content/hiddenWindow.xul b/browser/base/content/hiddenWindow.xul deleted file mode 100644 index bf201fd60..000000000 --- a/browser/base/content/hiddenWindow.xul +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0"?> -# -*- Mode: HTML -*- -# -# 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/. - -#ifdef XP_MACOSX -<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?> - -<window id="main-window" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -#include browserMountPoints.inc - -</window> - -#endif diff --git a/browser/base/content/highlighter.css b/browser/base/content/highlighter.css deleted file mode 100644 index 8fb9d8085..000000000 --- a/browser/base/content/highlighter.css +++ /dev/null @@ -1,105 +0,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/. */ - -.highlighter-container { - pointer-events: none; -} - -.highlighter-controls { - position: absolute; - top: 0; - left: 0; -} - -.highlighter-outline-container { - overflow: hidden; - position: relative; -} - -.highlighter-outline { - position: absolute; -} - -.highlighter-outline[hidden] { - opacity: 0; - pointer-events: none; - display: -moz-box; -} - -.highlighter-outline:not([disable-transitions]) { - transition-property: opacity, top, left, width, height; - transition-duration: 0.1s; - transition-timing-function: linear; -} - -/* - * Node Infobar - */ - -.highlighter-nodeinfobar-container { - position: absolute; - max-width: 95%; -} - -.highlighter-nodeinfobar-container[hidden] { - opacity: 0; - pointer-events: none; - display: -moz-box; -} - -.highlighter-nodeinfobar-container:not([disable-transitions]), -.highlighter-nodeinfobar-container[disable-transitions][force-transitions] { - transition-property: transform, opacity, top, left; - transition-duration: 0.1s; - transition-timing-function: linear; -} - -.highlighter-nodeinfobar-text { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - direction: ltr; -} - -.highlighter-nodeinfobar-button > .toolbarbutton-text { - display: none; -} - -.highlighter-nodeinfobar-container:not([locked]):not(:hover) > .highlighter-nodeinfobar > .highlighter-nodeinfobar-button { - visibility: hidden; -} - -.highlighter-nodeinfobar-container[locked] > .highlighter-nodeinfobar, -.highlighter-nodeinfobar-container:not([locked]):hover > .highlighter-nodeinfobar { - pointer-events: auto; -} - -html|*.highlighter-nodeinfobar-id, -html|*.highlighter-nodeinfobar-classes, -html|*.highlighter-nodeinfobar-pseudo-classes, -html|*.highlighter-nodeinfobar-tagname { - -moz-user-select: text; - -moz-user-focus: normal; - cursor: text; -} - -.highlighter-nodeinfobar-arrow { - display: none; -} - -.highlighter-nodeinfobar-container[position="top"]:not([hide-arrow]) > .highlighter-nodeinfobar-arrow-bottom { - display: block; -} - -.highlighter-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > .highlighter-nodeinfobar-arrow-top { - display: block; -} - -.highlighter-nodeinfobar-container[disabled] { - visibility: hidden; -} - -html|*.highlighter-nodeinfobar-tagname { - text-transform: lowercase; -} diff --git a/browser/base/content/jsConsoleOverlay.xul b/browser/base/content/jsConsoleOverlay.xul deleted file mode 100644 index 1bc518d4f..000000000 --- a/browser/base/content/jsConsoleOverlay.xul +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0"?> -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?> - -<overlay id="jsConsoleOverlay" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<window id="JSConsoleWindow"> - -#include browserMountPoints.inc - -</window> - -</overlay> diff --git a/browser/base/content/macBrowserOverlay.xul b/browser/base/content/macBrowserOverlay.xul deleted file mode 100644 index a4d583e16..000000000 --- a/browser/base/content/macBrowserOverlay.xul +++ /dev/null @@ -1,64 +0,0 @@ -<?xml version="1.0"?> -# -*- Mode: HTML -*- -# -# 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/content/places/places.css" type="text/css"?> - -<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> -<?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?> -<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?> - -# All DTD information is stored in a separate file so that it can be shared by -# hiddenWindow.xul. -#include browser-doctype.inc - -<overlay id="hidden-overlay" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -# All JS files which are not content (only) dependent that browser.xul -# wishes to include *must* go into the global-scripts.inc file -# so that they can be shared by this overlay. -#include global-scripts.inc - -<script type="application/javascript"> - function OpenBrowserWindowFromDockMenu(options) { - let win = OpenBrowserWindow(options); - win.addEventListener("load", function listener() { - win.removeEventListener("load", listener); - let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"] - .getService(Ci.nsIMacDockSupport); - dockSupport.activateApplication(true); - }); - - return win; - } - - addEventListener("load", function() { gBrowserInit.nonBrowserWindowStartup() }, false); - addEventListener("unload", function() { gBrowserInit.nonBrowserWindowShutdown() }, false); -</script> - -# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the -# browser-sets.inc file for sharing with hiddenWindow.xul. -#include browser-sets.inc - -# The entire main menubar is placed into browser-menubar.inc, so that it can be shared by -# hiddenWindow.xul. -#include browser-menubar.inc - -<!-- Dock menu --> -<popupset> - <menupopup id="menu_mac_dockmenu"> - <!-- The command cannot be cmd_newNavigator because we need to activate - the application. --> - <menuitem label="&newNavigatorCmd.label;" oncommand="OpenBrowserWindowFromDockMenu();" - id="macDockMenuNewWindow" /> - <menuitem label="&newPrivateWindow.label;" oncommand="OpenBrowserWindowFromDockMenu({private: true});" /> - </menupopup> -</popupset> - -</overlay> diff --git a/browser/base/content/newtab/cells.js b/browser/base/content/newtab/cells.js deleted file mode 100644 index 47d4ef52d..000000000 --- a/browser/base/content/newtab/cells.js +++ /dev/null @@ -1,126 +0,0 @@ -#ifdef 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 - -/** - * This class manages a cell's DOM node (not the actually cell content, a site). - * It's mostly read-only, i.e. all manipulation of both position and content - * aren't handled here. - */ -function Cell(aGrid, aNode) { - this._grid = aGrid; - this._node = aNode; - this._node._newtabCell = this; - - // Register drag-and-drop event handlers. - ["dragenter", "dragover", "dragexit", "drop"].forEach(function (aType) { - this._node.addEventListener(aType, this, false); - }, this); -} - -Cell.prototype = { - /** - * The grid. - */ - _grid: null, - - /** - * The cell's DOM node. - */ - get node() { return this._node; }, - - /** - * The cell's offset in the grid. - */ - get index() { - let index = this._grid.cells.indexOf(this); - - // Cache this value, overwrite the getter. - Object.defineProperty(this, "index", {value: index, enumerable: true}); - - return index; - }, - - /** - * The previous cell in the grid. - */ - get previousSibling() { - let prev = this.node.previousElementSibling; - prev = prev && prev._newtabCell; - - // Cache this value, overwrite the getter. - Object.defineProperty(this, "previousSibling", {value: prev, enumerable: true}); - - return prev; - }, - - /** - * The next cell in the grid. - */ - get nextSibling() { - let next = this.node.nextElementSibling; - next = next && next._newtabCell; - - // Cache this value, overwrite the getter. - Object.defineProperty(this, "nextSibling", {value: next, enumerable: true}); - - return next; - }, - - /** - * The site contained in the cell, if any. - */ - get site() { - let firstChild = this.node.firstElementChild; - return firstChild && firstChild._newtabSite; - }, - - /** - * Checks whether the cell contains a pinned site. - * @return Whether the cell contains a pinned site. - */ - containsPinnedSite: function Cell_containsPinnedSite() { - let site = this.site; - return site && site.isPinned(); - }, - - /** - * Checks whether the cell contains a site (is empty). - * @return Whether the cell is empty. - */ - isEmpty: function Cell_isEmpty() { - return !this.site; - }, - - /** - * Handles all cell events. - */ - handleEvent: function Cell_handleEvent(aEvent) { - // We're not responding to external drag/drop events - // when our parent window is in private browsing mode. - if (inPrivateBrowsingMode() && !gDrag.draggedSite) - return; - - if (aEvent.type != "dragexit" && !gDrag.isValid(aEvent)) - return; - - switch (aEvent.type) { - case "dragenter": - aEvent.preventDefault(); - gDrop.enter(this, aEvent); - break; - case "dragover": - aEvent.preventDefault(); - break; - case "dragexit": - gDrop.exit(this, aEvent); - break; - case "drop": - aEvent.preventDefault(); - gDrop.drop(this, aEvent); - break; - } - } -}; diff --git a/browser/base/content/newtab/drag.js b/browser/base/content/newtab/drag.js deleted file mode 100644 index 8f0bf674e..000000000 --- a/browser/base/content/newtab/drag.js +++ /dev/null @@ -1,151 +0,0 @@ -#ifdef 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 - -/** - * This singleton implements site dragging functionality. - */ -let gDrag = { - /** - * The site offset to the drag start point. - */ - _offsetX: null, - _offsetY: null, - - /** - * The site that is dragged. - */ - _draggedSite: null, - get draggedSite() { return this._draggedSite; }, - - /** - * The cell width/height at the point the drag started. - */ - _cellWidth: null, - _cellHeight: null, - get cellWidth() { return this._cellWidth; }, - get cellHeight() { return this._cellHeight; }, - - /** - * Start a new drag operation. - * @param aSite The site that's being dragged. - * @param aEvent The 'dragstart' event. - */ - start: function Drag_start(aSite, aEvent) { - this._draggedSite = aSite; - - // Mark nodes as being dragged. - let selector = ".newtab-site, .newtab-control, .newtab-thumbnail"; - let parentCell = aSite.node.parentNode; - let nodes = parentCell.querySelectorAll(selector); - for (let i = 0; i < nodes.length; i++) - nodes[i].setAttribute("dragged", "true"); - - parentCell.setAttribute("dragged", "true"); - - this._setDragData(aSite, aEvent); - - // Store the cursor offset. - let node = aSite.node; - let rect = node.getBoundingClientRect(); - this._offsetX = aEvent.clientX - rect.left; - this._offsetY = aEvent.clientY - rect.top; - - // Store the cell dimensions. - let cellNode = aSite.cell.node; - this._cellWidth = cellNode.offsetWidth; - this._cellHeight = cellNode.offsetHeight; - - gTransformation.freezeSitePosition(aSite); - }, - - /** - * Handles the 'drag' event. - * @param aSite The site that's being dragged. - * @param aEvent The 'drag' event. - */ - drag: function Drag_drag(aSite, aEvent) { - // Get the viewport size. - let {clientWidth, clientHeight} = document.documentElement; - - // We'll want a padding of 5px. - let border = 5; - - // Enforce minimum constraints to keep the drag image inside the window. - let left = Math.max(scrollX + aEvent.clientX - this._offsetX, border); - let top = Math.max(scrollY + aEvent.clientY - this._offsetY, border); - - // Enforce maximum constraints to keep the drag image inside the window. - left = Math.min(left, scrollX + clientWidth - this.cellWidth - border); - top = Math.min(top, scrollY + clientHeight - this.cellHeight - border); - - // Update the drag image's position. - gTransformation.setSitePosition(aSite, {left: left, top: top}); - }, - - /** - * Ends the current drag operation. - * @param aSite The site that's being dragged. - * @param aEvent The 'dragend' event. - */ - end: function Drag_end(aSite, aEvent) { - let nodes = gGrid.node.querySelectorAll("[dragged]") - for (let i = 0; i < nodes.length; i++) - nodes[i].removeAttribute("dragged"); - - // Slide the dragged site back into its cell (may be the old or the new cell). - gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true}); - - this._draggedSite = null; - }, - - /** - * Checks whether we're responsible for a given drag event. - * @param aEvent The drag event to check. - * @return Whether we should handle this drag and drop operation. - */ - isValid: function Drag_isValid(aEvent) { - let link = gDragDataHelper.getLinkFromDragEvent(aEvent); - - // Check that the drag data is non-empty. - // Can happen when dragging places folders. - if (!link || !link.url) { - return false; - } - - // Check that we're not accepting URLs which would inherit the caller's - // principal (such as javascript: or data:). - return gLinkChecker.checkLoadURI(link.url); - }, - - /** - * Initializes the drag data for the current drag operation. - * @param aSite The site that's being dragged. - * @param aEvent The 'dragstart' event. - */ - _setDragData: function Drag_setDragData(aSite, aEvent) { - let {url, title} = aSite; - - let dt = aEvent.dataTransfer; - dt.mozCursor = "default"; - dt.effectAllowed = "move"; - dt.setData("text/plain", url); - dt.setData("text/uri-list", url); - dt.setData("text/x-moz-url", url + "\n" + title); - dt.setData("text/html", "<a href=\"" + url + "\">" + url + "</a>"); - - // Create and use an empty drag element. We don't want to use the default - // drag image with its default opacity. - let dragElement = document.createElementNS(HTML_NAMESPACE, "div"); - dragElement.classList.add("newtab-drag"); - let scrollbox = document.getElementById("newtab-scrollbox"); - scrollbox.appendChild(dragElement); - dt.setDragImage(dragElement, 0, 0); - - // After the 'dragstart' event has been processed we can remove the - // temporary drag element from the DOM. - setTimeout(() => scrollbox.removeChild(dragElement), 0); - } -}; diff --git a/browser/base/content/newtab/dragDataHelper.js b/browser/base/content/newtab/dragDataHelper.js deleted file mode 100644 index a66e4e87e..000000000 --- a/browser/base/content/newtab/dragDataHelper.js +++ /dev/null @@ -1,22 +0,0 @@ -#ifdef 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 - -let gDragDataHelper = { - get mimeType() { - return "text/x-moz-url"; - }, - - getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) { - let dt = aEvent.dataTransfer; - if (!dt || !dt.types.contains(this.mimeType)) { - return null; - } - - let data = dt.getData(this.mimeType) || ""; - let [url, title] = data.split(/[\r\n]+/); - return {url: url, title: title}; - } -}; diff --git a/browser/base/content/newtab/drop.js b/browser/base/content/newtab/drop.js deleted file mode 100644 index d7bf30506..000000000 --- a/browser/base/content/newtab/drop.js +++ /dev/null @@ -1,150 +0,0 @@ -#ifdef 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 - -// A little delay that prevents the grid from being too sensitive when dragging -// sites around. -const DELAY_REARRANGE_MS = 100; - -/** - * This singleton implements site dropping functionality. - */ -let gDrop = { - /** - * The last drop target. - */ - _lastDropTarget: null, - - /** - * Handles the 'dragenter' event. - * @param aCell The drop target cell. - */ - enter: function Drop_enter(aCell) { - this._delayedRearrange(aCell); - }, - - /** - * Handles the 'dragexit' event. - * @param aCell The drop target cell. - * @param aEvent The 'dragexit' event. - */ - exit: function Drop_exit(aCell, aEvent) { - if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) { - this._delayedRearrange(); - } else { - // The drag operation has been cancelled. - this._cancelDelayedArrange(); - this._rearrange(); - } - }, - - /** - * Handles the 'drop' event. - * @param aCell The drop target cell. - * @param aEvent The 'dragexit' event. - */ - drop: function Drop_drop(aCell, aEvent) { - // The cell that is the drop target could contain a pinned site. We need - // to find out where that site has gone and re-pin it there. - if (aCell.containsPinnedSite()) - this._repinSitesAfterDrop(aCell); - - // Pin the dragged or insert the new site. - this._pinDraggedSite(aCell, aEvent); - - this._cancelDelayedArrange(); - - // Update the grid and move all sites to their new places. - gUpdater.updateGrid(); - }, - - /** - * Re-pins all pinned sites in their (new) positions. - * @param aCell The drop target cell. - */ - _repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) { - let sites = gDropPreview.rearrange(aCell); - - // Filter out pinned sites. - let pinnedSites = sites.filter(function (aSite) { - return aSite && aSite.isPinned(); - }); - - // Re-pin all shifted pinned cells. - pinnedSites.forEach(aSite => aSite.pin(sites.indexOf(aSite))); - }, - - /** - * Pins the dragged site in its new place. - * @param aCell The drop target cell. - * @param aEvent The 'dragexit' event. - */ - _pinDraggedSite: function Drop_pinDraggedSite(aCell, aEvent) { - let index = aCell.index; - let draggedSite = gDrag.draggedSite; - - if (draggedSite) { - // Pin the dragged site at its new place. - if (aCell != draggedSite.cell) - draggedSite.pin(index); - } else { - let link = gDragDataHelper.getLinkFromDragEvent(aEvent); - if (link) { - // A new link was dragged onto the grid. Create it by pinning its URL. - gPinnedLinks.pin(link, index); - - // Make sure the newly added link is not blocked. - gBlockedLinks.unblock(link); - } - } - }, - - /** - * Time a rearrange with a little delay. - * @param aCell The drop target cell. - */ - _delayedRearrange: function Drop_delayedRearrange(aCell) { - // The last drop target didn't change so there's no need to re-arrange. - if (this._lastDropTarget == aCell) - return; - - let self = this; - - function callback() { - self._rearrangeTimeout = null; - self._rearrange(aCell); - } - - this._cancelDelayedArrange(); - this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS); - - // Store the last drop target. - this._lastDropTarget = aCell; - }, - - /** - * Cancels a timed rearrange, if any. - */ - _cancelDelayedArrange: function Drop_cancelDelayedArrange() { - if (this._rearrangeTimeout) { - clearTimeout(this._rearrangeTimeout); - this._rearrangeTimeout = null; - } - }, - - /** - * Rearrange all sites in the grid depending on the current drop target. - * @param aCell The drop target cell. - */ - _rearrange: function Drop_rearrange(aCell) { - let sites = gGrid.sites; - - // We need to rearrange the grid only if there's a current drop target. - if (aCell) - sites = gDropPreview.rearrange(aCell); - - gTransformation.rearrangeSites(sites, {unfreeze: !aCell}); - } -}; diff --git a/browser/base/content/newtab/dropPreview.js b/browser/base/content/newtab/dropPreview.js deleted file mode 100644 index 903762345..000000000 --- a/browser/base/content/newtab/dropPreview.js +++ /dev/null @@ -1,222 +0,0 @@ -#ifdef 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 - -/** - * This singleton provides the ability to re-arrange the current grid to - * indicate the transformation that results from dropping a cell at a certain - * position. - */ -let gDropPreview = { - /** - * Rearranges the sites currently contained in the grid when a site would be - * dropped onto the given cell. - * @param aCell The drop target cell. - * @return The re-arranged array of sites. - */ - rearrange: function DropPreview_rearrange(aCell) { - let sites = gGrid.sites; - - // Insert the dragged site into the current grid. - this._insertDraggedSite(sites, aCell); - - // After the new site has been inserted we need to correct the positions - // of all pinned tabs that have been moved around. - this._repositionPinnedSites(sites, aCell); - - return sites; - }, - - /** - * Inserts the currently dragged site into the given array of sites. - * @param aSites The array of sites to insert into. - * @param aCell The drop target cell. - */ - _insertDraggedSite: function DropPreview_insertDraggedSite(aSites, aCell) { - let dropIndex = aCell.index; - let draggedSite = gDrag.draggedSite; - - // We're currently dragging a site. - if (draggedSite) { - let dragCell = draggedSite.cell; - let dragIndex = dragCell.index; - - // Move the dragged site into its new position. - if (dragIndex != dropIndex) { - aSites.splice(dragIndex, 1); - aSites.splice(dropIndex, 0, draggedSite); - } - // We're handling an external drag item. - } else { - aSites.splice(dropIndex, 0, null); - } - }, - - /** - * Correct the position of all pinned sites that might have been moved to - * different positions after the dragged site has been inserted. - * @param aSites The array of sites containing the dragged site. - * @param aCell The drop target cell. - */ - _repositionPinnedSites: - function DropPreview_repositionPinnedSites(aSites, aCell) { - - // Collect all pinned sites. - let pinnedSites = this._filterPinnedSites(aSites, aCell); - - // Correct pinned site positions. - pinnedSites.forEach(function (aSite) { - aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index]; - aSites[aSite.cell.index] = aSite; - }, this); - - // There might be a pinned cell that got pushed out of the grid, try to - // sneak it in by removing a lower-priority cell. - if (this._hasOverflowedPinnedSite(aSites, aCell)) - this._repositionOverflowedPinnedSite(aSites, aCell); - }, - - /** - * Filter pinned sites out of the grid that are still on their old positions - * and have not moved. - * @param aSites The array of sites to filter. - * @param aCell The drop target cell. - * @return The filtered array of sites. - */ - _filterPinnedSites: function DropPreview_filterPinnedSites(aSites, aCell) { - let draggedSite = gDrag.draggedSite; - - // When dropping on a cell that contains a pinned site make sure that all - // pinned cells surrounding the drop target are moved as well. - let range = this._getPinnedRange(aCell); - - return aSites.filter(function (aSite, aIndex) { - // The site must be valid, pinned and not the dragged site. - if (!aSite || aSite == draggedSite || !aSite.isPinned()) - return false; - - let index = aSite.cell.index; - - // If it's not in the 'pinned range' it's a valid pinned site. - return (index > range.end || index < range.start); - }); - }, - - /** - * Determines the range of pinned sites surrounding the drop target cell. - * @param aCell The drop target cell. - * @return The range of pinned cells. - */ - _getPinnedRange: function DropPreview_getPinnedRange(aCell) { - let dropIndex = aCell.index; - let range = {start: dropIndex, end: dropIndex}; - - // We need a pinned range only when dropping on a pinned site. - if (aCell.containsPinnedSite()) { - let links = gPinnedLinks.links; - - // Find all previous siblings of the drop target that are pinned as well. - while (range.start && links[range.start - 1]) - range.start--; - - let maxEnd = links.length - 1; - - // Find all next siblings of the drop target that are pinned as well. - while (range.end < maxEnd && links[range.end + 1]) - range.end++; - } - - return range; - }, - - /** - * Checks if the given array of sites contains a pinned site that has - * been pushed out of the grid. - * @param aSites The array of sites to check. - * @param aCell The drop target cell. - * @return Whether there is an overflowed pinned cell. - */ - _hasOverflowedPinnedSite: - function DropPreview_hasOverflowedPinnedSite(aSites, aCell) { - - // If the drop target isn't pinned there's no way a pinned site has been - // pushed out of the grid so we can just exit here. - if (!aCell.containsPinnedSite()) - return false; - - let cells = gGrid.cells; - - // No cells have been pushed out of the grid, nothing to do here. - if (aSites.length <= cells.length) - return false; - - let overflowedSite = aSites[cells.length]; - - // Nothing to do if the site that got pushed out of the grid is not pinned. - return (overflowedSite && overflowedSite.isPinned()); - }, - - /** - * We have a overflowed pinned site that we need to re-position so that it's - * visible again. We try to find a lower-priority cell (empty or containing - * an unpinned site) that we can move it to. - * @param aSites The array of sites. - * @param aCell The drop target cell. - */ - _repositionOverflowedPinnedSite: - function DropPreview_repositionOverflowedPinnedSite(aSites, aCell) { - - // Try to find a lower-priority cell (empty or containing an unpinned site). - let index = this._indexOfLowerPrioritySite(aSites, aCell); - - if (index > -1) { - let cells = gGrid.cells; - let dropIndex = aCell.index; - - // Move all pinned cells to their new positions to let the overflowed - // site fit into the grid. - for (let i = index + 1, lastPosition = index; i < aSites.length; i++) { - if (i != dropIndex) { - aSites[lastPosition] = aSites[i]; - lastPosition = i; - } - } - - // Finally, remove the overflowed site from its previous position. - aSites.splice(cells.length, 1); - } - }, - - /** - * Finds the index of the last cell that is empty or contains an unpinned - * site. These are considered to be of a lower priority. - * @param aSites The array of sites. - * @param aCell The drop target cell. - * @return The cell's index. - */ - _indexOfLowerPrioritySite: - function DropPreview_indexOfLowerPrioritySite(aSites, aCell) { - - let cells = gGrid.cells; - let dropIndex = aCell.index; - - // Search (beginning with the last site in the grid) for a site that is - // empty or unpinned (an thus lower-priority) and can be pushed out of the - // grid instead of the pinned site. - for (let i = cells.length - 1; i >= 0; i--) { - // The cell that is our drop target is not a good choice. - if (i == dropIndex) - continue; - - let site = aSites[i]; - - // We can use the cell only if it's empty or the site is un-pinned. - if (!site || !site.isPinned()) - return i; - } - - return -1; - } -}; diff --git a/browser/base/content/newtab/dropTargetShim.js b/browser/base/content/newtab/dropTargetShim.js deleted file mode 100644 index a85a6ccd6..000000000 --- a/browser/base/content/newtab/dropTargetShim.js +++ /dev/null @@ -1,188 +0,0 @@ -#ifdef 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 - -/** - * This singleton provides a custom drop target detection. We need this because - * the default DnD target detection relies on the cursor's position. We want - * to pick a drop target based on the dragged site's position. - */ -let gDropTargetShim = { - /** - * Cache for the position of all cells, cleaned after drag finished. - */ - _cellPositions: null, - - /** - * The last drop target that was hovered. - */ - _lastDropTarget: null, - - /** - * Initializes the drop target shim. - */ - init: function DropTargetShim_init() { - let node = gGrid.node; - - // Add drag event handlers. - node.addEventListener("dragstart", this, true); - node.addEventListener("dragend", this, true); - }, - - /** - * Handles all shim events. - */ - handleEvent: function DropTargetShim_handleEvent(aEvent) { - switch (aEvent.type) { - case "dragstart": - this._start(aEvent); - break; - case "dragover": - this._dragover(aEvent); - break; - case "dragend": - this._end(aEvent); - break; - } - }, - - /** - * Handles the 'dragstart' event. - * @param aEvent The 'dragstart' event. - */ - _start: function DropTargetShim_start(aEvent) { - if (aEvent.target.classList.contains("newtab-link")) { - gGrid.lock(); - - // XXX bug 505521 - Listen for dragover on the document. - document.documentElement.addEventListener("dragover", this, false); - } - }, - - /** - * Handles the 'drag' event and determines the current drop target. - * @param aEvent The 'drag' event. - */ - _drag: function DropTargetShim_drag(aEvent) { - // Let's see if we find a drop target. - let target = this._findDropTarget(aEvent); - - if (target != this._lastDropTarget) { - if (this._lastDropTarget) - // We left the last drop target. - this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget); - - if (target) - // We're now hovering a (new) drop target. - this._dispatchEvent(aEvent, "dragenter", target); - - if (this._lastDropTarget) - // We left the last drop target. - this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget); - - this._lastDropTarget = target; - } - }, - - /** - * Handles the 'dragover' event as long as bug 505521 isn't fixed to get - * current mouse cursor coordinates while dragging. - * @param aEvent The 'dragover' event. - */ - _dragover: function DropTargetShim_dragover(aEvent) { - let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode; - gDrag.drag(sourceNode._newtabSite, aEvent); - - this._drag(aEvent); - }, - - /** - * Handles the 'dragend' event. - * @param aEvent The 'dragend' event. - */ - _end: function DropTargetShim_end(aEvent) { - // Make sure to determine the current drop target in case the dragenter - // event hasn't been fired. - this._drag(aEvent); - - if (this._lastDropTarget) { - if (aEvent.dataTransfer.mozUserCancelled) { - // The drag operation was cancelled. - this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget); - this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget); - } else { - // A site was successfully dropped. - this._dispatchEvent(aEvent, "drop", this._lastDropTarget); - } - - // Clean up. - this._lastDropTarget = null; - this._cellPositions = null; - } - - gGrid.unlock(); - - // XXX bug 505521 - Remove the document's dragover listener. - document.documentElement.removeEventListener("dragover", this, false); - }, - - /** - * Determines the current drop target by matching the dragged site's position - * against all cells in the grid. - * @return The currently hovered drop target or null. - */ - _findDropTarget: function DropTargetShim_findDropTarget() { - // These are the minimum intersection values - we want to use the cell if - // the site is >= 50% hovering its position. - let minWidth = gDrag.cellWidth / 2; - let minHeight = gDrag.cellHeight / 2; - - let cellPositions = this._getCellPositions(); - let rect = gTransformation.getNodePosition(gDrag.draggedSite.node); - - // Compare each cell's position to the dragged site's position. - for (let i = 0; i < cellPositions.length; i++) { - let inter = rect.intersect(cellPositions[i].rect); - - // If the intersection is big enough we found a drop target. - if (inter.width >= minWidth && inter.height >= minHeight) - return cellPositions[i].cell; - } - - // No drop target found. - return null; - }, - - /** - * Gets the positions of all cell nodes. - * @return The (cached) cell positions. - */ - _getCellPositions: function DropTargetShim_getCellPositions() { - if (this._cellPositions) - return this._cellPositions; - - return this._cellPositions = gGrid.cells.map(function (cell) { - return {cell: cell, rect: gTransformation.getNodePosition(cell.node)}; - }); - }, - - /** - * Dispatches a custom DragEvent on the given target node. - * @param aEvent The source event. - * @param aType The event type. - * @param aTarget The target node that receives the event. - */ - _dispatchEvent: - function DropTargetShim_dispatchEvent(aEvent, aType, aTarget) { - - let node = aTarget.node; - let event = document.createEvent("DragEvents"); - - event.initDragEvent(aType, true, true, window, 0, 0, 0, 0, 0, false, false, - false, false, 0, node, aEvent.dataTransfer); - - node.dispatchEvent(event); - } -}; diff --git a/browser/base/content/newtab/grid.js b/browser/base/content/newtab/grid.js deleted file mode 100644 index 37559a063..000000000 --- a/browser/base/content/newtab/grid.js +++ /dev/null @@ -1,171 +0,0 @@ -#ifdef 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 - -/** - * This singleton represents the grid that contains all sites. - */ -let gGrid = { - /** - * The DOM node of the grid. - */ - _node: null, - get node() { return this._node; }, - - /** - * The cached DOM fragment for sites. - */ - _siteFragment: null, - - /** - * All cells contained in the grid. - */ - _cells: null, - get cells() { return this._cells; }, - - /** - * All sites contained in the grid's cells. Sites may be empty. - */ - get sites() { return [for (cell of this.cells) cell.site]; }, - - // Tells whether the grid has already been initialized. - get ready() { return !!this._node; }, - - /** - * Initializes the grid. - * @param aSelector The query selector of the grid. - */ - init: function Grid_init() { - this._node = document.getElementById("newtab-grid"); - this._createSiteFragment(); - this._render(); - }, - - /** - * Creates a new site in the grid. - * @param aLink The new site's link. - * @param aCell The cell that will contain the new site. - * @return The newly created site. - */ - createSite: function Grid_createSite(aLink, aCell) { - let node = aCell.node; - node.appendChild(this._siteFragment.cloneNode(true)); - return new Site(node.firstElementChild, aLink); - }, - - /** - * Refreshes the grid and re-creates all sites. - */ - refresh: function Grid_refresh() { - // Remove all sites. - this.cells.forEach(function (cell) { - let node = cell.node; - let child = node.firstElementChild; - - if (child) - node.removeChild(child); - }, this); - - // Render the grid again. - this._render(); - }, - - /** - * Locks the grid to block all pointer events. - */ - lock: function Grid_lock() { - this.node.setAttribute("locked", "true"); - }, - - /** - * Unlocks the grid to allow all pointer events. - */ - unlock: function Grid_unlock() { - this.node.removeAttribute("locked"); - }, - - /** - * Creates the newtab grid. - */ - _renderGrid: function Grid_renderGrid() { - let row = document.createElementNS(HTML_NAMESPACE, "div"); - let cell = document.createElementNS(HTML_NAMESPACE, "div"); - row.classList.add("newtab-row"); - cell.classList.add("newtab-cell"); - - // Clear the grid - this._node.innerHTML = ""; - - // Creates the structure of one row - for (let i = 0; i < gGridPrefs.gridColumns; i++) { - row.appendChild(cell.cloneNode(true)); - } - // Creates the grid - for (let j = 0; j < gGridPrefs.gridRows; j++) { - this._node.appendChild(row.cloneNode(true)); - } - - // (Re-)initialize all cells. - let cellElements = this.node.querySelectorAll(".newtab-cell"); - this._cells = [new Cell(this, cell) for (cell of cellElements)]; - }, - - /** - * Creates the DOM fragment that is re-used when creating sites. - */ - _createSiteFragment: function Grid_createSiteFragment() { - let site = document.createElementNS(HTML_NAMESPACE, "div"); - site.classList.add("newtab-site"); - site.setAttribute("draggable", "true"); - - // Create the site's inner HTML code. - site.innerHTML = - '<a class="newtab-link">' + - ' <span class="newtab-thumbnail"/>' + - ' <span class="newtab-title"/>' + - '</a>' + - '<input type="button" title="' + newTabString("pin") + '"' + - ' class="newtab-control newtab-control-pin"/>' + - '<input type="button" title="' + newTabString("block") + '"' + - ' class="newtab-control newtab-control-block"/>'; - - this._siteFragment = document.createDocumentFragment(); - this._siteFragment.appendChild(site); - }, - - /** - * Renders the sites, creates all sites and puts them into their cells. - */ - _renderSites: function Grid_renderSites() { - let cells = this.cells; - // Put sites into the cells. - let links = gLinks.getLinks(); - let length = Math.min(links.length, cells.length); - - for (let i = 0; i < length; i++) { - if (links[i]) - this.createSite(links[i], cells[i]); - } - }, - - /** - * Renders the grid. - */ - _render: function Grid_render() { - if (this._shouldRenderGrid()) { - this._renderGrid(); - } - - this._renderSites(); - }, - - _shouldRenderGrid : function Grid_shouldRenderGrid() { - let rowsLength = this._node.querySelectorAll(".newtab-row").length; - let cellsLength = this._node.querySelectorAll(".newtab-cell").length; - - return (rowsLength != gGridPrefs.gridRows || - cellsLength != (gGridPrefs.gridRows * gGridPrefs.gridColumns)); - } -}; diff --git a/browser/base/content/newtab/newTab.css b/browser/base/content/newtab/newTab.css deleted file mode 100644 index 830e4a8c1..000000000 --- a/browser/base/content/newtab/newTab.css +++ /dev/null @@ -1,209 +0,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/. */ - -input[type=button] { - cursor: pointer; -} - -/* SCROLLBOX */ -#newtab-scrollbox { - display: -moz-box; - position: relative; - -moz-box-flex: 1; - -moz-user-focus: normal; -} - -#newtab-scrollbox:not([page-disabled]) { - overflow: auto; -} - -/* UNDO */ -#newtab-undo-container { - transition: opacity 100ms ease-out; - display: -moz-box; - -moz-box-align: center; - -moz-box-pack: center; -} - -#newtab-undo-container[undo-disabled] { - opacity: 0; - pointer-events: none; -} - -/* TOGGLE */ -#newtab-toggle { - position: absolute; - top: 12px; - right: 12px; -} - -#newtab-toggle:-moz-locale-dir(rtl) { - left: 12px; - right: auto; -} - -/* MARGINS */ -#newtab-vertical-margin { - display: -moz-box; - position: relative; - -moz-box-flex: 1; - -moz-box-orient: vertical; -} - -#newtab-margin-top { - min-height: 50px; - max-height: 80px; - display: -moz-box; - -moz-box-flex: 1; - -moz-box-align: center; - -moz-box-pack: center; -} - -#newtab-margin-bottom { - min-height: 40px; - max-height: 100px; - -moz-box-flex: 1; -} - -#newtab-horizontal-margin { - display: -moz-box; - -moz-box-flex: 5; -} - -.newtab-side-margin { - min-width: 40px; - max-width: 300px; - -moz-box-flex: 1; -} - -/* GRID */ -#newtab-grid { - display: -moz-box; - -moz-box-flex: 5; - -moz-box-orient: vertical; - min-width: 600px; - min-height: 400px; - transition: 100ms ease-out; - transition-property: opacity; -} - -#newtab-grid[page-disabled] { - opacity: 0; -} - -#newtab-grid[locked], -#newtab-grid[page-disabled] { - pointer-events: none; -} - -/* ROWS */ -.newtab-row { - display: -moz-box; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -moz-box-flex: 1; -} - -/* CELLS */ -.newtab-cell { - display: -moz-box; - -moz-box-flex: 1; -} - -/* SITES */ -.newtab-site { - position: relative; - -moz-box-flex: 1; - transition: 100ms ease-out; - transition-property: top, left, opacity; -} - -.newtab-site[frozen] { - position: absolute; - pointer-events: none; -} - -.newtab-site[dragged] { - transition-property: none; - z-index: 10; -} - -/* LINK + THUMBNAILS */ -.newtab-link, -.newtab-thumbnail { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; -} - -.newtab-thumbnail { - opacity: .8; - transition: opacity 100ms ease-out; -} - -.newtab-thumbnail[dragged], -.newtab-link:-moz-focusring > .newtab-thumbnail, -.newtab-site:hover > .newtab-link > .newtab-thumbnail { - opacity: 1; -} - -/* TITLES */ -.newtab-title { - position: absolute; - left: 0; - right: 0; - bottom: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -/* CONTROLS */ -.newtab-control { - position: absolute; - top: 4px; - opacity: 0; - transition: opacity 100ms ease-out; -} - -.newtab-control:-moz-focusring, -.newtab-site:hover > .newtab-control { - opacity: 1; -} - -.newtab-control[dragged] { - opacity: 0 !important; -} - -@media (-moz-touch-enabled) { - .newtab-control { - opacity: 1; - } -} - -.newtab-control-pin:-moz-locale-dir(ltr), -.newtab-control-block:-moz-locale-dir(rtl) { - left: 4px; -} - -.newtab-control-block:-moz-locale-dir(ltr), -.newtab-control-pin:-moz-locale-dir(rtl) { - right: 4px; -} - -/* DRAG & DROP */ - -/* - * This is just a temporary drag element used for dataTransfer.setDragImage() - * so that we can use custom drag images and elements. It needs an opacity of - * 0.01 so that the core code detects that it's in fact a visible element. - */ -.newtab-drag { - width: 1px; - height: 1px; - background-color: #fff; - opacity: 0.01; -} diff --git a/browser/base/content/newtab/newTab.js b/browser/base/content/newtab/newTab.js deleted file mode 100644 index 77c929125..000000000 --- a/browser/base/content/newtab/newTab.js +++ /dev/null @@ -1,57 +0,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/. */ - -"use strict"; - -let Cu = Components.utils; -let Ci = Components.interfaces; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/PageThumbs.jsm"); -Cu.import("resource://gre/modules/NewTabUtils.jsm"); -Cu.import("resource:///modules/promise.js"); - -XPCOMUtils.defineLazyModuleGetter(this, "Rect", - "resource://gre/modules/Geometry.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", - "resource://gre/modules/PrivateBrowsingUtils.jsm"); - -let { - links: gLinks, - allPages: gAllPages, - linkChecker: gLinkChecker, - pinnedLinks: gPinnedLinks, - blockedLinks: gBlockedLinks, - gridPrefs: gGridPrefs -} = NewTabUtils; - -XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() { - return Services.strings. - createBundle("chrome://browser/locale/newTab.properties"); -}); - -function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name); - -function inPrivateBrowsingMode() { - return PrivateBrowsingUtils.isWindowPrivate(window); -} - -const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; - -#include transformations.js -#include page.js -#include grid.js -#include cells.js -#include sites.js -#include drag.js -#include dragDataHelper.js -#include drop.js -#include dropTargetShim.js -#include dropPreview.js -#include updater.js -#include undo.js - -// Everything is loaded. Initialize the New Tab Page. -gPage.init(); diff --git a/browser/base/content/newtab/newTab.xul b/browser/base/content/newtab/newTab.xul deleted file mode 100644 index 6fc202f29..000000000 --- a/browser/base/content/newtab/newTab.xul +++ /dev/null @@ -1,55 +0,0 @@ -<?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/. --> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<?xml-stylesheet href="chrome://browser/content/newtab/newTab.css" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/newtab/newTab.css" type="text/css"?> - -<!DOCTYPE window [ - <!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd"> - %newTabDTD; -]> - -<xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - title="&newtab.pageTitle;"> - - <div id="newtab-scrollbox"> - - <div id="newtab-vertical-margin"> - <div id="newtab-margin-top"> - <div id="newtab-undo-container" undo-disabled="true"> - <xul:label id="newtab-undo-label" - value="&newtab.undo.removedLabel;" /> - <xul:button id="newtab-undo-button" tabindex="-1" - label="&newtab.undo.undoButton;" - class="newtab-undo-button" /> - <xul:button id="newtab-undo-restore-button" tabindex="-1" - label="&newtab.undo.restoreButton;" - class="newtab-undo-button" /> - <xul:toolbarbutton id="newtab-undo-close-button" tabindex="-1" - class="close-icon" - tooltiptext="&newtab.undo.closeTooltip;" /> - </div> - </div> - - <div id="newtab-horizontal-margin"> - <div class="newtab-side-margin"/> - - <div id="newtab-grid"> - </div> - - <div class="newtab-side-margin"/> - </div> - - <div id="newtab-margin-bottom"/> - </div> - <input id="newtab-toggle" type="button"/> - </div> - - <xul:script type="text/javascript;version=1.8" - src="chrome://browser/content/newtab/newTab.js"/> -</xul:window> diff --git a/browser/base/content/newtab/page.js b/browser/base/content/newtab/page.js deleted file mode 100644 index afe5bfba8..000000000 --- a/browser/base/content/newtab/page.js +++ /dev/null @@ -1,135 +0,0 @@ -#ifdef 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 - -/** - * This singleton represents the whole 'New Tab Page' and takes care of - * initializing all its components. - */ -let gPage = { - /** - * Initializes the page. - */ - init: function Page_init() { - // Add ourselves to the list of pages to receive notifications. - gAllPages.register(this); - - // Listen for 'unload' to unregister this page. - addEventListener("unload", this, false); - - // Listen for toggle button clicks. - let button = document.getElementById("newtab-toggle"); - button.addEventListener("click", this, false); - - // Check if the new tab feature is enabled. - let enabled = gAllPages.enabled; - if (enabled) - this._init(); - - this._updateAttributes(enabled); - }, - - /** - * Listens for notifications specific to this page. - */ - observe: function Page_observe() { - let enabled = gAllPages.enabled; - this._updateAttributes(enabled); - - // Initialize the whole page if we haven't done that, yet. - if (enabled) { - this._init(); - } else { - gUndoDialog.hide(); - } - }, - - /** - * Updates the whole page and the grid when the storage has changed. - */ - update: function Page_update() { - // The grid might not be ready yet as we initialize it asynchronously. - if (gGrid.ready) { - gGrid.refresh(); - } - }, - - /** - * Internally initializes the page. This runs only when/if the feature - * is/gets enabled. - */ - _init: function Page_init() { - if (this._initialized) - return; - - this._initialized = true; - - gLinks.populateCache(function () { - // Initialize and render the grid. - gGrid.init(); - - // Initialize the drop target shim. - gDropTargetShim.init(); - -#ifdef XP_MACOSX - // Workaround to prevent a delay on MacOSX due to a slow drop animation. - document.addEventListener("dragover", this, false); - document.addEventListener("drop", this, false); -#endif - }.bind(this)); - }, - - /** - * Updates the 'page-disabled' attributes of the respective DOM nodes. - * @param aValue Whether the New Tab Page is enabled or not. - */ - _updateAttributes: function Page_updateAttributes(aValue) { - // Set the nodes' states. - let nodeSelector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid"; - for (let node of document.querySelectorAll(nodeSelector)) { - if (aValue) - node.removeAttribute("page-disabled"); - else - node.setAttribute("page-disabled", "true"); - } - - // Enables/disables the control and link elements. - let inputSelector = ".newtab-control, .newtab-link"; - for (let input of document.querySelectorAll(inputSelector)) { - if (aValue) - input.removeAttribute("tabindex"); - else - input.setAttribute("tabindex", "-1"); - } - - // Update the toggle button's title. - let toggle = document.getElementById("newtab-toggle"); - toggle.setAttribute("title", newTabString(aValue ? "hide" : "show")); - }, - - /** - * Handles all page events. - */ - handleEvent: function Page_handleEvent(aEvent) { - switch (aEvent.type) { - case "unload": - gAllPages.unregister(this); - break; - case "click": - gAllPages.enabled = !gAllPages.enabled; - break; - case "dragover": - if (gDrag.isValid(aEvent) && gDrag.draggedSite) - aEvent.preventDefault(); - break; - case "drop": - if (gDrag.isValid(aEvent) && gDrag.draggedSite) { - aEvent.preventDefault(); - aEvent.stopPropagation(); - } - break; - } - } -}; diff --git a/browser/base/content/newtab/sites.js b/browser/base/content/newtab/sites.js deleted file mode 100644 index 873ef201c..000000000 --- a/browser/base/content/newtab/sites.js +++ /dev/null @@ -1,192 +0,0 @@ -#ifdef 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 - -/** - * This class represents a site that is contained in a cell and can be pinned, - * moved around or deleted. - */ -function Site(aNode, aLink) { - this._node = aNode; - this._node._newtabSite = this; - - this._link = aLink; - - this._render(); - this._addEventHandlers(); -} - -Site.prototype = { - /** - * The site's DOM node. - */ - get node() { return this._node; }, - - /** - * The site's link. - */ - get link() { return this._link; }, - - /** - * The url of the site's link. - */ - get url() { return this.link.url; }, - - /** - * The title of the site's link. - */ - get title() { return this.link.title; }, - - /** - * The site's parent cell. - */ - get cell() { - let parentNode = this.node.parentNode; - return parentNode && parentNode._newtabCell; - }, - - /** - * Pins the site on its current or a given index. - * @param aIndex The pinned index (optional). - */ - pin: function Site_pin(aIndex) { - if (typeof aIndex == "undefined") - aIndex = this.cell.index; - - this._updateAttributes(true); - gPinnedLinks.pin(this._link, aIndex); - }, - - /** - * Unpins the site and calls the given callback when done. - */ - unpin: function Site_unpin() { - if (this.isPinned()) { - this._updateAttributes(false); - gPinnedLinks.unpin(this._link); - gUpdater.updateGrid(); - } - }, - - /** - * Checks whether this site is pinned. - * @return Whether this site is pinned. - */ - isPinned: function Site_isPinned() { - return gPinnedLinks.isPinned(this._link); - }, - - /** - * Blocks the site (removes it from the grid) and calls the given callback - * when done. - */ - block: function Site_block() { - if (!gBlockedLinks.isBlocked(this._link)) { - gUndoDialog.show(this); - gBlockedLinks.block(this._link); - gUpdater.updateGrid(); - } - }, - - /** - * Gets the DOM node specified by the given query selector. - * @param aSelector The query selector. - * @return The DOM node we found. - */ - _querySelector: function Site_querySelector(aSelector) { - return this.node.querySelector(aSelector); - }, - - /** - * Updates attributes for all nodes which status depends on this site being - * pinned or unpinned. - * @param aPinned Whether this site is now pinned or unpinned. - */ - _updateAttributes: function (aPinned) { - let control = this._querySelector(".newtab-control-pin"); - - if (aPinned) { - control.setAttribute("pinned", true); - control.setAttribute("title", newTabString("unpin")); - } else { - control.removeAttribute("pinned"); - control.setAttribute("title", newTabString("pin")); - } - }, - - /** - * Renders the site's data (fills the HTML fragment). - */ - _render: function Site_render() { - let url = this.url; - let title = this.title || url; - let tooltip = (title == url ? title : title + "\n" + url); - - let link = this._querySelector(".newtab-link"); - link.setAttribute("title", tooltip); - link.setAttribute("href", url); - this._querySelector(".newtab-title").textContent = title; - - if (this.isPinned()) - this._updateAttributes(true); - - let thumbnailURL = PageThumbs.getThumbnailURL(this.url); - let thumbnail = this._querySelector(".newtab-thumbnail"); - thumbnail.style.backgroundImage = "url(" + thumbnailURL + ")"; - }, - - /** - * Adds event handlers for the site and its buttons. - */ - _addEventHandlers: function Site_addEventHandlers() { - // Register drag-and-drop event handlers. - this._node.addEventListener("dragstart", this, false); - this._node.addEventListener("dragend", this, false); - this._node.addEventListener("mouseover", this, false); - - let controls = this.node.querySelectorAll(".newtab-control"); - for (let i = 0; i < controls.length; i++) - controls[i].addEventListener("click", this, false); - }, - - /** - * Speculatively opens a connection to the current site. - */ - _speculativeConnect: function Site_speculativeConnect() { - let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect); - let uri = Services.io.newURI(this.url, null, null); - sc.speculativeConnect(uri, null); - }, - - /** - * Handles all site events. - */ - handleEvent: function Site_handleEvent(aEvent) { - switch (aEvent.type) { - case "click": - aEvent.preventDefault(); - if (aEvent.target.classList.contains("newtab-control-block")) - this.block(); - else if (this.isPinned()) - this.unpin(); - else - this.pin(); - break; - case "mouseover": - this._node.removeEventListener("mouseover", this, false); - this._speculativeConnect(); - break; - case "dragstart": - gDrag.start(this, aEvent); - break; - case "drag": - gDrag.drag(this, aEvent); - break; - case "dragend": - gDrag.end(this, aEvent); - break; - } - } -}; diff --git a/browser/base/content/newtab/transformations.js b/browser/base/content/newtab/transformations.js deleted file mode 100644 index 6d1554f5f..000000000 --- a/browser/base/content/newtab/transformations.js +++ /dev/null @@ -1,265 +0,0 @@ -#ifdef 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 - -/** - * This singleton allows to transform the grid by repositioning a site's node - * in the DOM and by showing or hiding the node. It additionally provides - * convenience methods to work with a site's DOM node. - */ -let gTransformation = { - /** - * Returns the width of the left and top border of a cell. We need to take it - * into account when measuring and comparing site and cell positions. - */ - get _cellBorderWidths() { - let cstyle = window.getComputedStyle(gGrid.cells[0].node, null); - let widths = { - left: parseInt(cstyle.getPropertyValue("border-left-width")), - top: parseInt(cstyle.getPropertyValue("border-top-width")) - }; - - // Cache this value, overwrite the getter. - Object.defineProperty(this, "_cellBorderWidths", - {value: widths, enumerable: true}); - - return widths; - }, - - /** - * Gets a DOM node's position. - * @param aNode The DOM node. - * @return A Rect instance with the position. - */ - getNodePosition: function Transformation_getNodePosition(aNode) { - let {left, top, width, height} = aNode.getBoundingClientRect(); - return new Rect(left + scrollX, top + scrollY, width, height); - }, - - /** - * Fades a given node from zero to full opacity. - * @param aNode The node to fade. - * @param aCallback The callback to call when finished. - */ - fadeNodeIn: function Transformation_fadeNodeIn(aNode, aCallback) { - this._setNodeOpacity(aNode, 1, function () { - // Clear the style property. - aNode.style.opacity = ""; - - if (aCallback) - aCallback(); - }); - }, - - /** - * Fades a given node from full to zero opacity. - * @param aNode The node to fade. - * @param aCallback The callback to call when finished. - */ - fadeNodeOut: function Transformation_fadeNodeOut(aNode, aCallback) { - this._setNodeOpacity(aNode, 0, aCallback); - }, - - /** - * Fades a given site from zero to full opacity. - * @param aSite The site to fade. - * @param aCallback The callback to call when finished. - */ - showSite: function Transformation_showSite(aSite, aCallback) { - this.fadeNodeIn(aSite.node, aCallback); - }, - - /** - * Fades a given site from full to zero opacity. - * @param aSite The site to fade. - * @param aCallback The callback to call when finished. - */ - hideSite: function Transformation_hideSite(aSite, aCallback) { - this.fadeNodeOut(aSite.node, aCallback); - }, - - /** - * Allows to set a site's position. - * @param aSite The site to re-position. - * @param aPosition The desired position for the given site. - */ - setSitePosition: function Transformation_setSitePosition(aSite, aPosition) { - let style = aSite.node.style; - let {top, left} = aPosition; - - style.top = top + "px"; - style.left = left + "px"; - }, - - /** - * Freezes a site in its current position by positioning it absolute. - * @param aSite The site to freeze. - */ - freezeSitePosition: function Transformation_freezeSitePosition(aSite) { - if (this._isFrozen(aSite)) - return; - - let style = aSite.node.style; - let comp = getComputedStyle(aSite.node, null); - style.width = comp.getPropertyValue("width") - style.height = comp.getPropertyValue("height"); - - aSite.node.setAttribute("frozen", "true"); - this.setSitePosition(aSite, this.getNodePosition(aSite.node)); - }, - - /** - * Unfreezes a site by removing its absolute positioning. - * @param aSite The site to unfreeze. - */ - unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) { - if (!this._isFrozen(aSite)) - return; - - let style = aSite.node.style; - style.left = style.top = style.width = style.height = ""; - aSite.node.removeAttribute("frozen"); - }, - - /** - * Slides the given site to the target node's position. - * @param aSite The site to move. - * @param aTarget The slide target. - * @param aOptions Set of options (see below). - * unfreeze - unfreeze the site after sliding - * callback - the callback to call when finished - */ - slideSiteTo: function Transformation_slideSiteTo(aSite, aTarget, aOptions) { - let currentPosition = this.getNodePosition(aSite.node); - let targetPosition = this.getNodePosition(aTarget.node) - let callback = aOptions && aOptions.callback; - - let self = this; - - function finish() { - if (aOptions && aOptions.unfreeze) - self.unfreezeSitePosition(aSite); - - if (callback) - callback(); - } - - // We need to take the width of a cell's border into account. - targetPosition.left += this._cellBorderWidths.left; - targetPosition.top += this._cellBorderWidths.top; - - // Nothing to do here if the positions already match. - if (currentPosition.left == targetPosition.left && - currentPosition.top == targetPosition.top) { - finish(); - } else { - this.setSitePosition(aSite, targetPosition); - this._whenTransitionEnded(aSite.node, finish); - } - }, - - /** - * Rearranges a given array of sites and moves them to their new positions or - * fades in/out new/removed sites. - * @param aSites An array of sites to rearrange. - * @param aOptions Set of options (see below). - * unfreeze - unfreeze the site after rearranging - * callback - the callback to call when finished - */ - rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) { - let batch = []; - let cells = gGrid.cells; - let callback = aOptions && aOptions.callback; - let unfreeze = aOptions && aOptions.unfreeze; - - aSites.forEach(function (aSite, aIndex) { - // Do not re-arrange empty cells or the dragged site. - if (!aSite || aSite == gDrag.draggedSite) - return; - - let deferred = Promise.defer(); - batch.push(deferred.promise); - let cb = function () deferred.resolve(); - - if (!cells[aIndex]) - // The site disappeared from the grid, hide it. - this.hideSite(aSite, cb); - else if (this._getNodeOpacity(aSite.node) != 1) - // The site disappeared before but is now back, show it. - this.showSite(aSite, cb); - else - // The site's position has changed, move it around. - this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: cb}); - }, this); - - let wait = Promise.promised(function () callback && callback()); - wait.apply(null, batch); - }, - - /** - * Listens for the 'transitionend' event on a given node and calls the given - * callback. - * @param aNode The node that is transitioned. - * @param aCallback The callback to call when finished. - */ - _whenTransitionEnded: - function Transformation_whenTransitionEnded(aNode, aCallback) { - - aNode.addEventListener("transitionend", function onEnd() { - aNode.removeEventListener("transitionend", onEnd, false); - aCallback(); - }, false); - }, - - /** - * Gets a given node's opacity value. - * @param aNode The node to get the opacity value from. - * @return The node's opacity value. - */ - _getNodeOpacity: function Transformation_getNodeOpacity(aNode) { - let cstyle = window.getComputedStyle(aNode, null); - return cstyle.getPropertyValue("opacity"); - }, - - /** - * Sets a given node's opacity. - * @param aNode The node to set the opacity value for. - * @param aOpacity The opacity value to set. - * @param aCallback The callback to call when finished. - */ - _setNodeOpacity: - function Transformation_setNodeOpacity(aNode, aOpacity, aCallback) { - - if (this._getNodeOpacity(aNode) == aOpacity) { - if (aCallback) - aCallback(); - } else { - if (aCallback) - this._whenTransitionEnded(aNode, aCallback); - - aNode.style.opacity = aOpacity; - } - }, - - /** - * Moves a site to the cell with the given index. - * @param aSite The site to move. - * @param aIndex The target cell's index. - * @param aOptions Options that are directly passed to slideSiteTo(). - */ - _moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) { - this.freezeSitePosition(aSite); - this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions); - }, - - /** - * Checks whether a site is currently frozen. - * @param aSite The site to check. - * @return Whether the given site is frozen. - */ - _isFrozen: function Transformation_isFrozen(aSite) { - return aSite.node.hasAttribute("frozen"); - } -}; diff --git a/browser/base/content/newtab/undo.js b/browser/base/content/newtab/undo.js deleted file mode 100644 index 5f619e980..000000000 --- a/browser/base/content/newtab/undo.js +++ /dev/null @@ -1,116 +0,0 @@ -#ifdef 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 - -/** - * Dialog allowing to undo the removal of single site or to completely restore - * the grid's original state. - */ -let gUndoDialog = { - /** - * The undo dialog's timeout in miliseconds. - */ - HIDE_TIMEOUT_MS: 15000, - - /** - * Contains undo information. - */ - _undoData: null, - - /** - * Initializes the undo dialog. - */ - init: function UndoDialog_init() { - this._undoContainer = document.getElementById("newtab-undo-container"); - this._undoContainer.addEventListener("click", this, false); - this._undoButton = document.getElementById("newtab-undo-button"); - this._undoCloseButton = document.getElementById("newtab-undo-close-button"); - this._undoRestoreButton = document.getElementById("newtab-undo-restore-button"); - }, - - /** - * Shows the undo dialog. - * @param aSite The site that just got removed. - */ - show: function UndoDialog_show(aSite) { - if (this._undoData) - clearTimeout(this._undoData.timeout); - - this._undoData = { - index: aSite.cell.index, - wasPinned: aSite.isPinned(), - blockedLink: aSite.link, - timeout: setTimeout(this.hide.bind(this), this.HIDE_TIMEOUT_MS) - }; - - this._undoContainer.removeAttribute("undo-disabled"); - this._undoButton.removeAttribute("tabindex"); - this._undoCloseButton.removeAttribute("tabindex"); - this._undoRestoreButton.removeAttribute("tabindex"); - }, - - /** - * Hides the undo dialog. - */ - hide: function UndoDialog_hide() { - if (!this._undoData) - return; - - clearTimeout(this._undoData.timeout); - this._undoData = null; - this._undoContainer.setAttribute("undo-disabled", "true"); - this._undoButton.setAttribute("tabindex", "-1"); - this._undoCloseButton.setAttribute("tabindex", "-1"); - this._undoRestoreButton.setAttribute("tabindex", "-1"); - }, - - /** - * The undo dialog event handler. - * @param aEvent The event to handle. - */ - handleEvent: function UndoDialog_handleEvent(aEvent) { - switch (aEvent.target.id) { - case "newtab-undo-button": - this._undo(); - break; - case "newtab-undo-restore-button": - this._undoAll(); - break; - case "newtab-undo-close-button": - this.hide(); - break; - } - }, - - /** - * Undo the last blocked site. - */ - _undo: function UndoDialog_undo() { - if (!this._undoData) - return; - - let {index, wasPinned, blockedLink} = this._undoData; - gBlockedLinks.unblock(blockedLink); - - if (wasPinned) { - gPinnedLinks.pin(blockedLink, index); - } - - gUpdater.updateGrid(); - this.hide(); - }, - - /** - * Undo all blocked sites. - */ - _undoAll: function UndoDialog_undoAll() { - NewTabUtils.undoAll(function() { - gUpdater.updateGrid(); - this.hide(); - }.bind(this)); - } -}; - -gUndoDialog.init(); diff --git a/browser/base/content/newtab/updater.js b/browser/base/content/newtab/updater.js deleted file mode 100644 index 7b483e037..000000000 --- a/browser/base/content/newtab/updater.js +++ /dev/null @@ -1,186 +0,0 @@ -#ifdef 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 - -/** - * This singleton provides functionality to update the current grid to a new - * set of pinned and blocked sites. It adds, moves and removes sites. - */ -let gUpdater = { - /** - * Updates the current grid according to its pinned and blocked sites. - * This removes old, moves existing and creates new sites to fill gaps. - * @param aCallback The callback to call when finished. - */ - updateGrid: function Updater_updateGrid(aCallback) { - let links = gLinks.getLinks().slice(0, gGrid.cells.length); - - // Find all sites that remain in the grid. - let sites = this._findRemainingSites(links); - - let self = this; - - // Remove sites that are no longer in the grid. - this._removeLegacySites(sites, function () { - // Freeze all site positions so that we can move their DOM nodes around - // without any visual impact. - self._freezeSitePositions(sites); - - // Move the sites' DOM nodes to their new position in the DOM. This will - // have no visual effect as all the sites have been frozen and will - // remain in their current position. - self._moveSiteNodes(sites); - - // Now it's time to animate the sites actually moving to their new - // positions. - self._rearrangeSites(sites, function () { - // Try to fill empty cells and finish. - self._fillEmptyCells(links, aCallback); - - // Update other pages that might be open to keep them synced. - gAllPages.update(gPage); - }); - }); - }, - - /** - * Takes an array of links and tries to correlate them to sites contained in - * the current grid. If no corresponding site can be found (i.e. the link is - * new and a site will be created) then just set it to null. - * @param aLinks The array of links to find sites for. - * @return Array of sites mapped to the given links (can contain null values). - */ - _findRemainingSites: function Updater_findRemainingSites(aLinks) { - let map = {}; - - // Create a map to easily retrieve the site for a given URL. - gGrid.sites.forEach(function (aSite) { - if (aSite) - map[aSite.url] = aSite; - }); - - // Map each link to its corresponding site, if any. - return aLinks.map(function (aLink) { - return aLink && (aLink.url in map) && map[aLink.url]; - }); - }, - - /** - * Freezes the given sites' positions. - * @param aSites The array of sites to freeze. - */ - _freezeSitePositions: function Updater_freezeSitePositions(aSites) { - aSites.forEach(function (aSite) { - if (aSite) - gTransformation.freezeSitePosition(aSite); - }); - }, - - /** - * Moves the given sites' DOM nodes to their new positions. - * @param aSites The array of sites to move. - */ - _moveSiteNodes: function Updater_moveSiteNodes(aSites) { - let cells = gGrid.cells; - - // Truncate the given array of sites to not have more sites than cells. - // This can happen when the user drags a bookmark (or any other new kind - // of link) onto the grid. - let sites = aSites.slice(0, cells.length); - - sites.forEach(function (aSite, aIndex) { - let cell = cells[aIndex]; - let cellSite = cell.site; - - // The site's position didn't change. - if (!aSite || cellSite != aSite) { - let cellNode = cell.node; - - // Empty the cell if necessary. - if (cellSite) - cellNode.removeChild(cellSite.node); - - // Put the new site in place, if any. - if (aSite) - cellNode.appendChild(aSite.node); - } - }, this); - }, - - /** - * Rearranges the given sites and slides them to their new positions. - * @param aSites The array of sites to re-arrange. - * @param aCallback The callback to call when finished. - */ - _rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) { - let options = {callback: aCallback, unfreeze: true}; - gTransformation.rearrangeSites(aSites, options); - }, - - /** - * Removes all sites from the grid that are not in the given links array or - * exceed the grid. - * @param aSites The array of sites remaining in the grid. - * @param aCallback The callback to call when finished. - */ - _removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) { - let batch = []; - - // Delete sites that were removed from the grid. - gGrid.sites.forEach(function (aSite) { - // The site must be valid and not in the current grid. - if (!aSite || aSites.indexOf(aSite) != -1) - return; - - let deferred = Promise.defer(); - batch.push(deferred.promise); - - // Fade out the to-be-removed site. - gTransformation.hideSite(aSite, function () { - let node = aSite.node; - - // Remove the site from the DOM. - node.parentNode.removeChild(node); - deferred.resolve(); - }); - }); - - let wait = Promise.promised(aCallback); - wait.apply(null, batch); - }, - - /** - * Tries to fill empty cells with new links if available. - * @param aLinks The array of links. - * @param aCallback The callback to call when finished. - */ - _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) { - let {cells, sites} = gGrid; - let batch = []; - - // Find empty cells and fill them. - sites.forEach(function (aSite, aIndex) { - if (aSite || !aLinks[aIndex]) - return; - - let deferred = Promise.defer(); - batch.push(deferred.promise); - - // Create the new site and fade it in. - let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]); - - // Set the site's initial opacity to zero. - site.node.style.opacity = 0; - - // Flush all style changes for the dynamically inserted site to make - // the fade-in transition work. - window.getComputedStyle(site.node).opacity; - gTransformation.showSite(site, function () deferred.resolve()); - }); - - let wait = Promise.promised(aCallback); - wait.apply(null, batch); - } -}; diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js deleted file mode 100644 index 8e6bc96c2..000000000 --- a/browser/base/content/nsContextMenu.js +++ /dev/null @@ -1,1588 +0,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/. - -Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); - -function nsContextMenu(aXulMenu, aIsShift) { - this.shouldDisplay = true; - this.initMenu(aXulMenu, aIsShift); -} - -// Prototype for nsContextMenu "class." -nsContextMenu.prototype = { - initMenu: function CM_initMenu(aXulMenu, aIsShift) { - // Get contextual info. - this.setTarget(document.popupNode, document.popupRangeParent, - document.popupRangeOffset); - if (!this.shouldDisplay) - return; - - this.hasPageMenu = false; - if (!aIsShift) { - this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(this.target, - aXulMenu); - } - - this.isFrameImage = document.getElementById("isFrameImage"); - this.ellipsis = "\u2026"; - try { - this.ellipsis = gPrefService.getComplexValue("intl.ellipsis", - Ci.nsIPrefLocalizedString).data; - } catch (e) { } - - this.isContentSelected = this.isContentSelection(); - this.onPlainTextLink = false; - - // Initialize (disable/remove) menu items. - this.initItems(); - }, - - hiding: function CM_hiding() { - InlineSpellCheckerUI.clearSuggestionsFromMenu(); - InlineSpellCheckerUI.clearDictionaryListFromMenu(); - InlineSpellCheckerUI.uninit(); - }, - - initItems: function CM_initItems() { - this.initPageMenuSeparator(); - this.initOpenItems(); - this.initNavigationItems(); - this.initViewItems(); - this.initMiscItems(); - this.initSpellingItems(); - this.initSaveItems(); - this.initClipboardItems(); - this.initMediaPlayerItems(); - this.initLeaveDOMFullScreenItems(); - this.initClickToPlayItems(); - }, - - initPageMenuSeparator: function CM_initPageMenuSeparator() { - this.showItem("page-menu-separator", this.hasPageMenu); - }, - - initOpenItems: function CM_initOpenItems() { - var isMailtoInternal = false; - if (this.onMailtoLink) { - var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"]. - getService(Ci.nsIExternalProtocolService). - getProtocolHandlerInfo("mailto"); - isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling && - mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp && - (mailtoHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp)); - } - - // Time to do some bad things and see if we've highlighted a URL that - // isn't actually linked. - if (this.isTextSelected && !this.onLink) { - // Ok, we have some text, let's figure out if it looks like a URL. - let selection = document.commandDispatcher.focusedWindow - .getSelection(); - let linkText = selection.toString().trim(); - let uri; - if (/^(?:https?|ftp):/i.test(linkText)) { - try { - uri = makeURI(linkText); - } catch (ex) {} - } - // Check if this could be a valid url, just missing the protocol. - else if (/^[-a-z\d\.]+\.[-a-z\d]{2,}[-_=~:#%&\?\w\/\.]*$/i.test(linkText)) { - let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"] - .getService(Ci.nsIURIFixup); - try { - uri = uriFixup.createFixupURI(linkText, uriFixup.FIXUP_FLAG_NONE); - } catch (ex) {} - } - - if (uri && uri.host) { - this.linkURI = uri; - this.linkURL = this.linkURI.spec; - this.onPlainTextLink = true; - } - } - - var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink; - var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window); - this.showItem("context-openlink", shouldShow && !isWindowPrivate); - this.showItem("context-openlinkprivate", shouldShow); - this.showItem("context-openlinkintab", shouldShow); - this.showItem("context-openlinkincurrent", shouldShow); - this.showItem("context-sep-open", shouldShow); - }, - - initNavigationItems: function CM_initNavigationItems() { - var shouldShow = !(this.isContentSelected || this.onLink || this.onImage || - this.onCanvas || this.onVideo || this.onAudio || - this.onTextInput); - this.showItem("context-back", shouldShow); - this.showItem("context-forward", shouldShow); - - let stopped = XULBrowserWindow.stopCommand.getAttribute("disabled") == "true"; - - let stopReloadItem = ""; - if (shouldShow) { - stopReloadItem = stopped ? "reload" : "stop"; - } - - this.showItem("context-reload", stopReloadItem == "reload"); - this.showItem("context-stop", stopReloadItem == "stop"); - this.showItem("context-sep-stop", !!stopReloadItem); - - // XXX: Stop is determined in browser.js; the canStop broadcaster is broken - //this.setItemAttrFromNode( "context-stop", "disabled", "canStop" ); - }, - - initLeaveDOMFullScreenItems: function CM_initLeaveFullScreenItem() { - // only show the option if the user is in DOM fullscreen - var shouldShow = (this.target.ownerDocument.mozFullScreenElement != null); - this.showItem("context-leave-dom-fullscreen", shouldShow); - - // Explicitly show if in DOM fullscreen, but do not hide it has already been shown - if (shouldShow) - this.showItem("context-media-sep-commands", true); - }, - - initSaveItems: function CM_initSaveItems() { - var shouldShow = !(this.onTextInput || this.onLink || - this.isContentSelected || this.onImage || - this.onCanvas || this.onVideo || this.onAudio); - this.showItem("context-savepage", shouldShow); - this.showItem("context-sendpage", shouldShow); - - // Save+Send link depends on whether we're in a link, or selected text matches valid URL pattern. - this.showItem("context-savelink", this.onSaveableLink || this.onPlainTextLink); - this.showItem("context-sendlink", this.onSaveableLink || this.onPlainTextLink); - - // Save image depends on having loaded its content, video and audio don't. - this.showItem("context-saveimage", this.onLoadedImage || this.onCanvas); - this.showItem("context-savevideo", this.onVideo); - this.showItem("context-saveaudio", this.onAudio); - this.showItem("context-video-saveimage", this.onVideo); - this.setItemAttr("context-savevideo", "disabled", !this.mediaURL); - this.setItemAttr("context-saveaudio", "disabled", !this.mediaURL); - // Send media URL (but not for canvas, since it's a big data: URL) - this.showItem("context-sendimage", this.onImage); - this.showItem("context-sendvideo", this.onVideo); - this.showItem("context-sendaudio", this.onAudio); - this.setItemAttr("context-sendvideo", "disabled", !this.mediaURL); - this.setItemAttr("context-sendaudio", "disabled", !this.mediaURL); - }, - - initViewItems: function CM_initViewItems() { - // View source is always OK, unless in directory listing. - this.showItem("context-viewpartialsource-selection", - this.isContentSelected); - this.showItem("context-viewpartialsource-mathml", - this.onMathML && !this.isContentSelected); - - var shouldShow = !(this.isContentSelected || - this.onImage || this.onCanvas || - this.onVideo || this.onAudio || - this.onLink || this.onTextInput); - this.showItem("context-viewsource", shouldShow); - this.showItem("context-viewinfo", shouldShow); -#ifdef MOZ_DEVTOOLS - var showInspect = gPrefService.getBoolPref("devtools.inspector.enabled"); - this.showItem("inspect-separator", showInspect); - this.showItem("context-inspect", showInspect); -#endif - - this.showItem("context-sep-viewsource", shouldShow); - - // Set as Desktop background depends on whether an image was clicked on, - // and only works if we have a shell service. - var haveSetDesktopBackground = false; -#ifdef HAVE_SHELL_SERVICE - // Only enable Set as Desktop Background if we can get the shell service. - var shell = getShellService(); - if (shell) - haveSetDesktopBackground = shell.canSetDesktopBackground; -#endif - this.showItem("context-setDesktopBackground", - haveSetDesktopBackground && this.onLoadedImage); - - if (haveSetDesktopBackground && this.onLoadedImage) { - document.getElementById("context-setDesktopBackground") - .disabled = this.disableSetDesktopBackground(); - } - - // Reload image depends on an image that's not fully loaded - this.showItem("context-reloadimage", (this.onImage && !this.onCompletedImage)); - - // View image depends on having an image that's not standalone - // (or is in a frame), or a canvas. - this.showItem("context-viewimage", (this.onImage && - (!this.inSyntheticDoc || this.inFrame)) || this.onCanvas); - - // View video depends on not having a standalone video. - this.showItem("context-viewvideo", this.onVideo && (!this.inSyntheticDoc || this.inFrame)); - this.setItemAttr("context-viewvideo", "disabled", !this.mediaURL); - - // View background image depends on whether there is one, but don't make - // background images of a stand-alone media document available. - this.showItem("context-viewbgimage", shouldShow && - !this._hasMultipleBGImages && - !this.inSyntheticDoc); - this.showItem("context-sep-viewbgimage", shouldShow && - !this._hasMultipleBGImages && - !this.inSyntheticDoc); - document.getElementById("context-viewbgimage") - .disabled = !this.hasBGImage; - - this.showItem("context-viewimageinfo", this.onImage); - }, - - initMiscItems: function CM_initMiscItems() { - // Use "Bookmark This Link" if on a link. - this.showItem("context-bookmarkpage", - !(this.isContentSelected || this.onTextInput || this.onLink || - this.onImage || this.onVideo || this.onAudio)); - this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink) || - this.onPlainTextLink); - this.showItem("context-keywordfield", - this.onTextInput && this.onKeywordField); - this.showItem("frame", this.inFrame); - - let showSearchSelect = (this.isTextSelected || this.onLink) && !this.onImage; - this.showItem("context-searchselect", showSearchSelect); - if (showSearchSelect) { - this.formatSearchContextItem(); - } - - // srcdoc cannot be opened separately due to concerns about web - // content with about:srcdoc in location bar masquerading as trusted - // chrome/addon content. - // No need to also test for this.inFrame as this is checked in the parent - // submenu. - this.showItem("context-showonlythisframe", !this.inSrcdocFrame); - this.showItem("context-openframeintab", !this.inSrcdocFrame); - this.showItem("context-openframe", !this.inSrcdocFrame); - this.showItem("context-bookmarkframe", !this.inSrcdocFrame); - this.showItem("open-frame-sep", !this.inSrcdocFrame); - - this.showItem("frame-sep", this.inFrame && this.isTextSelected); - - // Hide menu entries for images, show otherwise - if (this.inFrame) { - if (mimeTypeIsTextBased(this.target.ownerDocument.contentType)) - this.isFrameImage.removeAttribute('hidden'); - else - this.isFrameImage.setAttribute('hidden', 'true'); - } - - // BiDi UI - this.showItem("context-sep-bidi", top.gBidiUI); - this.showItem("context-bidi-text-direction-toggle", - this.onTextInput && top.gBidiUI); - this.showItem("context-bidi-page-direction-toggle", - !this.onTextInput && top.gBidiUI); - }, - - initSpellingItems: function() { - var canSpell = InlineSpellCheckerUI.canSpellCheck && this.canSpellCheck; - var onMisspelling = InlineSpellCheckerUI.overMisspelling; - var showUndo = canSpell && InlineSpellCheckerUI.canUndo(); - this.showItem("spell-check-enabled", canSpell); - this.showItem("spell-separator", canSpell || this.onEditableArea); - document.getElementById("spell-check-enabled") - .setAttribute("checked", canSpell && InlineSpellCheckerUI.enabled); - - this.showItem("spell-add-to-dictionary", onMisspelling); - this.showItem("spell-undo-add-to-dictionary", showUndo); - - // suggestion list - this.showItem("spell-suggestions-separator", onMisspelling || showUndo); - if (onMisspelling) { - var suggestionsSeparator = - document.getElementById("spell-add-to-dictionary"); - var numsug = - InlineSpellCheckerUI.addSuggestionsToMenu(suggestionsSeparator.parentNode, - suggestionsSeparator, 5); - this.showItem("spell-no-suggestions", numsug == 0); - } - else - this.showItem("spell-no-suggestions", false); - - // dictionary list - this.showItem("spell-dictionaries", canSpell && InlineSpellCheckerUI.enabled); - if (canSpell) { - var dictMenu = document.getElementById("spell-dictionaries-menu"); - var dictSep = document.getElementById("spell-language-separator"); - InlineSpellCheckerUI.addDictionaryListToMenu(dictMenu, dictSep); - this.showItem("spell-add-dictionaries-main", false); - } - else if (this.onEditableArea) { - // when there is no spellchecker but we might be able to spellcheck - // add the add to dictionaries item. This will ensure that people - // with no dictionaries will be able to download them - this.showItem("spell-add-dictionaries-main", true); - } - else - this.showItem("spell-add-dictionaries-main", false); - }, - - initClipboardItems: function() { - // Copy depends on whether there is selected text. - // Enabling this context menu item is now done through the global - // command updating system - // this.setItemAttr( "context-copy", "disabled", !this.isTextSelected() ); - goUpdateGlobalEditMenuItems(); - - this.showItem("context-undo", this.onTextInput); - this.showItem("context-sep-undo", this.onTextInput); - this.showItem("context-cut", this.onTextInput); - this.showItem("context-copy", - this.isContentSelected || this.onTextInput); - this.showItem("context-paste", this.onTextInput); - this.showItem("context-delete", this.onTextInput); - this.showItem("context-sep-paste", this.onTextInput); - this.showItem("context-selectall", !(this.onLink || this.onImage || - this.onVideo || this.onAudio || - this.inSyntheticDoc) || - this.isDesignMode); - this.showItem("context-sep-selectall", this.isContentSelected ); - - // XXX dr - // ------ - // nsDocumentViewer.cpp has code to determine whether we're - // on a link or an image. we really ought to be using that... - - // Copy email link depends on whether we're on an email link. - this.showItem("context-copyemail", this.onMailtoLink); - - // Copy link location depends on whether we're on a non-mailto link. - this.showItem("context-copylink", this.onLink && !this.onMailtoLink); - this.showItem("context-sep-copylink", this.onLink && - (this.onImage || this.onVideo || this.onAudio)); - -#ifdef CONTEXT_COPY_IMAGE_CONTENTS - // Copy image contents depends on whether we're on an image. - this.showItem("context-copyimage-contents", this.onImage); -#endif - // Copy image location depends on whether we're on an image. - this.showItem("context-copyimage", this.onImage); - this.showItem("context-copyvideourl", this.onVideo); - this.showItem("context-copyaudiourl", this.onAudio); - this.setItemAttr("context-copyvideourl", "disabled", !this.mediaURL); - this.setItemAttr("context-copyaudiourl", "disabled", !this.mediaURL); - this.showItem("context-sep-copyimage", this.onImage || - this.onVideo || this.onAudio); - }, - - initMediaPlayerItems: function() { - var onMedia = (this.onVideo || this.onAudio); - // Several mutually exclusive items... play/pause, mute/unmute, show/hide - this.showItem("context-media-play", onMedia && (this.target.paused || this.target.ended)); - this.showItem("context-media-pause", onMedia && !this.target.paused && !this.target.ended); - this.showItem("context-media-mute", onMedia && !this.target.muted); - this.showItem("context-media-unmute", onMedia && this.target.muted); - this.showItem("context-media-playbackrate", onMedia); - this.showItem("context-media-showcontrols", onMedia && !this.target.controls); - this.showItem("context-media-hidecontrols", onMedia && this.target.controls); - this.showItem("context-video-fullscreen", this.onVideo && this.target.ownerDocument.mozFullScreenElement == null); - var statsShowing = this.onVideo && XPCNativeWrapper.unwrap(this.target).mozMediaStatisticsShowing; - this.showItem("context-video-showstats", this.onVideo && this.target.controls && !statsShowing); - this.showItem("context-video-hidestats", this.onVideo && this.target.controls && statsShowing); - - // Disable them when there isn't a valid media source loaded. - if (onMedia) { - this.setItemAttr("context-media-playbackrate-050x", "checked", this.target.playbackRate == 0.5); - this.setItemAttr("context-media-playbackrate-100x", "checked", this.target.playbackRate == 1.0); - this.setItemAttr("context-media-playbackrate-150x", "checked", this.target.playbackRate == 1.5); - this.setItemAttr("context-media-playbackrate-200x", "checked", this.target.playbackRate == 2.0); - var hasError = this.target.error != null || - this.target.networkState == this.target.NETWORK_NO_SOURCE; - this.setItemAttr("context-media-play", "disabled", hasError); - this.setItemAttr("context-media-pause", "disabled", hasError); - this.setItemAttr("context-media-mute", "disabled", hasError); - this.setItemAttr("context-media-unmute", "disabled", hasError); - this.setItemAttr("context-media-playbackrate", "disabled", hasError); - this.setItemAttr("context-media-playbackrate-050x", "disabled", hasError); - this.setItemAttr("context-media-playbackrate-100x", "disabled", hasError); - this.setItemAttr("context-media-playbackrate-150x", "disabled", hasError); - this.setItemAttr("context-media-playbackrate-200x", "disabled", hasError); - this.setItemAttr("context-media-showcontrols", "disabled", hasError); - this.setItemAttr("context-media-hidecontrols", "disabled", hasError); - if (this.onVideo) { - let canSaveSnapshot = this.target.readyState >= this.target.HAVE_CURRENT_DATA; - this.setItemAttr("context-video-saveimage", "disabled", !canSaveSnapshot); - this.setItemAttr("context-video-fullscreen", "disabled", hasError); - this.setItemAttr("context-video-showstats", "disabled", hasError); - this.setItemAttr("context-video-hidestats", "disabled", hasError); - } - } - this.showItem("context-media-sep-commands", onMedia); - }, - - initClickToPlayItems: function() { - this.showItem("context-ctp-play", this.onCTPPlugin); - this.showItem("context-ctp-hide", this.onCTPPlugin); - this.showItem("context-sep-ctp", this.onCTPPlugin); - }, - - inspectNode: function CM_inspectNode() { - let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); - let gBrowser = this.browser.ownerDocument.defaultView.gBrowser; - let tt = devtools.TargetFactory.forTab(gBrowser.selectedTab); - return gDevTools.showToolbox(tt, "inspector").then(function(toolbox) { - let inspector = toolbox.getCurrentPanel(); - inspector.selection.setNode(this.target, "browser-context-menu"); - }.bind(this)); - }, - - // Set various context menu attributes based on the state of the world. - setTarget: function (aNode, aRangeParent, aRangeOffset) { - const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - if (aNode.namespaceURI == xulNS || - aNode.nodeType == Node.DOCUMENT_NODE || - this.isDisabledForEvents(aNode)) { - this.shouldDisplay = false; - return; - } - - // Initialize contextual info. - this.onImage = false; - this.onLoadedImage = false; - this.onCompletedImage = false; - this.onCanvas = false; - this.onVideo = false; - this.onAudio = false; - this.onTextInput = false; - this.onKeywordField = false; - this.mediaURL = ""; - this.onLink = false; - this.onMailtoLink = false; - this.onSaveableLink = false; - this.link = null; - this.linkURL = ""; - this.linkURI = null; - this.linkProtocol = ""; - this.linkDownload = ""; - this.onMathML = false; - this.inFrame = false; - this.inSrcdocFrame = false; - this.inSyntheticDoc = false; - this.hasBGImage = false; - this.bgImageURL = ""; - this.onEditableArea = false; - this.isDesignMode = false; - this.onCTPPlugin = false; - this.canSpellCheck = false; - this.textSelected = getBrowserSelection(); - this.isTextSelected = this.textSelected.length != 0; - - // Remember the node that was clicked. - this.target = aNode; - - this.browser = this.target.ownerDocument.defaultView - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler; - - // Check if we are in a synthetic document (stand alone image, video, etc.). - this.inSyntheticDoc = this.target.ownerDocument.mozSyntheticDocument; - // First, do checks for nodes that never have children. - if (this.target.nodeType == Node.ELEMENT_NODE) { - // See if the user clicked on an image. - if (this.target instanceof Ci.nsIImageLoadingContent && - this.target.currentURI) { - this.onImage = true; - - var request = - this.target.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); - if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE)) - this.onLoadedImage = true; - if (request && (request.imageStatus & request.STATUS_LOAD_COMPLETE)) - this.onCompletedImage = true; - - this.mediaURL = this.target.currentURI.spec; - } - else if (this.target instanceof HTMLCanvasElement) { - this.onCanvas = true; - } - else if (this.target instanceof HTMLVideoElement) { - this.mediaURL = this.target.currentSrc || this.target.src; - // Firefox always creates a HTMLVideoElement when loading an ogg file - // directly. If the media is actually audio, be smarter and provide a - // context menu with audio operations. - if (this.target.readyState >= this.target.HAVE_METADATA && - (this.target.videoWidth == 0 || this.target.videoHeight == 0)) { - this.onAudio = true; - } else { - this.onVideo = true; - } - } - else if (this.target instanceof HTMLAudioElement) { - this.onAudio = true; - this.mediaURL = this.target.currentSrc || this.target.src; - } - else if (this.target instanceof HTMLInputElement ) { - this.onTextInput = this.isTargetATextBox(this.target); - // Allow spellchecking UI on all text and search inputs. - if (this.onTextInput && ! this.target.readOnly && - (this.target.type == "text" || this.target.type == "search")) { - this.onEditableArea = true; - InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor); - InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset); - } - this.onKeywordField = this.isTargetAKeywordField(this.target); - } - else if (this.target instanceof HTMLTextAreaElement) { - this.onTextInput = true; - if (!this.target.readOnly) { - this.onEditableArea = true; - InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor); - InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset); - } - } - else if (this.target instanceof HTMLHtmlElement) { - var bodyElt = this.target.ownerDocument.body; - if (bodyElt) { - let computedURL; - try { - computedURL = this.getComputedURL(bodyElt, "background-image"); - this._hasMultipleBGImages = false; - } catch (e) { - this._hasMultipleBGImages = true; - } - if (computedURL) { - this.hasBGImage = true; - this.bgImageURL = makeURLAbsolute(bodyElt.baseURI, - computedURL); - } - } - } - else if ((this.target instanceof HTMLEmbedElement || - this.target instanceof HTMLObjectElement || - this.target instanceof HTMLAppletElement) && - this.target.displayedType == HTMLObjectElement.TYPE_NULL && - this.target.pluginFallbackType == HTMLObjectElement.PLUGIN_CLICK_TO_PLAY) { - this.onCTPPlugin = true; - } - - this.canSpellCheck = this._isSpellCheckEnabled(this.target); - } - else if (this.target.nodeType == Node.TEXT_NODE) { - // For text nodes, look at the parent node to determine the spellcheck attribute. - this.canSpellCheck = this.target.parentNode && - this._isSpellCheckEnabled(this.target); - } - - // Second, bubble out, looking for items of interest that can have childen. - // Always pick the innermost link, background image, etc. - const XMLNS = "http://www.w3.org/XML/1998/namespace"; - var elem = this.target; - while (elem) { - if (elem.nodeType == Node.ELEMENT_NODE) { - // Link? - if (!this.onLink && - // Be consistent with what hrefAndLinkNodeForClickEvent - // does in browser.js - ((elem instanceof HTMLAnchorElement && elem.href) || - (elem instanceof HTMLAreaElement && elem.href) || - elem instanceof HTMLLinkElement || - elem.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple")) { - - // Target is a link or a descendant of a link. - this.onLink = true; - - // Remember corresponding element. - this.link = elem; - this.linkURL = this.getLinkURL(); - this.linkURI = this.getLinkURI(); - this.linkProtocol = this.getLinkProtocol(); - this.onMailtoLink = (this.linkProtocol == "mailto"); - this.onSaveableLink = this.isLinkSaveable( this.link ); - try { - if (elem.download) { - // Ignore download attribute on cross-origin links? - // This shoudn't be an issue because the download link presents - // the originating URL domain and protocol to help user understand - // from where file is downloaded and make right decision. - // If we decide we want this restriction: - // this.principal.checkMayLoad(this.linkURI, false, true); - this.linkDownload = elem.download; - } - } - catch (ex) {} - } - - // Background image? Don't bother if we've already found a - // background image further down the hierarchy. Otherwise, - // we look for the computed background-image style. - if (!this.hasBGImage && - !this._hasMultipleBGImages) { - let bgImgUrl; - try { - bgImgUrl = this.getComputedURL(elem, "background-image"); - this._hasMultipleBGImages = false; - } catch (e) { - this._hasMultipleBGImages = true; - } - if (bgImgUrl) { - this.hasBGImage = true; - this.bgImageURL = makeURLAbsolute(elem.baseURI, - bgImgUrl); - } - } - } - - elem = elem.parentNode; - } - - // See if the user clicked on MathML - const NS_MathML = "http://www.w3.org/1998/Math/MathML"; - if ((this.target.nodeType == Node.TEXT_NODE && - this.target.parentNode.namespaceURI == NS_MathML) - || (this.target.namespaceURI == NS_MathML)) - this.onMathML = true; - - // See if the user clicked in a frame. - var docDefaultView = this.target.ownerDocument.defaultView; - if (docDefaultView != docDefaultView.top) { - this.inFrame = true; - - if (this.target.ownerDocument.isSrcdocDocument) { - this.inSrcdocFrame = true; - } - } - - // if the document is editable, show context menu like in text inputs - if (!this.onEditableArea) { - var win = this.target.ownerDocument.defaultView; - if (win) { - var isEditable = false; - try { - var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIEditingSession); - if (editingSession.windowIsEditable(win) && - this.getComputedStyle(this.target, "-moz-user-modify") == "read-write") { - isEditable = true; - } - } - catch(ex) { - // If someone built with composer disabled, we can't get an editing session. - } - - if (isEditable) { - this.onTextInput = true; - this.onKeywordField = false; - this.onImage = false; - this.onLoadedImage = false; - this.onCompletedImage = false; - this.onMathML = false; - this.inFrame = false; - this.inSrcdocFrame = false; - this.hasBGImage = false; - this.isDesignMode = true; - this.onEditableArea = true; - InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win)); - var canSpell = InlineSpellCheckerUI.canSpellCheck && this.canSpellCheck; - InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset); - this.showItem("spell-check-enabled", canSpell); - this.showItem("spell-separator", canSpell); - } - } - } - }, - - // Returns the computed style attribute for the given element. - getComputedStyle: function(aElem, aProp) { - return aElem.ownerDocument - .defaultView - .getComputedStyle(aElem, "").getPropertyValue(aProp); - }, - - // Returns a "url"-type computed style attribute value, with the url() stripped. - getComputedURL: function(aElem, aProp) { - var url = aElem.ownerDocument - .defaultView.getComputedStyle(aElem, "") - .getPropertyCSSValue(aProp); - if (url instanceof CSSValueList) { - if (url.length != 1) - throw "found multiple URLs"; - url = url[0]; - } - return url.primitiveType == CSSPrimitiveValue.CSS_URI ? - url.getStringValue() : null; - }, - - // Returns true if clicked-on link targets a resource that can be saved. - isLinkSaveable: function(aLink) { - // We don't do the Right Thing for news/snews yet, so turn them off - // until we do. - return this.linkProtocol && !( - this.linkProtocol == "mailto" || - this.linkProtocol == "javascript" || - this.linkProtocol == "news" || - this.linkProtocol == "snews" ); - }, - - _isSpellCheckEnabled: function(aNode) { - // We can always force-enable spellchecking on textboxes - if (this.isTargetATextBox(aNode)) { - return true; - } - // We can never spell check something which is not content editable - var editable = aNode.isContentEditable; - if (!editable && aNode.ownerDocument) { - editable = aNode.ownerDocument.designMode == "on"; - } - if (!editable) { - return false; - } - // Otherwise make sure that nothing in the parent chain disables spellchecking - return aNode.spellcheck; - }, - - // Open linked-to URL in a new window. - openLink : function () { - var doc = this.target.ownerDocument; - urlSecurityCheck(this.linkURL, doc.nodePrincipal); - openLinkIn(this.linkURL, "window", - { charset: doc.characterSet, - referrerURI: doc.documentURIObject }); - }, - - // Open linked-to URL in a new private window. - openLinkInPrivateWindow : function () { - var doc = this.target.ownerDocument; - urlSecurityCheck(this.linkURL, doc.nodePrincipal); - openLinkIn(this.linkURL, "window", - { charset: doc.characterSet, - referrerURI: doc.documentURIObject, - private: true }); - }, - - // Open linked-to URL in a new tab. - openLinkInTab: function() { - var doc = this.target.ownerDocument; - urlSecurityCheck(this.linkURL, doc.nodePrincipal); - openLinkIn(this.linkURL, "tab", - { charset: doc.characterSet, - referrerURI: doc.documentURIObject }); - }, - - // open URL in current tab - openLinkInCurrent: function() { - var doc = this.target.ownerDocument; - urlSecurityCheck(this.linkURL, doc.nodePrincipal); - openLinkIn(this.linkURL, "current", - { charset: doc.characterSet, - referrerURI: doc.documentURIObject }); - }, - - // Open frame in a new tab. - openFrameInTab: function() { - var doc = this.target.ownerDocument; - var frameURL = doc.location.href; - var referrer = doc.referrer; - openLinkIn(frameURL, "tab", - { charset: doc.characterSet, - referrerURI: referrer ? makeURI(referrer) : null }); - }, - - // Reload clicked-in frame. - reloadFrame: function() { - this.target.ownerDocument.location.reload(); - }, - - // Open clicked-in frame in its own window. - openFrame: function() { - var doc = this.target.ownerDocument; - var frameURL = doc.location.href; - var referrer = doc.referrer; - openLinkIn(frameURL, "window", - { charset: doc.characterSet, - referrerURI: referrer ? makeURI(referrer) : null }); - }, - - // Open clicked-in frame in the same window. - showOnlyThisFrame: function() { - var doc = this.target.ownerDocument; - var frameURL = doc.location.href; - - urlSecurityCheck(frameURL, this.browser.contentPrincipal, - Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); - var referrer = doc.referrer; - openUILinkIn(frameURL, "current", { disallowInheritPrincipal: true, - referrerURI: referrer ? makeURI(referrer) : null }); - }, - - reload: function(event) { - BrowserReloadOrDuplicate(event); - }, - - // View Partial Source - viewPartialSource: function(aContext) { - var focusedWindow = document.commandDispatcher.focusedWindow; - if (focusedWindow == window) - focusedWindow = content; - - var docCharset = null; - if (focusedWindow) - docCharset = "charset=" + focusedWindow.document.characterSet; - - // "View Selection Source" and others such as "View MathML Source" - // are mutually exclusive, with the precedence given to the selection - // when there is one - var reference = null; - if (aContext == "selection") - reference = focusedWindow.getSelection(); - else if (aContext == "mathml") - reference = this.target; - else - throw "not reached"; - - // unused (and play nice for fragments generated via XSLT too) - var docUrl = null; - window.openDialog("chrome://global/content/viewPartialSource.xul", - "_blank", "scrollbars,resizable,chrome,dialog=no", - docUrl, docCharset, reference, aContext); - }, - - // Open new "view source" window with the frame's URL. - viewFrameSource: function() { - BrowserViewSourceOfDocument(this.target.ownerDocument); - }, - - viewInfo: function() { - BrowserPageInfo(this.target.ownerDocument.defaultView.top.document); - }, - - viewImageInfo: function() { - BrowserPageInfo(this.target.ownerDocument.defaultView.top.document, - "mediaTab", this.target); - }, - - viewFrameInfo: function() { - BrowserPageInfo(this.target.ownerDocument); - }, - - reloadImage: function(e) { - urlSecurityCheck(this.mediaURL, - this.browser.contentPrincipal, - Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); - - if (this.target instanceof Ci.nsIImageLoadingContent) - this.target.forceReload(); - }, - - // Change current window to the URL of the image, video, or audio. - viewMedia: function(e) { - var viewURL; - var doc = this.target.ownerDocument; - if (this.onCanvas) { - var target = this.target; - var win = doc.defaultView; - if (!win) { - Components.utils.reportError( - "View Image (on the <canvas> element):\n" + - "This feature cannot be used, because it hasn't found " + - "an appropriate window."); - } else { - new Promise.resolve({then: function (resolve) { - target.toBlob((blob) => { - resolve(win.URL.createObjectURL(blob)); - }) - }}).then(function (blobURL) { - openUILink(blobURL, e, { disallowInheritPrincipal: true, - referrerURI: doc.documentURIObject }); - }, Components.utils.reportError); - } - } else { - viewURL = this.mediaURL; - urlSecurityCheck(viewURL, - this.browser.contentPrincipal, - Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); - let doc = this.target.ownerDocument; - openUILink(viewURL, e, { disallowInheritPrincipal: true, - referrerURI: doc.documentURIObject }); - } - }, - - saveVideoFrameAsImage: function () { - urlSecurityCheck(this.mediaURL, this.browser.contentPrincipal, - Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); - let name = ""; - try { - let uri = makeURI(this.mediaURL); - let url = uri.QueryInterface(Ci.nsIURL); - if (url.fileBaseName) - name = decodeURI(url.fileBaseName) + ".jpg"; - } catch (e) { } - if (!name) - name = "snapshot.jpg"; - var video = this.target; - var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); - canvas.width = video.videoWidth; - canvas.height = video.videoHeight; - var ctxDraw = canvas.getContext("2d"); - ctxDraw.drawImage(video, 0, 0); - saveImageURL(canvas.toDataURL("image/jpeg", ""), name, "SaveImageTitle", true, false, document.documentURIObject, this.target.ownerDocument); - }, - - fullScreenVideo: function () { - let video = this.target; - if (document.mozFullScreenEnabled) - video.mozRequestFullScreen(); - }, - - leaveDOMFullScreen: function() { - document.mozCancelFullScreen(); - }, - - // Change current window to the URL of the background image. - viewBGImage: function(e) { - urlSecurityCheck(this.bgImageURL, - this.browser.contentPrincipal, - Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); - var doc = this.target.ownerDocument; - openUILink(this.bgImageURL, e, { disallowInheritPrincipal: true, - referrerURI: doc.documentURIObject }); - }, - - disableSetDesktopBackground: function() { - // Disable the Set as Desktop Background menu item if we're still trying - // to load the image or the load failed. - if (!(this.target instanceof Ci.nsIImageLoadingContent)) - return true; - - if (("complete" in this.target) && !this.target.complete) - return true; - - if (this.target.currentURI.schemeIs("javascript")) - return true; - - var request = this.target - .QueryInterface(Ci.nsIImageLoadingContent) - .getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); - if (!request) - return true; - - return false; - }, - - setDesktopBackground: function() { - // Paranoia: check disableSetDesktopBackground again, in case the - // image changed since the context menu was initiated. - if (this.disableSetDesktopBackground()) - return; - - urlSecurityCheck(this.target.currentURI.spec, - this.target.ownerDocument.nodePrincipal); - - // Confirm since it's annoying if you hit this accidentally. - const kDesktopBackgroundURL = - "chrome://browser/content/setDesktopBackground.xul"; -#ifdef XP_MACOSX - // On Mac, the Set Desktop Background window is not modal. - // Don't open more than one Set Desktop Background window. - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - var dbWin = wm.getMostRecentWindow("Shell:SetDesktopBackground"); - if (dbWin) { - dbWin.gSetBackground.init(this.target); - dbWin.focus(); - } - else { - openDialog(kDesktopBackgroundURL, "", - "centerscreen,chrome,dialog=no,dependent,resizable=no", - this.target); - } -#else - // On non-Mac platforms, the Set Wallpaper dialog is modal. - openDialog(kDesktopBackgroundURL, "", - "centerscreen,chrome,dialog,modal,dependent", - this.target); -#endif - }, - - // Save URL of clicked-on frame. - saveFrame: function () { - saveDocument(this.target.ownerDocument); - }, - - // Helper function to wait for appropriate MIME-type headers and - // then prompt the user with a file picker - saveHelper: function(linkURL, linkText, dialogTitle, bypassCache, doc, - linkDownload) { - // canonical def in nsURILoader.h - const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020; - - // an object to proxy the data through to - // nsIExternalHelperAppService.doContent, which will wait for the - // appropriate MIME-type headers and then prompt the user with a - // file picker - function saveAsListener() {} - saveAsListener.prototype = { - extListener: null, - - onStartRequest: function saveLinkAs_onStartRequest(aRequest, aContext) { - - // if the timer fired, the error status will have been caused by that, - // and we'll be restarting in onStopRequest, so no reason to notify - // the user - if (aRequest.status == NS_ERROR_SAVE_LINK_AS_TIMEOUT) - return; - - timer.cancel(); - - // some other error occured; notify the user... - if (!Components.isSuccessCode(aRequest.status)) { - try { - const sbs = Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService); - const bundle = sbs.createBundle( - "chrome://mozapps/locale/downloads/downloads.properties"); - - const title = bundle.GetStringFromName("downloadErrorAlertTitle"); - const msg = bundle.GetStringFromName("downloadErrorGeneric"); - - const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"]. - getService(Ci.nsIPromptService); - promptSvc.alert(doc.defaultView, title, msg); - } catch (ex) {} - return; - } - - var extHelperAppSvc = - Cc["@mozilla.org/uriloader/external-helper-app-service;1"]. - getService(Ci.nsIExternalHelperAppService); - var channel = aRequest.QueryInterface(Ci.nsIChannel); - this.extListener = - extHelperAppSvc.doContent(channel.contentType, aRequest, - doc.defaultView, true); - this.extListener.onStartRequest(aRequest, aContext); - }, - - onStopRequest: function saveLinkAs_onStopRequest(aRequest, aContext, - aStatusCode) { - if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) { - // do it the old fashioned way, which will pick the best filename - // it can without waiting. - saveURL(linkURL, linkText, dialogTitle, bypassCache, false, doc.documentURIObject, doc); - } - if (this.extListener) - this.extListener.onStopRequest(aRequest, aContext, aStatusCode); - }, - - onDataAvailable: function saveLinkAs_onDataAvailable(aRequest, aContext, - aInputStream, - aOffset, aCount) { - this.extListener.onDataAvailable(aRequest, aContext, aInputStream, - aOffset, aCount); - } - } - - function callbacks() {} - callbacks.prototype = { - getInterface: function sLA_callbacks_getInterface(aIID) { - if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) { - // If the channel demands authentication prompt, we must cancel it - // because the save-as-timer would expire and cancel the channel - // before we get credentials from user. Both authentication dialog - // and save as dialog would appear on the screen as we fall back to - // the old fashioned way after the timeout. - timer.cancel(); - channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT); - } - throw Cr.NS_ERROR_NO_INTERFACE; - } - } - - // if it we don't have the headers after a short time, the user - // won't have received any feedback from their click. that's bad. so - // we give up waiting for the filename. - function timerCallback() {} - timerCallback.prototype = { - notify: function sLA_timer_notify(aTimer) { - channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT); - return; - } - } - - // set up a channel to do the saving - var ioService = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var channel = ioService.newChannelFromURI(makeURI(linkURL)); - if (linkDownload) - channel.contentDispositionFilename = linkDownload; - if (channel instanceof Ci.nsIPrivateBrowsingChannel) { - let docIsPrivate = PrivateBrowsingUtils.isWindowPrivate(doc.defaultView); - channel.setPrivate(docIsPrivate); - } - channel.notificationCallbacks = new callbacks(); - - let flags = Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; - - if (bypassCache) - flags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; - - if (channel instanceof Ci.nsICachingChannel) - flags |= Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY; - - channel.loadFlags |= flags; - - if (channel instanceof Ci.nsIHttpChannel) { - channel.referrer = doc.documentURIObject; - if (channel instanceof Ci.nsIHttpChannelInternal) - channel.forceAllowThirdPartyCookie = true; - } - - // fallback to the old way if we don't see the headers quickly - var timeToWait = - gPrefService.getIntPref("browser.download.saveLinkAsFilenameTimeout"); - var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - timer.initWithCallback(new timerCallback(), timeToWait, - timer.TYPE_ONE_SHOT); - - // kick off the channel with our proxy object as the listener - channel.asyncOpen(new saveAsListener(), null); - }, - - // Save URL of clicked-on link. - saveLink: function() { - var doc = this.target.ownerDocument; - var linkText; - // If selected text is found to match valid URL pattern. - if (this.onPlainTextLink) - linkText = document.commandDispatcher.focusedWindow.getSelection().toString().trim(); - else - linkText = this.linkText(); - urlSecurityCheck(this.linkURL, doc.nodePrincipal); - - this.saveHelper(this.linkURL, linkText, null, true, doc, - this.linkDownload); - }, - - sendLink: function() { - // we don't know the title of the link so pass in an empty string - MailIntegration.sendMessage( this.linkURL, "" ); - }, - - // Backwards-compatibility wrapper - saveImage : function() { - if (this.onCanvas || this.onImage) - this.saveMedia(); - }, - - // Save URL of the clicked upon image, video, or audio. - saveMedia: function() { - var doc = this.target.ownerDocument; - if (this.onCanvas) { - // Bypass cache, since it's a blob: URL. - var target = this.target; - var win = doc.defaultView; - if (!win) { - Components.utils.reportError( - "Save Image As (on the <canvas> element):\n" + - "This feature cannot be used, because it hasn't found " + - "an appropriate window."); - } else { - new Promise.resolve({then: function (resolve) { - target.toBlob((blob) => { - resolve(win.URL.createObjectURL(blob)); - }) - }}).then(function (blobURL) { - saveImageURL(blobURL, "canvas.png", "SaveImageTitle", true, - false, doc.documentURIObject, doc); - }, Components.utils.reportError); - } - } else if (this.onImage) { - urlSecurityCheck(this.mediaURL, doc.nodePrincipal); - saveImageURL(this.mediaURL, null, "SaveImageTitle", false, - false, doc.documentURIObject, doc); - } else if (this.onVideo || this.onAudio) { - urlSecurityCheck(this.mediaURL, doc.nodePrincipal); - var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle"; - this.saveHelper(this.mediaURL, null, dialogTitle, false, doc, ""); - } - }, - - // Backwards-compatibility wrapper - sendImage : function() { - if (this.onCanvas || this.onImage) - this.sendMedia(); - }, - - sendMedia: function() { - MailIntegration.sendMessage(this.mediaURL, ""); - }, - - playPlugin: function() { - gPluginHandler._showClickToPlayNotification(this.browser, this.target); - }, - - hidePlugin: function() { - gPluginHandler.hideClickToPlayOverlay(this.target); - }, - - // Generate email address and put it on clipboard. - copyEmail: function() { - // Copy the comma-separated list of email addresses only. - // There are other ways of embedding email addresses in a mailto: - // link, but such complex parsing is beyond us. - var url = this.linkURL; - var qmark = url.indexOf("?"); - var addresses; - - // 7 == length of "mailto:" - addresses = qmark > 7 ? url.substring(7, qmark) : url.substr(7); - - // Let's try to unescape it using a character set - // in case the address is not ASCII. - try { - var characterSet = this.target.ownerDocument.characterSet; - const textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"]. - getService(Ci.nsITextToSubURI); - addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses); - } - catch(ex) { - // Do nothing. - } - - var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]. - getService(Ci.nsIClipboardHelper); - clipboard.copyString(addresses, document); - }, - - /////////////// - // Utilities // - /////////////// - - // Show/hide one item (specified via name or the item element itself). - showItem: function(aItemOrId, aShow) { - var item = aItemOrId.constructor == String ? - document.getElementById(aItemOrId) : aItemOrId; - if (item) - item.hidden = !aShow; - }, - - // Set given attribute of specified context-menu item. If the - // value is null, then it removes the attribute (which works - // nicely for the disabled attribute). - setItemAttr: function(aID, aAttr, aVal ) { - var elem = document.getElementById(aID); - if (elem) { - if (aVal == null) { - // null indicates attr should be removed. - elem.removeAttribute(aAttr); - } - else { - // Set attr=val. - elem.setAttribute(aAttr, aVal); - } - } - }, - - // Set context menu attribute according to like attribute of another node - // (such as a broadcaster). - setItemAttrFromNode: function(aItem_id, aAttr, aOther_id) { - var elem = document.getElementById(aOther_id); - if (elem && elem.getAttribute(aAttr) == "true") - this.setItemAttr(aItem_id, aAttr, "true"); - else - this.setItemAttr(aItem_id, aAttr, null); - }, - - // Temporary workaround for DOM api not yet implemented by XUL nodes. - cloneNode: function(aItem) { - // Create another element like the one we're cloning. - var node = document.createElement(aItem.tagName); - - // Copy attributes from argument item to the new one. - var attrs = aItem.attributes; - for (var i = 0; i < attrs.length; i++) { - var attr = attrs.item(i); - node.setAttribute(attr.nodeName, attr.nodeValue); - } - - // Voila! - return node; - }, - - // Generate fully qualified URL for clicked-on link. - getLinkURL: function() { - var href = this.link.href; - if (href) - return href; - - href = this.link.getAttributeNS("http://www.w3.org/1999/xlink", - "href"); - - if (!href || !href.match(/\S/)) { - // Without this we try to save as the current doc, - // for example, HTML case also throws if empty - throw "Empty href"; - } - - return makeURLAbsolute(this.link.baseURI, href); - }, - - getLinkURI: function() { - try { - return makeURI(this.linkURL); - } - catch (ex) { - // e.g. empty URL string - } - - return null; - }, - - getLinkProtocol: function() { - if (this.linkURI) - return this.linkURI.scheme; // can be |undefined| - - return null; - }, - - // Get text of link. - linkText: function() { - var text = gatherTextUnder(this.link); - if (!text || !text.match(/\S/)) { - text = this.link.getAttribute("title"); - if (!text || !text.match(/\S/)) { - text = this.link.getAttribute("alt"); - if (!text || !text.match(/\S/)) - text = this.linkURL; - } - } - - return text; - }, - - // Returns true if anything is selected. - isContentSelection: function() { - return !document.commandDispatcher.focusedWindow.getSelection().isCollapsed; - }, - - toString: function () { - return "contextMenu.target = " + this.target + "\n" + - "contextMenu.onImage = " + this.onImage + "\n" + - "contextMenu.onLink = " + this.onLink + "\n" + - "contextMenu.link = " + this.link + "\n" + - "contextMenu.inFrame = " + this.inFrame + "\n" + - "contextMenu.hasBGImage = " + this.hasBGImage + "\n"; - }, - - isDisabledForEvents: function(aNode) { - let ownerDoc = aNode.ownerDocument; - return - ownerDoc.defaultView && - ownerDoc.defaultView - .QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsIDOMWindowUtils) - .isNodeDisabledForEvents(aNode); - }, - - isTargetATextBox: function(node) { - if (node instanceof HTMLInputElement) - return node.mozIsTextField(false); - - return (node instanceof HTMLTextAreaElement); - }, - - isTargetAKeywordField: function(aNode) { - if (!(aNode instanceof HTMLInputElement)) - return false; - - var form = aNode.form; - if (!form || aNode.type == "password") - return false; - - var method = form.method.toUpperCase(); - - // These are the following types of forms we can create keywords for: - // - // method encoding type can create keyword - // GET * YES - // * YES - // POST YES - // POST application/x-www-form-urlencoded YES - // POST text/plain NO (a little tricky to do) - // POST multipart/form-data NO - // POST everything else YES - return (method == "GET" || method == "") || - (form.enctype != "text/plain") && (form.enctype != "multipart/form-data"); - }, - - // Determines whether or not the separator with the specified ID should be - // shown or not by determining if there are any non-hidden items between it - // and the previous separator. - shouldShowSeparator: function (aSeparatorID) { - var separator = document.getElementById(aSeparatorID); - if (separator) { - var sibling = separator.previousSibling; - while (sibling && sibling.localName != "menuseparator") { - if (!sibling.hidden) - return true; - sibling = sibling.previousSibling; - } - } - return false; - }, - - addDictionaries: function() { - var uri = formatURL("browser.dictionaries.download.url", true); - - var locale = "-"; - try { - locale = gPrefService.getComplexValue("intl.accept_languages", - Ci.nsIPrefLocalizedString).data; - } - catch (e) { } - - var version = "-"; - try { - version = Cc["@mozilla.org/xre/app-info;1"]. - getService(Ci.nsIXULAppInfo).version; - } - catch (e) { } - - uri = uri.replace(/%LOCALE%/, escape(locale)).replace(/%VERSION%/, version); - - var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow"); - var where = newWindowPref == 3 ? "tab" : "window"; - - openUILinkIn(uri, where); - }, - - bookmarkThisPage: function CM_bookmarkThisPage() { - window.top.PlacesCommandHook.bookmarkPage(this.browser, PlacesUtils.bookmarksMenuFolderId, true); - }, - - bookmarkLink: function CM_bookmarkLink() { - var linkText; - // If selected text is found to match valid URL pattern. - if (this.onPlainTextLink) - linkText = document.commandDispatcher.focusedWindow.getSelection().toString().trim(); - else - linkText = this.linkText(); - window.top.PlacesCommandHook.bookmarkLink(PlacesUtils.bookmarksMenuFolderId, this.linkURL, - linkText); - }, - - addBookmarkForFrame: function CM_addBookmarkForFrame() { - var doc = this.target.ownerDocument; - var uri = doc.documentURIObject; - - var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri); - if (itemId == -1) { - var title = doc.title; - var description = PlacesUIUtils.getDescriptionFromDocument(doc); - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "bookmark" - , uri: uri - , title: title - , description: description - , hiddenRows: [ "description" - , "location" - , "loadInSidebar" - , "keyword" ] - }, window.top); - } - else { - PlacesUIUtils.showBookmarkDialog({ action: "edit" - , type: "bookmark" - , itemId: itemId - }, window.top); - } - }, - - savePageAs: function CM_savePageAs() { - saveDocument(this.browser.contentDocument); - }, - - sendPage: function CM_sendPage() { - MailIntegration.sendLinkForWindow(this.browser.contentWindow); - }, - - printFrame: function CM_printFrame() { - PrintUtils.print(this.target.ownerDocument.defaultView); - }, - - switchPageDirection: function CM_switchPageDirection() { - SwitchDocumentDirection(this.browser.contentWindow); - }, - - mediaCommand : function CM_mediaCommand(command, data) { - var media = this.target; - - switch (command) { - case "play": - media.play(); - break; - case "pause": - media.pause(); - break; - case "mute": - media.muted = true; - break; - case "unmute": - media.muted = false; - break; - case "playbackRate": - media.playbackRate = data; - break; - case "hidecontrols": - media.removeAttribute("controls"); - break; - case "showcontrols": - media.setAttribute("controls", "true"); - break; - case "hidestats": - case "showstats": - var event = media.ownerDocument.createEvent("CustomEvent"); - event.initCustomEvent("media-showStatistics", false, true, command == "showstats"); - media.dispatchEvent(event); - break; - } - }, - - copyMediaLocation : function () { - var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]. - getService(Ci.nsIClipboardHelper); - clipboard.copyString(this.mediaURL, document); - }, - - get imageURL() { - if (this.onImage) - return this.mediaURL; - return ""; - }, - - // Formats the 'Search <engine> for "<selection or link text>"' context menu. - formatSearchContextItem: function() { - var menuItem = document.getElementById("context-searchselect"); - var selectedText = this.isTextSelected ? this.textSelected : this.linkText(); - - // Store searchTerms in context menu item so we know what to search onclick - menuItem.searchTerms = selectedText; - - if (selectedText.length > 15) - selectedText = selectedText.substr(0,15) + this.ellipsis; - - // Use the current engine if the search bar is visible, the default - // engine otherwise. - var engineName = ""; - var ss = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); - if (isElementVisible(BrowserSearch.searchBar)) - engineName = ss.currentEngine.name; - else - engineName = ss.defaultEngine.name; - - // format "Search <engine> for <selection>" string to show in menu - var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearch", - [engineName, - selectedText]); - menuItem.label = menuLabel; - menuItem.accessKey = gNavigatorBundle.getString("contextMenuSearch.accesskey"); - } -}; diff --git a/browser/base/content/openLocation.js b/browser/base/content/openLocation.js deleted file mode 100644 index 5b731c7e8..000000000 --- a/browser/base/content/openLocation.js +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ - -/* 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/. */ - -var browser; -var dialog = {}; -var pref = null; -let openLocationModule = {}; -try { - pref = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); -} catch (ex) { - // not critical, remain silent -} - -Components.utils.import("resource:///modules/openLocationLastURL.jsm", openLocationModule); -let gOpenLocationLastURL = new openLocationModule.OpenLocationLastURL(window.opener); - -function onLoad() -{ - dialog.input = document.getElementById("dialog.input"); - dialog.open = document.documentElement.getButton("accept"); - dialog.openWhereList = document.getElementById("openWhereList"); - dialog.openTopWindow = document.getElementById("currentWindow"); - dialog.bundle = document.getElementById("openLocationBundle"); - - if ("arguments" in window && window.arguments.length >= 1) - browser = window.arguments[0]; - - dialog.openWhereList.selectedItem = dialog.openTopWindow; - - if (pref) { - try { - var useAutoFill = pref.getBoolPref("browser.urlbar.autoFill"); - if (useAutoFill) - dialog.input.setAttribute("completedefaultindex", "true"); - } catch (ex) {} - - try { - var value = pref.getIntPref("general.open_location.last_window_choice"); - var element = dialog.openWhereList.getElementsByAttribute("value", value)[0]; - if (element) - dialog.openWhereList.selectedItem = element; - dialog.input.value = gOpenLocationLastURL.value; - } - catch(ex) { - } - if (dialog.input.value) - dialog.input.select(); // XXX should probably be done automatically - } - - doEnabling(); -} - -function doEnabling() -{ - dialog.open.disabled = !dialog.input.value; -} - -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; - - 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; - } - } - catch(exception) { - } - - 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(); - return false; -} - -function createInstance(contractid, iidName) -{ - var iid = Components.interfaces[iidName]; - return Components.classes[contractid].createInstance(iid); -} - -const nsIFilePicker = Components.interfaces.nsIFilePicker; -function onChooseFile() -{ - try { - let fp = Components.classes["@mozilla.org/filepicker;1"]. - createInstance(nsIFilePicker); - let fpCallback = function fpCallback_done(aResult) { - if (aResult == nsIFilePicker.returnOK && fp.fileURL.spec && - fp.fileURL.spec.length > 0) { - dialog.input.value = fp.fileURL.spec; - } - doEnabling(); - }; - - fp.init(window, dialog.bundle.getString("chooseFileDialogTitle"), - nsIFilePicker.modeOpen); - fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText | - nsIFilePicker.filterImages | nsIFilePicker.filterXML | - nsIFilePicker.filterHTML); - fp.open(fpCallback); - } catch (ex) { - } -} diff --git a/browser/base/content/openLocation.xul b/browser/base/content/openLocation.xul deleted file mode 100644 index 7bafed0fe..000000000 --- a/browser/base/content/openLocation.xul +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> - -<!DOCTYPE dialog SYSTEM "chrome://browser/locale/openLocation.dtd"> - -<dialog id="openLocation" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - title="&caption.label;" - onload="onLoad()" - buttonlabelaccept="&openBtn.label;" - buttoniconaccept="open" - ondialogaccept="open()" - style="width: 40em;" - persist="screenX screenY" - screenX="24" screenY="24"> - - <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/> - <script type="application/javascript" src="chrome://browser/content/openLocation.js"/> - <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/> - - <stringbundle id="openLocationBundle" src="chrome://browser/locale/openLocation.properties"/> - - <hbox> - <separator orient="vertical" class="thin"/> - <vbox flex="1"> - <description>&enter.label;</description> - <separator class="thin"/> - - <hbox align="center"> - <textbox id="dialog.input" flex="1" type="autocomplete" - completeselectedindex="true" - autocompletesearch="urlinline history" - enablehistory="true" - class="uri-element" - oninput="doEnabling();"/> - <button label="&chooseFile.label;" oncommand="onChooseFile();"/> - </hbox> - <hbox align="center"> - <label value="&openWhere.label;"/> - <menulist id="openWhereList"> - <menupopup> - <menuitem value="0" id="currentWindow" label="&topTab.label;"/> - <menuitem value="3" label="&newTab.label;"/> - <menuitem value="1" label="&newWindow.label;"/> - </menupopup> - </menulist> - <spacer flex="1"/> - </hbox> - </vbox> - </hbox> - -</dialog> diff --git a/browser/base/content/overrides/app-license.html b/browser/base/content/overrides/app-license.html deleted file mode 100644 index 2d2e3d55e..000000000 --- a/browser/base/content/overrides/app-license.html +++ /dev/null @@ -1,6 +0,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/. --> - <p><b>Binaries</b> of this product have been made available to you by the - <a href="http://www.palemoon.org/">Pale Moon Project</a> under the Pale Moon - Binary <a href="http://www.palemoon.org/redist.shtml">redistribution license</a>.</p>
\ No newline at end of file diff --git a/browser/base/content/padlock.css b/browser/base/content/padlock.css deleted file mode 100644 index 649cb2777..000000000 --- a/browser/base/content/padlock.css +++ /dev/null @@ -1,203 +0,0 @@ -#padlock-ib { - -moz-appearance: none; - min-width: 0px; - margin-right: 1px !important; - background-repeat: no-repeat; - background-position: center; - z-index: 1000 !important; - padding: 0px; - margin: 0px; - border: 0px; -} - -#padlock-ib[padshow="ib-trans-bg"][level="ev"] { - list-style-image: url("chrome://browser/content/padlock_mod_ev.png"); - background-color: transparent; -} - -#padlock-ib[padshow="ib-trans-bg"][level="high"] { - list-style-image: url("chrome://browser/content/padlock_mod_https.png"); - background-color: transparent; -} - -#padlock-ib[padshow="ib-trans-bg"][level="low"], -#padlock-ib[padshow="ib-trans-bg"][level="mixed"] { - list-style-image: url("chrome://browser/content/padlock_mod_low.png"); - background-color: transparent; -} - -#padlock-ib[padshow="ib-trans-bg"][level="broken"] { - list-style-image: url("chrome://browser/content/padlock_mod_broken.png"); - background-color: transparent; -} - -#padlock-ib-left { - -moz-appearance: none; - min-width: 0px; - margin-right: 1px !important; - background-repeat: no-repeat; - background-position: center; - z-index: 1000 !important; - padding: 0px; - margin: 0px; - border: 0px; -} - -#padlock-ib-left[padshow="ib-left"][level="ev"] { - list-style-image: url("chrome://browser/content/padlock_mod_ev.png"); - padding: 2px; - background-color: transparent; -} - -#padlock-ib-left[padshow="ib-left"][level="high"] { - list-style-image: url("chrome://browser/content/padlock_mod_https.png"); - padding: 2px; - background-color: transparent; -} - -#padlock-ib-left[padshow="ib-left"][level="low"], -#padlock-ib-left[padshow="ib-left"][level="mixed"] { - list-style-image: url("chrome://browser/content/padlock_mod_low.png"); - padding: 2px; - background-color: transparent; -} - -#padlock-ib-left[padshow="ib-left"][level="broken"] { - list-style-image: url("chrome://browser/content/padlock_mod_broken.png"); - padding: 2px; - background-color: transparent; -} - -#padlock-ub-right { - -moz-appearance: none; - min-width: 0px; - margin-right: 1px !important; - background-repeat: no-repeat; - background-position: center; - z-index: 1000 !important; - padding: 0px; - margin: 0px; - border: 0px; -} - -#padlock-ub-right[padshow="ub-right"][level="ev"] { - list-style-image: url("chrome://browser/content/padlock_mod_ev.png"); - background-color: transparent; -} - -#padlock-ub-right[padshow="ub-right"][level="high"] { - list-style-image: url("chrome://browser/content/padlock_mod_https.png"); - background-color: transparent; -} - -#padlock-ub-right[padshow="ub-right"][level="low"], -#padlock-ub-right[padshow="ub-right"][level="mixed"] { - list-style-image: url("chrome://browser/content/padlock_mod_low.png"); - background-color: transparent; -} - -#padlock-ub-right[padshow="ub-right"][level="broken"] { - list-style-image: url("chrome://browser/content/padlock_mod_broken.png"); - background-color: transparent; -} - -#padlock-sb { - -moz-appearance: none; - background-repeat: no-repeat; - background-position: center; -} - -#padlock-sb[padshow="statbar"][level="ev"] { - list-style-image: url("chrome://browser/content/padlock_mod_ev.png"); - background-color: transparent; -} - -#padlock-sb[padshow="statbar"][level="high"] { - list-style-image: url("chrome://browser/content/padlock_mod_https.png"); - background-color: transparent; -} - -#padlock-sb[padshow="statbar"][level="low"], -#padlock-sb[padshow="statbar"][level="mixed"] { - list-style-image: url("chrome://browser/content/padlock_mod_low.png"); - background-color: transparent; -} - -#padlock-sb[padshow="statbar"][level="broken"] { - list-style-image: url("chrome://browser/content/padlock_mod_broken.png"); - background-color: transparent; -} - -#padlock-tab { - -moz-appearance: none; - background-repeat: no-repeat; - background-position: center; -} - -#padlock-tab[padshow="tabs-bar"][level="ev"] { - list-style-image: url("chrome://browser/content/padlock_mod_ev.png"); - background-color: transparent; -} - -#padlock-tab[padshow="tabs-bar"][level="high"] { - list-style-image: url("chrome://browser/content/padlock_mod_https.png"); - background-color: transparent; -} - -#padlock-tab[padshow="tabs-bar"][level="low"], -#padlock-tab[padshow="tabs-bar"][level="mixed"] { - list-style-image: url("chrome://browser/content/padlock_mod_low.png"); - background-color: transparent; -} - -#padlock-tab[padshow="tabs-bar"][level="broken"] { - list-style-image: url("chrome://browser/content/padlock_mod_broken.png"); - background-color: transparent; -} - -/* Classic style */ -#padlock-ib[padshow="ib-trans-bg"][padstyle="classic"][level="ev"], -#padlock-ib-left[padshow="ib-left"][padstyle="classic"][level="ev"], -#padlock-ub-right[padshow="ub-right"][padstyle="classic"][level="ev"], -#padlock-sb[padshow="statbar"][padstyle="classic"][level="ev"], -#padlock-tab[padshow="tabs-bar"][padstyle="classic"][level="ev"] { - list-style-image: url("chrome://browser/content/padlock_classic_ev.png"); -} - -#padlock-ib[padshow="ib-trans-bg"][padstyle="classic"][level="high"], -#padlock-ib-left[padshow="ib-left"][padstyle="classic"][level="high"], -#padlock-ub-right[padshow="ub-right"][padstyle="classic"][level="high"], -#padlock-sb[padshow="statbar"][padstyle="classic"][level="high"], -#padlock-tab[padshow="tabs-bar"][padstyle="classic"][level="high"] { - list-style-image: url("chrome://browser/content/padlock_classic_https.png"); -} - -#padlock-ib[padshow="ib-trans-bg"][padstyle="classic"][level="low"], -#padlock-ib-left[padshow="ib-left"][padstyle="classic"][level="low"], -#padlock-ub-right[padshow="ub-right"][padstyle="classic"][level="low"], -#padlock-sb[padshow="statbar"][padstyle="classic"][level="low"], -#padlock-tab[padshow="tabs-bar"][padstyle="classic"][level="low"], -#padlock-ib[padshow="ib-trans-bg"][padstyle="classic"][level="mixed"], -#padlock-ib-left[padshow="ib-left"][padstyle="classic"][level="mixed"], -#padlock-ub-right[padshow="ub-right"][padstyle="classic"][level="mixed"], -#padlock-sb[padshow="statbar"][padstyle="classic"][level="mixed"], -#padlock-tab[padshow="tabs-bar"][padstyle="classic"][level="mixed"] { - list-style-image: url("chrome://browser/content/padlock_classic_low.png"); -} - -#padlock-ib[padshow="ib-trans-bg"][padstyle="classic"][level="broken"], -#padlock-ib-left[padshow="ib-left"][padstyle="classic"][level="broken"], -#padlock-ub-right[padshow="ub-right"][padstyle="classic"][level="broken"], -#padlock-sb[padshow="statbar"][padstyle="classic"][level="broken"], -#padlock-tab[padshow="tabs-bar"][padstyle="classic"][level="broken"] { - list-style-image: url("chrome://browser/content/padlock_classic_broken.png"); -} - -/* Remove a few px of dead space for disabled locations */ -#padlock-ib:not([padshow="ib-trans-bg"]), -#padlock-ib-left:not([padshow="ib-left"]), -#padlock-ub-right:not([padshow="ub-right"]), -#padlock-sb:not([padshow="statbar"]), -#padlock-tab:not([padshow="tabs-bar"]) { - visibility: collapse; -}
\ No newline at end of file diff --git a/browser/base/content/padlock.js b/browser/base/content/padlock.js deleted file mode 100644 index 53477fd17..000000000 --- a/browser/base/content/padlock.js +++ /dev/null @@ -1,234 +0,0 @@ -let Cc = Components.classes; -let Ci = Components.interfaces; -let Cu = Components.utils; -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -var padlock_PadLock = -{ - QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, - Ci.nsISupportsWeakReference]), - onButtonClick: function(event) { - event.stopPropagation(); - gIdentityHandler.handleMoreInfoClick(event); - }, - onStateChange: function() {}, - onProgressChange: function() {}, - onLocationChange: function() {}, - onStatusChange: function() {}, - onSecurityChange: function(aCallerWebProgress, aRequestWithState, aState) { - // aState is defined as a bitmask that may be extended in the future. - // We filter out any unknown bits before testing for known values. - const wpl = Ci.nsIWebProgressListener; - const wpl_security_bits = wpl.STATE_IS_SECURE | - wpl.STATE_IS_BROKEN | - wpl.STATE_IS_INSECURE | - wpl.STATE_IDENTITY_EV_TOPLEVEL | - wpl.STATE_SECURE_HIGH | - wpl.STATE_SECURE_MED | - wpl.STATE_SECURE_LOW; - var level; - var is_insecure; - var highlight_urlbar = false; - - switch (aState & wpl_security_bits) { - case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH | wpl.STATE_IDENTITY_EV_TOPLEVEL: - level = "ev"; - is_insecure = ""; - highlight_urlbar = true; - break; - case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH: - level = "high"; - is_insecure = ""; - highlight_urlbar = true; - break; - case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_MED: - case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW: - level = "low"; - is_insecure = "insecure"; - break; - case wpl.STATE_IS_BROKEN | wpl.STATE_SECURE_LOW: - level = "mixed"; - is_insecure = "insecure"; - highlight_urlbar = true; - break; - case wpl.STATE_IS_BROKEN: - level = "broken"; - is_insecure = "insecure"; - highlight_urlbar = true; - break; - default: // should not be reached - level = null; - is_insecure = "insecure"; - } - - try { - var proto = gBrowser.contentWindow.location.protocol; - if (proto == "about:" || proto == "chrome:" || proto == "file:" ) { - // do not warn when using local protocols - is_insecure = false; - } - } - catch (ex) {} - - let ub = document.getElementById("urlbar"); - if (ub) { // Only call if URL bar is present. - if (highlight_urlbar) { - ub.setAttribute("security_level", level); - } else { - ub.removeAttribute("security_level"); - } - } - - try { // URL bar may be hidden - padlock_PadLock.setPadlockLevel("padlock-ib", level); - padlock_PadLock.setPadlockLevel("padlock-ib-left", level); - padlock_PadLock.setPadlockLevel("padlock-ub-right", level); - } catch(e) {} - padlock_PadLock.setPadlockLevel("padlock-sb", level); - padlock_PadLock.setPadlockLevel("padlock-tab", level); - }, - setPadlockLevel: function(item, level) { - let secbut = document.getElementById(item); - var sectooltip = ""; - - if (level) { - secbut.setAttribute("level", level); - secbut.hidden = false; - } else { - secbut.hidden = true; - secbut.removeAttribute("level"); - } - - switch (level) { - case "ev": - sectooltip = "Extended Validated"; - break; - case "high": - sectooltip = "Secure"; - break; - case "low": - sectooltip = "Weak security"; - break; - case "mixed": - sectooltip = "Mixed mode (partially encrypted)"; - break; - case "broken": - sectooltip = "Not secure"; - break; - default: - sectooltip = ""; - } - secbut.setAttribute("tooltiptext", sectooltip); - }, - prefbranch : null, - onLoad: function() { - gBrowser.addProgressListener(padlock_PadLock); - - var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); - padlock_PadLock.prefbranch = prefService.getBranch("browser.padlock."); - padlock_PadLock.prefbranch.QueryInterface(Components.interfaces.nsIPrefBranch2); - padlock_PadLock.usePrefs(); - padlock_PadLock.prefbranch.addObserver("", padlock_PadLock, false); - }, - onUnLoad: function() { - padlock_PadLock.prefbranch.removeObserver("", padlock_PadLock); - }, - observe: function(subject, topic, data) - { - if (topic != "nsPref:changed") - return; - if (data != "style" && data != "urlbar_background" && data != "shown") - return; - padlock_PadLock.usePrefs(); - }, - usePrefs: function() { - var prefval = padlock_PadLock.prefbranch.getIntPref("style"); - var position; - var padstyle; - if (prefval == 2) { - position = "ib-left"; - padstyle = "modern"; - } - else if (prefval == 3) { - position = "ub-right"; - padstyle = "modern"; - } - else if (prefval == 4) { - position = "statbar"; - padstyle = "modern"; - } - else if (prefval == 5) { - position = "tabs-bar"; - padstyle = "modern"; - } - else if (prefval == 6) { - position = "ib-trans-bg"; - padstyle = "classic"; - } - else if (prefval == 7) { - position = "ib-left"; - padstyle = "classic"; - } - else if (prefval == 8) { - position = "ub-right"; - padstyle = "classic"; - } - else if (prefval == 9) { - position = "statbar"; - padstyle = "classic"; - } - else if (prefval == 10) { - position = "tabs-bar"; - padstyle = "classic"; - } - else { // 1 or anything else_ default - position = "ib-trans-bg"; - padstyle = "modern"; - } - - var colshow; - var colprefval = padlock_PadLock.prefbranch.getIntPref("urlbar_background"); - switch (colprefval) { - case 3: - colshow = "all"; - break; - case 2: - colshow = "secure-mixed"; - break; - case 1: - colshow = "secure-only"; - break; - default: - colshow = ""; // 0 or anything else: no shading - } - try { // URL bar may be hidden - document.getElementById("urlbar").setAttribute("https_color", colshow); - } catch(e) {} - - var lockenabled = padlock_PadLock.prefbranch.getBoolPref("shown"); - var padshow = ""; - if (lockenabled) { - padshow = position; - } - - try { // URL bar may be hidden - document.getElementById("padlock-ib").setAttribute("padshow", padshow); - document.getElementById("padlock-ib-left").setAttribute("padshow", padshow); - document.getElementById("padlock-ub-right").setAttribute("padshow", padshow); - } catch(e) {} - document.getElementById("padlock-sb").setAttribute("padshow", padshow); - document.getElementById("padlock-tab").setAttribute("padshow", padshow); - - try { // URL bar may be hidden - document.getElementById("padlock-ib").setAttribute("padstyle", padstyle); - document.getElementById("padlock-ib-left").setAttribute("padstyle", padstyle); - document.getElementById("padlock-ub-right").setAttribute("padstyle", padstyle); - } catch(e) {} - document.getElementById("padlock-sb").setAttribute("padstyle", padstyle); - document.getElementById("padlock-tab").setAttribute("padstyle", padstyle); - - } -}; - -window.addEventListener("load", padlock_PadLock.onLoad, false ); -window.addEventListener("unload", padlock_PadLock.onUnLoad, false ); diff --git a/browser/base/content/padlock.xul b/browser/base/content/padlock.xul deleted file mode 100644 index e820c19c7..000000000 --- a/browser/base/content/padlock.xul +++ /dev/null @@ -1,63 +0,0 @@ -<?xml version="1.0"?> -<?xml-stylesheet href="chrome://browser/content/padlock.css" type="text/css"?> - -<overlay - id="padlock" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<script type="application/x-javascript" src="chrome://browser/content/padlock.js"/> - - <hbox id="identity-box"> - <image id="padlock-ib" insertafter="identity-icon-labels" - class="urlbar-icon" - style="-moz-user-focus: none;" - hidden="false" - tooltiptext="" - onclick="return padlock_PadLock.onButtonClick(event);"/> - </hbox> - - <hbox id="identity-box"> - <image id="padlock-ib-left" insertbefore="identity-icon-labels" - class="urlbar-icon" - style="-moz-user-focus: none;" - hidden="false" - tooltiptext="" - onclick="return padlock_PadLock.onButtonClick(event);"/> - </hbox> - - <hbox id="urlbar-icons"> - <image id="padlock-ub-right" insertbefore="star-button" - class="urlbar-icon" - style="-moz-user-focus: none;" - hidden="false" - tooltiptext="" - onclick="return padlock_PadLock.onButtonClick(event);"/> - </hbox> - - <statusbar id="status-bar"> - <statusbarpanel insertafter="security-button" - id="padlock-sb-panel" - class="statusbar-iconic-text"> - <image id="padlock-sb" insertbefore="star-button" - class="urlbar-icon" - style="-moz-user-focus: none;" - hidden="false" - tooltiptext="" - onclick="return padlock_PadLock.onButtonClick(event);"/> - </statusbarpanel> - </statusbar> - - <toolbar id="TabsToolbar"> - <toolbaritem insertafter="tabs-closebutton" id="tabs-padlock-tbitem" - align="center" pack="center"> - <image id="padlock-tab" - class="urlbar-icon" - style="-moz-user-focus: none;" - hidden="false" - tooltiptext="" - onclick="return padlock_PadLock.onButtonClick(event);"/> - </toolbaritem> - </toolbar> - - -</overlay> diff --git a/browser/base/content/padlock_classic_broken.png b/browser/base/content/padlock_classic_broken.png Binary files differdeleted file mode 100644 index 437036fe8..000000000 --- a/browser/base/content/padlock_classic_broken.png +++ /dev/null diff --git a/browser/base/content/padlock_classic_ev.png b/browser/base/content/padlock_classic_ev.png Binary files differdeleted file mode 100644 index b3f80c0da..000000000 --- a/browser/base/content/padlock_classic_ev.png +++ /dev/null diff --git a/browser/base/content/padlock_classic_https.png b/browser/base/content/padlock_classic_https.png Binary files differdeleted file mode 100644 index 86026c04f..000000000 --- a/browser/base/content/padlock_classic_https.png +++ /dev/null diff --git a/browser/base/content/padlock_classic_low.png b/browser/base/content/padlock_classic_low.png Binary files differdeleted file mode 100644 index 652ad091f..000000000 --- a/browser/base/content/padlock_classic_low.png +++ /dev/null diff --git a/browser/base/content/padlock_mod_broken.png b/browser/base/content/padlock_mod_broken.png Binary files differdeleted file mode 100644 index 33a6c0645..000000000 --- a/browser/base/content/padlock_mod_broken.png +++ /dev/null diff --git a/browser/base/content/padlock_mod_ev.png b/browser/base/content/padlock_mod_ev.png Binary files differdeleted file mode 100644 index 3dfdcbde5..000000000 --- a/browser/base/content/padlock_mod_ev.png +++ /dev/null diff --git a/browser/base/content/padlock_mod_https.png b/browser/base/content/padlock_mod_https.png Binary files differdeleted file mode 100644 index d494b42b0..000000000 --- a/browser/base/content/padlock_mod_https.png +++ /dev/null diff --git a/browser/base/content/padlock_mod_low.png b/browser/base/content/padlock_mod_low.png Binary files differdeleted file mode 100644 index 29179efaf..000000000 --- a/browser/base/content/padlock_mod_low.png +++ /dev/null diff --git a/browser/base/content/pageinfo/feeds.js b/browser/base/content/pageinfo/feeds.js deleted file mode 100644 index 468d8c19d..000000000 --- a/browser/base/content/pageinfo/feeds.js +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -function initFeedTab() -{ - const feedTypes = { - "application/rss+xml": gBundle.getString("feedRss"), - "application/atom+xml": gBundle.getString("feedAtom"), - "text/xml": gBundle.getString("feedXML"), - "application/xml": gBundle.getString("feedXML"), - "application/rdf+xml": gBundle.getString("feedXML") - }; - - // get the feeds - var linkNodes = gDocument.getElementsByTagName("link"); - var length = linkNodes.length; - for (var i = 0; i < length; i++) { - var link = linkNodes[i]; - if (!link.href) - continue; - - var rel = link.rel && link.rel.toLowerCase(); - var rels = {}; - if (rel) { - for each (let relVal in rel.split(/\s+/)) - rels[relVal] = true; - } - - if (rels.feed || (link.type && rels.alternate && !rels.stylesheet)) { - var type = isValidFeed(link, gDocument.nodePrincipal, "feed" in rels); - if (type) { - type = feedTypes[type] || feedTypes["application/rss+xml"]; - addRow(link.title, type, link.href); - } - } - } - - var feedListbox = document.getElementById("feedListbox"); - document.getElementById("feedTab").hidden = feedListbox.getRowCount() == 0; -} - -function onSubscribeFeed() -{ - var listbox = document.getElementById("feedListbox"); - openUILinkIn(listbox.selectedItem.getAttribute("feedURL"), "current", - { ignoreAlt: true }); -} - -function addRow(name, type, url) -{ - var item = document.createElement("richlistitem"); - item.setAttribute("feed", "true"); - item.setAttribute("name", name); - item.setAttribute("type", type); - item.setAttribute("feedURL", url); - document.getElementById("feedListbox").appendChild(item); -} diff --git a/browser/base/content/pageinfo/feeds.xml b/browser/base/content/pageinfo/feeds.xml deleted file mode 100644 index 782c05a73..000000000 --- a/browser/base/content/pageinfo/feeds.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<!DOCTYPE bindings [ - <!ENTITY % pageInfoDTD SYSTEM "chrome://browser/locale/pageInfo.dtd"> - %pageInfoDTD; -]> - -<bindings id="feedBindings" - xmlns="http://www.mozilla.org/xbl" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:xbl="http://www.mozilla.org/xbl"> - - <binding id="feed" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem"> - <content> - <xul:vbox flex="1"> - <xul:hbox flex="1"> - <xul:textbox flex="1" readonly="true" xbl:inherits="value=name" - class="feedTitle"/> - <xul:label xbl:inherits="value=type"/> - </xul:hbox> - <xul:vbox> - <xul:vbox align="start"> - <xul:hbox> - <xul:label xbl:inherits="value=feedURL,tooltiptext=feedURL" class="text-link" flex="1" - onclick="openUILink(this.value, event);" crop="end"/> - </xul:hbox> - </xul:vbox> - </xul:vbox> - <xul:hbox flex="1" class="feed-subscribe"> - <xul:spacer flex="1"/> - <xul:button label="&feedSubscribe;" accesskey="&feedSubscribe.accesskey;" - oncommand="onSubscribeFeed()"/> - </xul:hbox> - </xul:vbox> - </content> - </binding> -</bindings> diff --git a/browser/base/content/pageinfo/pageInfo.css b/browser/base/content/pageinfo/pageInfo.css deleted file mode 100644 index 622b56bb5..000000000 --- a/browser/base/content/pageinfo/pageInfo.css +++ /dev/null @@ -1,26 +0,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/. */ - - -#viewGroup > radio { - -moz-binding: url("chrome://browser/content/pageinfo/pageInfo.xml#viewbutton"); -} - -richlistitem[feed] { - -moz-binding: url("chrome://browser/content/pageinfo/feeds.xml#feed"); -} - -richlistitem[feed]:not([selected="true"]) .feed-subscribe { - display: none; -} - -groupbox[closed="true"] > .groupbox-body { - visibility: collapse; -} - -#thepreviewimage { - display: block; -/* This following entry can be removed when Bug 522850 is fixed. */ - min-width: 1px; -} diff --git a/browser/base/content/pageinfo/pageInfo.js b/browser/base/content/pageinfo/pageInfo.js deleted file mode 100644 index ba93ee817..000000000 --- a/browser/base/content/pageinfo/pageInfo.js +++ /dev/null @@ -1,1285 +0,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/. */ - -const Cu = Components.utils; -Cu.import("resource://gre/modules/LoadContextInfo.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -//******** define a js object to implement nsITreeView -function pageInfoTreeView(treeid, copycol) -{ - // copycol is the index number for the column that we want to add to - // the copy-n-paste buffer when the user hits accel-c - this.treeid = treeid; - this.copycol = copycol; - this.rows = 0; - this.tree = null; - this.data = [ ]; - this.selection = null; - this.sortcol = -1; - this.sortdir = false; -} - -pageInfoTreeView.prototype = { - set rowCount(c) { throw "rowCount is a readonly property"; }, - get rowCount() { return this.rows; }, - - setTree: function(tree) - { - this.tree = tree; - }, - - getCellText: function(row, column) - { - // row can be null, but js arrays are 0-indexed. - // colidx cannot be null, but can be larger than the number - // of columns in the array. In this case it's the fault of - // whoever typoed while calling this function. - return this.data[row][column.index] || ""; - }, - - setCellValue: function(row, column, value) - { - }, - - setCellText: function(row, column, value) - { - this.data[row][column.index] = value; - }, - - addRow: function(row) - { - this.rows = this.data.push(row); - this.rowCountChanged(this.rows - 1, 1); - if (this.selection.count == 0 && this.rowCount && !gImageElement) - this.selection.select(0); - }, - - rowCountChanged: function(index, count) - { - this.tree.rowCountChanged(index, count); - }, - - invalidate: function() - { - this.tree.invalidate(); - }, - - clear: function() - { - if (this.tree) - this.tree.rowCountChanged(0, -this.rows); - this.rows = 0; - this.data = [ ]; - }, - - handleCopy: function(row) - { - return (row < 0 || this.copycol < 0) ? "" : (this.data[row][this.copycol] || ""); - }, - - performActionOnRow: function(action, row) - { - if (action == "copy") { - var data = this.handleCopy(row) - this.tree.treeBody.parentNode.setAttribute("copybuffer", data); - } - }, - - onPageMediaSort : function(columnname) - { - var tree = document.getElementById(this.treeid); - var treecol = tree.columns.getNamedColumn(columnname); - - this.sortdir = - gTreeUtils.sort( - tree, - this, - this.data, - treecol.index, - function textComparator(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }, - this.sortcol, - this.sortdir - ); - - this.sortcol = treecol.index; - }, - - getRowProperties: function(row) { return ""; }, - getCellProperties: function(row, column) { return ""; }, - getColumnProperties: function(column) { return ""; }, - isContainer: function(index) { return false; }, - isContainerOpen: function(index) { return false; }, - isSeparator: function(index) { return false; }, - isSorted: function() { }, - canDrop: function(index, orientation) { return false; }, - drop: function(row, orientation) { return false; }, - getParentIndex: function(index) { return 0; }, - hasNextSibling: function(index, after) { return false; }, - getLevel: function(index) { return 0; }, - getImageSrc: function(row, column) { }, - getProgressMode: function(row, column) { }, - getCellValue: function(row, column) { }, - toggleOpenState: function(index) { }, - cycleHeader: function(col) { }, - selectionChanged: function() { }, - cycleCell: function(row, column) { }, - isEditable: function(row, column) { return false; }, - isSelectable: function(row, column) { return false; }, - performAction: function(action) { }, - performActionOnCell: function(action, row, column) { } -}; - -// mmm, yummy. global variables. -var gWindow = null; -var gDocument = null; -var gImageElement = null; - -// column number to help using the data array -const COL_IMAGE_ADDRESS = 0; -const COL_IMAGE_TYPE = 1; -const COL_IMAGE_SIZE = 2; -const COL_IMAGE_ALT = 3; -const COL_IMAGE_COUNT = 4; -const COL_IMAGE_NODE = 5; -const COL_IMAGE_BG = 6; - -// column number to copy from, second argument to pageInfoTreeView's constructor -const COPYCOL_NONE = -1; -const COPYCOL_META_CONTENT = 1; -const COPYCOL_IMAGE = COL_IMAGE_ADDRESS; - -// one nsITreeView for each tree in the window -var gMetaView = new pageInfoTreeView('metatree', COPYCOL_META_CONTENT); -var gImageView = new pageInfoTreeView('imagetree', COPYCOL_IMAGE); - -gImageView.getCellProperties = function(row, col) { - var data = gImageView.data[row]; - var item = gImageView.data[row][COL_IMAGE_NODE]; - var props = ""; - if (!checkProtocol(data) || - item instanceof HTMLEmbedElement || - (item instanceof HTMLObjectElement && !item.type.startsWith("image/"))) - props += "broken"; - - if (col.element.id == "image-address") - props += " ltr"; - - return props; -}; - -gImageView.getCellText = function(row, column) { - var value = this.data[row][column.index]; - if (column.index == COL_IMAGE_SIZE) { - if (value == -1) { - return gStrings.unknown; - } else { - var kbSize = Number(Math.round(value / 1024 * 100) / 100); - return gBundle.getFormattedString("mediaFileSize", [kbSize]); - } - } - return value || ""; -}; - -gImageView.onPageMediaSort = function(columnname) { - var tree = document.getElementById(this.treeid); - var treecol = tree.columns.getNamedColumn(columnname); - - var comparator; - if (treecol.index == COL_IMAGE_SIZE || treecol.index == COL_IMAGE_COUNT) { - comparator = function numComparator(a, b) { return a - b; }; - } else { - comparator = function textComparator(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }; - } - - this.sortdir = - gTreeUtils.sort( - tree, - this, - this.data, - treecol.index, - comparator, - this.sortcol, - this.sortdir - ); - - this.sortcol = treecol.index; -}; - -var gImageHash = { }; - -// localized strings (will be filled in when the document is loaded) -// this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop -var gStrings = { }; -var gBundle; - -const PERMISSION_CONTRACTID = "@mozilla.org/permissionmanager;1"; -const PREFERENCES_CONTRACTID = "@mozilla.org/preferences-service;1"; -const ATOM_CONTRACTID = "@mozilla.org/atom-service;1"; - -// a number of services I'll need later -// the cache services -const nsICacheStorageService = Components.interfaces.nsICacheStorageService; -const nsICacheStorage = Components.interfaces.nsICacheStorage; -const cacheService = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"].getService(nsICacheStorageService); - -var loadContextInfo = LoadContextInfo.fromLoadContext( - window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsIWebNavigation) - .QueryInterface(Components.interfaces.nsILoadContext), false); -var diskStorage = cacheService.diskCacheStorage(loadContextInfo, false); - -const nsICookiePermission = Components.interfaces.nsICookiePermission; -const nsIPermissionManager = Components.interfaces.nsIPermissionManager; - -const nsICertificateDialogs = Components.interfaces.nsICertificateDialogs; -const CERTIFICATEDIALOGS_CONTRACTID = "@mozilla.org/nsCertificateDialogs;1" - -// clipboard helper -function getClipboardHelper() { - try { - return Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper); - } catch(e) { - // do nothing, later code will handle the error - } -} -const gClipboardHelper = getClipboardHelper(); - -// Interface for image loading content -const nsIImageLoadingContent = Components.interfaces.nsIImageLoadingContent; - -// namespaces, don't need all of these yet... -const XLinkNS = "http://www.w3.org/1999/xlink"; -const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; -const XMLNS = "http://www.w3.org/XML/1998/namespace"; -const XHTMLNS = "http://www.w3.org/1999/xhtml"; -const XHTML2NS = "http://www.w3.org/2002/06/xhtml2" - -const XHTMLNSre = "^http\:\/\/www\.w3\.org\/1999\/xhtml$"; -const XHTML2NSre = "^http\:\/\/www\.w3\.org\/2002\/06\/xhtml2$"; -const XHTMLre = RegExp(XHTMLNSre + "|" + XHTML2NSre, ""); - -/* Overlays register functions here. - * These arrays are used to hold callbacks that Page Info will call at - * various stages. Use them by simply appending a function to them. - * For example, add a function to onLoadRegistry by invoking - * "onLoadRegistry.push(XXXLoadFunc);" - * The XXXLoadFunc should be unique to the overlay module, and will be - * invoked as "XXXLoadFunc();" - */ - -// These functions are called to build the data displayed in the Page -// Info window. The global variables gDocument and gWindow are set. -var onLoadRegistry = [ ]; - -// These functions are called to remove old data still displayed in -// the window when the document whose information is displayed -// changes. For example, at this time, the list of images of the Media -// tab is cleared. -var onResetRegistry = [ ]; - -// These are called once for each subframe of the target document and -// the target document itself. The frame is passed as an argument. -var onProcessFrame = [ ]; - -// These functions are called once for each element (in all subframes, if any) -// in the target document. The element is passed as an argument. -var onProcessElement = [ ]; - -// These functions are called once when all the elements in all of the target -// document (and all of its subframes, if any) have been processed -var onFinished = [ ]; - -// These functions are called once when the Page Info window is closed. -var onUnloadRegistry = [ ]; - -// These functions are called once when an image preview is shown. -var onImagePreviewShown = [ ]; - -/* Called when PageInfo window is loaded. Arguments are: - * window.arguments[0] - (optional) an object consisting of - * - doc: (optional) document to use for source. if not provided, - * the calling window's document will be used - * - initialTab: (optional) id of the inital tab to display - */ -function onLoadPageInfo() -{ - gBundle = document.getElementById("pageinfobundle"); - gStrings.unknown = gBundle.getString("unknown"); - gStrings.notSet = gBundle.getString("notset"); - gStrings.mediaImg = gBundle.getString("mediaImg"); - gStrings.mediaBGImg = gBundle.getString("mediaBGImg"); - gStrings.mediaBorderImg = gBundle.getString("mediaBorderImg"); - gStrings.mediaListImg = gBundle.getString("mediaListImg"); - gStrings.mediaCursor = gBundle.getString("mediaCursor"); - gStrings.mediaObject = gBundle.getString("mediaObject"); - gStrings.mediaEmbed = gBundle.getString("mediaEmbed"); - gStrings.mediaLink = gBundle.getString("mediaLink"); - gStrings.mediaInput = gBundle.getString("mediaInput"); - gStrings.mediaVideo = gBundle.getString("mediaVideo"); - gStrings.mediaAudio = gBundle.getString("mediaAudio"); - - var args = "arguments" in window && - window.arguments.length >= 1 && - window.arguments[0]; - - if (!args || !args.doc) { - gWindow = window.opener.content; - gDocument = gWindow.document; - } - - // init media view - var imageTree = document.getElementById("imagetree"); - imageTree.view = gImageView; - - /* Select the requested tab, if the name is specified */ - loadTab(args); - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .notifyObservers(window, "page-info-dialog-loaded", null); - - // Make sure the page info window gets focus even if a doorhanger might - // otherwise (async) steal it. - window.focus(); -} - -function loadPageInfo() -{ - var titleFormat = gWindow != gWindow.top ? "pageInfo.frame.title" - : "pageInfo.page.title"; - document.title = gBundle.getFormattedString(titleFormat, [gDocument.location]); - - document.getElementById("main-window").setAttribute("relatedUrl", gDocument.location); - - // do the easy stuff first - makeGeneralTab(); - - // and then the hard stuff - makeTabs(gDocument, gWindow); - - initFeedTab(); - onLoadPermission(); - - /* Call registered overlay init functions */ - onLoadRegistry.forEach(function(func) { func(); }); -} - -function resetPageInfo(args) -{ - /* Reset Meta tags part */ - gMetaView.clear(); - - /* Reset Media tab */ - var mediaTab = document.getElementById("mediaTab"); - if (!mediaTab.hidden) { - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .removeObserver(imagePermissionObserver, "perm-changed"); - mediaTab.hidden = true; - } - gImageView.clear(); - gImageHash = {}; - - /* Reset Feeds Tab */ - var feedListbox = document.getElementById("feedListbox"); - while (feedListbox.firstChild) - feedListbox.removeChild(feedListbox.firstChild); - - /* Call registered overlay reset functions */ - onResetRegistry.forEach(function(func) { func(); }); - - /* Rebuild the data */ - loadTab(args); -} - -function onUnloadPageInfo() -{ - // Remove the observer, only if there is at least 1 image. - if (!document.getElementById("mediaTab").hidden) { - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .removeObserver(imagePermissionObserver, "perm-changed"); - } - - /* Call registered overlay unload functions */ - onUnloadRegistry.forEach(function(func) { func(); }); -} - -function doHelpButton() -{ - const helpTopics = { - "generalPanel": "pageinfo_general", - "mediaPanel": "pageinfo_media", - "feedPanel": "pageinfo_feed", - "permPanel": "pageinfo_permissions", - "securityPanel": "pageinfo_security" - }; - - var deck = document.getElementById("mainDeck"); - var helpdoc = helpTopics[deck.selectedPanel.id] || "pageinfo_general"; - openHelpLink(helpdoc); -} - -function showTab(id) -{ - var deck = document.getElementById("mainDeck"); - var pagel = document.getElementById(id + "Panel"); - deck.selectedPanel = pagel; -} - -function loadTab(args) -{ - if (args && args.doc) { - gDocument = args.doc; - gWindow = gDocument.defaultView; - } - - gImageElement = args && args.imageElement; - - /* Load the page info */ - loadPageInfo(); - - var initialTab = (args && args.initialTab) || "generalTab"; - var radioGroup = document.getElementById("viewGroup"); - initialTab = document.getElementById(initialTab) || document.getElementById("generalTab"); - radioGroup.selectedItem = initialTab; - radioGroup.selectedItem.doCommand(); - radioGroup.focus(); -} - -function onClickMore() -{ - var radioGrp = document.getElementById("viewGroup"); - var radioElt = document.getElementById("securityTab"); - radioGrp.selectedItem = radioElt; - showTab('security'); -} - -function toggleGroupbox(id) -{ - var elt = document.getElementById(id); - if (elt.hasAttribute("closed")) { - elt.removeAttribute("closed"); - if (elt.flexWhenOpened) - elt.flex = elt.flexWhenOpened; - } - else { - elt.setAttribute("closed", "true"); - if (elt.flex) { - elt.flexWhenOpened = elt.flex; - elt.flex = 0; - } - } -} - -function openCacheEntry(key, cb) -{ - var checkCacheListener = { - onCacheEntryCheck: function(entry, appCache) { - return Components.interfaces.nsICacheEntryOpenCallback.ENTRY_WANTED; - }, - onCacheEntryAvailable: function(entry, isNew, appCache, status) { - cb(entry); - }, - get mainThreadOnly() { return true; } - }; - diskStorage.asyncOpenURI(Services.io.newURI(key, null, null), "", nsICacheStorage.OPEN_READONLY, checkCacheListener); -} - -function makeGeneralTab() -{ - var title = (gDocument.title) ? gBundle.getFormattedString("pageTitle", [gDocument.title]) : gBundle.getString("noPageTitle"); - document.getElementById("titletext").value = title; - - var url = gDocument.location.toString(); - setItemValue("urltext", url); - - var referrer = ("referrer" in gDocument && gDocument.referrer); - setItemValue("refertext", referrer); - - var mode = ("compatMode" in gDocument && gDocument.compatMode == "BackCompat") ? "generalQuirksMode" : "generalStrictMode"; - document.getElementById("modetext").value = gBundle.getString(mode); - - // find out the mime type - var mimeType = gDocument.contentType; - setItemValue("typetext", mimeType); - - // get the document characterset - var encoding = gDocument.characterSet; - document.getElementById("encodingtext").value = encoding; - - // get the meta tags - var metaNodes = gDocument.getElementsByTagName("meta"); - var length = metaNodes.length; - - var metaGroup = document.getElementById("metaTags"); - if (!length) - metaGroup.collapsed = true; - else { - var metaTagsCaption = document.getElementById("metaTagsCaption"); - if (length == 1) - metaTagsCaption.label = gBundle.getString("generalMetaTag"); - else - metaTagsCaption.label = gBundle.getFormattedString("generalMetaTags", [length]); - var metaTree = document.getElementById("metatree"); - metaTree.view = gMetaView; - - for (var i = 0; i < length; i++) - gMetaView.addRow([metaNodes[i].name || metaNodes[i].httpEquiv, metaNodes[i].content]); - - metaGroup.collapsed = false; - } - - // get the date of last modification - var modifiedText = formatDate(gDocument.lastModified, gStrings.notSet); - document.getElementById("modifiedtext").value = modifiedText; - - // get cache info - var cacheKey = url.replace(/#.*$/, ""); - openCacheEntry(cacheKey, function(cacheEntry) { - var sizeText; - if (cacheEntry) { - var pageSize = cacheEntry.dataSize; - var kbSize = formatNumber(Math.round(pageSize / 1024 * 100) / 100); - sizeText = gBundle.getFormattedString("generalSize", [kbSize, formatNumber(pageSize)]); - } - setItemValue("sizetext", sizeText); - }); - - securityOnLoad(); -} - -//******** Generic Build-a-tab -// Assumes the views are empty. Only called once to build the tabs, and -// does so by farming the task off to another thread via setTimeout(). -// The actual work is done with a TreeWalker that calls doGrab() once for -// each element node in the document. - -var gFrameList = [ ]; - -function makeTabs(aDocument, aWindow) -{ - goThroughFrames(aDocument, aWindow); - processFrames(); -} - -function goThroughFrames(aDocument, aWindow) -{ - gFrameList.push(aDocument); - if (aWindow && aWindow.frames.length > 0) { - var num = aWindow.frames.length; - for (var i = 0; i < num; i++) - goThroughFrames(aWindow.frames[i].document, aWindow.frames[i]); // recurse through the frames - } -} - -function processFrames() -{ - if (gFrameList.length) { - var doc = gFrameList[0]; - onProcessFrame.forEach(function(func) { func(doc); }); - var iterator = doc.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT, grabAll); - gFrameList.shift(); - setTimeout(doGrab, 10, iterator); - onFinished.push(selectImage); - } - else - onFinished.forEach(function(func) { func(); }); -} - -function doGrab(iterator) -{ - for (var i = 0; i < 500; ++i) - if (!iterator.nextNode()) { - processFrames(); - return; - } - - setTimeout(doGrab, 10, iterator); -} - -function addImage(url, type, alt, elem, isBg) -{ - if (!url) - return; - - if (!gImageHash.hasOwnProperty(url)) - gImageHash[url] = { }; - if (!gImageHash[url].hasOwnProperty(type)) - gImageHash[url][type] = { }; - if (!gImageHash[url][type].hasOwnProperty(alt)) { - gImageHash[url][type][alt] = gImageView.data.length; - var row = [url, type, -1, alt, 1, elem, isBg]; - gImageView.addRow(row); - - // Fill in cache data asynchronously - openCacheEntry(url, function(cacheEntry) { - // The data at row[2] corresponds to the data size. - if (cacheEntry) { - row[2] = cacheEntry.dataSize; - // Invalidate the row to trigger a repaint. - gImageView.tree.invalidateRow(gImageView.data.indexOf(row)); - } - }); - - // Add the observer, only once. - if (gImageView.data.length == 1) { - document.getElementById("mediaTab").hidden = false; - Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService) - .addObserver(imagePermissionObserver, "perm-changed", false); - } - } - else { - var i = gImageHash[url][type][alt]; - gImageView.data[i][COL_IMAGE_COUNT]++; - if (elem == gImageElement) - gImageView.data[i][COL_IMAGE_NODE] = elem; - } -} - -function grabAll(elem) -{ - // check for images defined in CSS (e.g. background, borders), any node may have multiple - var computedStyle = elem.ownerDocument.defaultView.getComputedStyle(elem, ""); - - if (computedStyle) { - var addImgFunc = function (label, val) { - if (val.primitiveType == CSSPrimitiveValue.CSS_URI) { - addImage(val.getStringValue(), label, gStrings.notSet, elem, true); - } - else if (val.primitiveType == CSSPrimitiveValue.CSS_STRING) { - // This is for -moz-image-rect. - // TODO: Reimplement once bug 714757 is fixed - var strVal = val.getStringValue(); - if (strVal.search(/^.*url\(\"?/) > -1) { - url = strVal.replace(/^.*url\(\"?/,"").replace(/\"?\).*$/,""); - addImage(url, label, gStrings.notSet, elem, true); - } - } - else if (val.cssValueType == CSSValue.CSS_VALUE_LIST) { - // recursively resolve multiple nested CSS value lists - for (var i = 0; i < val.length; i++) - addImgFunc(label, val.item(i)); - } - }; - - addImgFunc(gStrings.mediaBGImg, computedStyle.getPropertyCSSValue("background-image")); - addImgFunc(gStrings.mediaBorderImg, computedStyle.getPropertyCSSValue("border-image-source")); - addImgFunc(gStrings.mediaListImg, computedStyle.getPropertyCSSValue("list-style-image")); - addImgFunc(gStrings.mediaCursor, computedStyle.getPropertyCSSValue("cursor")); - } - - // one swi^H^H^Hif-else to rule them all - if (elem instanceof HTMLImageElement) - addImage(elem.src, gStrings.mediaImg, - (elem.hasAttribute("alt")) ? elem.alt : gStrings.notSet, elem, false); - else if (elem instanceof SVGImageElement) { - try { - // Note: makeURLAbsolute will throw if either the baseURI is not a valid URI - // or the URI formed from the baseURI and the URL is not a valid URI - var href = makeURLAbsolute(elem.baseURI, elem.href.baseVal); - addImage(href, gStrings.mediaImg, "", elem, false); - } catch (e) { } - } - else if (elem instanceof HTMLVideoElement) { - addImage(elem.currentSrc, gStrings.mediaVideo, "", elem, false); - } - else if (elem instanceof HTMLAudioElement) { - addImage(elem.currentSrc, gStrings.mediaAudio, "", elem, false); - } - else if (elem instanceof HTMLLinkElement) { - if (elem.rel && /\bicon\b/i.test(elem.rel)) - addImage(elem.href, gStrings.mediaLink, "", elem, false); - } - else if (elem instanceof HTMLInputElement || elem instanceof HTMLButtonElement) { - if (elem.type.toLowerCase() == "image") - addImage(elem.src, gStrings.mediaInput, - (elem.hasAttribute("alt")) ? elem.alt : gStrings.notSet, elem, false); - } - else if (elem instanceof HTMLObjectElement) - addImage(elem.data, gStrings.mediaObject, getValueText(elem), elem, false); - else if (elem instanceof HTMLEmbedElement) - addImage(elem.src, gStrings.mediaEmbed, "", elem, false); - - onProcessElement.forEach(function(func) { func(elem); }); - - return NodeFilter.FILTER_ACCEPT; -} - -//******** Link Stuff -function openURL(target) -{ - var url = target.parentNode.childNodes[2].value; - window.open(url, "_blank", "chrome"); -} - -function onBeginLinkDrag(event,urlField,descField) -{ - if (event.originalTarget.localName != "treechildren") - return; - - var tree = event.target; - if (!("treeBoxObject" in tree)) - tree = tree.parentNode; - - var row = tree.treeBoxObject.getRowAt(event.clientX, event.clientY); - if (row == -1) - return; - - // Adding URL flavor - var col = tree.columns[urlField]; - var url = tree.view.getCellText(row, col); - col = tree.columns[descField]; - var desc = tree.view.getCellText(row, col); - - var dt = event.dataTransfer; - dt.setData("text/x-moz-url", url + "\n" + desc); - dt.setData("text/url-list", url); - dt.setData("text/plain", url); -} - -//******** Image Stuff -function getSelectedRows(tree) -{ - var start = { }; - var end = { }; - var numRanges = tree.view.selection.getRangeCount(); - - var rowArray = [ ]; - for (var t = 0; t < numRanges; t++) { - tree.view.selection.getRangeAt(t, start, end); - for (var v = start.value; v <= end.value; v++) - rowArray.push(v); - } - - return rowArray; -} - -function getSelectedRow(tree) -{ - var rows = getSelectedRows(tree); - return (rows.length == 1) ? rows[0] : -1; -} - -function selectSaveFolder(aCallback) -{ - const nsILocalFile = Components.interfaces.nsILocalFile; - const nsIFilePicker = Components.interfaces.nsIFilePicker; - let titleText = gBundle.getString("mediaSelectFolder"); - let fp = Components.classes["@mozilla.org/filepicker;1"]. - createInstance(nsIFilePicker); - let fpCallback = function fpCallback_done(aResult) { - if (aResult == nsIFilePicker.returnOK) { - aCallback(fp.file.QueryInterface(nsILocalFile)); - } else { - aCallback(null); - } - }; - - fp.init(window, titleText, nsIFilePicker.modeGetFolder); - fp.appendFilters(nsIFilePicker.filterAll); - try { - let prefs = Components.classes[PREFERENCES_CONTRACTID]. - getService(Components.interfaces.nsIPrefBranch); - let initialDir = prefs.getComplexValue("browser.download.dir", nsILocalFile); - if (initialDir) { - fp.displayDirectory = initialDir; - } - } catch (ex) { - } - fp.open(fpCallback); -} - -function saveMedia() -{ - var tree = document.getElementById("imagetree"); - var rowArray = getSelectedRows(tree); - if (rowArray.length == 1) { - var row = rowArray[0]; - var item = gImageView.data[row][COL_IMAGE_NODE]; - var url = gImageView.data[row][COL_IMAGE_ADDRESS]; - - if (url) { - var titleKey = "SaveImageTitle"; - - if (item instanceof HTMLVideoElement) - titleKey = "SaveVideoTitle"; - else if (item instanceof HTMLAudioElement) - titleKey = "SaveAudioTitle"; - - saveURL(url, null, titleKey, false, false, makeURI(item.baseURI), gDocument); - } - } else { - selectSaveFolder(function(aDirectory) { - if (aDirectory) { - var saveAnImage = function(aURIString, aChosenData, aBaseURI) { - internalSave(aURIString, null, null, null, null, false, "SaveImageTitle", - aChosenData, aBaseURI, gDocument); - }; - - for (var i = 0; i < rowArray.length; i++) { - var v = rowArray[i]; - var dir = aDirectory.clone(); - var item = gImageView.data[v][COL_IMAGE_NODE]; - var uriString = gImageView.data[v][COL_IMAGE_ADDRESS]; - var uri = makeURI(uriString); - - try { - uri.QueryInterface(Components.interfaces.nsIURL); - dir.append(decodeURIComponent(uri.fileName)); - } catch(ex) { - /* data: uris */ - } - - if (i == 0) { - saveAnImage(uriString, new AutoChosen(dir, uri), makeURI(item.baseURI)); - } else { - // This delay is a hack which prevents the download manager - // from opening many times. See bug 377339. - setTimeout(saveAnImage, 200, uriString, new AutoChosen(dir, uri), - makeURI(item.baseURI)); - } - } - } - }); - } -} - -function onBlockImage() -{ - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - - var checkbox = document.getElementById("blockImage"); - var uri = makeURI(document.getElementById("imageurltext").value); - if (checkbox.checked) - permissionManager.add(uri, "image", nsIPermissionManager.DENY_ACTION); - else - permissionManager.remove(uri.host, "image"); -} - -function onImageSelect() -{ - var previewBox = document.getElementById("mediaPreviewBox"); - var mediaSaveBox = document.getElementById("mediaSaveBox"); - var splitter = document.getElementById("mediaSplitter"); - var tree = document.getElementById("imagetree"); - var count = tree.view.selection.count; - if (count == 0) { - previewBox.collapsed = true; - mediaSaveBox.collapsed = true; - splitter.collapsed = true; - tree.flex = 1; - } - else if (count > 1) { - splitter.collapsed = true; - previewBox.collapsed = true; - mediaSaveBox.collapsed = false; - tree.flex = 1; - } - else { - mediaSaveBox.collapsed = true; - splitter.collapsed = false; - previewBox.collapsed = false; - tree.flex = 0; - makePreview(getSelectedRows(tree)[0]); - } -} - -function makePreview(row) -{ - var imageTree = document.getElementById("imagetree"); - var item = gImageView.data[row][COL_IMAGE_NODE]; - var url = gImageView.data[row][COL_IMAGE_ADDRESS]; - var isBG = gImageView.data[row][COL_IMAGE_BG]; - var isAudio = false; - - setItemValue("imageurltext", url); - - var imageText; - if (!isBG && - !(item instanceof SVGImageElement) && - !(gDocument instanceof ImageDocument)) { - imageText = item.title || item.alt; - - if (!imageText && !(item instanceof HTMLImageElement)) - imageText = getValueText(item); - } - setItemValue("imagetext", imageText); - - setItemValue("imagelongdesctext", item.longDesc); - - // get cache info - var cacheKey = url.replace(/#.*$/, ""); - openCacheEntry(cacheKey, function(cacheEntry) { - // find out the file size - var sizeText; - if (cacheEntry) { - var imageSize = cacheEntry.dataSize; - var kbSize = Math.round(imageSize / 1024 * 100) / 100; - sizeText = gBundle.getFormattedString("generalSize", - [formatNumber(kbSize), formatNumber(imageSize)]); - } - else - sizeText = gBundle.getString("mediaUnknownNotCached"); - setItemValue("imagesizetext", sizeText); - - var mimeType; - var numFrames = 1; - if (item instanceof HTMLObjectElement || - item instanceof HTMLEmbedElement || - item instanceof HTMLLinkElement) - mimeType = item.type; - - if (!mimeType && !isBG && item instanceof nsIImageLoadingContent) { - var imageRequest = item.getRequest(nsIImageLoadingContent.CURRENT_REQUEST); - if (imageRequest) { - mimeType = imageRequest.mimeType; - var image = imageRequest.image; - if (image) - numFrames = image.numFrames; - } - } - - if (!mimeType) - mimeType = getContentTypeFromHeaders(cacheEntry); - - // if we have a data url, get the MIME type from the url - if (!mimeType && url.startsWith("data:")) { - let dataMimeType = /^data:(image\/[^;,]+)/i.exec(url); - if (dataMimeType) - mimeType = dataMimeType[1].toLowerCase(); - } - - var imageType; - if (mimeType) { - // We found the type, try to display it nicely - let imageMimeType = /^image\/(.*)/i.exec(mimeType); - if (imageMimeType) { - imageType = imageMimeType[1].toUpperCase(); - if (numFrames > 1) - imageType = gBundle.getFormattedString("mediaAnimatedImageType", - [imageType, numFrames]); - else - imageType = gBundle.getFormattedString("mediaImageType", [imageType]); - } - else { - // the MIME type doesn't begin with image/, display the raw type - imageType = mimeType; - } - } - else { - // We couldn't find the type, fall back to the value in the treeview - imageType = gImageView.data[row][COL_IMAGE_TYPE]; - } - setItemValue("imagetypetext", imageType); - - var imageContainer = document.getElementById("theimagecontainer"); - var oldImage = document.getElementById("thepreviewimage"); - - var isProtocolAllowed = checkProtocol(gImageView.data[row]); - - var newImage = new Image; - newImage.id = "thepreviewimage"; - var physWidth = 0, physHeight = 0; - var width = 0, height = 0; - - if ((item instanceof HTMLLinkElement || item instanceof HTMLInputElement || - item instanceof HTMLImageElement || - item instanceof SVGImageElement || - (item instanceof HTMLObjectElement && mimeType && mimeType.startsWith("image/")) || isBG) && isProtocolAllowed) { - newImage.setAttribute("src", url); - physWidth = newImage.width || 0; - physHeight = newImage.height || 0; - - // "width" and "height" attributes must be set to newImage, - // even if there is no "width" or "height attribute in item; - // otherwise, the preview image cannot be displayed correctly. - if (!isBG) { - newImage.width = ("width" in item && item.width) || newImage.naturalWidth; - newImage.height = ("height" in item && item.height) || newImage.naturalHeight; - } - else { - // the Width and Height of an HTML tag should not be used for its background image - // (for example, "table" can have "width" or "height" attributes) - newImage.width = newImage.naturalWidth; - newImage.height = newImage.naturalHeight; - } - - if (item instanceof SVGImageElement) { - newImage.width = item.width.baseVal.value; - newImage.height = item.height.baseVal.value; - } - - width = newImage.width; - height = newImage.height; - - document.getElementById("theimagecontainer").collapsed = false - document.getElementById("brokenimagecontainer").collapsed = true; - } - else if (item instanceof HTMLVideoElement && isProtocolAllowed) { - newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video"); - newImage.id = "thepreviewimage"; - newImage.src = url; - newImage.controls = true; - width = physWidth = item.videoWidth; - height = physHeight = item.videoHeight; - - document.getElementById("theimagecontainer").collapsed = false; - document.getElementById("brokenimagecontainer").collapsed = true; - } - else if (item instanceof HTMLAudioElement && isProtocolAllowed) { - newImage = new Audio; - newImage.id = "thepreviewimage"; - newImage.src = url; - newImage.controls = true; - isAudio = true; - - document.getElementById("theimagecontainer").collapsed = false; - document.getElementById("brokenimagecontainer").collapsed = true; - } - else { - // fallback image for protocols not allowed (e.g., javascript:) - // or elements not [yet] handled (e.g., object, embed). - document.getElementById("brokenimagecontainer").collapsed = false; - document.getElementById("theimagecontainer").collapsed = true; - } - - var imageSize = ""; - if (url && !isAudio) { - if (width != physWidth || height != physHeight) { - imageSize = gBundle.getFormattedString("mediaDimensionsScaled", - [formatNumber(physWidth), - formatNumber(physHeight), - formatNumber(width), - formatNumber(height)]); - } - else { - imageSize = gBundle.getFormattedString("mediaDimensions", - [formatNumber(width), - formatNumber(height)]); - } - } - setItemValue("imagedimensiontext", imageSize); - - makeBlockImage(url); - - imageContainer.removeChild(oldImage); - imageContainer.appendChild(newImage); - - onImagePreviewShown.forEach(function(func) { func(); }); - }); -} - -function makeBlockImage(url) -{ - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - var prefs = Components.classes[PREFERENCES_CONTRACTID] - .getService(Components.interfaces.nsIPrefBranch); - - var checkbox = document.getElementById("blockImage"); - var imagePref = prefs.getIntPref("permissions.default.image"); - if (!(/^https?:/.test(url)) || imagePref == 2) - // We can't block the images from this host because either is is not - // for http(s) or we don't load images at all - checkbox.hidden = true; - else { - var uri = makeURI(url); - if (uri.host) { - checkbox.hidden = false; - checkbox.label = gBundle.getFormattedString("mediaBlockImage", [uri.host]); - var perm = permissionManager.testPermission(uri, "image"); - checkbox.checked = perm == nsIPermissionManager.DENY_ACTION; - } - else - checkbox.hidden = true; - } -} - -var imagePermissionObserver = { - observe: function (aSubject, aTopic, aData) - { - if (document.getElementById("mediaPreviewBox").collapsed) - return; - - if (aTopic == "perm-changed") { - var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); - if (permission.type == "image") { - var imageTree = document.getElementById("imagetree"); - 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) - makeBlockImage(url); - } - } - } -} - -function getContentTypeFromHeaders(cacheEntryDescriptor) -{ - if (!cacheEntryDescriptor) - return null; - - return (/^Content-Type:\s*(.*?)\s*(?:\;|$)/mi - .exec(cacheEntryDescriptor.getMetaDataElement("response-head")))[1]; -} - -//******** Other Misc Stuff -// Modified from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html -// parse a node to extract the contents of the node -function getValueText(node) -{ - var valueText = ""; - - // form input elements don't generally contain information that is useful to our callers, so return nothing - if (node instanceof HTMLInputElement || - node instanceof HTMLSelectElement || - node instanceof HTMLTextAreaElement) - return valueText; - - // otherwise recurse for each child - var length = node.childNodes.length; - for (var i = 0; i < length; i++) { - var childNode = node.childNodes[i]; - var nodeType = childNode.nodeType; - - // text nodes are where the goods are - if (nodeType == Node.TEXT_NODE) - valueText += " " + childNode.nodeValue; - // and elements can have more text inside them - else if (nodeType == Node.ELEMENT_NODE) { - // images are special, we want to capture the alt text as if the image weren't there - if (childNode instanceof HTMLImageElement) - valueText += " " + getAltText(childNode); - else - valueText += " " + getValueText(childNode); - } - } - - return stripWS(valueText); -} - -// Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html -// traverse the tree in search of an img or area element and grab its alt tag -function getAltText(node) -{ - var altText = ""; - - if (node.alt) - return node.alt; - var length = node.childNodes.length; - for (var i = 0; i < length; i++) - if ((altText = getAltText(node.childNodes[i]) != undefined)) // stupid js warning... - return altText; - return ""; -} - -// Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html -// strip leading and trailing whitespace, and replace multiple consecutive whitespace characters with a single space -function stripWS(text) -{ - var middleRE = /\s+/g; - var endRE = /(^\s+)|(\s+$)/g; - - text = text.replace(middleRE, " "); - return text.replace(endRE, ""); -} - -function setItemValue(id, value) -{ - var item = document.getElementById(id); - if (value) { - item.parentNode.collapsed = false; - item.value = value; - } - else - item.parentNode.collapsed = true; -} - -function formatNumber(number) -{ - return (+number).toLocaleString(); // coerce number to a numeric value before calling toLocaleString() -} - -function formatDate(datestr, unknown) -{ - // scriptable date formatter, for pretty printing dates - var dateService = Components.classes["@mozilla.org/intl/scriptabledateformat;1"] - .getService(Components.interfaces.nsIScriptableDateFormat); - - var date = new Date(datestr); - if (!date.valueOf()) - return unknown; - - return dateService.FormatDateTime("", dateService.dateFormatLong, - dateService.timeFormatSeconds, - date.getFullYear(), date.getMonth()+1, date.getDate(), - date.getHours(), date.getMinutes(), date.getSeconds()); -} - -function doCopy() -{ - if (!gClipboardHelper) - return; - - var elem = document.commandDispatcher.focusedElement; - - if (elem && "treeBoxObject" in elem) { - var view = elem.view; - var selection = view.selection; - var text = [], tmp = ''; - var min = {}, max = {}; - - var count = selection.getRangeCount(); - - for (var i = 0; i < count; i++) { - selection.getRangeAt(i, min, max); - - for (var row = min.value; row <= max.value; row++) { - view.performActionOnRow("copy", row); - - tmp = elem.getAttribute("copybuffer"); - if (tmp) - text.push(tmp); - elem.removeAttribute("copybuffer"); - } - } - gClipboardHelper.copyString(text.join("\n"), document); - } -} - -function doSelectAll() -{ - var elem = document.commandDispatcher.focusedElement; - - if (elem && "treeBoxObject" in elem) - elem.view.selection.selectAll(); -} - -function selectImage() -{ - if (!gImageElement) - return; - - var tree = document.getElementById("imagetree"); - for (var i = 0; i < tree.view.rowCount; i++) { - if (gImageElement == gImageView.data[i][COL_IMAGE_NODE] && - !gImageView.data[i][COL_IMAGE_BG]) { - tree.view.selection.select(i); - tree.treeBoxObject.ensureRowIsVisible(i); - tree.focus(); - return; - } - } -} - -function checkProtocol(img) -{ - var url = img[COL_IMAGE_ADDRESS]; - return /^data:image\//i.test(url) || - /^(https?|ftp|file|about|chrome|resource):/.test(url); -} diff --git a/browser/base/content/pageinfo/pageInfo.xml b/browser/base/content/pageinfo/pageInfo.xml deleted file mode 100644 index 20d330046..000000000 --- a/browser/base/content/pageinfo/pageInfo.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - -<bindings id="pageInfoBindings" - xmlns="http://www.mozilla.org/xbl" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:xbl="http://www.mozilla.org/xbl"> - - <!-- based on preferences.xml paneButton --> - <binding id="viewbutton" extends="chrome://global/content/bindings/radio.xml#radio"> - <content> - <xul:image class="viewButtonIcon" xbl:inherits="src"/> - <xul:label class="viewButtonLabel" xbl:inherits="value=label"/> - </content> - <implementation implements="nsIAccessibleProvider"> - <property name="accessibleType" readonly="true"> - <getter> - <![CDATA[ - return Components.interfaces.nsIAccessibleProvider.XULListitem; - ]]> - </getter> - </property> - </implementation> - </binding> - -</bindings> diff --git a/browser/base/content/pageinfo/pageInfo.xul b/browser/base/content/pageinfo/pageInfo.xul deleted file mode 100644 index 5bca1b495..000000000 --- a/browser/base/content/pageinfo/pageInfo.xul +++ /dev/null @@ -1,559 +0,0 @@ -<?xml version="1.0"?> -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -<?xml-stylesheet href="chrome://browser/content/pageinfo/pageInfo.css" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/pageInfo.css" type="text/css"?> - -<!DOCTYPE window [ - <!ENTITY % pageInfoDTD SYSTEM "chrome://browser/locale/pageInfo.dtd"> - %pageInfoDTD; -]> - -#ifdef XP_MACOSX -<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?> -#endif - -<window id="main-window" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - windowtype="Browser:page-info" - onload="onLoadPageInfo()" - onunload="onUnloadPageInfo()" - align="stretch" - screenX="10" screenY="10" - width="&pageInfoWindow.width;" height="&pageInfoWindow.height;" - persist="screenX screenY width height sizemode"> - - <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/> - <script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/> - <script type="application/javascript" src="chrome://global/content/treeUtils.js"/> - <script type="application/javascript" src="chrome://browser/content/pageinfo/pageInfo.js"/> - <script type="application/javascript" src="chrome://browser/content/pageinfo/feeds.js"/> - <script type="application/javascript" src="chrome://browser/content/pageinfo/permissions.js"/> - <script type="application/javascript" src="chrome://browser/content/pageinfo/security.js"/> - <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/> - - <stringbundleset id="pageinfobundleset"> - <stringbundle id="pageinfobundle" src="chrome://browser/locale/pageInfo.properties"/> - <stringbundle id="pkiBundle" src="chrome://pippki/locale/pippki.properties"/> - <stringbundle id="browserBundle" src="chrome://browser/locale/browser.properties"/> - </stringbundleset> - - <commandset id="pageInfoCommandSet"> - <command id="cmd_close" oncommand="window.close();"/> - <command id="cmd_help" oncommand="doHelpButton();"/> - <command id="cmd_copy" oncommand="doCopy();"/> - <command id="cmd_selectall" oncommand="doSelectAll();"/> - - <!-- permissions tab --> - <command id="cmd_imageDef" oncommand="onCheckboxClick('image');"/> - <command id="cmd_popupDef" oncommand="onCheckboxClick('popup');"/> - <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');"/> - <command id="cmd_imageToggle" oncommand="onRadioClick('image');"/> - <command id="cmd_popupToggle" oncommand="onRadioClick('popup');"/> - <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"> - <key key="&closeWindow.key;" modifiers="accel" command="cmd_close"/> - <key keycode="VK_ESCAPE" command="cmd_close"/> -#ifdef XP_MACOSX - <key key="." modifiers="meta" command="cmd_close"/> -#else - <key keycode="VK_F1" command="cmd_help"/> -#endif - <key key="©.key;" modifiers="accel" command="cmd_copy"/> - <key key="&selectall.key;" modifiers="accel" command="cmd_selectall"/> - <key key="&selectall.key;" modifiers="alt" command="cmd_selectall"/> - </keyset> - - <menupopup id="picontext"> - <menuitem id="menu_selectall" label="&selectall.label;" command="cmd_selectall" accesskey="&selectall.accesskey;"/> - <menuitem id="menu_copy" label="©.label;" command="cmd_copy" accesskey="©.accesskey;"/> - </menupopup> - - <windowdragbox id="topBar" class="viewGroupWrapper"> - <radiogroup id="viewGroup" class="chromeclass-toolbar" orient="horizontal"> - <radio id="generalTab" label="&generalTab;" accesskey="&generalTab.accesskey;" - oncommand="showTab('general');"/> - <radio id="mediaTab" label="&mediaTab;" accesskey="&mediaTab.accesskey;" - oncommand="showTab('media');" hidden="true"/> - <radio id="feedTab" label="&feedTab;" accesskey="&feedTab.accesskey;" - oncommand="showTab('feed');" hidden="true"/> - <radio id="permTab" label="&permTab;" accesskey="&permTab.accesskey;" - oncommand="showTab('perm');"/> - <radio id="securityTab" label="&securityTab;" accesskey="&securityTab.accesskey;" - oncommand="showTab('security');"/> - <!-- Others added by overlay --> - </radiogroup> - </windowdragbox> - - <deck id="mainDeck" flex="1"> - <!-- General page information --> - <vbox id="generalPanel"> - <textbox class="header" readonly="true" id="titletext"/> - <grid id="generalGrid"> - <columns> - <column/> - <column class="gridSeparator"/> - <column flex="1"/> - </columns> - <rows id="generalRows"> - <row id="generalURLRow"> - <label control="urltext" value="&generalURL;"/> - <separator/> - <textbox readonly="true" id="urltext"/> - </row> - <row id="generalSeparatorRow1"> - <separator class="thin"/> - </row> - <row id="generalTypeRow"> - <label control="typetext" value="&generalType;"/> - <separator/> - <textbox readonly="true" id="typetext"/> - </row> - <row id="generalModeRow"> - <label control="modetext" value="&generalMode;"/> - <separator/> - <textbox readonly="true" crop="end" id="modetext"/> - </row> - <row id="generalEncodingRow"> - <label control="encodingtext" value="&generalEncoding;"/> - <separator/> - <textbox readonly="true" id="encodingtext"/> - </row> - <row id="generalSizeRow"> - <label control="sizetext" value="&generalSize;"/> - <separator/> - <textbox readonly="true" id="sizetext"/> - </row> - <row id="generalReferrerRow"> - <label control="refertext" value="&generalReferrer;"/> - <separator/> - <textbox readonly="true" id="refertext"/> - </row> - <row id="generalSeparatorRow2"> - <separator class="thin"/> - </row> - <row id="generalModifiedRow"> - <label control="modifiedtext" value="&generalModified;"/> - <separator/> - <textbox readonly="true" id="modifiedtext"/> - </row> - </rows> - </grid> - <separator class="thin"/> - <groupbox id="metaTags" flex="1" class="collapsable treebox"> - <caption id="metaTagsCaption" onclick="toggleGroupbox('metaTags');"/> - <tree id="metatree" flex="1" hidecolumnpicker="true" contextmenu="picontext"> - <treecols> - <treecol id="meta-name" label="&generalMetaName;" - persist="width" flex="1" - onclick="gMetaView.onPageMediaSort('meta-name');"/> - <splitter class="tree-splitter"/> - <treecol id="meta-content" label="&generalMetaContent;" - persist="width" flex="4" - onclick="gMetaView.onPageMediaSort('meta-content');"/> - </treecols> - <treechildren id="metatreechildren" flex="1"/> - </tree> - </groupbox> - <groupbox id="securityBox"> - <caption id="securityBoxCaption" label="&securityHeader;"/> - <description id="general-security-identity" class="header"/> - <description id="general-security-privacy" class="header"/> - <hbox id="securityDetailsButtonBox" align="right"> - <button id="security-view-details" label="&generalSecurityDetails;" - accesskey="&generalSecurityDetails.accesskey;" - oncommand="onClickMore();"/> - </hbox> - </groupbox> - </vbox> - - <!-- Media information --> - <vbox id="mediaPanel"> - <tree id="imagetree" onselect="onImageSelect();" contextmenu="picontext" - ondragstart="onBeginLinkDrag(event,'image-address','image-alt')"> - <treecols> - <treecol sortSeparators="true" primary="true" persist="width" flex="10" - width="10" id="image-address" label="&mediaAddress;" - onclick="gImageView.onPageMediaSort('image-address');"/> - <splitter class="tree-splitter"/> - <treecol sortSeparators="true" persist="hidden width" flex="2" - width="2" id="image-type" label="&mediaType;" - onclick="gImageView.onPageMediaSort('image-type');"/> - <splitter class="tree-splitter"/> - <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="2" - width="2" id="image-size" label="&mediaSize;" value="size" - onclick="gImageView.onPageMediaSort('image-size');"/> - <splitter class="tree-splitter"/> - <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="4" - width="4" id="image-alt" label="&mediaAltHeader;" - onclick="gImageView.onPageMediaSort('image-alt');"/> - <splitter class="tree-splitter"/> - <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="1" - width="1" id="image-count" label="&mediaCount;" - onclick="gImageView.onPageMediaSort('image-count');"/> - </treecols> - <treechildren id="imagetreechildren" flex="1"/> - </tree> - <splitter orient="vertical" id="mediaSplitter"/> - <vbox flex="1" id="mediaPreviewBox" collapsed="true"> - <grid id="mediaGrid"> - <columns> - <column id="mediaLabelColumn"/> - <column class="gridSeparator"/> - <column flex="1"/> - </columns> - <rows id="mediaRows"> - <row id="mediaLocationRow"> - <label control="imageurltext" value="&mediaLocation;"/> - <separator/> - <textbox readonly="true" id="imageurltext"/> - </row> - <row id="mediaTypeRow"> - <label control="imagetypetext" value="&generalType;"/> - <separator/> - <textbox readonly="true" id="imagetypetext"/> - </row> - <row id="mediaSizeRow"> - <label control="imagesizetext" value="&generalSize;"/> - <separator/> - <textbox readonly="true" id="imagesizetext"/> - </row> - <row id="mediaDimensionRow"> - <label control="imagedimensiontext" value="&mediaDimension;"/> - <separator/> - <textbox readonly="true" id="imagedimensiontext"/> - </row> - <row id="mediaTextRow"> - <label control="imagetext" value="&mediaText;"/> - <separator/> - <textbox readonly="true" id="imagetext"/> - </row> - <row id="mediaLongdescRow"> - <label control="imagelongdesctext" value="&mediaLongdesc;"/> - <separator/> - <textbox readonly="true" id="imagelongdesctext"/> - </row> - </rows> - </grid> - <hbox id="imageSaveBox" align="end"> - <vbox id="blockImageBox"> - <checkbox id="blockImage" hidden="true" oncommand="onBlockImage()" - accesskey="&mediaBlockImage.accesskey;"/> - <label control="thepreviewimage" value="&mediaPreview;" class="header"/> - </vbox> - <spacer id="imageSaveBoxSpacer" flex="1"/> - <button label="&mediaSaveAs;" accesskey="&mediaSaveAs.accesskey;" - icon="save" id="imagesaveasbutton" - oncommand="saveMedia();"/> - </hbox> - <vbox id="imagecontainerbox" class="inset iframe" flex="1" pack="center"> - <hbox id="theimagecontainer" pack="center"> - <image id="thepreviewimage"/> - </hbox> - <hbox id="brokenimagecontainer" pack="center" collapsed="true"> - <image id="brokenimage" src="resource://gre-resources/broken-image.png"/> - </hbox> - </vbox> - </vbox> - <hbox id="mediaSaveBox" collapsed="true"> - <spacer id="mediaSaveBoxSpacer" flex="1"/> - <button label="&mediaSaveAs;" accesskey="&mediaSaveAs2.accesskey;" - icon="save" id="mediasaveasbutton" - oncommand="saveMedia();"/> - </hbox> - </vbox> - - <!-- Feeds --> - <vbox id="feedPanel"> - <richlistbox id="feedListbox" flex="1"/> - </vbox> - - <!-- Permissions --> - <vbox id="permPanel"> - <hbox id="permHostBox"> - <label value="&permissionsFor;" control="hostText" /> - <textbox id="hostText" class="header" readonly="true" - crop="end" flex="1"/> - </hbox> - - <vbox id="permList" flex="1"> - <vbox class="permission" id="permImageRow"> - <label class="permissionLabel" id="permImageLabel" - value="&permImage;" control="imageRadioGroup"/> - <hbox id="permImageBox" role="group" aria-labelledby="permImageLabel"> - <checkbox id="imageDef" command="cmd_imageDef" label="&permUseDefault;"/> - <spacer flex="1"/> - <radiogroup id="imageRadioGroup" orient="horizontal"> - <radio id="image#1" command="cmd_imageToggle" label="&permAllow;"/> - <radio id="image#2" command="cmd_imageToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> - <vbox class="permission" id="permPopupRow"> - <label class="permissionLabel" id="permPopupLabel" - value="&permPopup;" control="popupRadioGroup"/> - <hbox id="permPopupBox" role="group" aria-labelledby="permPopupLabel"> - <checkbox id="popupDef" command="cmd_popupDef" label="&permUseDefault;"/> - <spacer flex="1"/> - <radiogroup id="popupRadioGroup" orient="horizontal"> - <radio id="popup#1" command="cmd_popupToggle" label="&permAllow;"/> - <radio id="popup#2" command="cmd_popupToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> - <vbox class="permission" id="permCookieRow"> - <label class="permissionLabel" id="permCookieLabel" - value="&permCookie;" control="cookieRadioGroup"/> - <hbox id="permCookieBox" role="group" aria-labelledby="permCookieLabel"> - <checkbox id="cookieDef" command="cmd_cookieDef" label="&permUseDefault;"/> - <spacer flex="1"/> - <radiogroup id="cookieRadioGroup" orient="horizontal"> - <radio id="cookie#1" command="cmd_cookieToggle" label="&permAllow;"/> - <radio id="cookie#8" command="cmd_cookieToggle" label="&permAllowSession;"/> - <radio id="cookie#9" command="cmd_cookieToggle" label="&permAllowFirstPartyOnly;"/> - <radio id="cookie#2" command="cmd_cookieToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> - <vbox class="permission" id="permNotificationRow"> - <label class="permissionLabel" id="permNotificationLabel" - value="&permNotifications;" control="desktop-notificationRadioGroup"/> - <hbox role="group" aria-labelledby="permNotificationLabel"> - <checkbox id="desktop-notificationDef" command="cmd_desktop-notificationDef" label="&permUseDefault;"/> - <spacer flex="1"/> - <radiogroup id="desktop-notificationRadioGroup" orient="horizontal"> - <radio id="desktop-notification#0" command="cmd_desktop-notificationToggle" label="&permAskAlways;"/> - <radio id="desktop-notification#1" command="cmd_desktop-notificationToggle" label="&permAllow;"/> - <radio id="desktop-notification#2" command="cmd_desktop-notificationToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> - <vbox class="permission" id="permInstallRow"> - <label class="permissionLabel" id="permInstallLabel" - value="&permInstall;" control="installRadioGroup"/> - <hbox id="permInstallBox" role="group" aria-labelledby="permInstallLabel"> - <checkbox id="installDef" command="cmd_installDef" label="&permUseDefault;"/> - <spacer flex="1"/> - <radiogroup id="installRadioGroup" orient="horizontal"> - <radio id="install#1" command="cmd_installToggle" label="&permAllow;"/> - <radio id="install#2" command="cmd_installToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> - <vbox class="permission" id="permGeoRow" > - <label class="permissionLabel" id="permGeoLabel" - value="&permGeo;" control="geoRadioGroup"/> - <hbox id="permGeoBox" role="group" aria-labelledby="permGeoLabel"> - <checkbox id="geoDef" command="cmd_geoDef" label="&permAskAlways;"/> - <spacer flex="1"/> - <radiogroup id="geoRadioGroup" orient="horizontal"> - <radio id="geo#1" command="cmd_geoToggle" label="&permAllow;"/> - <radio id="geo#2" command="cmd_geoToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - </vbox> - <vbox class="permission" id="permIndexedDBRow"> - <label class="permissionLabel" id="permIndexedDBLabel" - value="&permIndexedDB;" control="indexedDBRadioGroup"/> - <hbox id="permIndexedDBBox" role="group" aria-labelledby="permIndexedDBLabel"> - <checkbox id="indexedDBDef" command="cmd_indexedDBDef" label="&permUseDefault;"/> - <spacer flex="1"/> - <radiogroup id="indexedDBRadioGroup" orient="horizontal"> - <radio id="indexedDB#0" command="cmd_indexedDBToggle" label="&permAskAlways;"/> - <radio id="indexedDB#1" command="cmd_indexedDBToggle" label="&permAllow;"/> - <radio id="indexedDB#2" command="cmd_indexedDBToggle" label="&permBlock;"/> - </radiogroup> - </hbox> - <hbox id="permIndexedDBExtras"> - <spacer flex="1"/> - <vbox id="permIndexedDBStatusBox" pack="center"> - <label id="indexedDBStatus" control="indexedDBClear" hidden="true"/> - </vbox> - <button id="indexedDBClear" label="&permClearStorage;" hidden="true" - accesskey="&permClearStorage.accesskey;" onclick="onIndexedDBClear();"/> - </hbox> - </vbox> - <vbox class="permission" id="permPluginsRow"> - <label class="permissionLabel" id="permPluginsLabel" - value="&permPlugins;" control="pluginsRadioGroup"/> - <hbox id="permPluginTemplate" role="group" aria-labelledby="permPluginsLabel" align="baseline"> - <label class="permPluginTemplateLabel"/> - <spacer flex="1"/> - <radiogroup class="permPluginTemplateRadioGroup" orient="horizontal" command="cmd_pluginsToggle"> - <radio class="permPluginTemplateRadioDefault" label="&permUseDefault;"/> - <radio class="permPluginTemplateRadioAsk" label="&permAskAlways;"/> - <radio class="permPluginTemplateRadioAllow" label="&permAllow;"/> - <radio class="permPluginTemplateRadioBlock" label="&permBlock;"/> - </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> - - <!-- Security & Privacy --> - <vbox id="securityPanel"> - <!-- Identity Section --> - <groupbox id="security-identity-groupbox" flex="1"> - <caption id="security-identity" label="&securityView.identity.header;"/> - <grid id="security-identity-grid" flex="1"> - <columns> - <column/> - <column flex="1"/> - </columns> - <rows id="security-identity-rows"> - <!-- Domain --> - <row id="security-identity-domain-row"> - <label id="security-identity-domain-label" - class="fieldLabel" - value="&securityView.identity.domain;" - control="security-identity-domain-value"/> - <textbox id="security-identity-domain-value" - class="fieldValue" readonly="true"/> - </row> - <!-- Owner --> - <row id="security-identity-owner-row"> - <label id="security-identity-owner-label" - class="fieldLabel" - value="&securityView.identity.owner;" - control="security-identity-owner-value"/> - <textbox id="security-identity-owner-value" - class="fieldValue" readonly="true"/> - </row> - <!-- Verifier --> - <row id="security-identity-verifier-row"> - <label id="security-identity-verifier-label" - class="fieldLabel" - value="&securityView.identity.verifier;" - control="security-identity-verifier-value"/> - <textbox id="security-identity-verifier-value" - class="fieldValue" readonly="true" /> - </row> - </rows> - </grid> - <spacer flex="1"/> - <!-- Cert button --> - <hbox id="security-view-cert-box" pack="end"> - <button id="security-view-cert" label="&securityView.certView;" - accesskey="&securityView.accesskey;" - oncommand="security.viewCert();"/> - </hbox> - </groupbox> - - <!-- Privacy & History section --> - <groupbox id="security-privacy-groupbox" flex="1"> - <caption id="security-privacy" label="&securityView.privacy.header;" /> - <grid id="security-privacy-grid"> - <columns> - <column flex="1"/> - <column flex="1"/> - </columns> - <rows id="security-privacy-rows"> - <!-- History --> - <row id="security-privacy-history-row"> - <label id="security-privacy-history-label" - control="security-privacy-history-value" - class="fieldLabel">&securityView.privacy.history;</label> - <textbox id="security-privacy-history-value" - class="fieldValue" - value="&securityView.unknown;" - readonly="true"/> - </row> - <!-- Cookies --> - <row id="security-privacy-cookies-row"> - <label id="security-privacy-cookies-label" - control="security-privacy-cookies-value" - class="fieldLabel">&securityView.privacy.cookies;</label> - <hbox id="security-privacy-cookies-box" align="center"> - <textbox id="security-privacy-cookies-value" - class="fieldValue" - value="&securityView.unknown;" - flex="1" - readonly="true"/> - <button id="security-view-cookies" - label="&securityView.privacy.viewCookies;" - accesskey="&securityView.privacy.viewCookies.accessKey;" - oncommand="security.viewCookies();"/> - </hbox> - </row> - <!-- Passwords --> - <row id="security-privacy-passwords-row"> - <label id="security-privacy-passwords-label" - control="security-privacy-passwords-value" - class="fieldLabel">&securityView.privacy.passwords;</label> - <hbox id="security-privacy-passwords-box" align="center"> - <textbox id="security-privacy-passwords-value" - class="fieldValue" - value="&securityView.unknown;" - flex="1" - readonly="true"/> - <button id="security-view-password" - label="&securityView.privacy.viewPasswords;" - accesskey="&securityView.privacy.viewPasswords.accessKey;" - oncommand="security.viewPasswords();"/> - </hbox> - </row> - </rows> - </grid> - </groupbox> - - <!-- Technical Details section --> - <groupbox id="security-technical-groupbox" flex="1"> - <caption id="security-technical" label="&securityView.technical.header;" /> - <vbox id="security-technical-box" flex="1"> - <label id="security-technical-shortform" class="fieldValue"/> - <description id="security-technical-longform1" class="fieldLabel"/> - <description id="security-technical-longform2" class="fieldLabel"/> - </vbox> - </groupbox> - </vbox> - <!-- Others added by overlay --> - </deck> - -#ifdef XP_MACOSX -#include ../browserMountPoints.inc -#endif - -</window> diff --git a/browser/base/content/pageinfo/permissions.js b/browser/base/content/pageinfo/permissions.js deleted file mode 100644 index 7a0006b61..000000000 --- a/browser/base/content/pageinfo/permissions.js +++ /dev/null @@ -1,398 +0,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/. */ - -const UNKNOWN = nsIPermissionManager.UNKNOWN_ACTION; // 0 -const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1 -const DENY = nsIPermissionManager.DENY_ACTION; // 2 -const SESSION = nsICookiePermission.ACCESS_SESSION; // 8 - -const IMAGE_DENY = 2; - -const COOKIE_DENY = 2; -const COOKIE_SESSION = 2; - -const nsIQuotaManager = Components.interfaces.nsIQuotaManager; - -var gPermURI; -var gPrefs; -var gUsageRequest; - -var gPermObj = { - image: function getImageDefaultPermission() - { - if (gPrefs.getIntPref("permissions.default.image") == IMAGE_DENY) { - return DENY; - } - return ALLOW; - }, - popup: function getPopupDefaultPermission() - { - if (gPrefs.getBoolPref("dom.disable_open_during_load")) { - return DENY; - } - return ALLOW; - }, - cookie: function getCookieDefaultPermission() - { - if (gPrefs.getIntPref("network.cookie.cookieBehavior") == COOKIE_DENY) { - return DENY; - } - if (gPrefs.getIntPref("network.cookie.lifetimePolicy") == COOKIE_SESSION) { - return SESSION; - } - return ALLOW; - }, - "desktop-notification": function getNotificationDefaultPermission() - { - if (!gPrefs.getBoolPref("dom.webnotifications.enabled")) { - return DENY; - } - return UNKNOWN; - }, - install: function getInstallDefaultPermission() - { - if (Services.prefs.getBoolPref("xpinstall.whitelist.required")) { - return DENY; - } - return ALLOW; - }, - geo: function getGeoDefaultPermissions() - { - if (!gPrefs.getBoolPref("geo.enabled")) { - return DENY; - } - return ALLOW; - }, - indexedDB: function getIndexedDBDefaultPermissions() - { - if (!gPrefs.getBoolPref("dom.indexedDB.enabled")) { - return DENY; - } - return UNKNOWN; - }, - plugins: function getPluginsDefaultPermissions() - { - 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 = { - observe: function (aSubject, aTopic, aData) - { - if (aTopic == "perm-changed") { - var permission = aSubject.QueryInterface( - Components.interfaces.nsIPermission); - if (permission.host == gPermURI.host) { - if (permission.type in gPermObj) - initRow(permission.type); - else if (permission.type.startsWith("plugin")) - setPluginsRadioState(); - } - } - } -}; - -function onLoadPermission() -{ - gPrefs = Components.classes[PREFERENCES_CONTRACTID] - .getService(Components.interfaces.nsIPrefBranch); - - var uri = gDocument.documentURIObject; - var permTab = document.getElementById("permTab"); - if (/^https?$/.test(uri.scheme)) { - gPermURI = uri; - var hostText = document.getElementById("hostText"); - hostText.value = gPermURI.host; - - for (var i in gPermObj) - initRow(i); - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.addObserver(permissionObserver, "perm-changed", false); - onUnloadRegistry.push(onUnloadPermission); - permTab.hidden = false; - } - else - permTab.hidden = true; -} - -function onUnloadPermission() -{ - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.removeObserver(permissionObserver, "perm-changed"); - - if (gUsageRequest) { - gUsageRequest.cancel(); - gUsageRequest = null; - } -} - -function initRow(aPartId) -{ - if (aPartId == "plugins") { - initPluginsRow(); - return; - } - - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - - var checkbox = document.getElementById(aPartId + "Def"); - var command = document.getElementById("cmd_" + aPartId + "Toggle"); - // Desktop Notification, Geolocation and PointerLock permission consumers - // use testExactPermission, not testPermission. - var perm; - if (aPartId == "desktop-notification" || aPartId == "geo" || aPartId == "pointerLock") - perm = permissionManager.testExactPermission(gPermURI, aPartId); - else - perm = permissionManager.testPermission(gPermURI, aPartId); - - if (perm) { - checkbox.checked = false; - command.removeAttribute("disabled"); - } - else { - checkbox.checked = true; - command.setAttribute("disabled", "true"); - perm = gPermObj[aPartId](); - } - setRadioState(aPartId, perm); - - if (aPartId == "indexedDB") { - initIndexedDBRow(); - } -} - -function onCheckboxClick(aPartId) -{ - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - - var command = document.getElementById("cmd_" + aPartId + "Toggle"); - var checkbox = document.getElementById(aPartId + "Def"); - if (checkbox.checked) { - permissionManager.remove(gPermURI.host, aPartId); - command.setAttribute("disabled", "true"); - var perm = gPermObj[aPartId](); - setRadioState(aPartId, perm); - } - else { - onRadioClick(aPartId); - command.removeAttribute("disabled"); - } -} - -function onPluginRadioClick(aEvent) { - onRadioClick(aEvent.originalTarget.getAttribute("id").split('#')[0]); -} - -function onRadioClick(aPartId) -{ - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - - var radioGroup = document.getElementById(aPartId + "RadioGroup"); - var id = radioGroup.selectedItem.id; - var permission = id.split('#')[1]; - if (permission == UNKNOWN) { - permissionManager.remove(gPermURI.host, aPartId); - } else { - permissionManager.add(gPermURI, aPartId, permission); - } -} - -function setRadioState(aPartId, aValue) -{ - var radio = document.getElementById(aPartId + "#" + aValue); - radio.radioGroup.selectedItem = radio; -} - -function initIndexedDBRow() -{ - let row = document.getElementById("permIndexedDBRow"); - let extras = document.getElementById("permIndexedDBExtras"); - - row.appendChild(extras); - - var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"] - .getService(nsIQuotaManager); - gUsageRequest = - quotaManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback); - - var status = document.getElementById("indexedDBStatus"); - var button = document.getElementById("indexedDBClear"); - - status.value = ""; - status.setAttribute("hidden", "true"); - button.setAttribute("hidden", "true"); -} - -function onIndexedDBClear() -{ - Components.classes["@mozilla.org/dom/quota/manager;1"] - .getService(nsIQuotaManager) - .clearStoragesForURI(gPermURI); - - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - permissionManager.remove(gPermURI.host, "indexedDB"); - initIndexedDBRow(); -} - -function onIndexedDBUsageCallback(uri, usage, fileUsage) -{ - if (!uri.equals(gPermURI)) { - throw new Error("Callback received for bad URI: " + uri); - } - - if (usage) { - if (!("DownloadUtils" in window)) { - Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); - } - - var status = document.getElementById("indexedDBStatus"); - var button = document.getElementById("indexedDBClear"); - - status.value = - gBundle.getFormattedString("indexedDBUsage", - DownloadUtils.convertByteUnits(usage)); - status.removeAttribute("hidden"); - button.removeAttribute("hidden"); - } -} - -// XXX copied this from browser-plugins.js - is there a way to share? -function makeNicePluginName(aName) { - if (aName == "Shockwave Flash") - return "Adobe Flash"; - - // Clean up the plugin name by stripping off any trailing version numbers - // or "plugin". EG, "Foo Bar Plugin 1.23_02" --> "Foo Bar" - // Do this by first stripping the numbers, etc. off the end, and then - // removing "Plugin" (and then trimming to get rid of any whitespace). - // (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled) - let newName = aName.replace(/[\s\d\.\-\_\(\)]+$/, "").replace(/\bplug-?in\b/i, "").trim(); - return newName; -} - -function fillInPluginPermissionTemplate(aPermissionString, aPluginObject) { - let permPluginTemplate = document.getElementById("permPluginTemplate") - .cloneNode(true); - permPluginTemplate.setAttribute("permString", aPermissionString); - permPluginTemplate.setAttribute("tooltiptext", aPluginObject.description); - let attrs = [ - [ ".permPluginTemplateLabel", "value", aPluginObject.name ], - [ ".permPluginTemplateRadioGroup", "id", aPermissionString + "RadioGroup" ], - [ ".permPluginTemplateRadioDefault", "id", aPermissionString + "#0" ], - [ ".permPluginTemplateRadioAsk", "id", aPermissionString + "#3" ], - [ ".permPluginTemplateRadioAllow", "id", aPermissionString + "#1" ], - [ ".permPluginTemplateRadioBlock", "id", aPermissionString + "#2" ] - ]; - - for (let attr of attrs) { - permPluginTemplate.querySelector(attr[0]).setAttribute(attr[1], attr[2]); - } - - return permPluginTemplate; -} - -function clearPluginPermissionTemplate() { - let permPluginTemplate = document.getElementById("permPluginTemplate"); - permPluginTemplate.hidden = true; - permPluginTemplate.removeAttribute("permString"); - permPluginTemplate.removeAttribute("tooltiptext"); - document.querySelector(".permPluginTemplateLabel").removeAttribute("value"); - document.querySelector(".permPluginTemplateRadioGroup").removeAttribute("id"); - document.querySelector(".permPluginTemplateRadioAsk").removeAttribute("id"); - document.querySelector(".permPluginTemplateRadioAllow").removeAttribute("id"); - document.querySelector(".permPluginTemplateRadioBlock").removeAttribute("id"); -} - -function initPluginsRow() { - let vulnerableLabel = document.getElementById("browserBundle") - .getString("pluginActivateVulnerable.label"); - let pluginHost = Components.classes["@mozilla.org/plugin/host;1"] - .getService(Components.interfaces.nsIPluginHost); - let tags = pluginHost.getPluginTags(); - - let permissionMap = new Map(); - - for (let plugin of tags) { - if (plugin.disabled) { - continue; - } - for (let mimeType of plugin.getMimeTypes()) { - if (mimeType == "application/x-shockwave-flash" && plugin.name != "Shockwave Flash") { - continue; - } - let permString = pluginHost.getPermissionStringForType(mimeType); - if (!permissionMap.has(permString)) { - var name = makeNicePluginName(plugin.name) + " " + plugin.version; - if (permString.startsWith("plugin-vulnerable:")) { - name += " \u2014 " + vulnerableLabel; - } - permissionMap.set(permString, { - "name": name, - "description": plugin.description, - }); - } - } - } - - let entries = [ - { - "permission": item[0], - "obj": item[1], - } - for (item of permissionMap) - ]; - entries.sort(function(a, b) { - return ((a.obj.name < b.obj.name) ? -1 : (a.obj.name == b.obj.name ? 0 : 1)); - }); - - let permissionEntries = [ - fillInPluginPermissionTemplate(p.permission, p.obj) for (p of entries) - ]; - - let permPluginsRow = document.getElementById("permPluginsRow"); - clearPluginPermissionTemplate(); - if (permissionEntries.length < 1) { - permPluginsRow.hidden = true; - return; - } - - for (let permissionEntry of permissionEntries) { - permPluginsRow.appendChild(permissionEntry); - } - - setPluginsRadioState(); -} - -function setPluginsRadioState() { - var permissionManager = Components.classes[PERMISSION_CONTRACTID] - .getService(nsIPermissionManager); - let box = document.getElementById("permPluginsRow"); - for (let permissionEntry of box.childNodes) { - if (permissionEntry.hasAttribute("permString")) { - let permString = permissionEntry.getAttribute("permString"); - let permission = permissionManager.testPermission(gPermURI, permString); - setRadioState(permString, permission); - } - } -} diff --git a/browser/base/content/pageinfo/security.js b/browser/base/content/pageinfo/security.js deleted file mode 100644 index e791ab92a..000000000 --- a/browser/base/content/pageinfo/security.js +++ /dev/null @@ -1,378 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -var security = { - // Display the server certificate (static) - viewCert : function () { - var cert = security._cert; - viewCertHelper(window, cert); - }, - - _getSecurityInfo : function() { - const nsIX509Cert = Components.interfaces.nsIX509Cert; - const nsIX509CertDB = Components.interfaces.nsIX509CertDB; - const nsX509CertDB = "@mozilla.org/security/x509certdb;1"; - const nsISSLStatusProvider = Components.interfaces.nsISSLStatusProvider; - const nsISSLStatus = Components.interfaces.nsISSLStatus; - - // We don't have separate info for a frame, return null until further notice - // (see bug 138479) - if (gWindow != gWindow.top) - return null; - - var hName = null; - try { - hName = gWindow.location.host; - } - catch (exception) { } - - var ui = security._getSecurityUI(); - if (!ui) - return null; - - var isBroken = - (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_BROKEN); - var isMixed = - (ui.state & (Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT | - Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT)); - var isInsecure = - (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_INSECURE); - var isEV = - (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL); - ui.QueryInterface(nsISSLStatusProvider); - var status = ui.SSLStatus; - - if (!isInsecure && status) { - status.QueryInterface(nsISSLStatus); - var cert = status.serverCert; - var issuerName = - this.mapIssuerOrganization(cert.issuerOrganization) || cert.issuerName; - - var retval = { - hostName : hName, - cAName : issuerName, - encryptionAlgorithm : undefined, - encryptionStrength : undefined, - encryptionSuite : undefined, - version: undefined, - isBroken : isBroken, - isMixed : isMixed, - isEV : isEV, - cert : cert, - fullLocation : gWindow.location - }; - - var version; - try { - retval.encryptionAlgorithm = status.cipherName; - retval.encryptionStrength = status.secretKeyLength; - retval.encryptionSuite = status.cipherSuite; - version = status.protocolVersion; - } - catch (e) { - } - - switch (version) { - case nsISSLStatus.SSL_VERSION_3: - retval.version = "SSL 3"; - break; - case nsISSLStatus.TLS_VERSION_1: - retval.version = "TLS 1.0"; - break; - case nsISSLStatus.TLS_VERSION_1_1: - retval.version = "TLS 1.1"; - break; - case nsISSLStatus.TLS_VERSION_1_2: - retval.version = "TLS 1.2" - break; - case nsISSLStatus.TLS_VERSION_1_3: - retval.version = "TLS 1.3" - break; - } - - return retval; - } else { - return { - hostName : hName, - cAName : "", - encryptionAlgorithm : "", - encryptionStrength : 0, - encryptionSuite : "", - version: "", - isBroken : isBroken, - isMixed : isMixed, - isEV : isEV, - cert : null, - fullLocation : gWindow.location - }; - } - }, - - // Find the secureBrowserUI object (if present) - _getSecurityUI : function() { - if (window.opener.gBrowser) - return window.opener.gBrowser.securityUI; - return null; - }, - - // Interface for mapping a certificate issuer organization to - // the value to be displayed. - // Bug 82017 - this implementation should be moved to pipnss C++ code - mapIssuerOrganization: function(name) { - if (!name) return null; - - if (name == "RSA Data Security, Inc.") return "Verisign, Inc."; - - // No mapping required - return name; - }, - - /** - * Open the cookie manager window - */ - viewCookies : function() - { - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - var win = wm.getMostRecentWindow("Browser:Cookies"); - var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]. - getService(Components.interfaces.nsIEffectiveTLDService); - - var eTLD; - var uri = gDocument.documentURIObject; - try { - eTLD = eTLDService.getBaseDomain(uri); - } - catch (e) { - // getBaseDomain will fail if the host is an IP address or is empty - eTLD = uri.asciiHost; - } - - if (win) { - win.gCookiesWindow.setFilter(eTLD); - win.focus(); - } - else - window.openDialog("chrome://browser/content/preferences/cookies.xul", - "Browser:Cookies", "", {filterString : eTLD}); - }, - - /** - * Open the login manager window - */ - viewPasswords : function() - { - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - var win = wm.getMostRecentWindow("Toolkit:PasswordManager"); - if (win) { - win.setFilter(this._getSecurityInfo().hostName); - win.focus(); - } - else - window.openDialog("chrome://passwordmgr/content/passwordManager.xul", - "Toolkit:PasswordManager", "", - {filterString : this._getSecurityInfo().hostName}); - }, - - _cert : null -}; - -function securityOnLoad() { - var info = security._getSecurityInfo(); - if (!info) { - document.getElementById("securityTab").hidden = true; - document.getElementById("securityBox").collapsed = true; - return; - } - else { - document.getElementById("securityTab").hidden = false; - document.getElementById("securityBox").collapsed = false; - } - - const pageInfoBundle = document.getElementById("pageinfobundle"); - - /* Set Identity section text */ - setText("security-identity-domain-value", info.hostName); - - var owner, verifier, generalPageIdentityString; - if (info.cert && !info.isBroken) { - // Try to pull out meaningful values. Technically these fields are optional - // so we'll employ fallbacks where appropriate. The EV spec states that Org - // fields must be specified for subject and issuer so that case is simpler. - if (info.isEV) { - owner = info.cert.organization; - verifier = security.mapIssuerOrganization(info.cAName); - generalPageIdentityString = pageInfoBundle.getFormattedString("generalSiteIdentity", - [owner, verifier]); - } - else { - // Technically, a non-EV cert might specify an owner in the O field or not, - // depending on the CA's issuing policies. However we don't have any programmatic - // way to tell those apart, and no policy way to establish which organization - // vetting standards are good enough (that's what EV is for) so we default to - // treating these certs as domain-validated only. - owner = pageInfoBundle.getString("securityNoOwner"); - verifier = security.mapIssuerOrganization(info.cAName || - info.cert.issuerCommonName || - info.cert.issuerName); - generalPageIdentityString = owner; - } - } - else { - // We don't have valid identity credentials. - owner = pageInfoBundle.getString("securityNoOwner"); - verifier = pageInfoBundle.getString("notset"); - generalPageIdentityString = owner; - } - - setText("security-identity-owner-value", owner); - setText("security-identity-verifier-value", verifier); - setText("general-security-identity", generalPageIdentityString); - - /* Manage the View Cert button*/ - var viewCert = document.getElementById("security-view-cert"); - if (info.cert) { - security._cert = info.cert; - viewCert.collapsed = false; - } - else - viewCert.collapsed = true; - - /* Set Privacy & History section text */ - var yesStr = pageInfoBundle.getString("yes"); - var noStr = pageInfoBundle.getString("no"); - - var uri = gDocument.documentURIObject; - setText("security-privacy-cookies-value", - hostHasCookies(uri) ? yesStr : noStr); - setText("security-privacy-passwords-value", - realmHasPasswords(uri) ? yesStr : noStr); - - var visitCount = previousVisitCount(info.hostName); - if(visitCount > 1) { - setText("security-privacy-history-value", - pageInfoBundle.getFormattedString("securityNVisits", [visitCount.toLocaleString()])); - } - else if (visitCount == 1) { - setText("security-privacy-history-value", - pageInfoBundle.getString("securityOneVisit")); - } - else { - setText("security-privacy-history-value", noStr); - } - - /* Set the Technical Detail section messages */ - const pkiBundle = document.getElementById("pkiBundle"); - var hdr; - var msg1; - var msg2; - - if (info.isBroken) { - if (info.isMixed) { - hdr = pkiBundle.getString("pageInfo_MixedContent"); - } else { - hdr = pkiBundle.getFormattedString("pageInfo_BrokenEncryption", - [info.encryptionAlgorithm, - info.encryptionStrength + "", - info.version]); - } - msg1 = pkiBundle.getString("pageInfo_Privacy_Broken1"); - msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); - } - else if (info.encryptionStrength > 0) { - hdr = pkiBundle.getFormattedString("pageInfo_EncryptionWithBitsAndProtocol", - [info.encryptionAlgorithm, - info.encryptionStrength + "", - info.version]); - msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1"); - msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2"); - security._cert = info.cert; - } - else { - hdr = pkiBundle.getString("pageInfo_NoEncryption"); - if (info.hostName != null) - msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [info.hostName]); - else - msg1 = pkiBundle.getString("pageInfo_Privacy_None3"); - msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); - } - setText("security-technical-shortform", hdr); - setText("security-technical-longform1", msg1); - setText("security-technical-longform2", msg2); - setText("general-security-privacy", hdr); -} - -function setText(id, value) -{ - var element = document.getElementById(id); - if (!element) - return; - if (element.localName == "textbox" || element.localName == "label") - element.value = value; - else { - if (element.hasChildNodes()) - element.removeChild(element.firstChild); - var textNode = document.createTextNode(value); - element.appendChild(textNode); - } -} - -function viewCertHelper(parent, cert) -{ - if (!cert) - return; - - var cd = Components.classes[CERTIFICATEDIALOGS_CONTRACTID].getService(nsICertificateDialogs); - cd.viewCert(parent, cert); -} - -/** - * Return true iff we have cookies for uri - */ -function hostHasCookies(uri) { - var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"] - .getService(Components.interfaces.nsICookieManager2); - - return cookieManager.countCookiesFromHost(uri.asciiHost) > 0; -} - -/** - * Return true iff realm (proto://host:port) (extracted from uri) has - * saved passwords - */ -function realmHasPasswords(uri) { - var passwordManager = Components.classes["@mozilla.org/login-manager;1"] - .getService(Components.interfaces.nsILoginManager); - return passwordManager.countLogins(uri.prePath, "", "") > 0; -} - -/** - * Return the number of previous visits recorded for host before today. - * - * @param host - the domain name to look for in history - */ -function previousVisitCount(host, endTimeReference) { - if (!host) - return false; - - var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"] - .getService(Components.interfaces.nsINavHistoryService); - - var options = historyService.getNewQueryOptions(); - options.resultType = options.RESULTS_AS_VISIT; - - // Search for visits to this host before today - var query = historyService.getNewQuery(); - query.endTimeReference = query.TIME_RELATIVE_TODAY; - query.endTime = 0; - query.domain = host; - - var result = historyService.executeQuery(query, options); - result.root.containerOpen = true; - var cc = result.root.childCount; - result.root.containerOpen = false; - return cc; -} diff --git a/browser/base/content/popup-notifications.inc b/browser/base/content/popup-notifications.inc deleted file mode 100644 index 04f4cb5b7..000000000 --- a/browser/base/content/popup-notifications.inc +++ /dev/null @@ -1,97 +0,0 @@ -# to be included inside a popupset element - - <panel id="notification-popup" - type="arrow" - footertype="promobox" - position="after_start" - hidden="true" - orient="vertical" - role="alert"/> - - <!-- Popup for site identity information --> - <panel id="identity-popup" - type="arrow" - hidden="true" - noautofocus="true" - consumeoutsideclicks="true" - onpopupshown="gIdentityHandler.onPopupShown(event);" - level="top"> - <hbox id="identity-popup-container" align="top"> - <image id="identity-popup-icon"/> - <vbox id="identity-popup-content-box"> - <label id="identity-popup-connectedToLabel" - class="identity-popup-label" - value="&identity.connectedTo;"/> - <label id="identity-popup-connectedToLabel2" - class="identity-popup-label" - value="&identity.unverifiedsite2;"/> - <description id="identity-popup-content-host" - class="identity-popup-description"/> - <label id="identity-popup-runByLabel" - class="identity-popup-label" - value="&identity.runBy;"/> - <description id="identity-popup-content-owner" - class="identity-popup-description"/> - <description id="identity-popup-content-supplemental" - class="identity-popup-description"/> - <description id="identity-popup-content-verifier" - class="identity-popup-description"/> - <hbox id="identity-popup-encryption" flex="1"> - <vbox> - <image id="identity-popup-encryption-icon"/> - </vbox> - <description id="identity-popup-encryption-label" flex="1" - class="identity-popup-description"/> - </hbox> - <!-- Footer button to open security page info --> - <hbox id="identity-popup-button-container" pack="end"> - <button id="identity-popup-more-info-button" - label="&identity.moreInfoLinkText;" - onblur="gIdentityHandler.hideIdentityPopup();" - oncommand="gIdentityHandler.handleMoreInfoClick(event);"/> - </hbox> - </vbox> - </hbox> - </panel> - - - <popupnotification id="webRTC-shareDevices-notification" hidden="true"> - <popupnotificationcontent id="webRTC-selectCamera" orient="vertical"> - <separator class="thin"/> - <label value="&getUserMedia.selectCamera.label;" - accesskey="&getUserMedia.selectCamera.accesskey;" - control="webRTC-selectCamera-menulist"/> - <menulist id="webRTC-selectCamera-menulist"> - <menupopup id="webRTC-selectCamera-menupopup"/> - </menulist> - </popupnotificationcontent> - <popupnotificationcontent id="webRTC-selectMicrophone" orient="vertical"> - <separator class="thin"/> - <label value="&getUserMedia.selectMicrophone.label;" - accesskey="&getUserMedia.selectMicrophone.accesskey;" - control="webRTC-selectMicrophone-menulist"/> - <menulist id="webRTC-selectMicrophone-menulist"> - <menupopup id="webRTC-selectMicrophone-menupopup"/> - </menulist> - </popupnotificationcontent> - </popupnotification> - - <popupnotification id="servicesInstall-notification" hidden="true"> - <popupnotificationcontent orient="vertical" align="start"> - <!-- XXX bug 974146, tests are looking for this, can't remove yet. --> - </popupnotificationcontent> - </popupnotification> - - <popupnotification id="pointerLock-notification" hidden="true"> - <popupnotificationcontent orient="vertical" align="start"> - <separator class="thin"/> - <label id="pointerLock-cancel" value="&pointerLock.notification.message;"/> - </popupnotificationcontent> - </popupnotification> - - <popupnotification id="mixed-content-blocked-notification" hidden="true"> - <popupnotificationcontent orient="vertical" align="start"> - <separator/> - <description id="mixed-content-blocked-moreinfo">&mixedContentBlocked.moreinfo;</description> - </popupnotificationcontent> - </popupnotification> diff --git a/browser/base/content/report-phishing-overlay.xul b/browser/base/content/report-phishing-overlay.xul deleted file mode 100644 index 76baf01da..000000000 --- a/browser/base/content/report-phishing-overlay.xul +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0"?> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<!DOCTYPE overlay [ -<!ENTITY % reportphishDTD SYSTEM "chrome://browser/locale/safebrowsing/report-phishing.dtd"> -%reportphishDTD; -<!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd"> -%safebrowsingDTD; -]> - -<overlay id="reportPhishingMenuOverlay" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <broadcasterset id="mainBroadcasterSet"> - <broadcaster id="reportPhishingBroadcaster" disabled="true"/> - <broadcaster id="reportPhishingErrorBroadcaster" disabled="true"/> - </broadcasterset> - <menupopup id="menu_HelpPopup"> - <menuitem id="menu_HelpPopup_reportPhishingtoolmenu" - label="&reportPhishSiteMenu.title2;" - accesskey="&reportPhishSiteMenu.accesskey;" - insertbefore="aboutSeparator" - observes="reportPhishingBroadcaster" - oncommand="openUILink(gSafeBrowsing.getReportURL('Phish'), event);" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu" - label="&safeb.palm.notforgery.label2;" - accesskey="&reportPhishSiteMenu.accesskey;" - insertbefore="aboutSeparator" - observes="reportPhishingErrorBroadcaster" - oncommand="openUILinkIn(gSafeBrowsing.getReportURL('Error'), 'tab');" - onclick="checkForMiddleClick(this, event);"/> - </menupopup> -</overlay> diff --git a/browser/base/content/safeMode.css b/browser/base/content/safeMode.css deleted file mode 100644 index 4f093a452..000000000 --- a/browser/base/content/safeMode.css +++ /dev/null @@ -1,8 +0,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/. */ - -#resetProfileFooter { - font-weight: bold; -} - diff --git a/browser/base/content/safeMode.js b/browser/base/content/safeMode.js deleted file mode 100644 index e1e5c7285..000000000 --- a/browser/base/content/safeMode.js +++ /dev/null @@ -1,128 +0,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/. */ - -const Cc = Components.classes, - Ci = Components.interfaces, - Cu = Components.utils; - -Cu.import("resource://gre/modules/AddonManager.jsm"); - -function restartApp() { - let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"] - .getService(Ci.nsIAppStartup); - appStartup.quit(Ci.nsIAppStartup.eForceQuit | Ci.nsIAppStartup.eRestart); -} - -function clearAllPrefs() { - var prefService = Cc["@mozilla.org/preferences-service;1"] - .getService(Ci.nsIPrefService); - prefService.resetUserPrefs(); - - // Remove the pref-overrides dir, if it exists - try { - var fileLocator = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); - const NS_APP_PREFS_OVERRIDE_DIR = "PrefDOverride"; - var prefOverridesDir = fileLocator.get(NS_APP_PREFS_OVERRIDE_DIR, - Ci.nsIFile); - prefOverridesDir.remove(true); - } catch (ex) { - Components.utils.reportError(ex); - } -} - -function restoreDefaultBookmarks() { - var prefBranch = Cc["@mozilla.org/preferences-service;1"] - .getService(Ci.nsIPrefBranch); - prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks", true); -} - -function deleteLocalstore() { - const nsIDirectoryServiceContractID = "@mozilla.org/file/directory_service;1"; - const nsIProperties = Ci.nsIProperties; - var directoryService = Cc[nsIDirectoryServiceContractID] - .getService(nsIProperties); - // Local store file - var localstoreFile = directoryService.get("LStoreS", Components.interfaces.nsIFile); - // XUL store file - var xulstoreFile = directoryService.get("ProfD", Components.interfaces.nsIFile); - xulstoreFile.append("xulstore.json"); - try { - xulstoreFile.remove(false); - if (localstoreFile.exists()) { - localstoreFile.remove(false); - } - } catch(e) { - Components.utils.reportError(e); - } -} - -function disableAddons() { - AddonManager.getAllAddons(function(aAddons) { - aAddons.forEach(function(aAddon) { - if (aAddon.type == "theme") { - // Setting userDisabled to false on the default theme activates it, - // disables all other themes and deactivates the applied persona, if - // any. - const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}"; - if (aAddon.id == DEFAULT_THEME_ID) - aAddon.userDisabled = false; - } - else { - aAddon.userDisabled = true; - } - }); - - restartApp(); - }); -} - -function restoreDefaultSearchEngines() { - var searchService = Cc["@mozilla.org/browser/search-service;1"] - .getService(Ci.nsIBrowserSearchService); - - searchService.restoreDefaultEngines(); -} - -function onOK() { - try { - if (document.getElementById("resetUserPrefs").checked) - clearAllPrefs(); - if (document.getElementById("deleteBookmarks").checked) - restoreDefaultBookmarks(); - if (document.getElementById("resetToolbars").checked) - deleteLocalstore(); - if (document.getElementById("restoreSearch").checked) - restoreDefaultSearchEngines(); - if (document.getElementById("disableAddons").checked) { - disableAddons(); - // disableAddons will asynchronously restart the application - return false; - } - } catch(e) { - } - - restartApp(); - return false; -} - -function onCancel() { - let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"] - .getService(Ci.nsIAppStartup); - appStartup.quit(Ci.nsIAppStartup.eForceQuit); -} - -function onLoad() { - document.getElementById("tasks") - .addEventListener("CheckboxStateChange", UpdateOKButtonState, false); -} - -function UpdateOKButtonState() { - document.documentElement.getButton("accept").disabled = - !document.getElementById("resetUserPrefs").checked && - !document.getElementById("deleteBookmarks").checked && - !document.getElementById("resetToolbars").checked && - !document.getElementById("disableAddons").checked && - !document.getElementById("restoreSearch").checked; -} diff --git a/browser/base/content/safeMode.xul b/browser/base/content/safeMode.xul deleted file mode 100644 index 656df6eaf..000000000 --- a/browser/base/content/safeMode.xul +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0"?> - -<!-- -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<!DOCTYPE prefwindow [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > -%brandDTD; -<!ENTITY % safeModeDTD SYSTEM "chrome://browser/locale/safeMode.dtd" > -%safeModeDTD; -<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" > -%browserDTD; -]> - -<?xml-stylesheet href="chrome://global/skin/"?> - -<dialog id="safeModeDialog" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - title="&safeModeDialog.title;" - buttons="accept,cancel,extra1" - buttonlabelaccept="&changeAndRestartButton.label;" -#ifdef XP_WIN - buttonlabelcancel="&quitApplicationCmdWin.label;" -#else - buttonlabelcancel="&quitApplicationCmd.label;" -#endif - buttonlabelextra1="&continueButton.label;" - width="&window.width;" - ondialogaccept="return onOK()" - ondialogcancel="onCancel()" - ondialogextra1="window.close()" - onload="onLoad();" - buttondisabledaccept="true"> - - <script type="application/javascript" src="chrome://browser/content/safeMode.js"/> - - <stringbundle id="preferencesBundle" src="chrome://browser/locale/preferences/preferences.properties"/> - - <description>&safeModeDescription.label;</description> - - <separator class="thin"/> - - <label value="&safeModeDescription2.label;"/> - <vbox id="tasks"> - <checkbox id="disableAddons" label="&disableAddons.label;" accesskey="&disableAddons.accesskey;"/> - <checkbox id="resetToolbars" label="&resetToolbars.label;" accesskey="&resetToolbars.accesskey;"/> - <checkbox id="deleteBookmarks" label="&deleteBookmarks.label;" accesskey="&deleteBookmarks.accesskey;"/> - <checkbox id="resetUserPrefs" label="&resetUserPrefs.label;" accesskey="&resetUserPrefs.accesskey;"/> - <checkbox id="restoreSearch" label="&restoreSearch.label;" accesskey="&restoreSearch.accesskey;"/> - </vbox> - - <separator class="thin"/> -</dialog> diff --git a/browser/base/content/sanitize.js b/browser/base/content/sanitize.js deleted file mode 100644 index 89843c86d..000000000 --- a/browser/base/content/sanitize.js +++ /dev/null @@ -1,527 +0,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/. - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", - "resource://gre/modules/PlacesUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FormHistory", - "resource://gre/modules/FormHistory.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Downloads", - "resource://gre/modules/Downloads.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource:///modules/promise.js"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "console", - "resource://gre/modules/devtools/Console.jsm"); - -function Sanitizer() {} -Sanitizer.prototype = { - // warning to the caller: this one may raise an exception (e.g. bug #265028) - clearItem: function (aItemName) - { - if (this.items[aItemName].canClear) - this.items[aItemName].clear(); - }, - - canClearItem: function (aItemName, aCallback, aArg) - { - let canClear = this.items[aItemName].canClear; - if (typeof canClear == "function") { - canClear(aCallback, aArg); - return false; - } - - aCallback(aItemName, canClear, aArg); - return canClear; - }, - - prefDomain: "", - isShutDown: false, - - getNameFromPreference: function (aPreferenceName) - { - return aPreferenceName.substr(this.prefDomain.length); - }, - - /** - * Deletes privacy sensitive data in a batch, according to user preferences. - * Returns a promise which is resolved if no errors occurred. If an error - * occurs, a message is reported to the console and all other items are still - * cleared before the promise is finally rejected. - */ - sanitize: function () - { - var deferred = Promise.defer(); - var psvc = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - var branch = psvc.getBranch(this.prefDomain); - var seenError = false; - - // Cache the range of times to clear - if (this.ignoreTimespan) - var range = null; // If we ignore timespan, clear everything - else - range = this.range || Sanitizer.getClearRange(); - - let itemCount = Object.keys(this.items).length; - let onItemComplete = function() { - if (!--itemCount) { - seenError ? deferred.reject() : deferred.resolve(); - } - }; - for (var itemName in this.items) { - let item = this.items[itemName]; - item.range = range; - item.isShutDown = this.isShutDown; - if ("clear" in item && branch.getBoolPref(itemName)) { - let clearCallback = (itemName, aCanClear) => { - // Some of these clear() may raise exceptions (see bug #265028) - // to sanitize as much as possible, we catch and store them, - // rather than fail fast. - // Callers should check returned errors and give user feedback - // about items that could not be sanitized - let item = this.items[itemName]; - try { - if (aCanClear) - item.clear(); - } catch(er) { - seenError = true; - console.error("Error sanitizing " + itemName + ": " + er + "\n"); - } - onItemComplete(); - }; - this.canClearItem(itemName, clearCallback); - } else { - onItemComplete(); - } - } - - return deferred.promise; - }, - - // Time span only makes sense in certain cases. Consumers who want - // to only clear some private data can opt in by setting this to false, - // and can optionally specify a specific range. If timespan is not ignored, - // and range is not set, sanitize() will use the value of the timespan - // pref to determine a range - ignoreTimespan : true, - range : null, - - items: { - cache: { - clear: function () - { - var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]. - getService(Ci.nsICacheStorageService); - try { - // Cache doesn't consult timespan, nor does it have the - // facility for timespan-based eviction. Wipe it. - cache.clear(); - } catch(er) {} - - var imageCache = Cc["@mozilla.org/image/tools;1"]. - getService(Ci.imgITools).getImgCacheForDocument(null); - try { - imageCache.clearCache(false); // true=chrome, false=content - } catch(er) {} - }, - - get canClear() - { - return true; - } - }, - - cookies: { - clear: function () - { - var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"] - .getService(Ci.nsICookieManager); - if (this.range) { - // Iterate through the cookies and delete any created after our cutoff. - var cookiesEnum = cookieMgr.enumerator; - while (cookiesEnum.hasMoreElements()) { - var cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2); - - if (cookie.creationTime > this.range[0]) - // This cookie was created after our cutoff, clear it - cookieMgr.remove(cookie.host, cookie.name, cookie.path, false); - } - } - else { - // Remove everything - cookieMgr.removeAll(); - } - - // Clear plugin data. - const phInterface = Ci.nsIPluginHost; - const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL; - let ph = Cc["@mozilla.org/plugin/host;1"].getService(phInterface); - - // Determine age range in seconds. (-1 means clear all.) We don't know - // that this.range[1] is actually now, so we compute age range based - // on the lower bound. If this.range results in a negative age, do - // nothing. - let age = this.range ? (Date.now() / 1000 - this.range[0] / 1000000) - : -1; - if (!this.range || age >= 0) { - let tags = ph.getPluginTags(); - for (let i = 0; i < tags.length; i++) { - try { - ph.clearSiteData(tags[i], null, FLAG_CLEAR_ALL, age); - } catch (e) { - // If the plugin doesn't support clearing by age, clear everything. - if (e.result == Components.results. - NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED) { - try { - ph.clearSiteData(tags[i], null, FLAG_CLEAR_ALL, -1); - } catch (e) { - // Ignore errors from the plugin - } - } - } - } - } - }, - - get canClear() - { - return true; - } - }, - - offlineApps: { - clear: function () - { - Components.utils.import("resource:///modules/offlineAppCache.jsm"); - OfflineAppCacheHelper.clear(); - if (!this.range || this.isShutDown) { - Components.utils.import("resource:///modules/QuotaManager.jsm"); - QuotaManagerHelper.clear(this.isShutDown); - } - }, - - get canClear() - { - return true; - } - }, - - history: { - clear: function () - { - if (this.range) - PlacesUtils.history.removeVisitsByTimeframe(this.range[0], this.range[1]); - else - PlacesUtils.history.removeAllPages(); - - try { - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.notifyObservers(null, "browser:purge-session-history", ""); - } - catch (e) { } - - // Clear last URL of the Open Web Location dialog - var prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); - try { - prefs.clearUserPref("general.open_location.last_url"); - } - catch (e) { } - }, - - get canClear() - { - // bug 347231: Always allow clearing history due to dependencies on - // the browser:purge-session-history notification. (like error console) - return true; - } - }, - - formdata: { - clear: function () - { - // Clear undo history of all searchBars - var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'] - .getService(Components.interfaces.nsIWindowMediator); - var windows = windowManager.getEnumerator("navigator:browser"); - while (windows.hasMoreElements()) { - let currentDocument = windows.getNext().document; - let searchBar = currentDocument.getElementById("searchbar"); - if (searchBar) - searchBar.textbox.reset(); - let findBar = currentDocument.getElementById("FindToolbar"); - if (findBar) - findBar.clear(); - } - - let change = { op: "remove" }; - if (this.range) { - [ change.firstUsedStart, change.firstUsedEnd ] = this.range; - } - FormHistory.update(change); - }, - - canClear : function(aCallback, aArg) - { - var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'] - .getService(Components.interfaces.nsIWindowMediator); - var windows = windowManager.getEnumerator("navigator:browser"); - while (windows.hasMoreElements()) { - let currentDocument = windows.getNext().document; - let searchBar = currentDocument.getElementById("searchbar"); - if (searchBar) { - let transactionMgr = searchBar.textbox.editor.transactionManager; - if (searchBar.value || - transactionMgr.numberOfUndoItems || - transactionMgr.numberOfRedoItems) { - aCallback("formdata", true, aArg); - return false; - } - } - let findBar = currentDocument.getElementById("FindToolbar"); - if (findBar && findBar.canClear) { - aCallback("formdata", true, aArg); - return false; - } - } - - let count = 0; - let countDone = { - handleResult : function(aResult) count = aResult, - handleError : function(aError) Components.utils.reportError(aError), - handleCompletion : - function(aReason) { aCallback("formdata", aReason == 0 && count > 0, aArg); } - }; - FormHistory.count({}, countDone); - return false; - } - }, - - downloads: { - clear: Task.async(function* (range) { - let refObj = {}; - try { - let filterByTime = null; - if (range) { - // Convert microseconds back to milliseconds for date comparisons. - let rangeBeginMs = range[0] / 1000; - let rangeEndMs = range[1] / 1000; - filterByTime = download => download.startTime >= rangeBeginMs && - download.startTime <= rangeEndMs; - } - - // Clear all completed/cancelled downloads - let list = yield Downloads.getList(Downloads.ALL); - list.removeFinished(filterByTime); - } finally {} - }), - - get canClear() - { - //Clearing is always possible with JSTransfers - return true; - } - }, - - passwords: { - clear: function () - { - var pwmgr = Components.classes["@mozilla.org/login-manager;1"] - .getService(Components.interfaces.nsILoginManager); - // Passwords are timeless, and don't respect the timeSpan setting - pwmgr.removeAllLogins(); - }, - - get canClear() - { - var pwmgr = Components.classes["@mozilla.org/login-manager;1"] - .getService(Components.interfaces.nsILoginManager); - var count = pwmgr.countLogins("", "", ""); // count all logins - return (count > 0); - } - }, - - sessions: { - clear: function () - { - // clear all auth tokens - var sdr = Components.classes["@mozilla.org/security/sdr;1"] - .getService(Components.interfaces.nsISecretDecoderRing); - sdr.logoutAndTeardown(); - - // clear FTP and plain HTTP auth sessions - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.notifyObservers(null, "net:clear-active-logins", null); - }, - - get canClear() - { - return true; - } - }, - - siteSettings: { - clear: function () - { - // Clear site-specific permissions like "Allow this site to open popups" - var pm = Components.classes["@mozilla.org/permissionmanager;1"] - .getService(Components.interfaces.nsIPermissionManager); - pm.removeAll(); - - // Clear site-specific settings like page-zoom level - var cps = Components.classes["@mozilla.org/content-pref/service;1"] - .getService(Components.interfaces.nsIContentPrefService2); - cps.removeAllDomains(null); - - // Clear "Never remember passwords for this site", which is not handled by - // the permission manager - var pwmgr = Components.classes["@mozilla.org/login-manager;1"] - .getService(Components.interfaces.nsILoginManager); - var hosts = pwmgr.getAllDisabledHosts(); - for each (var host in hosts) { - pwmgr.setLoginSavingEnabled(host, true); - } - }, - - get canClear() - { - return true; - } - }, - - connectivityData: { - clear: function () - { - // Clear site security settings - var sss = Components.classes["@mozilla.org/ssservice;1"] - .getService(Components.interfaces.nsISiteSecurityService); - sss.clearAll(); - }, - - get canClear() - { - return true; - } - } - } -}; - - - -// "Static" members -Sanitizer.prefDomain = "privacy.sanitize."; -Sanitizer.prefShutdown = "sanitizeOnShutdown"; -Sanitizer.prefDidShutdown = "didShutdownSanitize"; - -// Time span constants corresponding to values of the privacy.sanitize.timeSpan -// pref. Used to determine how much history to clear, for various items -Sanitizer.TIMESPAN_EVERYTHING = 0; -Sanitizer.TIMESPAN_HOUR = 1; -Sanitizer.TIMESPAN_2HOURS = 2; -Sanitizer.TIMESPAN_4HOURS = 3; -Sanitizer.TIMESPAN_TODAY = 4; - -Sanitizer.IS_SHUTDOWN = true; - -// Return a 2 element array representing the start and end times, -// in the uSec-since-epoch format that PRTime likes. If we should -// clear everything, return null. Use ts if it is defined; otherwise -// use the timeSpan pref. -Sanitizer.getClearRange = function (ts) { - if (ts === undefined) - ts = Sanitizer.prefs.getIntPref("timeSpan"); - if (ts === Sanitizer.TIMESPAN_EVERYTHING) - return null; - - // PRTime is microseconds while JS time is milliseconds - var endDate = Date.now() * 1000; - switch (ts) { - case Sanitizer.TIMESPAN_HOUR : - var startDate = endDate - 3600000000; // 1*60*60*1000000 - break; - case Sanitizer.TIMESPAN_2HOURS : - startDate = endDate - 7200000000; // 2*60*60*1000000 - break; - case Sanitizer.TIMESPAN_4HOURS : - startDate = endDate - 14400000000; // 4*60*60*1000000 - break; - case Sanitizer.TIMESPAN_TODAY : - var d = new Date(); // Start with today - d.setHours(0); // zero us back to midnight... - d.setMinutes(0); - d.setSeconds(0); - startDate = d.valueOf() * 1000; // convert to epoch usec - break; - default: - throw "Invalid time span for clear private data: " + ts; - } - return [startDate, endDate]; -}; - -Sanitizer._prefs = null; -Sanitizer.__defineGetter__("prefs", function() -{ - return Sanitizer._prefs ? Sanitizer._prefs - : Sanitizer._prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService) - .getBranch(Sanitizer.prefDomain); -}); - -// Shows sanitization UI -Sanitizer.showUI = function(aParentWindow) -{ - var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] - .getService(Components.interfaces.nsIWindowWatcher); -#ifdef XP_MACOSX - ww.openWindow(null, // make this an app-modal window on Mac -#else - ww.openWindow(aParentWindow, -#endif - "chrome://browser/content/sanitize.xul", - "Sanitize", - "chrome,titlebar,dialog,centerscreen,modal", - null); -}; - -/** - * Deletes privacy sensitive data in a batch, optionally showing the - * sanitize UI, according to user preferences - */ -Sanitizer.sanitize = function(aParentWindow) -{ - Sanitizer.showUI(aParentWindow); -}; - -Sanitizer.onStartup = function() -{ - // we check for unclean exit with pending sanitization - Sanitizer._checkAndSanitize(); -}; - -Sanitizer.onShutdown = function() -{ - // we check if sanitization is needed and perform it - Sanitizer._checkAndSanitize(Sanitizer.IS_SHUTDOWN); -}; - -// this is called on startup and shutdown, to perform pending sanitizations -Sanitizer._checkAndSanitize = function(isShutDown) -{ - const prefs = Sanitizer.prefs; - if (prefs.getBoolPref(Sanitizer.prefShutdown) && - !prefs.prefHasUserValue(Sanitizer.prefDidShutdown)) { - // this is a shutdown or a startup after an unclean exit - var s = new Sanitizer(); - s.prefDomain = "privacy.clearOnShutdown."; - s.isShutDown = isShutDown; - s.sanitize().then(function() { - prefs.setBoolPref(Sanitizer.prefDidShutdown, true); - }); - } -}; diff --git a/browser/base/content/sanitize.xul b/browser/base/content/sanitize.xul deleted file mode 100644 index 691be926e..000000000 --- a/browser/base/content/sanitize.xul +++ /dev/null @@ -1,190 +0,0 @@ -<?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/. - -<?xml-stylesheet href="chrome://global/skin/"?> -<?xml-stylesheet href="chrome://browser/skin/sanitizeDialog.css"?> - -#ifdef CRH_DIALOG_TREE_VIEW -<?xml-stylesheet href="chrome://browser/skin/places/places.css"?> -#endif - -<?xml-stylesheet href="chrome://browser/content/sanitizeDialog.css"?> - -<!DOCTYPE prefwindow [ - <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> - <!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd"> - %brandDTD; - %sanitizeDTD; -]> - -<prefwindow id="SanitizeDialog" type="child" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - dlgbuttons="accept,cancel" - title="&sanitizeDialog2.title;" - noneverythingtitle="&sanitizeDialog2.title;" - style="width: &dialog.width2;;" - ondialogaccept="return gSanitizePromptDialog.sanitize();"> - - <prefpane id="SanitizeDialogPane" onpaneload="gSanitizePromptDialog.init();"> - <stringbundle id="bundleBrowser" - src="chrome://browser/locale/browser.properties"/> - - <script type="application/javascript" - src="chrome://browser/content/sanitize.js"/> - -#ifdef CRH_DIALOG_TREE_VIEW - <script type="application/javascript" - src="chrome://global/content/globalOverlay.js"/> - <script type="application/javascript" - src="chrome://browser/content/places/treeView.js"/> - <script type="application/javascript"><![CDATA[ - Components.utils.import("resource://gre/modules/PlacesUtils.jsm"); - Components.utils.import("resource:///modules/PlacesUIUtils.jsm"); - ]]></script> -#endif - - <script type="application/javascript" - src="chrome://browser/content/sanitizeDialog.js"/> - - <preferences id="sanitizePreferences"> - <preference id="privacy.cpd.history" name="privacy.cpd.history" type="bool"/> - <preference id="privacy.cpd.formdata" name="privacy.cpd.formdata" type="bool"/> - <preference id="privacy.cpd.downloads" name="privacy.cpd.downloads" type="bool" disabled="true"/> - <preference id="privacy.cpd.cookies" name="privacy.cpd.cookies" type="bool"/> - <preference id="privacy.cpd.cache" name="privacy.cpd.cache" type="bool"/> - <preference id="privacy.cpd.sessions" name="privacy.cpd.sessions" type="bool"/> - <preference id="privacy.cpd.offlineApps" name="privacy.cpd.offlineApps" type="bool"/> - <preference id="privacy.cpd.siteSettings" name="privacy.cpd.siteSettings" type="bool"/> - <preference id="privacy.cpd.connectivityData" name="privacy.cpd.connectivityData" type="bool"/> - </preferences> - - <preferences id="nonItemPreferences"> - <preference id="privacy.sanitize.timeSpan" - name="privacy.sanitize.timeSpan" - type="int"/> - </preferences> - - <hbox id="SanitizeDurationBox" align="center"> - <label value="&clearTimeDuration.label;" - accesskey="&clearTimeDuration.accesskey;" - control="sanitizeDurationChoice" - id="sanitizeDurationLabel"/> - <menulist id="sanitizeDurationChoice" - preference="privacy.sanitize.timeSpan" - onselect="gSanitizePromptDialog.selectByTimespan();" - flex="1"> - <menupopup id="sanitizeDurationPopup"> -#ifdef CRH_DIALOG_TREE_VIEW - <menuitem label="" value="-1" id="sanitizeDurationCustom"/> -#endif - <menuitem label="&clearTimeDuration.lastHour;" value="1"/> - <menuitem label="&clearTimeDuration.last2Hours;" value="2"/> - <menuitem label="&clearTimeDuration.last4Hours;" value="3"/> - <menuitem label="&clearTimeDuration.today;" value="4"/> - <menuseparator/> - <menuitem label="&clearTimeDuration.everything;" value="0"/> - </menupopup> - </menulist> - <label id="sanitizeDurationSuffixLabel" - value="&clearTimeDuration.suffix;"/> - </hbox> - - <separator class="thin"/> - -#ifdef CRH_DIALOG_TREE_VIEW - <deck id="durationDeck"> - <tree id="placesTree" flex="1" hidecolumnpicker="true" rows="10" - disabled="true" disableKeyNavigation="true"> - <treecols> - <treecol id="date" label="&clearTimeDuration.dateColumn;" flex="1"/> - <splitter class="tree-splitter"/> - <treecol id="title" label="&clearTimeDuration.nameColumn;" flex="5"/> - </treecols> - <treechildren id="placesTreechildren" - ondragstart="gSanitizePromptDialog.grippyMoved('ondragstart', event);" - ondragover="gSanitizePromptDialog.grippyMoved('ondragover', event);" - onkeypress="gSanitizePromptDialog.grippyMoved('onkeypress', event);" - onmousedown="gSanitizePromptDialog.grippyMoved('onmousedown', event);"/> - </tree> -#endif - - <vbox id="sanitizeEverythingWarningBox"> - <spacer flex="1"/> - <hbox align="center"> - <image id="sanitizeEverythingWarningIcon"/> - <vbox id="sanitizeEverythingWarningDescBox" flex="1"> - <description id="sanitizeEverythingWarning"/> - <description id="sanitizeEverythingUndoWarning">&sanitizeEverythingUndoWarning;</description> - </vbox> - </hbox> - <spacer flex="1"/> - </vbox> - -#ifdef CRH_DIALOG_TREE_VIEW - </deck> -#endif - - <separator class="thin"/> - - <hbox id="detailsExpanderWrapper" align="center"> - <button type="image" - id="detailsExpander" - class="expander-down" - persist="class" - oncommand="gSanitizePromptDialog.toggleItemList();"/> - <label id="detailsExpanderLabel" - value="&detailsProgressiveDisclosure.label;" - accesskey="&detailsProgressiveDisclosure.accesskey;" - control="detailsExpander"/> - </hbox> - <listbox id="itemList" rows="8" collapsed="true" persist="collapsed"> - <listitem label="&itemHistoryAndDownloads.label;" - type="checkbox" - accesskey="&itemHistoryAndDownloads.accesskey;" - preference="privacy.cpd.history" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - <listitem label="&itemFormSearchHistory.label;" - type="checkbox" - accesskey="&itemFormSearchHistory.accesskey;" - preference="privacy.cpd.formdata" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - <listitem label="&itemCookies.label;" - type="checkbox" - accesskey="&itemCookies.accesskey;" - preference="privacy.cpd.cookies" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - <listitem label="&itemCache.label;" - type="checkbox" - accesskey="&itemCache.accesskey;" - preference="privacy.cpd.cache" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - <listitem label="&itemActiveLogins.label;" - type="checkbox" - accesskey="&itemActiveLogins.accesskey;" - preference="privacy.cpd.sessions" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - <listitem label="&itemOfflineApps.label;" - type="checkbox" - accesskey="&itemOfflineApps.accesskey;" - preference="privacy.cpd.offlineApps" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - <listitem label="&itemSitePreferences.label;" - type="checkbox" - accesskey="&itemSitePreferences.accesskey;" - preference="privacy.cpd.siteSettings" - noduration="true" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - <listitem label="&itemConnectivityData.label;" - type="checkbox" - accesskey="&itemConnectivityData.accesskey;" - preference="privacy.cpd.connectivityData" - noduration="true" - onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> - </listbox> - - </prefpane> -</prefwindow> diff --git a/browser/base/content/sanitizeDialog.css b/browser/base/content/sanitizeDialog.css deleted file mode 100644 index 27c3c0866..000000000 --- a/browser/base/content/sanitizeDialog.css +++ /dev/null @@ -1,23 +0,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/. */ - -/* Places tree */ - -#placesTreechildren { - -moz-user-focus: normal; -} - -#placesTreechildren::-moz-tree-cell(grippyRow), -#placesTreechildren::-moz-tree-cell-text(grippyRow), -#placesTreechildren::-moz-tree-image(grippyRow) { - cursor: -moz-grab; -} - - -/* Sanitize everything warnings */ - -#sanitizeEverythingWarning, -#sanitizeEverythingUndoWarning { - white-space: pre-wrap; -} diff --git a/browser/base/content/sanitizeDialog.js b/browser/base/content/sanitizeDialog.js deleted file mode 100644 index 18df5e4a4..000000000 --- a/browser/base/content/sanitizeDialog.js +++ /dev/null @@ -1,910 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -const Cc = Components.classes; -const Ci = Components.interfaces; - -var gSanitizePromptDialog = { - - get bundleBrowser() - { - if (!this._bundleBrowser) - this._bundleBrowser = document.getElementById("bundleBrowser"); - return this._bundleBrowser; - }, - - get selectedTimespan() - { - var durList = document.getElementById("sanitizeDurationChoice"); - return parseInt(durList.value); - }, - - get sanitizePreferences() - { - if (!this._sanitizePreferences) { - this._sanitizePreferences = - document.getElementById("sanitizePreferences"); - } - return this._sanitizePreferences; - }, - - get warningBox() - { - return document.getElementById("sanitizeEverythingWarningBox"); - }, - - init: function () - { - // This is used by selectByTimespan() to determine if the window has loaded. - this._inited = true; - - var s = new Sanitizer(); - s.prefDomain = "privacy.cpd."; - - let sanitizeItemList = document.querySelectorAll("#itemList > [preference]"); - for (let i = 0; i < sanitizeItemList.length; i++) { - let prefItem = sanitizeItemList[i]; - let name = s.getNameFromPreference(prefItem.getAttribute("preference")); - s.canClearItem(name, function canClearCallback(aItem, aCanClear, aPrefItem) { - if (!aCanClear) { - aPrefItem.preference = null; - aPrefItem.checked = false; - aPrefItem.disabled = true; - } - }, prefItem); - } - - document.documentElement.getButton("accept").label = - this.bundleBrowser.getString("sanitizeButtonOK"); - - if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) { - this.prepareWarning(); - this.warningBox.hidden = false; - document.title = - this.bundleBrowser.getString("sanitizeDialog2.everything.title"); - } - else - this.warningBox.hidden = true; - }, - - selectByTimespan: function () - { - // This method is the onselect handler for the duration dropdown. As a - // result it's called a couple of times before onload calls init(). - if (!this._inited) - return; - - var warningBox = this.warningBox; - - // If clearing everything - if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) { - this.prepareWarning(); - if (warningBox.hidden) { - warningBox.hidden = false; - window.resizeBy(0, warningBox.boxObject.height); - } - window.document.title = - this.bundleBrowser.getString("sanitizeDialog2.everything.title"); - return; - } - - // If clearing a specific time range - if (!warningBox.hidden) { - window.resizeBy(0, -warningBox.boxObject.height); - warningBox.hidden = true; - } - window.document.title = - window.document.documentElement.getAttribute("noneverythingtitle"); - }, - - sanitize: function () - { - // Update pref values before handing off to the sanitizer (bug 453440) - this.updatePrefs(); - var s = new Sanitizer(); - s.prefDomain = "privacy.cpd."; - - s.range = Sanitizer.getClearRange(this.selectedTimespan); - s.ignoreTimespan = !s.range; - - // As the sanitize is async, we disable the buttons, update the label on - // the 'accept' button to indicate things are happening and return false - - // once the async operation completes (either with or without errors) - // we close the window. - let docElt = document.documentElement; - let acceptButton = docElt.getButton("accept"); - acceptButton.disabled = true; - acceptButton.setAttribute("label", - this.bundleBrowser.getString("sanitizeButtonClearing")); - docElt.getButton("cancel").disabled = true; - try { - s.sanitize().then(window.close, window.close); - } catch (er) { - Components.utils.reportError("Exception during sanitize: " + er); - return true; // We *do* want to close immediately on error. - } - return false; - }, - - /** - * If the panel that displays a warning when the duration is "Everything" is - * not set up, sets it up. Otherwise does nothing. - * - * @param aDontShowItemList Whether only the warning message should be updated. - * True means the item list visibility status should not - * be changed. - */ - prepareWarning: function (aDontShowItemList) { - // If the date and time-aware locale warning string is ever used again, - // initialize it here. Currently we use the no-visits warning string, - // which does not include date and time. See bug 480169 comment 48. - - var warningStringID; - if (this.hasNonSelectedItems()) { - warningStringID = "sanitizeSelectedWarning"; - if (!aDontShowItemList) - this.showItemList(); - } - else { - warningStringID = "sanitizeEverythingWarning2"; - } - - var warningDesc = document.getElementById("sanitizeEverythingWarning"); - warningDesc.textContent = - this.bundleBrowser.getString(warningStringID); - }, - - /** - * Called when the value of a preference element is synced from the actual - * pref. Enables or disables the OK button appropriately. - */ - onReadGeneric: function () - { - var found = false; - - // Find any other pref that's checked and enabled. - var i = 0; - while (!found && i < this.sanitizePreferences.childNodes.length) { - var preference = this.sanitizePreferences.childNodes[i]; - - found = !!preference.value && - !preference.disabled; - i++; - } - - try { - document.documentElement.getButton("accept").disabled = !found; - } - catch (e) { } - - // Update the warning prompt if needed - this.prepareWarning(true); - - return undefined; - }, - - /** - * Sanitizer.prototype.sanitize() requires the prefs to be up-to-date. - * Because the type of this prefwindow is "child" -- and that's needed because - * without it the dialog has no OK and Cancel buttons -- the prefs are not - * updated on dialogaccept on platforms that don't support instant-apply - * (i.e., Windows). We must therefore manually set the prefs from their - * corresponding preference elements. - */ - updatePrefs : function () - { - var tsPref = document.getElementById("privacy.sanitize.timeSpan"); - Sanitizer.prefs.setIntPref("timeSpan", this.selectedTimespan); - - // Keep the pref for the download history in sync with the history pref. - document.getElementById("privacy.cpd.downloads").value = - document.getElementById("privacy.cpd.history").value; - - // Now manually set the prefs from their corresponding preference - // elements. - var prefs = this.sanitizePreferences.rootBranch; - for (let i = 0; i < this.sanitizePreferences.childNodes.length; ++i) { - var p = this.sanitizePreferences.childNodes[i]; - prefs.setBoolPref(p.name, p.value); - } - }, - - /** - * Check if all of the history items have been selected like the default status. - */ - hasNonSelectedItems: function () { - let checkboxes = document.querySelectorAll("#itemList > [preference]"); - for (let i = 0; i < checkboxes.length; ++i) { - let pref = document.getElementById(checkboxes[i].getAttribute("preference")); - if (!pref.value) - return true; - } - return false; - }, - - /** - * Show the history items list. - */ - showItemList: function () { - var itemList = document.getElementById("itemList"); - var expanderButton = document.getElementById("detailsExpander"); - - if (itemList.collapsed) { - expanderButton.className = "expander-up"; - itemList.setAttribute("collapsed", "false"); - if (document.documentElement.boxObject.height) - window.resizeBy(0, itemList.boxObject.height); - } - }, - - /** - * Hide the history items list. - */ - hideItemList: function () { - var itemList = document.getElementById("itemList"); - var expanderButton = document.getElementById("detailsExpander"); - - if (!itemList.collapsed) { - expanderButton.className = "expander-down"; - window.resizeBy(0, -itemList.boxObject.height); - itemList.setAttribute("collapsed", "true"); - } - }, - - /** - * Called by the item list expander button to toggle the list's visibility. - */ - toggleItemList: function () - { - var itemList = document.getElementById("itemList"); - - if (itemList.collapsed) - this.showItemList(); - else - this.hideItemList(); - } - -#ifdef CRH_DIALOG_TREE_VIEW - // A duration value; used in the same context as Sanitizer.TIMESPAN_HOUR, - // Sanitizer.TIMESPAN_2HOURS, et al. This should match the value attribute - // of the sanitizeDurationCustom menuitem. - get TIMESPAN_CUSTOM() - { - return -1; - }, - - get placesTree() - { - if (!this._placesTree) - this._placesTree = document.getElementById("placesTree"); - return this._placesTree; - }, - - init: function () - { - // This is used by selectByTimespan() to determine if the window has loaded. - this._inited = true; - - var s = new Sanitizer(); - s.prefDomain = "privacy.cpd."; - - let sanitizeItemList = document.querySelectorAll("#itemList > [preference]"); - for (let i = 0; i < sanitizeItemList.length; i++) { - let prefItem = sanitizeItemList[i]; - let name = s.getNameFromPreference(prefItem.getAttribute("preference")); - s.canClearItem(name, function canClearCallback(aCanClear) { - if (!aCanClear) { - prefItem.preference = null; - prefItem.checked = false; - prefItem.disabled = true; - } - }); - } - - document.documentElement.getButton("accept").label = - this.bundleBrowser.getString("sanitizeButtonOK"); - - this.selectByTimespan(); - }, - - /** - * Sets up the hashes this.durationValsToRows, which maps duration values - * to rows in the tree, this.durationRowsToVals, which maps rows in - * the tree to duration values, and this.durationStartTimes, which maps - * duration values to their corresponding start times. - */ - initDurationDropdown: function () - { - // First, calculate the start times for each duration. - this.durationStartTimes = {}; - var durVals = []; - var durPopup = document.getElementById("sanitizeDurationPopup"); - var durMenuitems = durPopup.childNodes; - for (let i = 0; i < durMenuitems.length; i++) { - let durMenuitem = durMenuitems[i]; - let durVal = parseInt(durMenuitem.value); - if (durMenuitem.localName === "menuitem" && - durVal !== Sanitizer.TIMESPAN_EVERYTHING && - durVal !== this.TIMESPAN_CUSTOM) { - durVals.push(durVal); - let durTimes = Sanitizer.getClearRange(durVal); - this.durationStartTimes[durVal] = durTimes[0]; - } - } - - // Sort the duration values ascending. Because one tree index can map to - // more than one duration, this ensures that this.durationRowsToVals maps - // a row index to the largest duration possible in the code below. - durVals.sort(); - - // Now calculate the rows in the tree of the durations' start times. For - // each duration, we are looking for the node in the tree whose time is the - // smallest time greater than or equal to the duration's start time. - this.durationRowsToVals = {}; - this.durationValsToRows = {}; - var view = this.placesTree.view; - // For all rows in the tree except the grippy row... - for (let i = 0; i < view.rowCount - 1; i++) { - let unfoundDurVals = []; - let nodeTime = view.QueryInterface(Ci.nsINavHistoryResultTreeViewer). - nodeForTreeIndex(i).time; - // For all durations whose rows have not yet been found in the tree, see - // if index i is their index. An index may map to more than one duration, - // in which case the final duration (the largest) wins. - for (let j = 0; j < durVals.length; j++) { - let durVal = durVals[j]; - let durStartTime = this.durationStartTimes[durVal]; - if (nodeTime < durStartTime) { - this.durationValsToRows[durVal] = i - 1; - this.durationRowsToVals[i - 1] = durVal; - } - else - unfoundDurVals.push(durVal); - } - durVals = unfoundDurVals; - } - - // If any durations were not found above, then every node in the tree has a - // time greater than or equal to the duration. In other words, those - // durations include the entire tree (except the grippy row). - for (let i = 0; i < durVals.length; i++) { - let durVal = durVals[i]; - this.durationValsToRows[durVal] = view.rowCount - 2; - this.durationRowsToVals[view.rowCount - 2] = durVal; - } - }, - - /** - * If the Places tree is not set up, sets it up. Otherwise does nothing. - */ - ensurePlacesTreeIsInited: function () - { - if (this._placesTreeIsInited) - return; - - this._placesTreeIsInited = true; - - // Either "Last Four Hours" or "Today" will have the most history. If - // it's been more than 4 hours since today began, "Today" will. Otherwise - // "Last Four Hours" will. - var times = Sanitizer.getClearRange(Sanitizer.TIMESPAN_TODAY); - - // If it's been less than 4 hours since today began, use the past 4 hours. - if (times[1] - times[0] < 14400000000) { // 4*60*60*1000000 - times = Sanitizer.getClearRange(Sanitizer.TIMESPAN_4HOURS); - } - - var histServ = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var query = histServ.getNewQuery(); - query.beginTimeReference = query.TIME_RELATIVE_EPOCH; - query.beginTime = times[0]; - query.endTimeReference = query.TIME_RELATIVE_EPOCH; - query.endTime = times[1]; - var opts = histServ.getNewQueryOptions(); - opts.sortingMode = opts.SORT_BY_DATE_DESCENDING; - opts.queryType = opts.QUERY_TYPE_HISTORY; - var result = histServ.executeQuery(query, opts); - - var view = gContiguousSelectionTreeHelper.setTree(this.placesTree, - new PlacesTreeView()); - result.addObserver(view, false); - this.initDurationDropdown(); - }, - - /** - * Called on select of the duration dropdown and when grippyMoved() sets a - * duration based on the location of the grippy row. Selects all the nodes in - * the tree that are contained in the selected duration. If clearing - * everything, the warning panel is shown instead. - */ - selectByTimespan: function () - { - // This method is the onselect handler for the duration dropdown. As a - // result it's called a couple of times before onload calls init(). - if (!this._inited) - return; - - var durDeck = document.getElementById("durationDeck"); - var durList = document.getElementById("sanitizeDurationChoice"); - var durVal = parseInt(durList.value); - var durCustom = document.getElementById("sanitizeDurationCustom"); - - // If grippy row is not at a duration boundary, show the custom menuitem; - // otherwise, hide it. Since the user cannot specify a custom duration by - // using the dropdown, this conditional is true only when this method is - // called onselect from grippyMoved(), so no selection need be made. - if (durVal === this.TIMESPAN_CUSTOM) { - durCustom.hidden = false; - return; - } - durCustom.hidden = true; - - // If clearing everything, show the warning and change the dialog's title. - if (durVal === Sanitizer.TIMESPAN_EVERYTHING) { - this.prepareWarning(); - durDeck.selectedIndex = 1; - window.document.title = - this.bundleBrowser.getString("sanitizeDialog2.everything.title"); - document.documentElement.getButton("accept").disabled = false; - return; - } - - // Otherwise -- if clearing a specific time range -- select that time range - // in the tree. - this.ensurePlacesTreeIsInited(); - durDeck.selectedIndex = 0; - window.document.title = - window.document.documentElement.getAttribute("noneverythingtitle"); - var durRow = this.durationValsToRows[durVal]; - gContiguousSelectionTreeHelper.rangedSelect(durRow); - gContiguousSelectionTreeHelper.scrollToGrippy(); - - // If duration is empty (there are no selected rows), disable the dialog's - // OK button. - document.documentElement.getButton("accept").disabled = durRow < 0; - }, - - sanitize: function () - { - // Update pref values before handing off to the sanitizer (bug 453440) - this.updatePrefs(); - var s = new Sanitizer(); - s.prefDomain = "privacy.cpd."; - - var durList = document.getElementById("sanitizeDurationChoice"); - var durValue = parseInt(durList.value); - s.ignoreTimespan = durValue === Sanitizer.TIMESPAN_EVERYTHING; - - // Set the sanitizer's time range if we're not clearing everything. - if (!s.ignoreTimespan) { - // If user selected a custom timespan, use that. - if (durValue === this.TIMESPAN_CUSTOM) { - var view = this.placesTree.view; - var now = Date.now() * 1000; - // We disable the dialog's OK button if there's no selection, but we'll - // handle that case just in... case. - if (view.selection.getRangeCount() === 0) - s.range = [now, now]; - else { - var startIndexRef = {}; - // Tree sorted by visit date DEscending, so start time time comes last. - view.selection.getRangeAt(0, {}, startIndexRef); - view.QueryInterface(Ci.nsINavHistoryResultTreeViewer); - var startNode = view.nodeForTreeIndex(startIndexRef.value); - s.range = [startNode.time, now]; - } - } - // Otherwise use the predetermined range. - else - s.range = [this.durationStartTimes[durValue], Date.now() * 1000]; - } - - try { - s.sanitize(); - } catch (er) { - Components.utils.reportError("Exception during sanitize: " + er); - } - return true; - }, - - /** - * In order to mark the custom Places tree view and its nsINavHistoryResult - * for garbage collection, we need to break the reference cycle between the - * two. - */ - unload: function () - { - let result = this.placesTree.getResult(); - result.removeObserver(this.placesTree.view); - this.placesTree.view = null; - }, - - /** - * Called when the user moves the grippy by dragging it, clicking in the tree, - * or on keypress. Updates the duration dropdown so that it displays the - * appropriate specific or custom duration. - * - * @param aEventName - * The name of the event whose handler called this method, e.g., - * "ondragstart", "onkeypress", etc. - * @param aEvent - * The event captured in the event handler. - */ - grippyMoved: function (aEventName, aEvent) - { - gContiguousSelectionTreeHelper[aEventName](aEvent); - var lastSelRow = gContiguousSelectionTreeHelper.getGrippyRow() - 1; - var durList = document.getElementById("sanitizeDurationChoice"); - var durValue = parseInt(durList.value); - - // Multiple durations can map to the same row. Don't update the dropdown - // if the current duration is valid for lastSelRow. - if ((durValue !== this.TIMESPAN_CUSTOM || - lastSelRow in this.durationRowsToVals) && - (durValue === this.TIMESPAN_CUSTOM || - this.durationValsToRows[durValue] !== lastSelRow)) { - // Setting durList.value causes its onselect handler to fire, which calls - // selectByTimespan(). - if (lastSelRow in this.durationRowsToVals) - durList.value = this.durationRowsToVals[lastSelRow]; - else - durList.value = this.TIMESPAN_CUSTOM; - } - - // If there are no selected rows, disable the dialog's OK button. - document.documentElement.getButton("accept").disabled = lastSelRow < 0; - } -#endif - -}; - - -#ifdef CRH_DIALOG_TREE_VIEW -/** - * A helper for handling contiguous selection in the tree. - */ -var gContiguousSelectionTreeHelper = { - - /** - * Gets the tree associated with this helper. - */ - get tree() - { - return this._tree; - }, - - /** - * Sets the tree that this module handles. The tree is assigned a new view - * that is equipped to handle contiguous selection. You can pass in an - * object that will be used as the prototype of the new view. Otherwise - * the tree's current view is used as the prototype. - * - * @param aTreeElement - * The tree element - * @param aProtoTreeView - * If defined, this will be used as the prototype of the tree's new - * view - * @return The new view - */ - setTree: function CSTH_setTree(aTreeElement, aProtoTreeView) - { - this._tree = aTreeElement; - var newView = this._makeTreeView(aProtoTreeView || aTreeElement.view); - aTreeElement.view = newView; - return newView; - }, - - /** - * The index of the row that the grippy occupies. Note that the index of the - * last selected row is getGrippyRow() - 1. If getGrippyRow() is 0, then - * no selection exists. - * - * @return The row index of the grippy - */ - getGrippyRow: function CSTH_getGrippyRow() - { - var sel = this.tree.view.selection; - var rangeCount = sel.getRangeCount(); - if (rangeCount === 0) - return 0; - if (rangeCount !== 1) { - throw "contiguous selection tree helper: getGrippyRow called with " + - "multiple selection ranges"; - } - var max = {}; - sel.getRangeAt(0, {}, max); - return max.value + 1; - }, - - /** - * Helper function for the dragover event. Your dragover listener should - * call this. It updates the selection in the tree under the mouse. - * - * @param aEvent - * The observed dragover event - */ - ondragover: function CSTH_ondragover(aEvent) - { - // Without this when dragging on Windows the mouse cursor is a "no" sign. - // This makes it a drop symbol. - var ds = Cc["@mozilla.org/widget/dragservice;1"]. - getService(Ci.nsIDragService). - getCurrentSession(); - ds.canDrop = true; - ds.dragAction = 0; - - var tbo = this.tree.treeBoxObject; - aEvent.QueryInterface(Ci.nsIDOMMouseEvent); - var hoverRow = tbo.getRowAt(aEvent.clientX, aEvent.clientY); - - if (hoverRow < 0) - return; - - this.rangedSelect(hoverRow - 1); - }, - - /** - * Helper function for the dragstart event. Your dragstart listener should - * call this. It starts a drag session. - * - * @param aEvent - * The observed dragstart event - */ - ondragstart: function CSTH_ondragstart(aEvent) - { - var tbo = this.tree.treeBoxObject; - var clickedRow = tbo.getRowAt(aEvent.clientX, aEvent.clientY); - - if (clickedRow !== this.getGrippyRow()) - return; - - // This part is a hack. What we really want is a grab and slide, not - // drag and drop. Start a move drag session with dummy data and a - // dummy region. Set the region's coordinates to (Infinity, Infinity) - // so it's drawn offscreen and its size to (1, 1). - var arr = Cc["@mozilla.org/supports-array;1"]. - createInstance(Ci.nsISupportsArray); - var trans = Cc["@mozilla.org/widget/transferable;1"]. - createInstance(Ci.nsITransferable); - trans.init(null); - trans.setTransferData('dummy-flavor', null, 0); - arr.AppendElement(trans); - var reg = Cc["@mozilla.org/gfx/region;1"]. - createInstance(Ci.nsIScriptableRegion); - reg.setToRect(Infinity, Infinity, 1, 1); - var ds = Cc["@mozilla.org/widget/dragservice;1"]. - getService(Ci.nsIDragService); - ds.invokeDragSession(aEvent.target, arr, reg, ds.DRAGDROP_ACTION_MOVE); - }, - - /** - * Helper function for the keypress event. Your keypress listener should - * call this. Users can use Up, Down, Page Up/Down, Home, and End to move - * the bottom of the selection window. - * - * @param aEvent - * The observed keypress event - */ - onkeypress: function CSTH_onkeypress(aEvent) - { - var grippyRow = this.getGrippyRow(); - var tbo = this.tree.treeBoxObject; - var rangeEnd; - switch (aEvent.keyCode) { - case aEvent.DOM_VK_HOME: - rangeEnd = 0; - break; - case aEvent.DOM_VK_PAGE_UP: - rangeEnd = grippyRow - tbo.getPageLength(); - break; - case aEvent.DOM_VK_UP: - rangeEnd = grippyRow - 2; - break; - case aEvent.DOM_VK_DOWN: - rangeEnd = grippyRow; - break; - case aEvent.DOM_VK_PAGE_DOWN: - rangeEnd = grippyRow + tbo.getPageLength(); - break; - case aEvent.DOM_VK_END: - rangeEnd = this.tree.view.rowCount - 2; - break; - default: - return; - break; - } - - aEvent.stopPropagation(); - - // First, clip rangeEnd. this.rangedSelect() doesn't clip the range if we - // select past the ends of the tree. - if (rangeEnd < 0) - rangeEnd = -1; - else if (this.tree.view.rowCount - 2 < rangeEnd) - rangeEnd = this.tree.view.rowCount - 2; - - // Next, (de)select. - this.rangedSelect(rangeEnd); - - // Finally, scroll the tree. We always want one row above and below the - // grippy row to be visible if possible. - if (rangeEnd < grippyRow) // moved up - tbo.ensureRowIsVisible(rangeEnd < 0 ? 0 : rangeEnd); - else { // moved down - if (rangeEnd + 2 < this.tree.view.rowCount) - tbo.ensureRowIsVisible(rangeEnd + 2); - else if (rangeEnd + 1 < this.tree.view.rowCount) - tbo.ensureRowIsVisible(rangeEnd + 1); - } - }, - - /** - * Helper function for the mousedown event. Your mousedown listener should - * call this. Users can click on individual rows to make the selection - * jump to them immediately. - * - * @param aEvent - * The observed mousedown event - */ - onmousedown: function CSTH_onmousedown(aEvent) - { - var tbo = this.tree.treeBoxObject; - var clickedRow = tbo.getRowAt(aEvent.clientX, aEvent.clientY); - - if (clickedRow < 0 || clickedRow >= this.tree.view.rowCount) - return; - - if (clickedRow < this.getGrippyRow()) - this.rangedSelect(clickedRow); - else if (clickedRow > this.getGrippyRow()) - this.rangedSelect(clickedRow - 1); - }, - - /** - * Selects range [0, aEndRow] in the tree. The grippy row will then be at - * index aEndRow + 1. aEndRow may be -1, in which case the selection is - * cleared and the grippy row will be at index 0. - * - * @param aEndRow - * The range [0, aEndRow] will be selected. - */ - rangedSelect: function CSTH_rangedSelect(aEndRow) - { - var tbo = this.tree.treeBoxObject; - if (aEndRow < 0) - this.tree.view.selection.clearSelection(); - else - this.tree.view.selection.rangedSelect(0, aEndRow, false); - tbo.invalidateRange(tbo.getFirstVisibleRow(), tbo.getLastVisibleRow()); - }, - - /** - * Scrolls the tree so that the grippy row is in the center of the view. - */ - scrollToGrippy: function CSTH_scrollToGrippy() - { - var rowCount = this.tree.view.rowCount; - var tbo = this.tree.treeBoxObject; - var pageLen = tbo.getPageLength() || - parseInt(this.tree.getAttribute("rows")) || - 10; - - // All rows fit on a single page. - if (rowCount <= pageLen) - return; - - var scrollToRow = this.getGrippyRow() - Math.ceil(pageLen / 2.0); - - // Grippy row is in first half of first page. - if (scrollToRow < 0) - scrollToRow = 0; - - // Grippy row is in last half of last page. - else if (rowCount < scrollToRow + pageLen) - scrollToRow = rowCount - pageLen; - - tbo.scrollToRow(scrollToRow); - }, - - /** - * Creates a new tree view suitable for contiguous selection. If - * aProtoTreeView is specified, it's used as the new view's prototype. - * Otherwise the tree's current view is used as the prototype. - * - * @param aProtoTreeView - * Used as the new view's prototype if specified - */ - _makeTreeView: function CSTH__makeTreeView(aProtoTreeView) - { - var view = aProtoTreeView; - var that = this; - - //XXXadw: When Alex gets the grippy icon done, this may or may not change, - // depending on how we style it. - view.isSeparator = function CSTH_View_isSeparator(aRow) - { - return aRow === that.getGrippyRow(); - }; - - // rowCount includes the grippy row. - view.__defineGetter__("_rowCount", view.__lookupGetter__("rowCount")); - view.__defineGetter__("rowCount", - function CSTH_View_rowCount() - { - return this._rowCount + 1; - }); - - // This has to do with visual feedback in the view itself, e.g., drawing - // a small line underneath the dropzone. Not what we want. - view.canDrop = function CSTH_View_canDrop() { return false; }; - - // No clicking headers to sort the tree or sort feedback on columns. - view.cycleHeader = function CSTH_View_cycleHeader() {}; - view.sortingChanged = function CSTH_View_sortingChanged() {}; - - // Override a bunch of methods to account for the grippy row. - - view._getCellProperties = view.getCellProperties; - view.getCellProperties = - function CSTH_View_getCellProperties(aRow, aCol) - { - var grippyRow = that.getGrippyRow(); - if (aRow === grippyRow) - return "grippyRow"; - if (aRow < grippyRow) - return this._getCellProperties(aRow, aCol); - - return this._getCellProperties(aRow - 1, aCol); - }; - - view._getRowProperties = view.getRowProperties; - view.getRowProperties = - function CSTH_View_getRowProperties(aRow) - { - var grippyRow = that.getGrippyRow(); - if (aRow === grippyRow) - return "grippyRow"; - - if (aRow < grippyRow) - return this._getRowProperties(aRow); - - return this._getRowProperties(aRow - 1); - }; - - view._getCellText = view.getCellText; - view.getCellText = - function CSTH_View_getCellText(aRow, aCol) - { - var grippyRow = that.getGrippyRow(); - if (aRow === grippyRow) - return ""; - aRow = aRow < grippyRow ? aRow : aRow - 1; - return this._getCellText(aRow, aCol); - }; - - view._getImageSrc = view.getImageSrc; - view.getImageSrc = - function CSTH_View_getImageSrc(aRow, aCol) - { - var grippyRow = that.getGrippyRow(); - if (aRow === grippyRow) - return ""; - aRow = aRow < grippyRow ? aRow : aRow - 1; - return this._getImageSrc(aRow, aCol); - }; - - view.isContainer = function CSTH_View_isContainer(aRow) { return false; }; - view.getParentIndex = function CSTH_View_getParentIndex(aRow) { return -1; }; - view.getLevel = function CSTH_View_getLevel(aRow) { return 0; }; - view.hasNextSibling = function CSTH_View_hasNextSibling(aRow, aAfterIndex) - { - return aRow < this.rowCount - 1; - }; - - return view; - } -}; -#endif diff --git a/browser/base/content/softwareUpdateOverlay.xul b/browser/base/content/softwareUpdateOverlay.xul deleted file mode 100644 index 01170e46c..000000000 --- a/browser/base/content/softwareUpdateOverlay.xul +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0"?> -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?> - -<overlay id="softwareUpdateOverlay" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<window id="updates"> - -#include browserMountPoints.inc - -</window> - -</overlay> diff --git a/browser/base/content/sync/aboutSyncTabs-bindings.xml b/browser/base/content/sync/aboutSyncTabs-bindings.xml deleted file mode 100644 index e6108209a..000000000 --- a/browser/base/content/sync/aboutSyncTabs-bindings.xml +++ /dev/null @@ -1,46 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<bindings id="tabBindings" - xmlns="http://www.mozilla.org/xbl" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:xbl="http://www.mozilla.org/xbl"> - - <binding id="tab-listing" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem"> - <content> - <xul:hbox flex="1"> - <xul:vbox pack="start"> - <xul:image class="tabIcon" - xbl:inherits="src=icon"/> - </xul:vbox> - <xul:vbox pack="start" flex="1"> - <xul:label xbl:inherits="value=title,selected" - crop="end" flex="1" class="title"/> - <xul:label xbl:inherits="value=url,selected" - crop="end" flex="1" class="url"/> - </xul:vbox> - </xul:hbox> - </content> - <handlers> - <handler event="dblclick" button="0"> - <![CDATA[ - RemoteTabViewer.openSelected(); - ]]> - </handler> - </handlers> - </binding> - - <binding id="client-listing" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem"> - <content> - <xul:hbox pack="start" align="center" onfocus="event.target.blur()" onselect="return false;"> - <xul:image/> - <xul:label xbl:inherits="value=clientName" - class="clientName" - crop="center" flex="1"/> - </xul:hbox> - </content> - </binding> -</bindings> diff --git a/browser/base/content/sync/aboutSyncTabs.css b/browser/base/content/sync/aboutSyncTabs.css deleted file mode 100644 index 5a353175b..000000000 --- a/browser/base/content/sync/aboutSyncTabs.css +++ /dev/null @@ -1,11 +0,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/. */ - -richlistitem[type="tab"] { - -moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#tab-listing); -} - -richlistitem[type="client"] { - -moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#client-listing); -} diff --git a/browser/base/content/sync/aboutSyncTabs.js b/browser/base/content/sync/aboutSyncTabs.js deleted file mode 100644 index 535c43e56..000000000 --- a/browser/base/content/sync/aboutSyncTabs.js +++ /dev/null @@ -1,313 +0,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/. */ - -const Cu = Components.utils; - -Cu.import("resource://services-common/utils.js"); -Cu.import("resource://services-sync/main.js"); -Cu.import("resource:///modules/PlacesUIUtils.jsm"); -Cu.import("resource://gre/modules/PlacesUtils.jsm", this); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -let RemoteTabViewer = { - _tabsList: null, - - init: function () { - Services.obs.addObserver(this, "weave:service:login:finish", false); - Services.obs.addObserver(this, "weave:engine:sync:finish", false); - - this._tabsList = document.getElementById("tabsList"); - - this.buildList(true); - }, - - uninit: function () { - Services.obs.removeObserver(this, "weave:service:login:finish"); - Services.obs.removeObserver(this, "weave:engine:sync:finish"); - }, - - createItem: function(attrs) { - let item = document.createElement("richlistitem"); - - // Copy the attributes from the argument into the item - for (let attr in attrs) { - item.setAttribute(attr, attrs[attr]); - } - - if (attrs["type"] == "tab") { - item.label = attrs.title != "" ? attrs.title : attrs.url; - } - - return item; - }, - - filterTabs: function(event) { - let val = event.target.value.toLowerCase(); - let numTabs = this._tabsList.getRowCount(); - let clientTabs = 0; - let currentClient = null; - - for (let i = 0; i < numTabs; i++) { - let item = this._tabsList.getItemAtIndex(i); - let hide = false; - if (item.getAttribute("type") == "tab") { - if (!item.getAttribute("url").toLowerCase().includes(val) && - !item.getAttribute("title").toLowerCase().includes(val)) { - hide = true; - } else { - clientTabs++; - } - } - else if (item.getAttribute("type") == "client") { - if (currentClient) { - if (clientTabs == 0) { - currentClient.hidden = true; - } - } - currentClient = item; - clientTabs = 0; - } - item.hidden = hide; - } - if (clientTabs == 0) { - currentClient.hidden = true; - } - }, - - openSelected: function() { - let items = this._tabsList.selectedItems; - let urls = []; - for (let i = 0;i < items.length;i++) { - if (items[i].getAttribute("type") == "tab") { - urls.push(items[i].getAttribute("url")); - let index = this._tabsList.getIndexOfItem(items[i]); - this._tabsList.removeItemAt(index); - } - } - if (urls.length) { - getTopWin().gBrowser.loadTabs(urls); - this._tabsList.clearSelection(); - } - }, - - bookmarkSingleTab: function() { - let item = this._tabsList.selectedItems[0]; - let uri = Weave.Utils.makeURI(item.getAttribute("url")); - let title = item.getAttribute("title"); - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "bookmark" - , uri: uri - , title: title - , hiddenRows: [ "description" - , "location" - , "loadInSidebar" - , "keyword" ] - }, window.top); - }, - - bookmarkSelectedTabs: function() { - let items = this._tabsList.selectedItems; - let URIs = []; - for (let i = 0;i < items.length;i++) { - if (items[i].getAttribute("type") == "tab") { - let uri = Weave.Utils.makeURI(items[i].getAttribute("url")); - if (!uri) { - continue; - } - - URIs.push(uri); - } - } - if (URIs.length) { - PlacesUIUtils.showBookmarkDialog({ action: "add" - , type: "folder" - , URIList: URIs - , hiddenRows: [ "description" ] - }, window.top); - } - }, - - getIcon: function (iconUri, defaultIcon) { - try { - let iconURI = Weave.Utils.makeURI(iconUri); - return PlacesUtils.favicons.getFaviconLinkForIcon(iconURI).spec; - } catch (ex) { - // Do nothing. - } - - // Just give the provided default icon or the system's default. - return defaultIcon || PlacesUtils.favicons.defaultFavicon.spec; - }, - - _waitingForBuildList: false, - - _buildListRequested: false, - - buildList: function (force) { - if (this._waitingForBuildList) { - this._buildListRequested = true; - return; - } - - this._waitingForBuildList = true; - this._buildListRequested = false; - - this._clearTabList(); - - if (Weave.Service.isLoggedIn && this._refetchTabs(force)) { - this._generateWeaveTabList(); - } else { - //XXXzpao We should say something about not being logged in & not having data - // or tell the appropriate condition. (bug 583344) - } - - function complete() { - this._waitingForBuildList = false; - if (this._buildListRequested) { - CommonUtils.nextTick(this.buildList, this); - } - } - - complete(); - }, - - _clearTabList: function () { - let list = this._tabsList; - - // Clear out existing richlistitems - let count = list.getRowCount(); - if (count > 0) { - for (let i = count - 1; i >= 0; i--) { - list.removeItemAt(i); - } - } - }, - - _generateWeaveTabList: function () { - let engine = Weave.Service.engineManager.get("tabs"); - let list = this._tabsList; - - let seenURLs = new Set(); - let localURLs = engine.getOpenURLs(); - - for (let [guid, client] in Iterator(engine.getAllClients())) { - // Create the client node, but don't add it in-case we don't show any tabs - let appendClient = true; - - client.tabs.forEach(function({title, urlHistory, icon}) { - let url = urlHistory[0]; - if (!url || localURLs.has(url) || seenURLs.has(url)) { - return; - } - seenURLs.add(url); - - if (appendClient) { - let attrs = { - type: "client", - clientName: client.clientName, - class: Weave.Service.clientsEngine.isMobile(client.id) ? "mobile" : "desktop" - }; - let clientEnt = this.createItem(attrs); - list.appendChild(clientEnt); - appendClient = false; - clientEnt.disabled = true; - } - let attrs = { - type: "tab", - title: title || url, - url: url, - icon: this.getIcon(icon), - } - let tab = this.createItem(attrs); - list.appendChild(tab); - }, this); - } - }, - - adjustContextMenu: function(event) { - let mode = "all"; - switch (this._tabsList.selectedItems.length) { - case 0: - break; - case 1: - mode = "single" - break; - default: - mode = "multiple"; - break; - } - - let menu = document.getElementById("tabListContext"); - let el = menu.firstChild; - while (el) { - let showFor = el.getAttribute("showFor"); - if (showFor) { - el.hidden = showFor != mode && showFor != "all"; - } - - el = el.nextSibling; - } - }, - - _refetchTabs: function(force) { - if (!force) { - // Don't bother refetching tabs if we already did so recently - let lastFetch = 0; - try { - lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch"); - } - catch (e) { - /* Just use the default value of 0 */ - } - - let now = Math.floor(Date.now() / 1000); - if (now - lastFetch < 30) { - return false; - } - } - - // if Clients hasn't synced yet this session, we need to sync it as well. - if (Weave.Service.clientsEngine.lastSync == 0) { - Weave.Service.clientsEngine.sync(); - } - - // Force a sync only for the tabs engine - let engine = Weave.Service.engineManager.get("tabs"); - engine.lastModified = null; - engine.sync(); - Services.prefs.setIntPref("services.sync.lastTabFetch", - Math.floor(Date.now() / 1000)); - - return true; - }, - - observe: function(subject, topic, data) { - switch (topic) { - case "weave:service:login:finish": - this.buildList(true); - break; - case "weave:engine:sync:finish": - if (subject == "tabs") { - this.buildList(false); - } - break; - } - }, - - handleClick: function(event) { - if (event.target.getAttribute("type") != "tab") { - return; - } - - - if (event.button == 1) { - let url = event.target.getAttribute("url"); - openUILink(url, event); - let index = this._tabsList.getIndexOfItem(event.target); - this._tabsList.removeItemAt(index); - } - } -} - diff --git a/browser/base/content/sync/aboutSyncTabs.xul b/browser/base/content/sync/aboutSyncTabs.xul deleted file mode 100644 index a4aa0032f..000000000 --- a/browser/base/content/sync/aboutSyncTabs.xul +++ /dev/null @@ -1,68 +0,0 @@ -<?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/. --> - -<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/aboutSyncTabs.css" type="text/css"?> -<?xml-stylesheet href="chrome://browser/content/sync/aboutSyncTabs.css" type="text/css"?> - -<!DOCTYPE window [ - <!ENTITY % aboutSyncTabsDTD SYSTEM "chrome://browser/locale/aboutSyncTabs.dtd"> - %aboutSyncTabsDTD; -]> - -<window id="tabs-display" - onload="RemoteTabViewer.init()" - onunload="RemoteTabViewer.uninit()" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:html="http://www.w3.org/1999/xhtml" - title="&tabs.otherDevices.label;"> - <script type="application/javascript;version=1.8" src="chrome://browser/content/sync/aboutSyncTabs.js"/> - <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/> - <html:head> - <html:link rel="icon" href="chrome://browser/skin/sync-16.png"/> - </html:head> - - <popupset id="contextmenus"> - <menupopup id="tabListContext"> - <menuitem label="&tabs.context.openTab.label;" - accesskey="&tabs.context.openTab.accesskey;" - oncommand="RemoteTabViewer.openSelected()" - showFor="single"/> - <menuitem label="&tabs.context.bookmarkSingleTab.label;" - accesskey="&tabs.context.bookmarkSingleTab.accesskey;" - oncommand="RemoteTabViewer.bookmarkSingleTab(event)" - showFor="single"/> - <menuitem label="&tabs.context.openMultipleTabs.label;" - accesskey="&tabs.context.openMultipleTabs.accesskey;" - oncommand="RemoteTabViewer.openSelected()" - showFor="multiple"/> - <menuitem label="&tabs.context.bookmarkMultipleTabs.label;" - accesskey="&tabs.context.bookmarkMultipleTabs.accesskey;" - oncommand="RemoteTabViewer.bookmarkSelectedTabs()" - showFor="multiple"/> - <menuseparator/> - <menuitem label="&tabs.context.refreshList.label;" - accesskey="&tabs.context.refreshList.accesskey;" - oncommand="RemoteTabViewer.buildList()" - showFor="all"/> - </menupopup> - </popupset> - <richlistbox context="tabListContext" id="tabsList" seltype="multiple" - align="center" flex="1" - onclick="RemoteTabViewer.handleClick(event)" - oncontextmenu="RemoteTabViewer.adjustContextMenu(event)"> - <hbox id="headers" align="center"> - <label id="tabsListHeading" - value="&tabs.otherDevices.label;"/> - <spacer flex="1"/> - <textbox type="search" - emptytext="&tabs.searchText.label;" - oncommand="RemoteTabViewer.filterTabs(event)"/> - </hbox> - - </richlistbox> -</window> - diff --git a/browser/base/content/sync/addDevice.js b/browser/base/content/sync/addDevice.js deleted file mode 100644 index 556e75768..000000000 --- a/browser/base/content/sync/addDevice.js +++ /dev/null @@ -1,157 +0,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/. */ - -const Ci = Components.interfaces; -const Cc = Components.classes; -const Cu = Components.utils; - -Cu.import("resource://services-sync/main.js"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -const PIN_PART_LENGTH = 4; - -const ADD_DEVICE_PAGE = 0; -const SYNC_KEY_PAGE = 1; -const DEVICE_CONNECTED_PAGE = 2; - -let gSyncAddDevice = { - - init: function init() { - this.pin1.setAttribute("maxlength", PIN_PART_LENGTH); - this.pin2.setAttribute("maxlength", PIN_PART_LENGTH); - this.pin3.setAttribute("maxlength", PIN_PART_LENGTH); - - this.nextFocusEl = {pin1: this.pin2, - pin2: this.pin3, - pin3: this.wizard.getButton("next")}; - - this.throbber = document.getElementById("pairDeviceThrobber"); - this.errorRow = document.getElementById("errorRow"); - - // Kick off a sync. That way the server will have the most recent data from - // this computer and it will show up immediately on the new device. - Weave.Service.scheduler.scheduleNextSync(0); - }, - - onPageShow: function onPageShow() { - this.wizard.getButton("back").hidden = true; - - switch (this.wizard.pageIndex) { - case ADD_DEVICE_PAGE: - this.onTextBoxInput(); - this.wizard.canRewind = false; - this.wizard.getButton("next").hidden = false; - this.pin1.focus(); - break; - case SYNC_KEY_PAGE: - this.wizard.canAdvance = false; - this.wizard.canRewind = true; - this.wizard.getButton("back").hidden = false; - this.wizard.getButton("next").hidden = true; - document.getElementById("weavePassphrase").value = - Weave.Utils.hyphenatePassphrase(Weave.Service.identity.syncKey); - break; - case DEVICE_CONNECTED_PAGE: - this.wizard.canAdvance = true; - this.wizard.canRewind = false; - this.wizard.getButton("cancel").hidden = true; - break; - } - }, - - onWizardAdvance: function onWizardAdvance() { - switch (this.wizard.pageIndex) { - case ADD_DEVICE_PAGE: - this.startTransfer(); - return false; - case DEVICE_CONNECTED_PAGE: - window.close(); - return false; - } - return true; - }, - - startTransfer: function startTransfer() { - this.errorRow.hidden = true; - // When onAbort is called, Weave may already be gone. - const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT; - - let self = this; - let jpakeclient = this._jpakeclient = new Weave.JPAKEClient({ - onPaired: function onPaired() { - let credentials = {account: Weave.Service.identity.account, - password: Weave.Service.identity.basicPassword, - synckey: Weave.Service.identity.syncKey, - serverURL: Weave.Service.serverURL}; - jpakeclient.sendAndComplete(credentials); - }, - onComplete: function onComplete() { - delete self._jpakeclient; - self.wizard.pageIndex = DEVICE_CONNECTED_PAGE; - - // Schedule a Sync for soonish to fetch the data uploaded by the - // device with which we just paired. - Weave.Service.scheduler.scheduleNextSync(Weave.Service.scheduler.activeInterval); - }, - onAbort: function onAbort(error) { - delete self._jpakeclient; - - // Aborted by user, ignore. - if (error == JPAKE_ERROR_USERABORT) { - return; - } - - self.errorRow.hidden = false; - self.throbber.hidden = true; - self.pin1.value = self.pin2.value = self.pin3.value = ""; - self.pin1.disabled = self.pin2.disabled = self.pin3.disabled = false; - self.pin1.focus(); - } - }); - this.throbber.hidden = false; - this.pin1.disabled = this.pin2.disabled = this.pin3.disabled = true; - this.wizard.canAdvance = false; - - let pin = this.pin1.value + this.pin2.value + this.pin3.value; - let expectDelay = false; - jpakeclient.pairWithPIN(pin, expectDelay); - }, - - onWizardBack: function onWizardBack() { - if (this.wizard.pageIndex != SYNC_KEY_PAGE) - return true; - - this.wizard.pageIndex = ADD_DEVICE_PAGE; - return false; - }, - - onWizardCancel: function onWizardCancel() { - if (this._jpakeclient) { - this._jpakeclient.abort(); - delete this._jpakeclient; - } - return true; - }, - - onTextBoxInput: function onTextBoxInput(textbox) { - if (textbox && textbox.value.length == PIN_PART_LENGTH) - this.nextFocusEl[textbox.id].focus(); - - this.wizard.canAdvance = (this.pin1.value.length == PIN_PART_LENGTH - && this.pin2.value.length == PIN_PART_LENGTH - && this.pin3.value.length == PIN_PART_LENGTH); - }, - - goToSyncKeyPage: function goToSyncKeyPage() { - this.wizard.pageIndex = SYNC_KEY_PAGE; - } - -}; -// onWizardAdvance() and onPageShow() are run before init() so we'll set -// these up as lazy getters. -["wizard", "pin1", "pin2", "pin3"].forEach(function (id) { - XPCOMUtils.defineLazyGetter(gSyncAddDevice, id, function() { - return document.getElementById(id); - }); -}); diff --git a/browser/base/content/sync/addDevice.xul b/browser/base/content/sync/addDevice.xul deleted file mode 100644 index f2371aad0..000000000 --- a/browser/base/content/sync/addDevice.xul +++ /dev/null @@ -1,129 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/syncSetup.css" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?> - -<!DOCTYPE window [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> -<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd"> -<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd"> -%brandDTD; -%syncBrandDTD; -%syncSetupDTD; -]> -<wizard xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:html="http://www.w3.org/1999/xhtml" - id="wizard" - title="&pairDevice.title.label;" - windowtype="Sync:AddDevice" - persist="screenX screenY" - onwizardnext="return gSyncAddDevice.onWizardAdvance();" - onwizardback="return gSyncAddDevice.onWizardBack();" - onwizardcancel="gSyncAddDevice.onWizardCancel();" - onload="gSyncAddDevice.init();"> - - <script type="application/javascript" - src="chrome://browser/content/sync/addDevice.js"/> - <script type="application/javascript" - src="chrome://browser/content/sync/utils.js"/> - <script type="application/javascript" - src="chrome://browser/content/utilityOverlay.js"/> - <script type="application/javascript" - src="chrome://global/content/printUtils.js"/> - - <wizardpage id="addDevicePage" - label="&pairDevice.title.label;" - onpageshow="gSyncAddDevice.onPageShow();"> - <description> - &pairDevice.dialog.description.label; - <label class="text-link" - value="&addDevice.showMeHow.label;" - href="http://www.palemoon.org/sync/help/easy-setup.shtml"/> - </description> - <separator class="groove-thin"/> - <description> - &addDevice.dialog.enterCode.label; - </description> - <separator class="groove-thin"/> - <vbox align="center"> - <textbox id="pin1" - class="pin" - oninput="gSyncAddDevice.onTextBoxInput(this);" - onfocus="this.select();" - /> - <textbox id="pin2" - class="pin" - oninput="gSyncAddDevice.onTextBoxInput(this);" - onfocus="this.select();" - /> - <textbox id="pin3" - class="pin" - oninput="gSyncAddDevice.onTextBoxInput(this);" - onfocus="this.select();" - /> - </vbox> - <separator class="groove-thin"/> - <vbox id="pairDeviceThrobber" align="center" hidden="true"> - <image/> - </vbox> - <hbox id="errorRow" pack="center" hidden="true"> - <image class="statusIcon" status="error"/> - <label class="status" - value="&addDevice.dialog.tryAgain.label;"/> - </hbox> - <spacer flex="3"/> - <label class="text-link" - value="&addDevice.dontHaveDevice.label;" - onclick="gSyncAddDevice.goToSyncKeyPage();"/> - </wizardpage> - - <!-- Need a non-empty label here, otherwise we get a default label on Mac --> - <wizardpage id="syncKeyPage" - label=" " - onpageshow="gSyncAddDevice.onPageShow();"> - <description> - &addDevice.dialog.recoveryKey.label; - </description> - <spacer/> - - <groupbox> - <label value="&recoveryKeyEntry.label;" - accesskey="&recoveryKeyEntry.accesskey;" - control="weavePassphrase"/> - <textbox id="weavePassphrase" - readonly="true"/> - </groupbox> - - <groupbox align="center"> - <description>&recoveryKeyBackup.description;</description> - <hbox> - <button id="printSyncKeyButton" - label="&button.syncKeyBackup.print.label;" - accesskey="&button.syncKeyBackup.print.accesskey;" - oncommand="gSyncUtils.passphrasePrint('weavePassphrase');"/> - <button id="saveSyncKeyButton" - label="&button.syncKeyBackup.save.label;" - accesskey="&button.syncKeyBackup.save.accesskey;" - oncommand="gSyncUtils.passphraseSave('weavePassphrase');"/> - </hbox> - </groupbox> - </wizardpage> - - <wizardpage id="deviceConnectedPage" - label="&addDevice.dialog.connected.label;" - onpageshow="gSyncAddDevice.onPageShow();"> - <vbox align="center"> - <image id="successPageIcon"/> - </vbox> - <separator/> - <description class="normal"> - &addDevice.dialog.successful.label; - </description> - </wizardpage> - -</wizard> diff --git a/browser/base/content/sync/genericChange.js b/browser/base/content/sync/genericChange.js deleted file mode 100644 index 6d1ce9485..000000000 --- a/browser/base/content/sync/genericChange.js +++ /dev/null @@ -1,234 +0,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/. */ - -const Ci = Components.interfaces; -const Cc = Components.classes; - -Components.utils.import("resource://services-sync/main.js"); -Components.utils.import("resource://gre/modules/Services.jsm"); - -let Change = { - _dialog: null, - _dialogType: null, - _status: null, - _statusIcon: null, - _firstBox: null, - _secondBox: null, - - get _passphraseBox() { - delete this._passphraseBox; - return this._passphraseBox = document.getElementById("passphraseBox"); - }, - - get _currentPasswordInvalid() { - return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED; - }, - - get _updatingPassphrase() { - return this._dialogType == "UpdatePassphrase"; - }, - - onLoad: function Change_onLoad() { - /* Load labels */ - let introText = document.getElementById("introText"); - let introText2 = document.getElementById("introText2"); - let warningText = document.getElementById("warningText"); - - // load some other elements & info from the window - this._dialog = document.getElementById("change-dialog"); - this._dialogType = window.arguments[0]; - this._duringSetup = window.arguments[1]; - this._status = document.getElementById("status"); - this._statusIcon = document.getElementById("statusIcon"); - this._statusRow = document.getElementById("statusRow"); - this._firstBox = document.getElementById("textBox1"); - this._secondBox = document.getElementById("textBox2"); - - this._dialog.getButton("finish").disabled = true; - this._dialog.getButton("back").hidden = true; - - this._stringBundle = - Services.strings.createBundle("chrome://browser/locale/syncGenericChange.properties"); - - switch (this._dialogType) { - case "UpdatePassphrase": - case "ResetPassphrase": - document.getElementById("textBox1Row").hidden = true; - document.getElementById("textBox2Row").hidden = true; - document.getElementById("passphraseLabel").value - = this._str("new.recoverykey.label"); - document.getElementById("passphraseSpacer").hidden = false; - - if (this._updatingPassphrase) { - document.getElementById("passphraseHelpBox").hidden = false; - document.title = this._str("new.recoverykey.title"); - introText.textContent = this._str("new.recoverykey.introText"); - this._dialog.getButton("finish").label - = this._str("new.recoverykey.acceptButton"); - } - else { - document.getElementById("generatePassphraseButton").hidden = false; - document.getElementById("passphraseBackupButtons").hidden = false; - let pp = Weave.Service.identity.syncKey; - if (Weave.Utils.isPassphrase(pp)) - pp = Weave.Utils.hyphenatePassphrase(pp); - this._passphraseBox.value = pp; - this._passphraseBox.focus(); - document.title = this._str("change.recoverykey.title"); - introText.textContent = this._str("change.synckey.introText2"); - warningText.textContent = this._str("change.recoverykey.warningText"); - this._dialog.getButton("finish").label - = this._str("change.recoverykey.acceptButton"); - if (this._duringSetup) { - this._dialog.getButton("finish").disabled = false; - } - } - break; - case "ChangePassword": - document.getElementById("passphraseRow").hidden = true; - let box1label = document.getElementById("textBox1Label"); - let box2label = document.getElementById("textBox2Label"); - box1label.value = this._str("new.password.label"); - - if (this._currentPasswordInvalid) { - document.title = this._str("new.password.title"); - introText.textContent = this._str("new.password.introText"); - this._dialog.getButton("finish").label - = this._str("new.password.acceptButton"); - document.getElementById("textBox2Row").hidden = true; - } - else { - document.title = this._str("change.password.title"); - box2label.value = this._str("new.password.confirm"); - introText.textContent = this._str("change.password3.introText"); - warningText.textContent = this._str("change.password.warningText"); - this._dialog.getButton("finish").label - = this._str("change.password.acceptButton"); - } - break; - } - document.getElementById("change-page") - .setAttribute("label", document.title); - }, - - _clearStatus: function _clearStatus() { - this._status.value = ""; - this._statusIcon.removeAttribute("status"); - }, - - _updateStatus: function Change__updateStatus(str, state) { - this._updateStatusWithString(this._str(str), state); - }, - - _updateStatusWithString: function Change__updateStatusWithString(string, state) { - this._statusRow.hidden = false; - this._status.value = string; - this._statusIcon.setAttribute("status", state); - - let error = state == "error"; - this._dialog.getButton("cancel").disabled = !error; - this._dialog.getButton("finish").disabled = !error; - document.getElementById("printSyncKeyButton").disabled = !error; - document.getElementById("saveSyncKeyButton").disabled = !error; - - if (state == "success") - window.setTimeout(window.close, 1500); - }, - - onDialogAccept: function() { - switch (this._dialogType) { - case "UpdatePassphrase": - case "ResetPassphrase": - return this.doChangePassphrase(); - break; - case "ChangePassword": - return this.doChangePassword(); - break; - } - }, - - doGeneratePassphrase: function () { - let passphrase = Weave.Utils.generatePassphrase(); - this._passphraseBox.value = Weave.Utils.hyphenatePassphrase(passphrase); - this._dialog.getButton("finish").disabled = false; - }, - - doChangePassphrase: function Change_doChangePassphrase() { - let pp = Weave.Utils.normalizePassphrase(this._passphraseBox.value); - if (this._updatingPassphrase) { - Weave.Service.identity.syncKey = pp; - if (Weave.Service.login()) { - this._updateStatus("change.recoverykey.success", "success"); - Weave.Service.persistLogin(); - Weave.Service.scheduler.delayedAutoConnect(0); - } - else { - this._updateStatus("new.passphrase.status.incorrect", "error"); - } - } - else { - this._updateStatus("change.recoverykey.label", "active"); - - if (Weave.Service.changePassphrase(pp)) - this._updateStatus("change.recoverykey.success", "success"); - else - this._updateStatus("change.recoverykey.error", "error"); - } - - return false; - }, - - doChangePassword: function Change_doChangePassword() { - if (this._currentPasswordInvalid) { - Weave.Service.identity.basicPassword = this._firstBox.value; - if (Weave.Service.login()) { - this._updateStatus("change.password.status.success", "success"); - Weave.Service.persistLogin(); - } - else { - this._updateStatus("new.password.status.incorrect", "error"); - } - } - else { - this._updateStatus("change.password.status.active", "active"); - - if (Weave.Service.changePassword(this._firstBox.value)) - this._updateStatus("change.password.status.success", "success"); - else - this._updateStatus("change.password.status.error", "error"); - } - - return false; - }, - - validate: function (event) { - let valid = false; - let errorString = ""; - - if (this._dialogType == "ChangePassword") { - if (this._currentPasswordInvalid) - [valid, errorString] = gSyncUtils.validatePassword(this._firstBox); - else - [valid, errorString] = gSyncUtils.validatePassword(this._firstBox, this._secondBox); - } - else { - //Pale Moon: Enforce minimum length of 8 for allowed custom passphrase - //and don't restrict it to "out of sync" situations only. People who - //go to this page generally know what they are doing ;) - valid = this._passphraseBox.value.length >= 8; - } - - if (errorString == "") - this._clearStatus(); - else - this._updateStatusWithString(errorString, "error"); - - this._statusRow.hidden = valid; - this._dialog.getButton("finish").disabled = !valid; - }, - - _str: function Change__string(str) { - return this._stringBundle.GetStringFromName(str); - } -}; diff --git a/browser/base/content/sync/genericChange.xul b/browser/base/content/sync/genericChange.xul deleted file mode 100644 index 3c0b2cd6c..000000000 --- a/browser/base/content/sync/genericChange.xul +++ /dev/null @@ -1,123 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/syncSetup.css" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?> - -<!DOCTYPE window [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> -<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd"> -<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd"> -%brandDTD; -%syncBrandDTD; -%syncSetupDTD; -]> -<wizard xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:html="http://www.w3.org/1999/xhtml" - id="change-dialog" - windowtype="Weave:ChangeSomething" - persist="screenX screenY" - onwizardnext="Change.onLoad()" - onwizardfinish="return Change.onDialogAccept();"> - - <script type="application/javascript" - src="chrome://browser/content/sync/genericChange.js"/> - <script type="application/javascript" - src="chrome://browser/content/sync/utils.js"/> - <script type="application/javascript" - src="chrome://global/content/printUtils.js"/> - - <wizardpage id="change-page" - label=""> - - <description id="introText"> - </description> - - <separator class="thin"/> - - <groupbox> - <grid> - <columns> - <column align="right"/> - <column flex="3"/> - <column flex="1"/> - </columns> - <rows> - <row id="textBox1Row" align="center"> - <label id="textBox1Label" control="textBox1"/> - <textbox id="textBox1" type="password" oninput="Change.validate()"/> - <spacer/> - </row> - <row id="textBox2Row" align="center"> - <label id="textBox2Label" control="textBox2"/> - <textbox id="textBox2" type="password" oninput="Change.validate()"/> - <spacer/> - </row> - </rows> - </grid> - - <vbox id="passphraseRow"> - <hbox flex="1"> - <label id="passphraseLabel" control="passphraseBox"/> - <spacer flex="1"/> - <label id="generatePassphraseButton" - hidden="true" - value="&syncGenerateNewKey.label;" - class="text-link inline-link" - onclick="event.stopPropagation(); - Change.doGeneratePassphrase();"/> - </hbox> - <textbox id="passphraseBox" - flex="1" - onfocus="this.select()" - oninput="Change.validate()"/> - </vbox> - - <vbox id="feedback" pack="center"> - <hbox id="statusRow" align="center"> - <image id="statusIcon" class="statusIcon"/> - <label id="status" class="status" value=" "/> - </hbox> - </vbox> - </groupbox> - - <separator class="thin"/> - - <hbox id="passphraseBackupButtons" - hidden="true" - pack="center"> - <button id="printSyncKeyButton" - label="&button.syncKeyBackup.print.label;" - accesskey="&button.syncKeyBackup.print.accesskey;" - oncommand="gSyncUtils.passphrasePrint('passphraseBox');"/> - <button id="saveSyncKeyButton" - label="&button.syncKeyBackup.save.label;" - accesskey="&button.syncKeyBackup.save.accesskey;" - oncommand="gSyncUtils.passphraseSave('passphraseBox');"/> - </hbox> - - <vbox id="passphraseHelpBox" - hidden="true"> - <description> - &existingRecoveryKey.description; - <label class="text-link" - href="http://www.palemoon.org/sync/help/recoverykey.shtml"> - &addDevice.showMeHow.label; - </label> - </description> - </vbox> - - <spacer id="passphraseSpacer" - flex="1" - hidden="true"/> - - <description id="warningText" class="data"> - </description> - - <spacer flex="1"/> - </wizardpage> -</wizard> diff --git a/browser/base/content/sync/key.xhtml b/browser/base/content/sync/key.xhtml deleted file mode 100644 index 92abf0ee6..000000000 --- a/browser/base/content/sync/key.xhtml +++ /dev/null @@ -1,54 +0,0 @@ -<?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/. --> - -<!DOCTYPE html [ - <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> - %htmlDTD; - <!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd"> - %syncBrandDTD; - <!ENTITY % syncKeyDTD SYSTEM "chrome://browser/locale/syncKey.dtd"> - %syncKeyDTD; - <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd" > - %globalDTD; -]> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> - <title>&syncKey.page.title;</title> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> - <meta name="robots" content="noindex"/> - <style type="text/css"> - #synckey { font-size: 150% } - footer { font-size: 70% } - /* Bug 575675: Need to have an a:visited rule in a chrome document. */ - a:visited { color: purple; } - </style> -</head> - -<body dir="&locale.dir;"> -<h1>&syncKey.page.title;</h1> - -<p id="synckey" dir="ltr">SYNCKEY</p> - -<p>&syncKey.page.description2;</p> - -<div id="column1"> - <h2>&syncKey.keepItSecret.heading;</h2> - <p>&syncKey.keepItSecret.description;</p> -</div> - -<div id="column2"> - <h2>&syncKey.keepItSafe.heading;</h2> - <p><em>&syncKey.keepItSafe1.description;</em>&syncKey.keepItSafe2.description;<em>&syncKey.keepItSafe3.description;</em>&syncKey.keepItSafe4a.description;</p> -</div> - -<p>&syncKey.findOutMore1.label;<a href="http://www.palemoon.org/sync/">http://www.palemoon.org/sync/</a>&syncKey.findOutMore2.label;</p> - -<footer> - &syncKey.footer1.label;<a id="tosLink" href="termsURL">termsURL</a>&syncKey.footer2.label;<a id="ppLink" href="privacyURL">privacyURL</a>&syncKey.footer3.label; -</footer> - -</body> -</html> diff --git a/browser/base/content/sync/notification.xml b/browser/base/content/sync/notification.xml deleted file mode 100644 index 7a2b77382..000000000 --- a/browser/base/content/sync/notification.xml +++ /dev/null @@ -1,129 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<!DOCTYPE bindings [ -<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd"> -%notificationDTD; -]> - -<bindings id="notificationBindings" - xmlns="http://www.mozilla.org/xbl" - xmlns:xbl="http://www.mozilla.org/xbl" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - - <binding id="notificationbox" extends="chrome://global/content/bindings/notification.xml#notificationbox"> - <content> - <xul:vbox xbl:inherits="hidden=notificationshidden"> - <xul:spacer/> - <children includes="notification"/> - </xul:vbox> - <children/> - </content> - - <implementation> - <constructor><![CDATA[ - let temp = {}; - Cu.import("resource://services-common/observers.js", temp); - temp.Observers.add("weave:notification:added", this.onNotificationAdded, this); - temp.Observers.add("weave:notification:removed", this.onNotificationRemoved, this); - - for each (var notification in Weave.Notifications.notifications) - this._appendNotification(notification); - ]]></constructor> - - <destructor><![CDATA[ - let temp = {}; - Cu.import("resource://services-common/observers.js", temp); - temp.Observers.remove("weave:notification:added", this.onNotificationAdded, this); - temp.Observers.remove("weave:notification:removed", this.onNotificationRemoved, this); - ]]></destructor> - - <method name="onNotificationAdded"> - <parameter name="subject"/> - <parameter name="data"/> - <body><![CDATA[ - this._appendNotification(subject); - ]]></body> - </method> - - <method name="onNotificationRemoved"> - <parameter name="subject"/> - <parameter name="data"/> - <body><![CDATA[ - // If the view of the notification hasn't been removed yet, remove it. - var notifications = this.allNotifications; - for each (var notification in notifications) { - if (notification.notification == subject) { - notification.close(); - break; - } - } - ]]></body> - </method> - - <method name="_appendNotification"> - <parameter name="notification"/> - <body><![CDATA[ - var node = this.appendNotification(notification.description, - notification.title, - notification.iconURL, - notification.priority, - notification.buttons); - node.notification = notification; - ]]></body> - </method> - - </implementation> - </binding> - - <binding id="notification" extends="chrome://global/content/bindings/notification.xml#notification"> - <content> - <xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type"> - <xul:toolbarbutton ondblclick="event.stopPropagation();" - class="messageCloseButton close-icon tabbable" - xbl:inherits="hidden=hideclose" - tooltiptext="&closeNotification.tooltip;" - oncommand="document.getBindingParent(this).close()"/> - <xul:hbox anonid="details" align="center" flex="1"> - <xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image"/> - <xul:description anonid="messageText" class="messageText" xbl:inherits="xbl:text=label"/> - - <!-- The children are the buttons defined by the notification. --> - <xul:hbox oncommand="document.getBindingParent(this)._doButtonCommand(event);"> - <children/> - </xul:hbox> - </xul:hbox> - </xul:hbox> - </content> - <implementation> - <!-- Note: this used to be a field, but for some reason it kept getting - - reset to its default value for TabNotification elements. - - As a property, that doesn't happen, even though the property stores - - its value in a JS property |_notification| that is not defined - - in XBL as a field or property. Maybe this is wrong, but it works. - --> - <property name="notification" - onget="return this._notification" - onset="this._notification = val; return val;"/> - <method name="close"> - <body><![CDATA[ - Weave.Notifications.remove(this.notification); - - // We should be able to call the base class's close method here - // to remove the notification element from the notification box, - // but we can't because of bug 373652, so instead we copied its code - // and execute it below. - var control = this.control; - if (control) - control.removeNotification(this); - else - this.hidden = true; - ]]></body> - </method> - </implementation> - </binding> - -</bindings> diff --git a/browser/base/content/sync/progress.js b/browser/base/content/sync/progress.js deleted file mode 100644 index 2063f612a..000000000 --- a/browser/base/content/sync/progress.js +++ /dev/null @@ -1,71 +0,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/. */ - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://services-sync/main.js"); - -let gProgressBar; -let gCounter = 0; - -function onLoad(event) { - Services.obs.addObserver(onEngineSync, "weave:engine:sync:finish", false); - Services.obs.addObserver(onEngineSync, "weave:engine:sync:error", false); - Services.obs.addObserver(onServiceSync, "weave:service:sync:finish", false); - Services.obs.addObserver(onServiceSync, "weave:service:sync:error", false); - - gProgressBar = document.getElementById('uploadProgressBar'); - - if (Services.prefs.getPrefType("services.sync.firstSync") != Ci.nsIPrefBranch.PREF_INVALID) { - gProgressBar.hidden = false; - } - else { - gProgressBar.hidden = true; - } -} - -function onUnload(event) { - cleanUpObservers(); -} - -function cleanUpObservers() { - try { - Services.obs.removeObserver(onEngineSync, "weave:engine:sync:finish"); - Services.obs.removeObserver(onEngineSync, "weave:engine:sync:error"); - Services.obs.removeObserver(onServiceSync, "weave:service:sync:finish"); - Services.obs.removeObserver(onServiceSync, "weave:service:sync:error"); - } - catch (e) { - // may be double called by unload & exit. Ignore. - } -} - -function onEngineSync(subject, topic, data) { - // The Clients engine syncs first. At this point we don't necessarily know - // yet how many engines will be enabled, so we'll ignore the Clients engine - // and evaluate how many engines are enabled when the first "real" engine - // syncs. - if (data == "clients") { - return; - } - - if (!gCounter && - Services.prefs.getPrefType("services.sync.firstSync") != Ci.nsIPrefBranch.PREF_INVALID) { - gProgressBar.max = Weave.Service.engineManager.getEnabled().length; - } - - gCounter += 1; - gProgressBar.setAttribute("value", gCounter); -} - -function onServiceSync(subject, topic, data) { - // To address the case where 0 engines are synced, we will fill the - // progress bar so the user knows that the sync has finished. - gProgressBar.setAttribute("value", gProgressBar.max); - cleanUpObservers(); -} - -function closeTab() { - window.close(); -} diff --git a/browser/base/content/sync/progress.xhtml b/browser/base/content/sync/progress.xhtml deleted file mode 100644 index d403cb20d..000000000 --- a/browser/base/content/sync/progress.xhtml +++ /dev/null @@ -1,55 +0,0 @@ -<?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/. --> - -<!DOCTYPE html [ - <!ENTITY % htmlDTD - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "DTD/xhtml1-strict.dtd"> - %htmlDTD; - <!ENTITY % syncProgressDTD - SYSTEM "chrome://browser/locale/syncProgress.dtd"> - %syncProgressDTD; - <!ENTITY % syncSetupDTD - SYSTEM "chrome://browser/locale/syncSetup.dtd"> - %syncSetupDTD; - <!ENTITY % globalDTD - SYSTEM "chrome://global/locale/global.dtd"> - %globalDTD; -]> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <title>&syncProgress.pageTitle;</title> - - <link rel="stylesheet" type="text/css" media="all" - href="chrome://browser/skin/syncProgress.css"/> - - <link rel="icon" type="image/png" id="favicon" - href="chrome://browser/skin/sync-16.png"/> - - <script type="text/javascript;version=1.8" - src="chrome://browser/content/sync/progress.js"/> - </head> - <body onload="onLoad(event)" onunload="onUnload(event)" dir="&locale.dir;"> - <title>&setup.successPage.title;</title> - <div id="floatingBox" class="main-content"> - <div id="title"> - <h1>&setup.successPage.title;</h1> - </div> - <div id="successLogo"> - <img id="brandSyncLogo" src="chrome://browser/skin/sync-128.png" alt="&syncProgress.logoAltText;" /> - </div> - <div id="loadingText"> - <p id="blurb">&syncProgress.textBlurb; </p> - </div> - <div id="progressBar"> - <progress id="uploadProgressBar" value="0"/> - </div> - <div id="bottomRow"> - <button id="closeButton" onclick="closeTab()">&syncProgress.closeButton; </button> - </div> - </div> - </body> -</html> diff --git a/browser/base/content/sync/quota.js b/browser/base/content/sync/quota.js deleted file mode 100644 index 7117a2ddf..000000000 --- a/browser/base/content/sync/quota.js +++ /dev/null @@ -1,267 +0,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/. */ - -const Ci = Components.interfaces; -const Cc = Components.classes; -const Cr = Components.results; -const Cu = Components.utils; - -Cu.import("resource://services-sync/main.js"); -Cu.import("resource://gre/modules/DownloadUtils.jsm"); - -let gSyncQuota = { - - init: function init() { - this.bundle = document.getElementById("quotaStrings"); - let caption = document.getElementById("treeCaption"); - caption.firstChild.nodeValue = this.bundle.getString("quota.treeCaption.label"); - - gUsageTreeView.init(); - this.tree = document.getElementById("usageTree"); - this.tree.view = gUsageTreeView; - - this.loadData(); - }, - - loadData: function loadData() { - this._usage_req = Weave.Service.getStorageInfo(Weave.INFO_COLLECTION_USAGE, - function (error, usage) { - delete gSyncQuota._usage_req; - // displayUsageData handles null values, so no need to check 'error'. - gUsageTreeView.displayUsageData(usage); - }); - - let usageLabel = document.getElementById("usageLabel"); - let bundle = this.bundle; - - this._quota_req = Weave.Service.getStorageInfo(Weave.INFO_QUOTA, - function (error, quota) { - delete gSyncQuota._quota_req; - - if (error) { - usageLabel.value = bundle.getString("quota.usageError.label"); - return; - } - let used = gSyncQuota.convertKB(quota[0]); - if (!quota[1]) { - // No quota on the server. - usageLabel.value = bundle.getFormattedString( - "quota.usageNoQuota.label", used); - return; - } - let percent = Math.round(100 * quota[0] / quota[1]); - let total = gSyncQuota.convertKB(quota[1]); - usageLabel.value = bundle.getFormattedString( - "quota.usagePercentage.label", [percent].concat(used).concat(total)); - }); - }, - - onCancel: function onCancel() { - if (this._usage_req) { - this._usage_req.abort(); - } - if (this._quota_req) { - this._quota_req.abort(); - } - return true; - }, - - onAccept: function onAccept() { - let engines = gUsageTreeView.getEnginesToDisable(); - for each (let engine in engines) { - Weave.Service.engineManager.get(engine).enabled = false; - } - if (engines.length) { - // The 'Weave' object will disappear once the window closes. - let Service = Weave.Service; - Weave.Utils.nextTick(function() { Service.sync(); }); - } - return this.onCancel(); - }, - - convertKB: function convertKB(value) { - return DownloadUtils.convertByteUnits(value * 1024); - } - -}; - -let gUsageTreeView = { - - _ignored: {keys: true, - meta: true, - clients: true}, - - /* - * Internal data structures underlaying the tree. - */ - _collections: [], - _byname: {}, - - init: function init() { - let retrievingLabel = gSyncQuota.bundle.getString("quota.retrieving.label"); - for each (let engine in Weave.Service.engineManager.getEnabled()) { - if (this._ignored[engine.name]) - continue; - - // Some engines use the same pref, which means they can only be turned on - // and off together. We need to combine them here as well. - let existing = this._byname[engine.prefName]; - if (existing) { - existing.engines.push(engine.name); - continue; - } - - let obj = {name: engine.prefName, - title: this._collectionTitle(engine), - engines: [engine.name], - enabled: true, - sizeLabel: retrievingLabel}; - this._collections.push(obj); - this._byname[engine.prefName] = obj; - } - }, - - _collectionTitle: function _collectionTitle(engine) { - try { - return gSyncQuota.bundle.getString( - "collection." + engine.prefName + ".label"); - } catch (ex) { - return engine.Name; - } - }, - - /* - * Process the quota information as returned by info/collection_usage. - */ - displayUsageData: function displayUsageData(data) { - for each (let coll in this._collections) { - coll.size = 0; - // If we couldn't retrieve any data, just blank out the label. - if (!data) { - coll.sizeLabel = ""; - continue; - } - - for each (let engineName in coll.engines) - coll.size += data[engineName] || 0; - let sizeLabel = ""; - sizeLabel = gSyncQuota.bundle.getFormattedString( - "quota.sizeValueUnit.label", gSyncQuota.convertKB(coll.size)); - coll.sizeLabel = sizeLabel; - } - let sizeColumn = this.treeBox.columns.getNamedColumn("size"); - this.treeBox.invalidateColumn(sizeColumn); - }, - - /* - * Handle click events on the tree. - */ - onTreeClick: function onTreeClick(event) { - if (event.button == 2) - return; - - let cell = this.treeBox.getCellAt(event.clientX, event.clientY); - if (cell.col && cell.col.id == "enabled") - this.toggle(cell.row); - }, - - /* - * Toggle enabled state of an engine. - */ - toggle: function toggle(row) { - // Update the tree - let collection = this._collections[row]; - collection.enabled = !collection.enabled; - this.treeBox.invalidateRow(row); - - // Display which ones will be removed - let freeup = 0; - let toremove = []; - for each (collection in this._collections) { - if (collection.enabled) - continue; - toremove.push(collection.name); - freeup += collection.size; - } - - let caption = document.getElementById("treeCaption"); - if (!toremove.length) { - caption.className = ""; - caption.firstChild.nodeValue = gSyncQuota.bundle.getString( - "quota.treeCaption.label"); - return; - } - - toremove = [this._byname[coll].title for each (coll in toremove)]; - toremove = toremove.join(gSyncQuota.bundle.getString("quota.list.separator")); - caption.firstChild.nodeValue = gSyncQuota.bundle.getFormattedString( - "quota.removal.label", [toremove]); - if (freeup) - caption.firstChild.nodeValue += gSyncQuota.bundle.getFormattedString( - "quota.freeup.label", gSyncQuota.convertKB(freeup)); - caption.className = "captionWarning"; - }, - - /* - * Return a list of engines (or rather their pref names) that should be - * disabled. - */ - getEnginesToDisable: function getEnginesToDisable() { - return [coll.name for each (coll in this._collections) if (!coll.enabled)]; - }, - - // nsITreeView - - get rowCount() { - return this._collections.length; - }, - - getRowProperties: function(index) { return ""; }, - getCellProperties: function(row, col) { return ""; }, - getColumnProperties: function(col) { return ""; }, - isContainer: function(index) { return false; }, - isContainerOpen: function(index) { return false; }, - isContainerEmpty: function(index) { return false; }, - isSeparator: function(index) { return false; }, - isSorted: function() { return false; }, - canDrop: function(index, orientation, dataTransfer) { return false; }, - drop: function(row, orientation, dataTransfer) {}, - getParentIndex: function(rowIndex) {}, - hasNextSibling: function(rowIndex, afterIndex) { return false; }, - getLevel: function(index) { return 0; }, - getImageSrc: function(row, col) {}, - - getCellValue: function(row, col) { - return this._collections[row].enabled; - }, - - getCellText: function getCellText(row, col) { - let collection = this._collections[row]; - switch (col.id) { - case "collection": - return collection.title; - case "size": - return collection.sizeLabel; - default: - return ""; - } - }, - - setTree: function setTree(tree) { - this.treeBox = tree; - }, - - toggleOpenState: function(index) {}, - cycleHeader: function(col) {}, - selectionChanged: function() {}, - cycleCell: function(row, col) {}, - isEditable: function(row, col) { return false; }, - isSelectable: function (row, col) { return false; }, - setCellValue: function(row, col, value) {}, - setCellText: function(row, col, value) {}, - performAction: function(action) {}, - performActionOnRow: function(action, row) {}, - performActionOnCell: function(action, row, col) {} - -}; diff --git a/browser/base/content/sync/quota.xul b/browser/base/content/sync/quota.xul deleted file mode 100644 index 99e6ed78b..000000000 --- a/browser/base/content/sync/quota.xul +++ /dev/null @@ -1,65 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/syncQuota.css"?> - -<!DOCTYPE dialog [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> -<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd"> -<!ENTITY % syncQuotaDTD SYSTEM "chrome://browser/locale/syncQuota.dtd"> -%brandDTD; -%syncBrandDTD; -%syncQuotaDTD; -]> -<dialog id="quotaDialog" - windowtype="Sync:ViewQuota" - persist="screenX screenY width height" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:html="http://www.w3.org/1999/xhtml" - onload="gSyncQuota.init()" - buttons="accept,cancel" - title=""a.dialogTitle.label;" - ondialogcancel="return gSyncQuota.onCancel();" - ondialogaccept="return gSyncQuota.onAccept();"> - - <script type="application/javascript" - src="chrome://browser/content/sync/quota.js"/> - - <stringbundleset id="stringbundleset"> - <stringbundle id="quotaStrings" - src="chrome://browser/locale/syncQuota.properties"/> - </stringbundleset> - - <vbox flex="1"> - <label id="usageLabel" - value=""a.retrievingInfo.label;"/> - <separator/> - <tree id="usageTree" - seltype="single" - hidecolumnpicker="true" - onclick="gUsageTreeView.onTreeClick(event);" - flex="1"> - <treecols> - <treecol id="enabled" - type="checkbox" - fixed="true"/> - <splitter class="tree-splitter"/> - <treecol id="collection" - label=""a.typeColumn.label;" - flex="1"/> - <splitter class="tree-splitter"/> - <treecol id="size" - label=""a.sizeColumn.label;" - flex="1"/> - </treecols> - <treechildren flex="1"/> - </tree> - <separator/> - <description id="treeCaption"> </description> - </vbox> - -</dialog> diff --git a/browser/base/content/sync/setup.js b/browser/base/content/sync/setup.js deleted file mode 100644 index 99faa038e..000000000 --- a/browser/base/content/sync/setup.js +++ /dev/null @@ -1,1071 +0,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/. */ - -const Ci = Components.interfaces; -const Cc = Components.classes; -const Cr = Components.results; -const Cu = Components.utils; - -// page consts - -const PAIR_PAGE = 0; -const INTRO_PAGE = 1; -const NEW_ACCOUNT_START_PAGE = 2; -const EXISTING_ACCOUNT_CONNECT_PAGE = 3; -const EXISTING_ACCOUNT_LOGIN_PAGE = 4; -const OPTIONS_PAGE = 5; -const OPTIONS_CONFIRM_PAGE = 6; - -// Broader than we'd like, but after this changed from api-secure.recaptcha.net -// we had no choice. At least we only do this for the duration of setup. -// See discussion in Bugs 508112 and 653307. -const RECAPTCHA_DOMAIN = "https://www.google.com"; - -const PIN_PART_LENGTH = 4; - -Cu.import("resource://services-sync/main.js"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/PlacesUtils.jsm"); -Cu.import("resource://gre/modules/PluralForm.jsm"); - - -function setVisibility(element, visible) { - element.style.visibility = visible ? "visible" : "hidden"; -} - -var gSyncSetup = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, - Ci.nsIWebProgressListener, - Ci.nsISupportsWeakReference]), - - captchaBrowser: null, - wizard: null, - _disabledSites: [], - - status: { - password: false, - email: false, - server: false - }, - - get _remoteSites() [Weave.Service.serverURL, RECAPTCHA_DOMAIN], - - get _usingMainServers() { - if (this._settingUpNew) - return document.getElementById("server").selectedIndex == 0; - return document.getElementById("existingServer").selectedIndex == 0; - }, - - init: function () { - let obs = [ - ["weave:service:change-passphrase", "onResetPassphrase"], - ["weave:service:login:start", "onLoginStart"], - ["weave:service:login:error", "onLoginEnd"], - ["weave:service:login:finish", "onLoginEnd"]]; - - // Add the observers now and remove them on unload - let self = this; - let addRem = function(add) { - obs.forEach(function([topic, func]) { - //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling - // of `this`. Fix in a followup. (bug 583347) - if (add) - Weave.Svc.Obs.add(topic, self[func], self); - else - Weave.Svc.Obs.remove(topic, self[func], self); - }); - }; - addRem(true); - window.addEventListener("unload", function() addRem(false), false); - - window.setTimeout(function () { - // Force Service to be loaded so that engines are registered. - // See Bug 670082. - Weave.Service; - }, 0); - - this.captchaBrowser = document.getElementById("captcha"); - - this.wizardType = null; - if (window.arguments && window.arguments[0]) { - this.wizardType = window.arguments[0]; - } - switch (this.wizardType) { - case null: - this.wizard.pageIndex = INTRO_PAGE; - // Fall through! - case "pair": - this.captchaBrowser.addProgressListener(this); - Weave.Svc.Prefs.set("firstSync", "notReady"); - break; - case "reset": - this._resettingSync = true; - this.wizard.pageIndex = OPTIONS_PAGE; - break; - } - - this.wizard.getButton("extra1").label = - this._stringBundle.GetStringFromName("button.syncOptions.label"); - - // Remember these values because the options pages change them temporarily. - this._nextButtonLabel = this.wizard.getButton("next").label; - this._nextButtonAccesskey = this.wizard.getButton("next") - .getAttribute("accesskey"); - this._backButtonLabel = this.wizard.getButton("back").label; - this._backButtonAccesskey = this.wizard.getButton("back") - .getAttribute("accesskey"); - }, - - startNewAccountSetup: function () { - if (!Weave.Utils.ensureMPUnlocked()) - return false; - this._settingUpNew = true; - this.wizard.pageIndex = NEW_ACCOUNT_START_PAGE; - }, - - useExistingAccount: function () { - if (!Weave.Utils.ensureMPUnlocked()) - return false; - this._settingUpNew = false; - if (this.wizardType == "pair") { - // We're already pairing, so there's no point in pairing again. - // Go straight to the manual login page. - this.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE; - } else { - this.wizard.pageIndex = EXISTING_ACCOUNT_CONNECT_PAGE; - } - }, - - resetPassphrase: function resetPassphrase() { - // Apply the existing form fields so that - // Weave.Service.changePassphrase() has the necessary credentials. - Weave.Service.identity.account = document.getElementById("existingAccountName").value; - Weave.Service.identity.basicPassword = document.getElementById("existingPassword").value; - - // Generate a new passphrase so that Weave.Service.login() will - // actually do something. - let passphrase = Weave.Utils.generatePassphrase(); - Weave.Service.identity.syncKey = passphrase; - - // Only open the dialog if username + password are actually correct. - Weave.Service.login(); - if ([Weave.LOGIN_FAILED_INVALID_PASSPHRASE, - Weave.LOGIN_FAILED_NO_PASSPHRASE, - Weave.LOGIN_SUCCEEDED].indexOf(Weave.Status.login) == -1) { - return; - } - - // Hide any errors about the passphrase, we know it's not right. - let feedback = document.getElementById("existingPassphraseFeedbackRow"); - feedback.hidden = true; - let el = document.getElementById("existingPassphrase"); - el.value = Weave.Utils.hyphenatePassphrase(passphrase); - - // changePassphrase() will sync, make sure we set the "firstSync" pref - // according to the user's pref. - Weave.Svc.Prefs.reset("firstSync"); - this.setupInitialSync(); - gSyncUtils.resetPassphrase(true); - }, - - onResetPassphrase: function () { - document.getElementById("existingPassphrase").value = - Weave.Utils.hyphenatePassphrase(Weave.Service.identity.syncKey); - this.checkFields(); - this.wizard.advance(); - }, - - onLoginStart: function () { - this.toggleLoginFeedback(false); - }, - - onLoginEnd: function () { - this.toggleLoginFeedback(true); - }, - - sendCredentialsAfterSync: function () { - let send = function() { - Services.obs.removeObserver("weave:service:sync:finish", send); - Services.obs.removeObserver("weave:service:sync:error", send); - let credentials = {account: Weave.Service.identity.account, - password: Weave.Service.identity.basicPassword, - synckey: Weave.Service.identity.syncKey, - serverURL: Weave.Service.serverURL}; - this._jpakeclient.sendAndComplete(credentials); - }.bind(this); - Services.obs.addObserver("weave:service:sync:finish", send, false); - Services.obs.addObserver("weave:service:sync:error", send, false); - }, - - toggleLoginFeedback: function (stop) { - document.getElementById("login-throbber").hidden = stop; - let password = document.getElementById("existingPasswordFeedbackRow"); - let server = document.getElementById("existingServerFeedbackRow"); - let passphrase = document.getElementById("existingPassphraseFeedbackRow"); - - if (!stop || (Weave.Status.login == Weave.LOGIN_SUCCEEDED)) { - password.hidden = server.hidden = passphrase.hidden = true; - return; - } - - let feedback; - switch (Weave.Status.login) { - case Weave.LOGIN_FAILED_NETWORK_ERROR: - case Weave.LOGIN_FAILED_SERVER_ERROR: - feedback = server; - break; - case Weave.LOGIN_FAILED_LOGIN_REJECTED: - case Weave.LOGIN_FAILED_NO_USERNAME: - case Weave.LOGIN_FAILED_NO_PASSWORD: - feedback = password; - break; - case Weave.LOGIN_FAILED_INVALID_PASSPHRASE: - feedback = passphrase; - break; - } - this._setFeedbackMessage(feedback, false, Weave.Status.login); - }, - - setupInitialSync: function () { - let action = document.getElementById("mergeChoiceRadio").selectedItem.id; - switch (action) { - case "resetClient": - // if we're not resetting sync, we don't need to explicitly - // call resetClient - if (!this._resettingSync) - return; - // otherwise, fall through - case "wipeClient": - case "wipeRemote": - Weave.Svc.Prefs.set("firstSync", action); - break; - } - }, - - // fun with validation! - checkFields: function () { - this.wizard.canAdvance = this.readyToAdvance(); - }, - - readyToAdvance: function () { - switch (this.wizard.pageIndex) { - case INTRO_PAGE: - return false; - case NEW_ACCOUNT_START_PAGE: - for (let i in this.status) { - if (!this.status[i]) - return false; - } - if (this._usingMainServers) - return document.getElementById("tos").checked; - - return true; - case EXISTING_ACCOUNT_LOGIN_PAGE: - let hasUser = document.getElementById("existingAccountName").value != ""; - let hasPass = document.getElementById("existingPassword").value != ""; - let hasKey = document.getElementById("existingPassphrase").value != ""; - - if (hasUser && hasPass && hasKey) { - if (this._usingMainServers) - return true; - - if (this._validateServer(document.getElementById("existingServer"))) { - return true; - } - } - return false; - } - // Default, e.g. wizard's special page -1 etc. - return true; - }, - - onPINInput: function onPINInput(textbox) { - if (textbox && textbox.value.length == PIN_PART_LENGTH) { - this.nextFocusEl[textbox.id].focus(); - } - this.wizard.canAdvance = (this.pin1.value.length == PIN_PART_LENGTH && - this.pin2.value.length == PIN_PART_LENGTH && - this.pin3.value.length == PIN_PART_LENGTH); - }, - - onEmailInput: function () { - // Check account validity when the user stops typing for 1 second. - if (this._checkAccountTimer) - window.clearTimeout(this._checkAccountTimer); - this._checkAccountTimer = window.setTimeout(function () { - gSyncSetup.checkAccount(); - }, 1000); - }, - - checkAccount: function() { - delete this._checkAccountTimer; - let value = Weave.Utils.normalizeAccount( - document.getElementById("weaveEmail").value); - if (!value) { - this.status.email = false; - this.checkFields(); - return; - } - - let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - let feedback = document.getElementById("emailFeedbackRow"); - let valid = re.test(value); - - let str = ""; - if (!valid) { - str = "invalidEmail.label"; - } else { - let availCheck = Weave.Service.checkAccount(value); - valid = availCheck == "available"; - if (!valid) { - if (availCheck == "notAvailable") - str = "usernameNotAvailable.label"; - else - str = availCheck; - } - } - - this._setFeedbackMessage(feedback, valid, str); - this.status.email = valid; - if (valid) - Weave.Service.identity.account = value; - this.checkFields(); - }, - - onPasswordChange: function () { - let password = document.getElementById("weavePassword"); - let pwconfirm = document.getElementById("weavePasswordConfirm"); - let [valid, errorString] = gSyncUtils.validatePassword(password, pwconfirm); - - let feedback = document.getElementById("passwordFeedbackRow"); - this._setFeedback(feedback, valid, errorString); - - this.status.password = valid; - this.checkFields(); - }, - - onPageShow: function() { - switch (this.wizard.pageIndex) { - case PAIR_PAGE: - this.wizard.getButton("back").hidden = true; - this.wizard.getButton("extra1").hidden = true; - this.onPINInput(); - this.pin1.focus(); - break; - case INTRO_PAGE: - // We may not need the captcha in the Existing Account branch of the - // wizard. However, we want to preload it to avoid any flickering while - // the Create Account page is shown. - this.loadCaptcha(); - this.wizard.getButton("next").hidden = true; - this.wizard.getButton("back").hidden = true; - this.wizard.getButton("extra1").hidden = true; - this.checkFields(); - break; - case NEW_ACCOUNT_START_PAGE: - this.wizard.getButton("extra1").hidden = false; - this.wizard.getButton("next").hidden = false; - this.wizard.getButton("back").hidden = false; - this.onServerCommand(); - this.wizard.canRewind = true; - this.checkFields(); - break; - case EXISTING_ACCOUNT_CONNECT_PAGE: - Weave.Svc.Prefs.set("firstSync", "existingAccount"); - this.wizard.getButton("next").hidden = false; - this.wizard.getButton("back").hidden = false; - this.wizard.getButton("extra1").hidden = false; - this.wizard.canAdvance = false; - this.wizard.canRewind = true; - this.startEasySetup(); - break; - case EXISTING_ACCOUNT_LOGIN_PAGE: - this.wizard.getButton("next").hidden = false; - this.wizard.getButton("back").hidden = false; - this.wizard.getButton("extra1").hidden = false; - this.wizard.canRewind = true; - this.checkFields(); - break; - case OPTIONS_PAGE: - this.wizard.canRewind = false; - this.wizard.canAdvance = true; - if (!this._resettingSync) { - this.wizard.getButton("next").label = - this._stringBundle.GetStringFromName("button.syncOptionsDone.label"); - this.wizard.getButton("next").removeAttribute("accesskey"); - } - this.wizard.getButton("next").hidden = false; - this.wizard.getButton("back").hidden = true; - this.wizard.getButton("cancel").hidden = !this._resettingSync; - this.wizard.getButton("extra1").hidden = true; - document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName; - document.getElementById("syncOptions").collapsed = this._resettingSync; - document.getElementById("mergeOptions").collapsed = this._settingUpNew; - break; - case OPTIONS_CONFIRM_PAGE: - this.wizard.canRewind = true; - this.wizard.canAdvance = true; - this.wizard.getButton("back").label = - this._stringBundle.GetStringFromName("button.syncOptionsCancel.label"); - this.wizard.getButton("back").removeAttribute("accesskey"); - this.wizard.getButton("back").hidden = this._resettingSync; - this.wizard.getButton("next").hidden = false; - this.wizard.getButton("finish").hidden = true; - break; - } - }, - - onWizardAdvance: function () { - // Check pageIndex so we don't prompt before the Sync setup wizard appears. - // This is a fallback in case the Master Password gets locked mid-wizard. - if ((this.wizard.pageIndex >= 0) && - !Weave.Utils.ensureMPUnlocked()) { - return false; - } - - switch (this.wizard.pageIndex) { - case PAIR_PAGE: - this.startPairing(); - return false; - case NEW_ACCOUNT_START_PAGE: - // If the user selects Next (e.g. by hitting enter) when we haven't - // executed the delayed checks yet, execute them immediately. - if (this._checkAccountTimer) { - this.checkAccount(); - } - if (this._checkServerTimer) { - this.checkServer(); - } - if (!this.wizard.canAdvance) { - return false; - } - - let doc = this.captchaBrowser.contentDocument; - let getField = function getField(field) { - let node = doc.getElementById("recaptcha_" + field + "_field"); - return node && node.value; - }; - - // Display throbber - let feedback = document.getElementById("captchaFeedback"); - let image = feedback.firstChild; - let label = image.nextSibling; - image.setAttribute("status", "active"); - label.value = this._stringBundle.GetStringFromName("verifying.label"); - setVisibility(feedback, true); - - let password = document.getElementById("weavePassword").value; - let email = Weave.Utils.normalizeAccount( - document.getElementById("weaveEmail").value); - let challenge = getField("challenge"); - let response = getField("response"); - - let error = Weave.Service.createAccount(email, password, - challenge, response); - - if (error == null) { - Weave.Service.identity.account = email; - Weave.Service.identity.basicPassword = password; - Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase(); - this._handleNoScript(false); - Weave.Svc.Prefs.set("firstSync", "newAccount"); - this.wizardFinish(); - return false; - } - - image.setAttribute("status", "error"); - label.value = Weave.Utils.getErrorString(error); - return false; - case EXISTING_ACCOUNT_LOGIN_PAGE: - Weave.Service.identity.account = Weave.Utils.normalizeAccount( - document.getElementById("existingAccountName").value); - Weave.Service.identity.basicPassword = - document.getElementById("existingPassword").value; - let pp = document.getElementById("existingPassphrase").value; - Weave.Service.identity.syncKey = Weave.Utils.normalizePassphrase(pp); - if (Weave.Service.login()) { - this.wizardFinish(); - } - return false; - case OPTIONS_PAGE: - let desc = document.getElementById("mergeChoiceRadio").selectedIndex; - // No confirmation needed on new account setup or merge option - // with existing account. - if (this._settingUpNew || (!this._resettingSync && desc == 0)) - return this.returnFromOptions(); - return this._handleChoice(); - case OPTIONS_CONFIRM_PAGE: - if (this._resettingSync) { - this.wizardFinish(); - return false; - } - return this.returnFromOptions(); - } - return true; - }, - - onWizardBack: function () { - switch (this.wizard.pageIndex) { - case NEW_ACCOUNT_START_PAGE: - case EXISTING_ACCOUNT_LOGIN_PAGE: - this.wizard.pageIndex = INTRO_PAGE; - return false; - case EXISTING_ACCOUNT_CONNECT_PAGE: - this.abortEasySetup(); - this.wizard.pageIndex = INTRO_PAGE; - return false; - case EXISTING_ACCOUNT_LOGIN_PAGE: - // If we were already pairing on entry, we went straight to the manual - // login page. If subsequently we go back, return to the page that lets - // us choose whether we already have an account. - if (this.wizardType == "pair") { - this.wizard.pageIndex = INTRO_PAGE; - return false; - } - return true; - case OPTIONS_CONFIRM_PAGE: - // Backing up from the confirmation page = resetting first sync to merge. - document.getElementById("mergeChoiceRadio").selectedIndex = 0; - return this.returnFromOptions(); - } - return true; - }, - - wizardFinish: function () { - this.setupInitialSync(); - - if (this.wizardType == "pair") { - this.completePairing(); - } - - if (!this._resettingSync) { - function isChecked(element) { - return document.getElementById(element).hasAttribute("checked"); - } - - let prefs = ["engine.bookmarks", "engine.passwords", "engine.history", - "engine.tabs", "engine.prefs", "engine.addons"]; - for (let i = 0;i < prefs.length;i++) { - Weave.Svc.Prefs.set(prefs[i], isChecked(prefs[i])); - } - - // XXX: Addons syncing is currently not operational; - // Make doubly-sure to always disable addons syncing pref - Weave.Svc.Prefs.set("engine.addons", false); - - this._handleNoScript(false); - if (Weave.Svc.Prefs.get("firstSync", "") == "notReady") - Weave.Svc.Prefs.reset("firstSync"); - - Weave.Service.persistLogin(); - Weave.Svc.Obs.notify("weave:service:setup-complete"); - - gSyncUtils.openFirstSyncProgressPage(); - } - Weave.Utils.nextTick(Weave.Service.sync, Weave.Service); - window.close(); - }, - - onWizardCancel: function () { - if (this._resettingSync) - return; - - this.abortEasySetup(); - this._handleNoScript(false); - Weave.Service.startOver(); - }, - - onSyncOptions: function () { - this._beforeOptionsPage = this.wizard.pageIndex; - this.wizard.pageIndex = OPTIONS_PAGE; - }, - - returnFromOptions: function() { - this.wizard.getButton("next").label = this._nextButtonLabel; - this.wizard.getButton("next").setAttribute("accesskey", - this._nextButtonAccesskey); - this.wizard.getButton("back").label = this._backButtonLabel; - this.wizard.getButton("back").setAttribute("accesskey", - this._backButtonAccesskey); - this.wizard.getButton("cancel").hidden = false; - this.wizard.getButton("extra1").hidden = false; - this.wizard.pageIndex = this._beforeOptionsPage; - return false; - }, - - startPairing: function startPairing() { - this.pairDeviceErrorRow.hidden = true; - // When onAbort is called, Weave may already be gone. - const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT; - - let self = this; - let jpakeclient = this._jpakeclient = new Weave.JPAKEClient({ - onPaired: function onPaired() { - self.wizard.pageIndex = INTRO_PAGE; - }, - onComplete: function onComplete() { - // This method will never be called since SendCredentialsController - // will take over after the wizard completes. - }, - onAbort: function onAbort(error) { - delete self._jpakeclient; - - // Aborted by user, ignore. The window is almost certainly going to close - // or is already closed. - if (error == JPAKE_ERROR_USERABORT) { - return; - } - - self.pairDeviceErrorRow.hidden = false; - self.pairDeviceThrobber.hidden = true; - self.pin1.value = self.pin2.value = self.pin3.value = ""; - self.pin1.disabled = self.pin2.disabled = self.pin3.disabled = false; - if (self.wizard.pageIndex == PAIR_PAGE) { - self.pin1.focus(); - } - } - }); - this.pairDeviceThrobber.hidden = false; - this.pin1.disabled = this.pin2.disabled = this.pin3.disabled = true; - this.wizard.canAdvance = false; - - let pin = this.pin1.value + this.pin2.value + this.pin3.value; - let expectDelay = true; - jpakeclient.pairWithPIN(pin, expectDelay); - }, - - completePairing: function completePairing() { - if (!this._jpakeclient) { - // The channel was aborted while we were setting up the account - // locally. XXX TODO should we do anything here, e.g. tell - // the user on the last wizard page that it's ok, they just - // have to pair again? - return; - } - let controller = new Weave.SendCredentialsController(this._jpakeclient, - Weave.Service); - this._jpakeclient.controller = controller; - }, - - startEasySetup: function () { - // Don't do anything if we have a client already (e.g. we went to - // Sync Options and just came back). - if (this._jpakeclient) - return; - - // When onAbort is called, Weave may already be gone - const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT; - - let self = this; - this._jpakeclient = new Weave.JPAKEClient({ - displayPIN: function displayPIN(pin) { - document.getElementById("easySetupPIN1").value = pin.slice(0, 4); - document.getElementById("easySetupPIN2").value = pin.slice(4, 8); - document.getElementById("easySetupPIN3").value = pin.slice(8); - }, - - onPairingStart: function onPairingStart() {}, - - onComplete: function onComplete(credentials) { - Weave.Service.identity.account = credentials.account; - Weave.Service.identity.basicPassword = credentials.password; - Weave.Service.identity.syncKey = credentials.synckey; - Weave.Service.serverURL = credentials.serverURL; - gSyncSetup.wizardFinish(); - }, - - onAbort: function onAbort(error) { - delete self._jpakeclient; - - // Ignore if wizard is aborted. - if (error == JPAKE_ERROR_USERABORT) - return; - - // Automatically go to manual setup if we couldn't acquire a channel. - if (error == Weave.JPAKE_ERROR_CHANNEL) { - self.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE; - return; - } - - // Restart on all other errors. - self.startEasySetup(); - } - }); - this._jpakeclient.receiveNoPIN(); - }, - - abortEasySetup: function () { - document.getElementById("easySetupPIN1").value = ""; - document.getElementById("easySetupPIN2").value = ""; - document.getElementById("easySetupPIN3").value = ""; - if (!this._jpakeclient) - return; - - this._jpakeclient.abort(); - delete this._jpakeclient; - }, - - manualSetup: function () { - this.abortEasySetup(); - this.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE; - }, - - // _handleNoScript is needed because it blocks the captcha. So we temporarily - // allow the necessary sites so that we can verify the user is in fact a human. - // This was done with the help of Giorgio (NoScript author). See bug 508112. - _handleNoScript: function (addExceptions) { - // if NoScript isn't installed, or is disabled, bail out. - let ns = Cc["@maone.net/noscript-service;1"]; - if (ns == null) - return; - - ns = ns.getService().wrappedJSObject; - if (addExceptions) { - this._remoteSites.forEach(function(site) { - site = ns.getSite(site); - if (!ns.isJSEnabled(site)) { - this._disabledSites.push(site); // save status - ns.setJSEnabled(site, true); // allow site - } - }, this); - } - else { - this._disabledSites.forEach(function(site) { - ns.setJSEnabled(site, false); - }); - this._disabledSites = []; - } - }, - - onExistingServerCommand: function () { - let control = document.getElementById("existingServer"); - if (control.selectedIndex == 0) { - control.removeAttribute("editable"); - Weave.Svc.Prefs.reset("serverURL"); - } else { - control.setAttribute("editable", "true"); - // Force a style flush to ensure that the binding is attached. - control.clientTop; - control.value = ""; - control.inputField.focus(); - } - document.getElementById("existingServerFeedbackRow").hidden = true; - this.checkFields(); - }, - - onExistingServerInput: function () { - // Check custom server validity when the user stops typing for 1 second. - if (this._existingServerTimer) - window.clearTimeout(this._existingServerTimer); - this._existingServerTimer = window.setTimeout(function () { - gSyncSetup.checkFields(); - }, 1000); - }, - - onServerCommand: function () { - setVisibility(document.getElementById("TOSRow"), this._usingMainServers); - let control = document.getElementById("server"); - if (!this._usingMainServers) { - control.setAttribute("editable", "true"); - // Force a style flush to ensure that the binding is attached. - control.clientTop; - control.value = ""; - control.inputField.focus(); - // checkServer() will call checkAccount() and checkFields(). - this.checkServer(); - return; - } - control.removeAttribute("editable"); - Weave.Svc.Prefs.reset("serverURL"); - if (this._settingUpNew) { - this.loadCaptcha(); - } - this.checkAccount(); - this.status.server = true; - document.getElementById("serverFeedbackRow").hidden = true; - this.checkFields(); - }, - - onServerInput: function () { - // Check custom server validity when the user stops typing for 1 second. - if (this._checkServerTimer) - window.clearTimeout(this._checkServerTimer); - this._checkServerTimer = window.setTimeout(function () { - gSyncSetup.checkServer(); - }, 1000); - }, - - checkServer: function () { - delete this._checkServerTimer; - let el = document.getElementById("server"); - let valid = false; - let feedback = document.getElementById("serverFeedbackRow"); - let str = ""; - if (el.value) { - valid = this._validateServer(el); - let str = valid ? "" : "serverInvalid.label"; - this._setFeedbackMessage(feedback, valid, str); - } - else - this._setFeedbackMessage(feedback, true); - - // Recheck account against the new server. - if (valid) - this.checkAccount(); - - this.status.server = valid; - this.checkFields(); - }, - - _validateServer: function (element) { - let valid = false; - let val = element.value; - if (!val) - return false; - - let uri = Weave.Utils.makeURI(val); - - if (!uri) - uri = Weave.Utils.makeURI("https://" + val); - - if (uri && this._settingUpNew) { - function isValid(uri) { - Weave.Service.serverURL = uri.spec; - let check = Weave.Service.checkAccount("a"); - return (check == "available" || check == "notAvailable"); - } - - if (uri.schemeIs("http")) { - uri.scheme = "https"; - if (isValid(uri)) - valid = true; - else - // setting the scheme back to http - uri.scheme = "http"; - } - if (!valid) - valid = isValid(uri); - - if (valid) { - this.loadCaptcha(); - } - } - else if (uri) { - valid = true; - Weave.Service.serverURL = uri.spec; - } - - if (valid) - element.value = Weave.Service.serverURL; - else - Weave.Svc.Prefs.reset("serverURL"); - - return valid; - }, - - _handleChoice: function () { - let desc = document.getElementById("mergeChoiceRadio").selectedIndex; - document.getElementById("chosenActionDeck").selectedIndex = desc; - switch (desc) { - case 1: - if (this._case1Setup) - break; - - let places_db = PlacesUtils.history - .QueryInterface(Ci.nsPIPlacesDatabase) - .DBConnection; - if (Weave.Service.engineManager.get("history").enabled) { - let daysOfHistory = 0; - let stm = places_db.createStatement( - "SELECT ROUND(( " + - "strftime('%s','now','localtime','utc') - " + - "( " + - "SELECT visit_date FROM moz_historyvisits " + - "ORDER BY visit_date ASC LIMIT 1 " + - ")/1000000 " + - ")/86400) AS daysOfHistory "); - - if (stm.step()) - daysOfHistory = stm.getInt32(0); - // Support %S for historical reasons (see bug 600141) - document.getElementById("historyCount").value = - PluralForm.get(daysOfHistory, - this._stringBundle.GetStringFromName("historyDaysCount.label")) - .replace("%S", daysOfHistory) - .replace("#1", daysOfHistory); - } else { - document.getElementById("historyCount").hidden = true; - } - - if (Weave.Service.engineManager.get("bookmarks").enabled) { - let bookmarks = 0; - let stm = places_db.createStatement( - "SELECT count(*) AS bookmarks " + - "FROM moz_bookmarks b " + - "LEFT JOIN moz_bookmarks t ON " + - "b.parent = t.id WHERE b.type = 1 AND t.parent <> :tag"); - stm.params.tag = PlacesUtils.tagsFolderId; - if (stm.executeStep()) - bookmarks = stm.row.bookmarks; - // Support %S for historical reasons (see bug 600141) - document.getElementById("bookmarkCount").value = - PluralForm.get(bookmarks, - this._stringBundle.GetStringFromName("bookmarksCount.label")) - .replace("%S", bookmarks) - .replace("#1", bookmarks); - } else { - document.getElementById("bookmarkCount").hidden = true; - } - - if (Weave.Service.engineManager.get("passwords").enabled) { - let logins = Services.logins.getAllLogins({}); - // Support %S for historical reasons (see bug 600141) - document.getElementById("passwordCount").value = - PluralForm.get(logins.length, - this._stringBundle.GetStringFromName("passwordsCount.label")) - .replace("%S", logins.length) - .replace("#1", logins.length); - } else { - document.getElementById("passwordCount").hidden = true; - } - - if (!Weave.Service.engineManager.get("prefs").enabled) { - document.getElementById("prefsWipe").hidden = true; - } - - let addonsEngine = Weave.Service.engineManager.get("addons"); - if (addonsEngine.enabled) { - let ids = addonsEngine._store.getAllIDs(); - let blessedcount = 0; - for each (let i in ids) { - if (i) { - blessedcount++; - } - } - // bug 600141 does not apply, as this does not have to support existing strings - document.getElementById("addonCount").value = - PluralForm.get(blessedcount, - this._stringBundle.GetStringFromName("addonsCount.label")) - .replace("#1", blessedcount); - } else { - document.getElementById("addonCount").hidden = true; - } - - this._case1Setup = true; - break; - case 2: - if (this._case2Setup) - break; - let count = 0; - function appendNode(label) { - let box = document.getElementById("clientList"); - let node = document.createElement("label"); - node.setAttribute("value", label); - node.setAttribute("class", "data indent"); - box.appendChild(node); - } - - for each (let name in Weave.Service.clientsEngine.stats.names) { - // Don't list the current client - if (name == Weave.Service.clientsEngine.localName) - continue; - - // Only show the first several client names - if (++count <= 5) - appendNode(name); - } - if (count > 5) { - // Support %S for historical reasons (see bug 600141) - let label = - PluralForm.get(count - 5, - this._stringBundle.GetStringFromName("additionalClientCount.label")) - .replace("%S", count - 5) - .replace("#1", count - 5); - appendNode(label); - } - this._case2Setup = true; - break; - } - - return true; - }, - - // sets class and string on a feedback element - // if no property string is passed in, we clear label/style - _setFeedback: function (element, success, string) { - element.hidden = success || !string; - let classname = success ? "success" : "error"; - let image = element.getElementsByAttribute("class", "statusIcon")[0]; - image.setAttribute("status", classname); - let label = element.getElementsByAttribute("class", "status")[0]; - label.value = string; - }, - - // shim - _setFeedbackMessage: function (element, success, string) { - let str = ""; - if (string) { - try { - str = this._stringBundle.GetStringFromName(string); - } catch(e) {} - - if (!str) - str = Weave.Utils.getErrorString(string); - } - this._setFeedback(element, success, str); - }, - - loadCaptcha: function loadCaptcha() { - let captchaURI = Weave.Service.miscAPI + "captcha_html"; - // First check for NoScript and whitelist the right sites. - this._handleNoScript(true); - if (this.captchaBrowser.currentURI.spec != captchaURI) { - this.captchaBrowser.loadURI(captchaURI); - } - }, - - onStateChange: function(webProgress, request, stateFlags, status) { - // We're only looking for the end of the frame load - if ((stateFlags & Ci.nsIWebProgressListener.STATE_STOP) == 0) - return; - if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) == 0) - return; - if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) == 0) - return; - - // If we didn't find a captcha, assume it's not needed and don't show it. - let responseStatus = request.QueryInterface(Ci.nsIHttpChannel).responseStatus; - setVisibility(this.captchaBrowser, responseStatus != 404); - //XXX TODO we should really log any responseStatus other than 200 - }, - onProgressChange: function() {}, - onStatusChange: function() {}, - onSecurityChange: function() {}, - onLocationChange: function () {} -}; - -// Define lazy getters for various XUL elements. -// -// onWizardAdvance() and onPageShow() are run before init(), so we'll even -// define things that will almost certainly be used (like 'wizard') as a lazy -// getter here. -["wizard", - "pin1", - "pin2", - "pin3", - "pairDeviceErrorRow", - "pairDeviceThrobber"].forEach(function (id) { - XPCOMUtils.defineLazyGetter(gSyncSetup, id, function() { - return document.getElementById(id); - }); -}); -XPCOMUtils.defineLazyGetter(gSyncSetup, "nextFocusEl", function () { - return {pin1: this.pin2, - pin2: this.pin3, - pin3: this.wizard.getButton("next")}; -}); -XPCOMUtils.defineLazyGetter(gSyncSetup, "_stringBundle", function() { - return Services.strings.createBundle("chrome://browser/locale/syncSetup.properties"); -}); diff --git a/browser/base/content/sync/setup.xul b/browser/base/content/sync/setup.xul deleted file mode 100644 index cf2cc77e4..000000000 --- a/browser/base/content/sync/setup.xul +++ /dev/null @@ -1,491 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/syncSetup.css" type="text/css"?> -<?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?> - -<!DOCTYPE window [ -<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> -<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd"> -<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd"> -%brandDTD; -%syncBrandDTD; -%syncSetupDTD; -]> -<wizard id="wizard" - title="&accountSetupTitle.label;" - windowtype="Weave:AccountSetup" - persist="screenX screenY" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:html="http://www.w3.org/1999/xhtml" - onwizardnext="return gSyncSetup.onWizardAdvance()" - onwizardback="return gSyncSetup.onWizardBack()" - onwizardcancel="gSyncSetup.onWizardCancel()" - onload="gSyncSetup.init()"> - - <script type="application/javascript" - src="chrome://browser/content/sync/setup.js"/> - <script type="application/javascript" - src="chrome://browser/content/sync/utils.js"/> - <script type="application/javascript" - src="chrome://browser/content/utilityOverlay.js"/> - <script type="application/javascript" - src="chrome://global/content/printUtils.js"/> - - <wizardpage id="addDevicePage" - label="&pairDevice.title.label;" - onpageshow="gSyncSetup.onPageShow()"> - <description> - &pairDevice.dialog.description.label; - <label class="text-link" - value="&addDevice.showMeHow.label;" - href="http://www.palemoon.org/sync/help/easy-setup.shtml"/> - </description> - <separator class="groove-thin"/> - <description> - &addDevice.dialog.enterCode.label; - </description> - <separator class="groove-thin"/> - <vbox align="center"> - <textbox id="pin1" - class="pin" - oninput="gSyncSetup.onPINInput(this);" - onfocus="this.select();" - /> - <textbox id="pin2" - class="pin" - oninput="gSyncSetup.onPINInput(this);" - onfocus="this.select();" - /> - <textbox id="pin3" - class="pin" - oninput="gSyncSetup.onPINInput(this);" - onfocus="this.select();" - /> - </vbox> - <separator class="groove-thin"/> - <vbox id="pairDeviceThrobber" align="center" hidden="true"> - <image/> - </vbox> - <hbox id="pairDeviceErrorRow" pack="center" hidden="true"> - <image class="statusIcon" status="error"/> - <label class="status" - value="&addDevice.dialog.tryAgain.label;"/> - </hbox> - </wizardpage> - - <wizardpage id="pickSetupType" - label="&syncBrand.fullName.label;" - onpageshow="gSyncSetup.onPageShow()"> - <vbox align="center" flex="1"> - <description style="padding: 0 7em;"> - &setup.pickSetupType.description2; - </description> - <spacer flex="3"/> - <button id="newAccount" - class="accountChoiceButton" - label="&button.createNewAccount.label;" - oncommand="gSyncSetup.startNewAccountSetup()" - align="center"/> - <spacer flex="1"/> - </vbox> - <separator class="groove"/> - <vbox align="center" flex="1"> - <spacer flex="1"/> - <button id="existingAccount" - class="accountChoiceButton" - label="&button.haveAccount.label;" - oncommand="gSyncSetup.useExistingAccount()"/> - <spacer flex="3"/> - </vbox> - </wizardpage> - - <wizardpage label="&setup.newAccountDetailsPage.title.label;" - id="newAccountStart" - onextra1="gSyncSetup.onSyncOptions()" - onpageshow="gSyncSetup.onPageShow();"> - <grid> - <columns> - <column/> - <column class="inputColumn" flex="1"/> - </columns> - <rows> - <row id="emailRow" align="center"> - <label value="&setup.emailAddress.label;" - accesskey="&setup.emailAddress.accesskey;" - control="weaveEmail"/> - <textbox id="weaveEmail" - oninput="gSyncSetup.onEmailInput()"/> - </row> - <row id="emailFeedbackRow" align="center" hidden="true"> - <spacer/> - <hbox> - <image class="statusIcon"/> - <label class="status" value=" "/> - </hbox> - </row> - <row id="passwordRow" align="center"> - <label value="&setup.choosePassword.label;" - accesskey="&setup.choosePassword.accesskey;" - control="weavePassword"/> - <textbox id="weavePassword" - type="password" - onchange="gSyncSetup.onPasswordChange()"/> - </row> - <row id="confirmRow" align="center"> - <label value="&setup.confirmPassword.label;" - accesskey="&setup.confirmPassword.accesskey;" - control="weavePasswordConfirm"/> - <textbox id="weavePasswordConfirm" - type="password" - onchange="gSyncSetup.onPasswordChange()"/> - </row> - <row id="passwordFeedbackRow" align="center" hidden="true"> - <spacer/> - <hbox> - <image class="statusIcon"/> - <label class="status" value=" "/> - </hbox> - </row> - <row align="center"> - <label control="server" - value="&server.label;"/> - <menulist id="server" - oncommand="gSyncSetup.onServerCommand()" - oninput="gSyncSetup.onServerInput()"> - <menupopup> - <menuitem label="&serverType.default.label;" - value="main"/> - <menuitem label="&serverType.custom2.label;" - value="custom"/> - </menupopup> - </menulist> - </row> - <row id="serverFeedbackRow" align="center" hidden="true"> - <spacer/> - <hbox> - <image class="statusIcon"/> - <label class="status" value=" "/> - </hbox> - </row> - <row id="TOSRow" align="center"> - <spacer/> - <hbox align="center"> - <checkbox id="tos" - accesskey="&setup.tosAgree1.accesskey;" - oncommand="this.focus(); gSyncSetup.checkFields();"/> - <description id="tosDesc" - flex="1" - onclick="document.getElementById('tos').focus(); - document.getElementById('tos').click()"> - &setup.tosAgree1.label; - <label class="text-link inline-link" - onclick="event.stopPropagation();gSyncUtils.openToS();"> - &setup.tosLink.label; - </label> - &setup.tosAgree2.label; - <label class="text-link inline-link" - onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();"> - &setup.ppLink.label; - </label> - &setup.tosAgree3.label; - </description> - </hbox> - </row> - </rows> - </grid> - <spacer flex="1"/> - <vbox flex="1" align="center"> - <browser height="150" - width="500" - id="captcha" - type="content" - disablehistory="true"/> - <spacer flex="1"/> - <hbox id="captchaFeedback"> - <image class="statusIcon"/> - <label class="status" value=" "/> - </hbox> - </vbox> - </wizardpage> - - <wizardpage id="addDevice" - label="&pairDevice.title.label;" - onextra1="gSyncSetup.onSyncOptions()" - onpageshow="gSyncSetup.onPageShow()"> - <description> - &pairDevice.setup.description.label; - <label class="text-link" - value="&addDevice.showMeHow.label;" - href="http://www.palemoon.org/sync/help/easy-setup.shtml"/> - </description> - <label value="&addDevice.setup.enterCode.label;" - control="easySetupPIN1"/> - <spacer flex="1"/> - <vbox align="center" flex="1"> - <textbox id="easySetupPIN1" - class="pin" - value="" - readonly="true" - /> - <textbox id="easySetupPIN2" - class="pin" - value="" - readonly="true" - /> - <textbox id="easySetupPIN3" - class="pin" - value="" - readonly="true" - /> - </vbox> - <spacer flex="3"/> - <label class="text-link" - value="&addDevice.dontHaveDevice.label;" - onclick="gSyncSetup.manualSetup();"/> - </wizardpage> - - <wizardpage id="existingAccount" - label="&setup.signInPage.title.label;" - onextra1="gSyncSetup.onSyncOptions()" - onpageshow="gSyncSetup.onPageShow()"> - <grid> - <columns> - <column/> - <column class="inputColumn" flex="1"/> - </columns> - <rows> - <row id="existingAccountRow" align="center"> - <label id="existingAccountLabel" - value="&signIn.account2.label;" - accesskey="&signIn.account2.accesskey;" - control="existingAccount"/> - <textbox id="existingAccountName" - oninput="gSyncSetup.checkFields(event)" - onchange="gSyncSetup.checkFields(event)"/> - </row> - <row id="existingPasswordRow" align="center"> - <label id="existingPasswordLabel" - value="&signIn.password.label;" - accesskey="&signIn.password.accesskey;" - control="existingPassword"/> - <textbox id="existingPassword" - type="password" - onkeyup="gSyncSetup.checkFields(event)" - onchange="gSyncSetup.checkFields(event)"/> - </row> - <row id="existingPasswordFeedbackRow" align="center" hidden="true"> - <spacer/> - <hbox> - <image class="statusIcon"/> - <label class="status" value=" "/> - </hbox> - </row> - <row align="center"> - <spacer/> - <label class="text-link" - value="&resetPassword.label;" - onclick="gSyncUtils.resetPassword(); return false;"/> - </row> - <row align="center"> - <label control="existingServer" - value="&server.label;"/> - <menulist id="existingServer" - oncommand="gSyncSetup.onExistingServerCommand()" - oninput="gSyncSetup.onExistingServerInput()"> - <menupopup> - <menuitem label="&serverType.default.label;" - value="main"/> - <menuitem label="&serverType.custom2.label;" - value="custom"/> - </menupopup> - </menulist> - </row> - <row id="existingServerFeedbackRow" align="center" hidden="true"> - <spacer/> - <hbox> - <image class="statusIcon"/> - <vbox> - <label class="status" value=" "/> - </vbox> - </hbox> - </row> - </rows> - </grid> - - <groupbox> - <label id="existingPassphraseLabel" - value="&signIn.recoveryKey.label;" - accesskey="&signIn.recoveryKey.accesskey;" - control="existingPassphrase"/> - <textbox id="existingPassphrase" - oninput="gSyncSetup.checkFields()"/> - <hbox id="login-throbber" hidden="true"> - <image/> - <label value="&verifying.label;"/> - </hbox> - <vbox align="left" id="existingPassphraseFeedbackRow" hidden="true"> - <hbox> - <image class="statusIcon"/> - <label class="status" value=" "/> - </hbox> - </vbox> - </groupbox> - - <vbox id="passphraseHelpBox"> - <description> - &existingRecoveryKey.description; - <label class="text-link" - href="http://www.palemoon.org/sync/help/recoverykey.shtml"> - &addDevice.showMeHow.label; - </label> - <spacer id="passphraseHelpSpacer"/> - <label class="text-link" - onclick="gSyncSetup.resetPassphrase(); return false;"> - &resetSyncKey.label; - </label> - </description> - </vbox> - </wizardpage> - - <wizardpage id="syncOptionsPage" - label="&setup.optionsPage.title;" - onpageshow="gSyncSetup.onPageShow()"> - <groupbox id="syncOptions"> - <grid> - <columns> - <column/> - <column flex="1" style="-moz-margin-end: 2px"/> - </columns> - <rows> - <row align="center"> - <label value="&syncDeviceName.label;" - accesskey="&syncDeviceName.accesskey;" - control="syncComputerName"/> - <textbox id="syncComputerName" flex="1" - onchange="gSyncUtils.changeName(this)"/> - </row> - <row> - <label value="&syncMy.label;" /> - <vbox> - <checkbox label="&engine.addons.label;" - accesskey="&engine.addons.accesskey;" - id="engine.addons" - checked="false" - hidden="true"/> - <checkbox label="&engine.bookmarks.label;" - accesskey="&engine.bookmarks.accesskey;" - id="engine.bookmarks" - checked="true"/> - <checkbox label="&engine.passwords.label;" - accesskey="&engine.passwords.accesskey;" - id="engine.passwords" - checked="true"/> - <checkbox label="&engine.prefs.label;" - accesskey="&engine.prefs.accesskey;" - id="engine.prefs" - checked="true"/> - <checkbox label="&engine.history.label;" - accesskey="&engine.history.accesskey;" - id="engine.history" - checked="true"/> - <checkbox label="&engine.tabs.label;" - accesskey="&engine.tabs.accesskey;" - id="engine.tabs" - checked="true"/> - </vbox> - </row> - </rows> - </grid> - </groupbox> - - <groupbox id="mergeOptions"> - <radiogroup id="mergeChoiceRadio" pack="start"> - <grid> - <columns> - <column/> - <column flex="1"/> - </columns> - <rows flex="1"> - <row align="center"> - <radio id="resetClient" - class="mergeChoiceButton" - aria-labelledby="resetClientLabel"/> - <label id="resetClientLabel" control="resetClient"> - <html:strong>&choice2.merge.recommended.label;</html:strong> - &choice2a.merge.main.label; - </label> - </row> - <row align="center"> - <radio id="wipeClient" - class="mergeChoiceButton" - aria-labelledby="wipeClientLabel"/> - <label id="wipeClientLabel" - control="wipeClient"> - &choice2a.client.main.label; - </label> - </row> - <row align="center"> - <radio id="wipeRemote" - class="mergeChoiceButton" - aria-labelledby="wipeRemoteLabel"/> - <label id="wipeRemoteLabel" - control="wipeRemote"> - &choice2a.server.main.label; - </label> - </row> - </rows> - </grid> - </radiogroup> - </groupbox> - </wizardpage> - - <wizardpage id="syncOptionsConfirm" - label="&setup.optionsConfirmPage.title;" - onpageshow="gSyncSetup.onPageShow()"> - <deck id="chosenActionDeck"> - <vbox id="chosenActionMerge" class="confirm"> - <description class="normal"> - &confirm.merge2.label; - </description> - </vbox> - <vbox id="chosenActionWipeClient" class="confirm"> - <description class="normal"> - &confirm.client3.label; - </description> - <separator class="thin"/> - <vbox id="dataList"> - <label class="data indent" id="bookmarkCount"/> - <label class="data indent" id="historyCount"/> - <label class="data indent" id="passwordCount"/> - <label class="data indent" id="addonCount"/> - <label class="data indent" id="prefsWipe" - value="&engine.prefs.label;"/> - </vbox> - <separator class="thin"/> - <description class="normal"> - &confirm.client2.moreinfo.label; - </description> - </vbox> - <vbox id="chosenActionWipeServer" class="confirm"> - <description class="normal"> - &confirm.server2.label; - </description> - <separator class="thin"/> - <vbox id="clientList"> - </vbox> - </vbox> - </deck> - </wizardpage> - <!-- In terms of the wizard flow shown to the user, the 'syncOptionsConfirm' - page above is not the last wizard page. To prevent the wizard binding from - assuming that it is, we're inserting this dummy page here. This also means - that the wizard needs to always be closed manually via wizardFinish(). --> - <wizardpage> - </wizardpage> -</wizard> - diff --git a/browser/base/content/sync/utils.js b/browser/base/content/sync/utils.js deleted file mode 100644 index 0c02b5bc0..000000000 --- a/browser/base/content/sync/utils.js +++ /dev/null @@ -1,218 +0,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/. */ - -// Equivalent to 0o600 permissions; used for saved Sync Recovery Key. -// This constant can be replaced when the equivalent values are available to -// chrome JS; see Bug 433295 and Bug 757351. -const PERMISSIONS_RWUSR = 0x180; - -// Weave should always exist before before this file gets included. -let gSyncUtils = { - get bundle() { - delete this.bundle; - return this.bundle = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties"); - }, - - // opens in a new window if we're in a modal prefwindow world, in a new tab otherwise - _openLink: function (url) { - let thisDocEl = document.documentElement, - openerDocEl = window.opener && window.opener.document.documentElement; - if (thisDocEl.id == "accountSetup" && window.opener && - openerDocEl.id == "BrowserPreferences" && !openerDocEl.instantApply) - openUILinkIn(url, "window"); - else if (thisDocEl.id == "BrowserPreferences" && !thisDocEl.instantApply) - openUILinkIn(url, "window"); - else if (document.documentElement.id == "change-dialog") - Services.wm.getMostRecentWindow("navigator:browser") - .openUILinkIn(url, "tab"); - else - openUILinkIn(url, "tab"); - }, - - changeName: function changeName(input) { - // Make sure to update to a modified name, e.g., empty-string -> default - Weave.Service.clientsEngine.localName = input.value; - input.value = Weave.Service.clientsEngine.localName; - }, - - openChange: function openChange(type, duringSetup) { - // Just re-show the dialog if it's already open - let openedDialog = Services.wm.getMostRecentWindow("Sync:" + type); - if (openedDialog != null) { - openedDialog.focus(); - return; - } - - // Open up the change dialog - let changeXUL = "chrome://browser/content/sync/genericChange.xul"; - let changeOpt = "centerscreen,chrome,resizable=no"; - Services.ww.activeWindow.openDialog(changeXUL, "", changeOpt, - type, duringSetup); - }, - - changePassword: function () { - if (Weave.Utils.ensureMPUnlocked()) - this.openChange("ChangePassword"); - }, - - resetPassphrase: function (duringSetup) { - if (Weave.Utils.ensureMPUnlocked()) - this.openChange("ResetPassphrase", duringSetup); - }, - - updatePassphrase: function () { - if (Weave.Utils.ensureMPUnlocked()) - this.openChange("UpdatePassphrase"); - }, - - resetPassword: function () { - this._openLink(Weave.Service.pwResetURL); - }, - - openToS: function () { - this._openLink(Weave.Svc.Prefs.get("termsURL")); - }, - - openPrivacyPolicy: function () { - this._openLink(Weave.Svc.Prefs.get("privacyURL")); - }, - - openFirstSyncProgressPage: function () { - this._openLink("about:sync-progress"); - }, - - /** - * Prepare an invisible iframe with the passphrase backup document. - * Used by both the print and saving methods. - * - * @param elid : ID of the form element containing the passphrase. - * @param callback : Function called once the iframe has loaded. - */ - _preparePPiframe: function(elid, callback) { - let pp = document.getElementById(elid).value; - - // Create an invisible iframe whose contents we can print. - let iframe = document.createElement("iframe"); - iframe.setAttribute("src", "chrome://browser/content/sync/key.xhtml"); - iframe.collapsed = true; - document.documentElement.appendChild(iframe); - iframe.contentWindow.addEventListener("load", function() { - iframe.contentWindow.removeEventListener("load", arguments.callee, false); - - // Insert the Sync Key into the page. - let el = iframe.contentDocument.getElementById("synckey"); - el.firstChild.nodeValue = pp; - - // Insert the TOS and Privacy Policy URLs into the page. - let termsURL = Weave.Svc.Prefs.get("termsURL"); - el = iframe.contentDocument.getElementById("tosLink"); - el.setAttribute("href", termsURL); - el.firstChild.nodeValue = termsURL; - - let privacyURL = Weave.Svc.Prefs.get("privacyURL"); - el = iframe.contentDocument.getElementById("ppLink"); - el.setAttribute("href", privacyURL); - el.firstChild.nodeValue = privacyURL; - - callback(iframe); - }, false); - }, - - /** - * Print passphrase backup document. - * - * @param elid : ID of the form element containing the passphrase. - */ - passphrasePrint: function(elid) { - this._preparePPiframe(elid, function(iframe) { - let webBrowserPrint = iframe.contentWindow - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebBrowserPrint); - let printSettings = PrintUtils.getPrintSettings(); - - // Display no header/footer decoration except for the date. - printSettings.headerStrLeft - = printSettings.headerStrCenter - = printSettings.headerStrRight - = printSettings.footerStrLeft - = printSettings.footerStrCenter = ""; - printSettings.footerStrRight = "&D"; - - try { - webBrowserPrint.print(printSettings, null); - } catch (ex) { - // print()'s return codes are expressed as exceptions. Ignore. - } - }); - }, - - /** - * Save passphrase backup document to disk as HTML file. - * - * @param elid : ID of the form element containing the passphrase. - */ - passphraseSave: function(elid) { - let dialogTitle = this.bundle.GetStringFromName("save.recoverykey.title"); - let defaultSaveName = this.bundle.GetStringFromName("save.recoverykey.defaultfilename"); - this._preparePPiframe(elid, function(iframe) { - let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); - let fpCallback = function fpCallback_done(aResult) { - if (aResult == Ci.nsIFilePicker.returnOK || - aResult == Ci.nsIFilePicker.returnReplace) { - let stream = Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(Ci.nsIFileOutputStream); - stream.init(fp.file, -1, PERMISSIONS_RWUSR, 0); - - let serializer = new XMLSerializer(); - let output = serializer.serializeToString(iframe.contentDocument); - output = output.replace(/<!DOCTYPE (.|\n)*?]>/, - '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' + - '"DTD/xhtml1-strict.dtd">'); - output = Weave.Utils.encodeUTF8(output); - stream.write(output, output.length); - } - }; - - fp.init(window, dialogTitle, Ci.nsIFilePicker.modeSave); - fp.appendFilters(Ci.nsIFilePicker.filterHTML); - fp.defaultString = defaultSaveName; - fp.open(fpCallback); - return false; - }); - }, - - /** - * validatePassword - * - * @param el1 : the first textbox element in the form - * @param el2 : the second textbox element, if omitted it's an update form - * - * returns [valid, errorString] - */ - validatePassword: function (el1, el2) { - let valid = false; - let val1 = el1.value; - let val2 = el2 ? el2.value : ""; - let error = ""; - - if (!el2) - valid = val1.length >= Weave.MIN_PASS_LENGTH; - else if (val1 && val1 == Weave.Service.identity.username) - error = "change.password.pwSameAsUsername"; - else if (val1 && val1 == Weave.Service.identity.account) - error = "change.password.pwSameAsEmail"; - else if (val1 && val1 == Weave.Service.identity.basicPassword) - error = "change.password.pwSameAsPassword"; - else if (val1 && val2) { - if (val1 == val2 && val1.length >= Weave.MIN_PASS_LENGTH) - valid = true; - else if (val1.length < Weave.MIN_PASS_LENGTH) - error = "change.password.tooShort"; - else if (val1 != val2) - error = "change.password.mismatch"; - } - let errorString = error ? Weave.Utils.getErrorString(error) : ""; - return [valid, errorString]; - } -}; diff --git a/browser/base/content/tabbrowser.css b/browser/base/content/tabbrowser.css deleted file mode 100644 index 94d6dbb2e..000000000 --- a/browser/base/content/tabbrowser.css +++ /dev/null @@ -1,68 +0,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/. */ - -.tabbrowser-tabbox { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabbox"); - /* Make the content area follow the system colors before load */ - background: Menu; - color: MenuText; -} - -.tabbrowser-arrowscrollbox { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-arrowscrollbox"); -} - -.tab-close-button { - -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button"); - display: none; -} - -.tabbrowser-tabs[closebuttons="activetab"] > * > * > * > .tab-close-button:not([pinned])[selected="true"], -.tabbrowser-tabs[closebuttons="alltabs"] > * > * > * > .tab-close-button:not([pinned]) { - display: -moz-box; -} - -.tab-label[pinned] { - width: 0; - margin-left: 0 !important; - margin-right: 0 !important; - padding-left: 0 !important; - padding-right: 0 !important; -} - -.tab-stack { - vertical-align: top; /* for pinned tabs */ -} - -tabpanels { - background-color: transparent; -} - -.tab-drop-indicator { - position: relative; - z-index: 2; -} - -.tab-throbber:not([busy]), -.tab-throbber[busy] + .tab-icon-image { - display: none; -} - -.closing-tabs-spacer { - pointer-events: none; -} - -.tabbrowser-tabs:not(:hover) > .tabbrowser-arrowscrollbox > .closing-tabs-spacer { - transition: width .15s ease-out; -} - -/** - * Optimization for tabs that are restored lazily. We can save a good amount of - * memory that to-be-restored tabs would otherwise consume simply by setting - * their browsers to 'display: none' as that will prevent them from having to - * create a presentation and the like. - */ -browser[pending] { - display: none; -} diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml deleted file mode 100644 index 51f7063f3..000000000 --- a/browser/base/content/tabbrowser.xml +++ /dev/null @@ -1,4971 +0,0 @@ -<?xml version="1.0"?> - -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<!DOCTYPE bindings [ -<!ENTITY % tabBrowserDTD SYSTEM "chrome://browser/locale/tabbrowser.dtd" > -%tabBrowserDTD; -]> - -<bindings id="tabBrowserBindings" - xmlns="http://www.mozilla.org/xbl" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:xbl="http://www.mozilla.org/xbl"> - - <binding id="tabbrowser"> - <resources> - <stylesheet src="chrome://browser/content/tabbrowser.css"/> - </resources> - - <content> - <xul:stringbundle anonid="tbstringbundle" src="chrome://browser/locale/tabbrowser.properties"/> - <xul:tabbox anonid="tabbox" class="tabbrowser-tabbox" - flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown" - onselect="if (event.target.localName == 'tabpanels') this.parentNode.updateCurrentBrowser();"> - <xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer"> - <xul:notificationbox flex="1"> - <xul:hbox flex="1" class="browserSidebarContainer"> - <xul:vbox flex="1" class="browserContainer"> - <xul:stack flex="1" class="browserStack" anonid="browserStack"> - <xul:browser anonid="initialBrowser" type="content-primary" message="true" disablehistory="true" - xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/> - </xul:stack> - </xul:vbox> - </xul:hbox> - </xul:notificationbox> - </xul:tabpanels> - </xul:tabbox> - <children/> - </content> - <implementation implements="nsIDOMEventListener, nsIMessageListener"> - - <property name="tabContextMenu" readonly="true" - onget="return this.tabContainer.contextMenu;"/> - - <field name="tabContainer" readonly="true"> - document.getElementById(this.getAttribute("tabcontainer")); - </field> - <field name="tabs" readonly="true"> - this.tabContainer.childNodes; - </field> - - <property name="visibleTabs" readonly="true"> - <getter><![CDATA[ - if (!this._visibleTabs) - this._visibleTabs = Array.filter(this.tabs, - function (tab) !tab.hidden && !tab.closing); - return this._visibleTabs; - ]]></getter> - </property> - - <field name="closingTabsEnum" readonly="true">({ ALL: 0, OTHER: 1, TO_END: 2 });</field> - - <field name="_visibleTabs">null</field> - - <field name="mURIFixup" readonly="true"> - Components.classes["@mozilla.org/docshell/urifixup;1"] - .getService(Components.interfaces.nsIURIFixup); - </field> - <field name="mFaviconService" readonly="true"> - Components.classes["@mozilla.org/browser/favicon-service;1"] - .getService(Components.interfaces.nsIFaviconService); - </field> - <field name="_placesAutocomplete" readonly="true"> - Components.classes["@mozilla.org/autocomplete/search;1?name=history"] - .getService(Components.interfaces.mozIPlacesAutoComplete); - </field> - <field name="mTabBox" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "tabbox"); - </field> - <field name="mPanelContainer" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "panelcontainer"); - </field> - <field name="mStringBundle"> - document.getAnonymousElementByAttribute(this, "anonid", "tbstringbundle"); - </field> - <field name="mCurrentTab"> - null - </field> - <field name="_lastRelatedTab"> - null - </field> - <field name="mCurrentBrowser"> - null - </field> - <field name="mProgressListeners"> - [] - </field> - <field name="mTabsProgressListeners"> - [] - </field> - <field name="mTabListeners"> - [] - </field> - <field name="mTabFilters"> - [] - </field> - <field name="mIsBusy"> - false - </field> - <field name="_outerWindowIDBrowserMap"> - new Map(); - </field> - <field name="arrowKeysShouldWrap" readonly="true"> -#ifdef XP_MACOSX - true -#else - false -#endif - </field> - - <field name="_autoScrollPopup"> - null - </field> - - <field name="_previewMode"> - false - </field> - - <property name="_numPinnedTabs" readonly="true"> - <getter><![CDATA[ - for (var i = 0; i < this.tabs.length; i++) { - if (!this.tabs[i].pinned) - break; - } - return i; - ]]></getter> - </property> - - <property name="formValidationAnchor" readonly="true"> - <getter><![CDATA[ - if (this.mCurrentTab._formValidationAnchor) { - return this.mCurrentTab._formValidationAnchor; - } - let stack = this.mCurrentBrowser.parentNode; - // Create an anchor for the form validation popup - const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let formValidationAnchor = document.createElementNS(NS_XUL, "hbox"); - formValidationAnchor.className = "form-validation-anchor"; - formValidationAnchor.hidden = true; - stack.appendChild(formValidationAnchor); - return this.mCurrentTab._formValidationAnchor = formValidationAnchor; - ]]></getter> - </property> - - <method name="updateWindowResizers"> - <body><![CDATA[ - if (!window.gShowPageResizers) - return; - - var show = document.getElementById("addon-bar").collapsed && - window.windowState == window.STATE_NORMAL; - for (let i = 0; i < this.browsers.length; i++) { - this.browsers[i].showWindowResizer = show; - } - ]]></body> - </method> - - <method name="_setCloseKeyState"> - <parameter name="aEnabled"/> - <body><![CDATA[ - let keyClose = document.getElementById("key_close"); - let closeKeyEnabled = keyClose.getAttribute("disabled") != "true"; - if (closeKeyEnabled == aEnabled) - return; - - if (aEnabled) - keyClose.removeAttribute("disabled"); - else - keyClose.setAttribute("disabled", "true"); - - // We also want to remove the keyboard shortcut from the file menu - // when the shortcut is disabled, and bring it back when it's - // renabled. - // - // Fixing bug 630826 could make that happen automatically. - // Fixing bug 630830 could avoid the ugly hack below. - - let closeMenuItem = document.getElementById("menu_close"); - let parentPopup = closeMenuItem.parentNode; - let nextItem = closeMenuItem.nextSibling; - let clonedItem = closeMenuItem.cloneNode(true); - - parentPopup.removeChild(closeMenuItem); - - if (aEnabled) - clonedItem.setAttribute("key", "key_close"); - else - clonedItem.removeAttribute("key"); - - parentPopup.insertBefore(clonedItem, nextItem); - ]]></body> - </method> - - <method name="pinTab"> - <parameter name="aTab"/> - <body><![CDATA[ - if (aTab.pinned) - return; - - if (aTab.hidden) - this.showTab(aTab); - - this.moveTabTo(aTab, this._numPinnedTabs); - aTab.setAttribute("pinned", "true"); - this.tabContainer._unlockTabSizing(); - this.tabContainer._positionPinnedTabs(); - this.tabContainer.adjustTabstrip(); - - this.getBrowserForTab(aTab).docShell.isAppTab = true; - - if (aTab.selected) - this._setCloseKeyState(false); - - let event = document.createEvent("Events"); - event.initEvent("TabPinned", true, false); - aTab.dispatchEvent(event); - ]]></body> - </method> - - <method name="unpinTab"> - <parameter name="aTab"/> - <body><![CDATA[ - if (!aTab.pinned) - return; - - this.moveTabTo(aTab, this._numPinnedTabs - 1); - aTab.setAttribute("fadein", "true"); - aTab.removeAttribute("pinned"); - aTab.style.MozMarginStart = ""; - this.tabContainer._unlockTabSizing(); - this.tabContainer._positionPinnedTabs(); - this.tabContainer.adjustTabstrip(); - - this.getBrowserForTab(aTab).docShell.isAppTab = false; - - if (aTab.selected) - this._setCloseKeyState(true); - - let event = document.createEvent("Events"); - event.initEvent("TabUnpinned", true, false); - aTab.dispatchEvent(event); - ]]></body> - </method> - - <method name="previewTab"> - <parameter name="aTab"/> - <parameter name="aCallback"/> - <body> - <![CDATA[ - let currentTab = this.selectedTab; - try { - // Suppress focus, ownership and selected tab changes - this._previewMode = true; - this.selectedTab = aTab; - aCallback(); - } finally { - this.selectedTab = currentTab; - this._previewMode = false; - } - ]]> - </body> - </method> - - <method name="getBrowserAtIndex"> - <parameter name="aIndex"/> - <body> - <![CDATA[ - return this.browsers[aIndex]; - ]]> - </body> - </method> - - <method name="getBrowserIndexForDocument"> - <parameter name="aDocument"/> - <body> - <![CDATA[ - var tab = this._getTabForContentWindow(aDocument.defaultView); - return tab ? tab._tPos : -1; - ]]> - </body> - </method> - - <method name="getBrowserForDocument"> - <parameter name="aDocument"/> - <body> - <![CDATA[ - var tab = this._getTabForContentWindow(aDocument.defaultView); - return tab ? tab.linkedBrowser : null; - ]]> - </body> - </method> - - <method name="getBrowserForOuterWindowID"> - <parameter name="aID"/> - <body> - <![CDATA[ - return this._outerWindowIDBrowserMap.get(aID); - ]]> - </body> - </method> - - <method name="_getTabForContentWindow"> - <parameter name="aWindow"/> - <body> - <![CDATA[ - for (let i = 0; i < this.browsers.length; i++) { - if (this.browsers[i].contentWindow == aWindow) - return this.tabs[i]; - } - return null; - ]]> - </body> - </method> - - <!-- Binding from browser to tab --> - <field name="_tabForBrowser" readonly="true"> - <![CDATA[ - new WeakMap(); - ]]> - </field> - - <method name="_getTabForBrowser"> - <parameter name="aBrowser" /> - <body> - <![CDATA[ - let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated; - let text = "_getTabForBrowser` is now deprecated, please use `getTabForBrowser"; - let url = "https://developer.mozilla.org/docs/Mozilla/Tech/XUL/Method/getTabForBrowser"; - Deprecated.warning(text, url); - return this.getTabForBrowser(aBrowser); - ]]> - </body> - </method> - - <method name="getTabForBrowser"> - <parameter name="aBrowser"/> - <body> - <![CDATA[ - return this._tabForBrowser.get(aBrowser); - ]]> - </body> - </method> - - <method name="getNotificationBox"> - <parameter name="aBrowser"/> - <body> - <![CDATA[ - return this.getSidebarContainer(aBrowser).parentNode; - ]]> - </body> - </method> - - <method name="getSidebarContainer"> - <parameter name="aBrowser"/> - <body> - <![CDATA[ - return this.getBrowserContainer(aBrowser).parentNode; - ]]> - </body> - </method> - - <method name="getBrowserContainer"> - <parameter name="aBrowser"/> - <body> - <![CDATA[ - return (aBrowser || this.mCurrentBrowser).parentNode.parentNode; - ]]> - </body> - </method> - - <method name="getTabModalPromptBox"> - <parameter name="aBrowser"/> - <body> - <![CDATA[ - const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let browser = (aBrowser || this.mCurrentBrowser); - let stack = browser.parentNode; - let self = this; - - let promptBox = { - appendPrompt : function(args, onCloseCallback) { - let newPrompt = document.createElementNS(XUL_NS, "tabmodalprompt"); - stack.appendChild(newPrompt); - browser.setAttribute("tabmodalPromptShowing", true); - - newPrompt.clientTop; // style flush to assure binding is attached - - let tab = self._getTabForContentWindow(browser.contentWindow); - newPrompt.init(args, tab, onCloseCallback); - return newPrompt; - }, - - removePrompt : function(aPrompt) { - stack.removeChild(aPrompt); - - let prompts = this.listPrompts(); - if (prompts.length) { - let prompt = prompts[prompts.length - 1]; - prompt.Dialog.setDefaultFocus(); - } else { - browser.removeAttribute("tabmodalPromptShowing"); - browser.focus(); - } - }, - - listPrompts : function(aPrompt) { - let els = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt"); - // NodeList --> real JS array - let prompts = Array.slice(els); - return prompts; - }, - }; - - return promptBox; - ]]> - </body> - </method> - - <method name="_callProgressListeners"> - <parameter name="aBrowser"/> - <parameter name="aMethod"/> - <parameter name="aArguments"/> - <parameter name="aCallGlobalListeners"/> - <parameter name="aCallTabsListeners"/> - <body><![CDATA[ - var rv = true; - - if (!aBrowser) - aBrowser = this.mCurrentBrowser; - - if (aCallGlobalListeners != false && - aBrowser == this.mCurrentBrowser) { - this.mProgressListeners.forEach(function (p) { - if (aMethod in p) { - try { - if (!p[aMethod].apply(p, aArguments)) - rv = false; - } catch (e) { - // don't inhibit other listeners - Components.utils.reportError(e); - } - } - }); - } - - if (aCallTabsListeners != false) { - aArguments.unshift(aBrowser); - - this.mTabsProgressListeners.forEach(function (p) { - if (aMethod in p) { - try { - if (!p[aMethod].apply(p, aArguments)) - rv = false; - } catch (e) { - // don't inhibit other listeners - Components.utils.reportError(e); - } - } - }); - } - - return rv; - ]]></body> - </method> - - <!-- A web progress listener object definition for a given tab. --> - <method name="mTabProgressListener"> - <parameter name="aTab"/> - <parameter name="aBrowser"/> - <parameter name="aStartsBlank"/> - <body> - <![CDATA[ - return ({ - mTabBrowser: this, - mTab: aTab, - mBrowser: aBrowser, - mBlank: aStartsBlank, - - // cache flags for correct status UI update after tab switching - mStateFlags: 0, - mStatus: 0, - mMessage: "", - mTotalProgress: 0, - - // count of open requests (should always be 0 or 1) - mRequestCount: 0, - - destroy: function () { - delete this.mTab; - delete this.mBrowser; - delete this.mTabBrowser; - }, - - _callProgressListeners: function () { - Array.unshift(arguments, this.mBrowser); - return this.mTabBrowser._callProgressListeners.apply(this.mTabBrowser, arguments); - }, - - _shouldShowProgress: function (aRequest) { - if (this.mBlank) - return false; - - if (gMultiProcessBrowser) - return true; - - // Don't show progress indicators in tabs for about: URIs - // pointing to local resources. - try { - let channel = aRequest.QueryInterface(Ci.nsIChannel); - if (channel.originalURI.schemeIs("about") && - (channel.URI.schemeIs("jar") || channel.URI.schemeIs("file"))) - return false; - } catch (e) {} - - return true; - }, - - onProgressChange: function (aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, - aCurTotalProgress, aMaxTotalProgress) { - this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0; - - if (!this._shouldShowProgress(aRequest)) - return; - - if (this.mTotalProgress) - this.mTab.setAttribute("progress", "true"); - - this._callProgressListeners("onProgressChange", - [aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, - aCurTotalProgress, aMaxTotalProgress]); - }, - - onProgressChange64: function (aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, - aCurTotalProgress, aMaxTotalProgress) { - return this.onProgressChange(aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, - aMaxTotalProgress); - }, - - onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) { - if (!aRequest) - return; - - var oldBlank = this.mBlank; - - const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; - const nsIChannel = Components.interfaces.nsIChannel; - - if (aStateFlags & nsIWebProgressListener.STATE_START) { - this.mRequestCount++; - } - else if (aStateFlags & nsIWebProgressListener.STATE_STOP) { - const NS_ERROR_UNKNOWN_HOST = 2152398878; - if (--this.mRequestCount > 0 && aStatus == NS_ERROR_UNKNOWN_HOST) { - // to prevent bug 235825: wait for the request handled - // by the automatic keyword resolver - return; - } - // since we (try to) only handle STATE_STOP of the last request, - // the count of open requests should now be 0 - this.mRequestCount = 0; - } - - 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; - - if (this._shouldShowProgress(aRequest)) { - if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) { - this.mTab.setAttribute("busy", "true"); - if (!gMultiProcessBrowser) { - if (aWebProgress.isTopLevel && - !(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_RELOAD)) - this.mTabBrowser.setTabTitleLoading(this.mTab); - } - } - - if (this.mTab.selected) - this.mTabBrowser.mIsBusy = true; - } - } - else if (aStateFlags & nsIWebProgressListener.STATE_STOP && - aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { - - if (this.mTab.hasAttribute("busy")) { - this.mTab.removeAttribute("busy"); - this.mTabBrowser._tabAttrModified(this.mTab); - if (!this.mTab.selected) - this.mTab.setAttribute("unread", "true"); - } - this.mTab.removeAttribute("progress"); - - if (aWebProgress.isTopLevel) { - if (!Components.isSuccessCode(aStatus) && - !isTabEmpty(this.mTab)) { - // Restore the current document's location in case the - // request was stopped (possibly from a content script) - // before the location changed. - - this.mBrowser.userTypedValue = null; - - 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--; - } - - if (!this.mBrowser.mIconURL) - this.mTabBrowser.useDefaultIcon(this.mTab); - } - - 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; - - if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.connecting")) - this.mTabBrowser.setTabTitle(this.mTab); - - if (this.mTab.selected) - this.mTabBrowser.mIsBusy = false; - } - - if (oldBlank) { - this._callProgressListeners("onUpdateCurrentBrowser", - [aStateFlags, aStatus, "", 0], - true, false); - } else { - this._callProgressListeners("onStateChange", - [aWebProgress, aRequest, aStateFlags, aStatus], - true, false); - } - - this._callProgressListeners("onStateChange", - [aWebProgress, aRequest, aStateFlags, aStatus], - false); - - if (aStateFlags & (nsIWebProgressListener.STATE_START | - nsIWebProgressListener.STATE_STOP)) { - // reset cached temporary values at beginning and end - this.mMessage = ""; - this.mTotalProgress = 0; - } - this.mStateFlags = aStateFlags; - this.mStatus = aStatus; - }, - - onLocationChange: function (aWebProgress, aRequest, aLocation, - aFlags) { - // OnLocationChange is called for both the top-level content - // and the subframes. - 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 - // 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 || - ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) && - aLocation.spec != "about:blank")) - this.mBrowser.userTypedValue = null; - - // Don't clear the favicon if this onLocationChange was - // triggered by a pushState or a replaceState. See bug 550565. - if (!gMultiProcessBrowser) { - if (aWebProgress.isLoadingDocument && - !(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_PUSHSTATE)) - this.mBrowser.mIconURL = null; - } - - let autocomplete = this.mTabBrowser._placesAutocomplete; - if (this.mBrowser.registeredOpenURI) { - autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI); - delete this.mBrowser.registeredOpenURI; - } - // Tabs in private windows aren't registered as "Open" so - // that they don't appear as switch-to-tab candidates. - if (!isBlankPageURL(aLocation.spec) && - (!PrivateBrowsingUtils.isWindowPrivate(window) || - PrivateBrowsingUtils.permanentPrivateBrowsing)) { - autocomplete.registerOpenPage(aLocation); - this.mBrowser.registeredOpenURI = aLocation; - } - } - - if (!this.mBlank) { - this._callProgressListeners("onLocationChange", - [aWebProgress, aRequest, aLocation, - aFlags]); - } - - if (topLevel) - this.mBrowser.lastURI = aLocation; - }, - - onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) { - if (this.mBlank) - return; - - this._callProgressListeners("onStatusChange", - [aWebProgress, aRequest, aStatus, aMessage]); - - this.mMessage = aMessage; - }, - - onSecurityChange: function (aWebProgress, aRequest, aState) { - this._callProgressListeners("onSecurityChange", - [aWebProgress, aRequest, aState]); - }, - - onRefreshAttempted: function (aWebProgress, aURI, aDelay, aSameURI) { - return this._callProgressListeners("onRefreshAttempted", - [aWebProgress, aURI, aDelay, aSameURI]); - }, - - QueryInterface: function (aIID) { - if (aIID.equals(Components.interfaces.nsIWebProgressListener) || - aIID.equals(Components.interfaces.nsIWebProgressListener2) || - aIID.equals(Components.interfaces.nsISupportsWeakReference) || - aIID.equals(Components.interfaces.nsISupports)) - return this; - throw Components.results.NS_NOINTERFACE; - } - }); - ]]> - </body> - </method> - - <method name="setIcon"> - <parameter name="aTab"/> - <parameter name="aURI"/> - <body> - <![CDATA[ - var browser = this.getBrowserForTab(aTab); - browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI; - - if (aURI && this.mFaviconService) { - if (!(aURI instanceof Ci.nsIURI)) - aURI = makeURI(aURI); - this.mFaviconService.setAndFetchFaviconForPage(browser.currentURI, - aURI, false, - PrivateBrowsingUtils.isWindowPrivate(window) ? - this.mFaviconService.FAVICON_LOAD_PRIVATE : - this.mFaviconService.FAVICON_LOAD_NON_PRIVATE); - } - - let sizedIconUrl = browser.mIconURL || ""; - if (sizedIconUrl) { - let size = Math.round(16 * window.devicePixelRatio); - sizedIconUrl += (sizedIconUrl.includes("#") ? "&" : "#") + - "-moz-resolution=" + size + "," + size; - } - if (sizedIconUrl != aTab.getAttribute("image")) { - if (browser.mIconURL) //PMed - aTab.setAttribute("image", sizedIconUrl); - else - aTab.removeAttribute("image"); - this._tabAttrModified(aTab); - } - - this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]); - ]]> - </body> - </method> - - <method name="getIcon"> - <parameter name="aTab"/> - <body> - <![CDATA[ - let browser = aTab ? this.getBrowserForTab(aTab) : this.selectedBrowser; - return browser.mIconURL; - ]]> - </body> - </method> - - <method name="shouldLoadFavIcon"> - <parameter name="aURI"/> - <body> - <![CDATA[ - return (aURI && - Services.prefs.getBoolPref("browser.chrome.site_icons") && - Services.prefs.getBoolPref("browser.chrome.favicons") && - ("schemeIs" in aURI) && (aURI.schemeIs("http") || aURI.schemeIs("https"))); - ]]> - </body> - </method> - - <method name="useDefaultIcon"> - <parameter name="aTab"/> - <body> - <![CDATA[ - // Bug 691610 - e10s support for useDefaultIcon - if (gMultiProcessBrowser) - return; - - var browser = this.getBrowserForTab(aTab); - var docURIObject = browser.contentDocument.documentURIObject; - var icon = null; - <!-- Pale Moon: new image icon method, see bug #305986 --> - let req = browser.contentDocument.imageRequest; - let sz = Services.prefs.getIntPref("browser.chrome.image_icons.max_size"); - if (browser.contentDocument instanceof ImageDocument && - req && req.image) { - if (Services.prefs.getBoolPref("browser.chrome.site_icons") && sz) { - try { - <!-- Main method: draw on a hidden canvas --> - var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); - var tabImg = document.getAnonymousElementByAttribute(aTab, "anonid", "tab-icon"); - var w = tabImg.boxObject.width; - var h = tabImg.boxObject.height; - canvas.width = w; - canvas.height = h; - var ctx = canvas.getContext('2d'); - ctx.drawImage(browser.contentDocument.body.firstChild, 0, 0, w, h); - icon = canvas.toDataURL(); - } - catch (e) { - <!-- Fallback method in case canvas method fails, restricted by sz --> - try { - - if (req && - req.image && - req.image.width <= sz && - req.image.height <= sz) - icon = browser.currentURI; - } - catch (e) { - <!-- Both methods fail (very large or corrupt image): icon remains null --> - } - } - } - } - // Use documentURIObject in the check for shouldLoadFavIcon so that we - // do the right thing with about:-style error pages. Bug 453442 - else if (this.shouldLoadFavIcon(docURIObject)) { - let url = docURIObject.prePath + "/favicon.ico"; - if (!this.isFailedIcon(url)) - icon = url; - } - this.setIcon(aTab, icon); - ]]> - </body> - </method> - - <method name="isFailedIcon"> - <parameter name="aURI"/> - <body> - <![CDATA[ - if (this.mFaviconService) { - if (!(aURI instanceof Ci.nsIURI)) - aURI = makeURI(aURI); - return this.mFaviconService.isFailedFavicon(aURI); - } - return null; - ]]> - </body> - </method> - - <method name="getWindowTitleForBrowser"> - <parameter name="aBrowser"/> - <body> - <![CDATA[ - var newTitle = ""; - var docElement = this.ownerDocument.documentElement; - var sep = docElement.getAttribute("titlemenuseparator"); - - // Strip out any null bytes in the content title, since the - // underlying widget implementations of nsWindow::SetTitle pass - // null-terminated strings to system APIs. - var docTitle = aBrowser.contentTitle.replace("\0", "", "g"); - - if (!docTitle) - docTitle = docElement.getAttribute("titledefault"); - - var modifier = docElement.getAttribute("titlemodifier"); - if (docTitle) { - newTitle += docElement.getAttribute("titlepreface"); - newTitle += docTitle; - if (modifier) - newTitle += sep; - } - newTitle += modifier; - - // If location bar is hidden and the URL type supports a host, - // add the scheme and host to the title to prevent spoofing. - // XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239 - try { - if (docElement.getAttribute("chromehidden").includes("location")) { - var uri = this.mURIFixup.createExposableURI( - aBrowser.currentURI); - if (uri.scheme == "about") - newTitle = uri.spec + sep + newTitle; - else - newTitle = uri.prePath + sep + newTitle; - } - } catch (e) {} - - return newTitle; - ]]> - </body> - </method> - - <method name="freezeTitlebar"> - <parameter name="aTitle"/> - <body> - <![CDATA[ - this._frozenTitle = aTitle || ""; - this.updateTitlebar(); - ]]> - </body> - </method> - - <method name="unfreezeTitlebar"> - <body> - <![CDATA[ - this._frozenTitle = ""; - this.updateTitlebar(); - ]]> - </body> - </method> - - <method name="updateTitlebar"> - <body> - <![CDATA[ - this.ownerDocument.title = this._frozenTitle || - this.getWindowTitleForBrowser(this.mCurrentBrowser); - ]]> - </body> - </method> - - <method name="updateCurrentBrowser"> - <parameter name="aForceUpdate"/> - <body> - <![CDATA[ - var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex); - if (this.mCurrentBrowser == newBrowser && !aForceUpdate) - return; - - if (!aForceUpdate) { - window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils) - .beginTabSwitch(); - } - - var oldTab = this.mCurrentTab; - - // Preview mode should not reset the owner - if (!this._previewMode && !oldTab.selected) - oldTab.owner = null; - - if (this._lastRelatedTab) { - if (!this._lastRelatedTab.selected) - this._lastRelatedTab.owner = null; - this._lastRelatedTab = null; - } - - var oldBrowser = this.mCurrentBrowser; - if (oldBrowser) { - oldBrowser.setAttribute("type", "content-targetable"); - oldBrowser.docShellIsActive = false; - this.finder.mListeners.forEach(l => oldBrowser.finder.removeResultListener(l)); - } - - var updateBlockedPopups = false; - if (!oldBrowser || - (oldBrowser.blockedPopups && !newBrowser.blockedPopups) || - (!oldBrowser.blockedPopups && newBrowser.blockedPopups)) - updateBlockedPopups = true; - - newBrowser.setAttribute("type", "content-primary"); - newBrowser.docShellIsActive = - (window.windowState != window.STATE_MINIMIZED); - this.mCurrentBrowser = newBrowser; - this.mCurrentTab = this.tabContainer.selectedItem; - this.finder.mListeners.forEach(l => this.mCurrentBrowser.finder.addResultListener(l)); - this.showTab(this.mCurrentTab); - - var backForwardContainer = document.getElementById("unified-back-forward-button"); - if (backForwardContainer) { - backForwardContainer.setAttribute("switchingtabs", "true"); - window.addEventListener("MozAfterPaint", function removeSwitchingtabsAttr() { - window.removeEventListener("MozAfterPaint", removeSwitchingtabsAttr); - backForwardContainer.removeAttribute("switchingtabs"); - }); - } - - if (updateBlockedPopups) - this.mCurrentBrowser.updateBlockedPopups(); - - // Update the URL bar. - var loc = this.mCurrentBrowser.currentURI; - - // Bug 666809 - SecurityUI support for e10s - var webProgress = this.mCurrentBrowser.webProgress; - var securityUI = this.mCurrentBrowser.securityUI; - - this._callProgressListeners(null, "onLocationChange", - [webProgress, null, loc, 0], true, - false); - - if (securityUI) { - this._callProgressListeners(null, "onSecurityChange", - [webProgress, null, securityUI.state], true, false); - } - - var listener = this.mTabListeners[this.tabContainer.selectedIndex] || null; - if (listener && listener.mStateFlags) { - this._callProgressListeners(null, "onUpdateCurrentBrowser", - [listener.mStateFlags, listener.mStatus, - listener.mMessage, listener.mTotalProgress], - true, false); - } - - if (!this._previewMode) { - this.mCurrentTab.removeAttribute("unread"); - this.selectedTab.lastAccessed = Date.now(); - - // Bug 666816 - TypeAheadFind support for e10s - if (!gMultiProcessBrowser) - this._fastFind.setDocShell(this.mCurrentBrowser.docShell); - - this.updateTitlebar(); - - this.mCurrentTab.removeAttribute("titlechanged"); - } - - // If the new tab is busy, and our current state is not busy, then - // we need to fire a start to all progress listeners. - const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; - if (this.mCurrentTab.hasAttribute("busy") && !this.mIsBusy) { - this.mIsBusy = true; - this._callProgressListeners(null, "onStateChange", - [webProgress, null, - nsIWebProgressListener.STATE_START | - nsIWebProgressListener.STATE_IS_NETWORK, 0], - true, false); - } - - // If the new tab is not busy, and our current state is busy, then - // we need to fire a stop to all progress listeners. - if (!this.mCurrentTab.hasAttribute("busy") && this.mIsBusy) { - this.mIsBusy = false; - this._callProgressListeners(null, "onStateChange", - [webProgress, null, - nsIWebProgressListener.STATE_STOP | - nsIWebProgressListener.STATE_IS_NETWORK, 0], - true, false); - } - - this._setCloseKeyState(!this.mCurrentTab.pinned); - - // TabSelect events are suppressed during preview mode to avoid confusing extensions and other bits of code - // that might rely upon the other changes suppressed. - // Focus is suppressed in the event that the main browser window is minimized - focusing a tab would restore the window - if (!this._previewMode) { - // We've selected the new tab, so go ahead and notify listeners. - let event = new CustomEvent("TabSelect", { - bubbles: true, - cancelable: false, - detail: { - previousTab: oldTab - } - }); - this.mCurrentTab.dispatchEvent(event); - - this._tabAttrModified(oldTab); - this._tabAttrModified(this.mCurrentTab); - - // Adjust focus - oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused); - do { - // When focus is in the tab bar, retain it there. - if (document.activeElement == oldTab) { - // We need to explicitly focus the new tab, because - // tabbox.xml does this only in some cases. - this.mCurrentTab.focus(); - break; - } - - // If there's a tabmodal prompt showing, focus it. - if (newBrowser.hasAttribute("tabmodalPromptShowing")) { - let XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let prompts = newBrowser.parentNode.getElementsByTagNameNS(XUL_NS, "tabmodalprompt"); - let prompt = prompts[prompts.length - 1]; - prompt.Dialog.setDefaultFocus(); - break; - } - - // Focus the location bar if it was previously focused for that tab. - // In full screen mode, only bother making the location bar visible - // if the tab is a blank one. - if (newBrowser._urlbarFocused && gURLBar) { - - // Explicitly close the popup if the URL bar retains focus - gURLBar.closePopup(); - - if (!window.fullScreen) { - gURLBar.focus(); - break; - } else if (isTabEmpty(this.mCurrentTab)) { - focusAndSelectUrlBar(); - break; - } - } - - // If the find bar is focused, keep it focused. - if (gFindBarInitialized && - !gFindBar.hidden && - gFindBar.getElement("findbar-textbox").getAttribute("focused") == "true") - break; - - // Otherwise, focus the content area. - let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); - let focusFlags = fm.FLAG_NOSCROLL; - - if (!gMultiProcessBrowser) { - let newFocusedElement = fm.getFocusedElementForWindow(window.content, true, {}); - - // for anchors, use FLAG_SHOWRING so that it is clear what link was - // last clicked when switching back to that tab - if (newFocusedElement && - (newFocusedElement instanceof HTMLAnchorElement || - newFocusedElement.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple")) - focusFlags |= fm.FLAG_SHOWRING; - } - fm.setFocus(newBrowser, focusFlags); - } while (false); - } - - this.tabContainer._setPositionalAttributes(); - ]]> - </body> - </method> - - <method name="_tabAttrModified"> - <parameter name="aTab"/> - <body><![CDATA[ - if (aTab.closing) - return; - - // This event should be dispatched when any of these attributes change: - // label, crop, busy, image, selected - var event = document.createEvent("Events"); - event.initEvent("TabAttrModified", true, false); - aTab.dispatchEvent(event); - ]]></body> - </method> - - <method name="setTabTitleLoading"> - <parameter name="aTab"/> - <body> - <![CDATA[ - aTab.label = this.mStringBundle.getString("tabs.connecting"); - aTab.crop = "end"; - this._tabAttrModified(aTab); - ]]> - </body> - </method> - - <method name="setTabTitle"> - <parameter name="aTab"/> - <body> - <![CDATA[ - var browser = this.getBrowserForTab(aTab); - var crop = "end"; - var title = browser.contentTitle; - - if (!title) { - if (browser.currentURI.spec) { - try { - title = this.mURIFixup.createExposableURI(browser.currentURI).spec; - } catch(ex) { - title = browser.currentURI.spec; - } - } - - if (title && !isBlankPageURL(title)) { - // At this point, we now have a URI. - // Let's try to unescape it using a character set - // in case the URI is not ASCII. - try { - var characterSet = browser.characterSet; - const textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"] - .getService(Components.interfaces.nsITextToSubURI); - title = textToSubURI.unEscapeNonAsciiURI(characterSet, title); - } catch(ex) { /* Do nothing. */ } - - crop = "center"; - - } else // Still no title? Fall back to our untitled string. - title = this.mStringBundle.getString("tabs.emptyTabTitle"); - } - - if (aTab.label == title && - aTab.crop == crop) - return false; - - aTab.label = title; - aTab.crop = crop; - this._tabAttrModified(aTab); - - if (aTab.selected) - this.updateTitlebar(); - - return true; - ]]> - </body> - </method> - - <method name="loadOneTab"> - <parameter name="aURI"/> - <parameter name="aReferrerURI"/> - <parameter name="aCharset"/> - <parameter name="aPostData"/> - <parameter name="aLoadInBackground"/> - <parameter name="aAllowThirdPartyFixup"/> - <body> - <![CDATA[ - var aFromExternal; - var aRelatedToCurrent; - if (arguments.length == 2 && - typeof arguments[1] == "object" && - !(arguments[1] instanceof Ci.nsIURI)) { - let params = arguments[1]; - aReferrerURI = params.referrerURI; - aCharset = params.charset; - aPostData = params.postData; - aLoadInBackground = params.inBackground; - aAllowThirdPartyFixup = params.allowThirdPartyFixup; - aFromExternal = params.fromExternal; - aRelatedToCurrent = params.relatedToCurrent; - } - - var bgLoad = (aLoadInBackground != null) ? aLoadInBackground : - Services.prefs.getBoolPref("browser.tabs.loadInBackground"); - var owner = bgLoad ? null : this.selectedTab; - var tab = this.addTab(aURI, { - referrerURI: aReferrerURI, - charset: aCharset, - postData: aPostData, - ownerTab: owner, - allowThirdPartyFixup: aAllowThirdPartyFixup, - fromExternal: aFromExternal, - relatedToCurrent: aRelatedToCurrent}); - if (!bgLoad) - this.selectedTab = tab; - - return tab; - ]]> - </body> - </method> - - <method name="loadTabs"> - <parameter name="aURIs"/> - <parameter name="aLoadInBackground"/> - <parameter name="aReplace"/> - <body><![CDATA[ - if (!aURIs.length) - return; - - // The tab selected after this new tab is closed (i.e. the new tab's - // "owner") is the next adjacent tab (i.e. not the previously viewed tab) - // when several urls are opened here (i.e. closing the first should select - // the next of many URLs opened) or if the pref to have UI links opened in - // the background is set (i.e. the link is not being opened modally) - // - // i.e. - // Number of URLs Load UI Links in BG Focus Last Viewed? - // == 1 false YES - // == 1 true NO - // > 1 false/true NO - var multiple = aURIs.length > 1; - var owner = multiple || aLoadInBackground ? null : this.selectedTab; - var firstTabAdded = null; - - if (aReplace) { - try { - this.loadURI(aURIs[0], null, null); - } 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}); - - var tabNum = this.tabContainer.selectedIndex; - for (let i = 1; i < aURIs.length; ++i) { - let tab = this.addTab(aURIs[i], {skipAnimation: true}); - if (aReplace) - this.moveTabTo(tab, ++tabNum); - } - - if (!aLoadInBackground) { - if (firstTabAdded) { - // .selectedTab setter focuses the content area - this.selectedTab = firstTabAdded; - } - else - this.selectedBrowser.focus(); - } - ]]></body> - </method> - - <method name="addTab"> - <parameter name="aURI"/> - <parameter name="aReferrerURI"/> - <parameter name="aCharset"/> - <parameter name="aPostData"/> - <parameter name="aOwner"/> - <parameter name="aAllowThirdPartyFixup"/> - <body> - <![CDATA[ - const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - var aFromExternal; - var aRelatedToCurrent; - var aSkipAnimation; - if (arguments.length == 2 && - typeof arguments[1] == "object" && - !(arguments[1] instanceof Ci.nsIURI)) { - let params = arguments[1]; - aReferrerURI = params.referrerURI; - aCharset = params.charset; - aPostData = params.postData; - aOwner = params.ownerTab; - aAllowThirdPartyFixup = params.allowThirdPartyFixup; - aFromExternal = params.fromExternal; - aRelatedToCurrent = params.relatedToCurrent; - aSkipAnimation = params.skipAnimation; - } - - // if we're adding tabs, we're past interrupt mode, ditch the owner - if (this.mCurrentTab.owner) - this.mCurrentTab.owner = null; - - var t = document.createElementNS(NS_XUL, "tab"); - - var uriIsAboutBlank = !aURI || aURI == "about:blank"; - - if (!aURI || isBlankPageURL(aURI)) - t.setAttribute("label", this.mStringBundle.getString("tabs.emptyTabTitle")); - else - t.setAttribute("label", aURI); - - t.setAttribute("crop", "end"); - t.setAttribute("validate", "never"); //PMed - t.setAttribute("onerror", "this.removeAttribute('image');"); - t.className = "tabbrowser-tab"; - - this.tabContainer._unlockTabSizing(); - - // When overflowing, new tabs are scrolled into view smoothly, which - // doesn't go well together with the width transition. So we skip the - // transition in that case. - let animate = !aSkipAnimation && - this.tabContainer.getAttribute("overflow") != "true" && - Services.prefs.getBoolPref("browser.tabs.animate"); - if (!animate) { - t.setAttribute("fadein", "true"); - setTimeout(function (tabContainer) { - tabContainer._handleNewTab(t); - }, 0, this.tabContainer); - } - - // invalidate caches - this._browsers = null; - this._visibleTabs = null; - - this.tabContainer.appendChild(t); - - // If this new tab is owned by another, assert that relationship - if (aOwner) - t.owner = aOwner; - - var b = document.createElementNS( - "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", - "browser"); - b.setAttribute("type", "content-targetable"); - b.setAttribute("message", "true"); - b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu")); - b.setAttribute("tooltip", this.getAttribute("contenttooltip")); - - if (Services.prefs.getPrefType("browser.tabs.remote") == Services.prefs.PREF_BOOL && - Services.prefs.getBoolPref("browser.tabs.remote")) { - b.setAttribute("remote", "true"); - } - - if (window.gShowPageResizers && document.getElementById("addon-bar").collapsed && - window.windowState == window.STATE_NORMAL) { - b.setAttribute("showresizer", "true"); - } - - if (this.hasAttribute("autocompletepopup")) - b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup")); - b.setAttribute("autoscrollpopup", this._autoScrollPopup.id); - - // Create the browserStack container - var stack = document.createElementNS(NS_XUL, "stack"); - stack.className = "browserStack"; - stack.appendChild(b); - stack.setAttribute("flex", "1"); - - // Create the browserContainer - var browserContainer = document.createElementNS(NS_XUL, "vbox"); - browserContainer.className = "browserContainer"; - browserContainer.appendChild(stack); - browserContainer.setAttribute("flex", "1"); - - // Create the sidebar container - var browserSidebarContainer = document.createElementNS(NS_XUL, - "hbox"); - browserSidebarContainer.className = "browserSidebarContainer"; - browserSidebarContainer.appendChild(browserContainer); - browserSidebarContainer.setAttribute("flex", "1"); - - // Add the Message and the Browser to the box - var notificationbox = document.createElementNS(NS_XUL, - "notificationbox"); - notificationbox.setAttribute("flex", "1"); - notificationbox.appendChild(browserSidebarContainer); - - var position = this.tabs.length - 1; - var uniqueId = "panel" + Date.now() + position; - notificationbox.id = uniqueId; - t.linkedPanel = uniqueId; - t.linkedBrowser = b; - this._tabForBrowser.set(b, t); - t._tPos = position; - this.tabContainer._setPositionalAttributes(); - - // Prevent the superfluous initial load of a blank document - // if we're going to load something other than about:blank. - if (!uriIsAboutBlank) { - b.setAttribute("nodefaultsrc", "true"); - } - - // NB: this appendChild call causes us to run constructors for the - // browser element, which fires off a bunch of notifications. Some - // of those notifications can cause code to run that inspects our - // state, so it is important that the tab element is fully - // initialized by this point. - this.mPanelContainer.appendChild(notificationbox); - - this.tabContainer.updateVisibility(); - - // wire up a progress listener for the new browser object. - var tabListener = this.mTabProgressListener(t, b, uriIsAboutBlank); - const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"] - .createInstance(Components.interfaces.nsIWebProgress); - filter.addProgressListener(tabListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL); - b.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL); - this.mTabListeners[position] = tabListener; - this.mTabFilters[position] = filter; - - b._fastFind = this.fastFind; - b.droppedLinkHandler = handleDroppedLink; - - // If we just created a new tab that loads the default - // newtab url, swap in a preloaded page if possible. - // Do nothing if we're a private window. - let docShellsSwapped = false; - if (aURI == BROWSER_NEW_TAB_URL && - !PrivateBrowsingUtils.isWindowPrivate(window)) { - docShellsSwapped = gBrowserNewTabPreloader.newTab(t); - } - - // Dispatch a new tab notification. We do this once we're - // entirely done, so that things are in a consistent state - // even if the event listener opens or closes tabs. - var evt = document.createEvent("Events"); - evt.initEvent("TabOpen", true, false); - t.dispatchEvent(evt); - - // If we didn't swap docShells with a preloaded browser - // then let's just continue loading the page normally. - if (!docShellsSwapped && !uriIsAboutBlank) { - // pretend the user typed this so it'll be available till - // the document successfully loads - if (aURI && gInitialPages.indexOf(aURI) == -1) - b.userTypedValue = aURI; - - let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; - if (aAllowThirdPartyFixup) { - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - } - if (aFromExternal) - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL; - try { - b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData); - } catch (ex) { - Cu.reportError(ex); - } - } - - // We start our browsers out as inactive, and then maintain - // activeness in the tab switcher. - b.docShellIsActive = false; - - // When addTab() is called with an URL that is not "about:blank" we - // set the "nodefaultsrc" attribute that prevents a frameLoader - // from being created as soon as the linked <browser> is inserted - // into the DOM. We thus have to register the new outerWindowID - // for non-remote browsers after we have called browser.loadURI(). - // - // Note: Only do this of we still have a docShell. The TabOpen - // event was dispatched above and a gBrowser.removeTab() call from - // one of its listeners could cause us to fail here. - if (Services.prefs.getPrefType("browser.tabs.remote") == Services.prefs.PREF_BOOL && - !Services.prefs.getBoolPref("browser.tabs.remote") - && b.docShell) { - this._outerWindowIDBrowserMap.set(b.outerWindowID, b); - } - - // Check if we're opening a tab related to the current tab and - // move it to after the current tab. - // aReferrerURI is null or undefined if the tab is opened from - // an external application or bookmark, i.e. somewhere other - // than the current tab. - if ((aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) && - Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) { - let newTabPos = (this._lastRelatedTab || - this.selectedTab)._tPos + 1; - if (this._lastRelatedTab) - this._lastRelatedTab.owner = null; - else - t.owner = this.selectedTab; - this.moveTabTo(t, newTabPos); - this._lastRelatedTab = t; - } - - if (animate) { - mozRequestAnimationFrame(function () { - this.tabContainer._handleTabTelemetryStart(t, aURI); - - // kick the animation off - t.setAttribute("fadein", "true"); - - // This call to adjustTabstrip is redundant but needed so that - // when opening a second tab, the first tab's close buttons - // appears immediately rather than when the transition ends. - if (this.tabs.length - this._removingTabs.length == 2) - this.tabContainer.adjustTabstrip(); - }.bind(this)); - } - - return t; - ]]> - </body> - </method> - - <method name="warnAboutClosingTabs"> - <parameter name="aCloseTabs"/> - <parameter name="aTab"/> - <body> - <![CDATA[ - var tabsToClose; - switch (aCloseTabs) { - case this.closingTabsEnum.ALL: - tabsToClose = this.tabs.length - this._removingTabs.length - - gBrowser._numPinnedTabs; - break; - case this.closingTabsEnum.OTHER: - tabsToClose = this.visibleTabs.length - 1 - gBrowser._numPinnedTabs; - break; - case this.closingTabsEnum.TO_END: - if (!aTab) - throw new Error("Required argument missing: aTab"); - - tabsToClose = this.getTabsToTheEndFrom(aTab).length; - break; - default: - throw new Error("Invalid argument: " + aCloseTabs); - } - - if (tabsToClose <= 1) - return true; - - const pref = aCloseTabs == this.closingTabsEnum.ALL ? - "browser.tabs.warnOnClose" : "browser.tabs.warnOnCloseOtherTabs"; - var shouldPrompt = Services.prefs.getBoolPref(pref); - if (!shouldPrompt) - return true; - - var ps = Services.prompt; - - // default to true: if it were false, we wouldn't get this far - var warnOnClose = { value: true }; - var bundle = this.mStringBundle; - - // focus the window before prompting. - // this will raise any minimized window, which will - // make it obvious which window the prompt is for and will - // solve the problem of windows "obscuring" the prompt. - // see bug #350299 for more details - window.focus(); - var buttonPressed = - ps.confirmEx(window, - bundle.getString("tabs.closeWarningTitle"), - bundle.getFormattedString("tabs.closeWarningMultipleTabs", - [tabsToClose]), - (ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0) - + (ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1), - bundle.getString("tabs.closeButtonMultiple"), - null, null, - aCloseTabs == this.closingTabsEnum.ALL ? - bundle.getString("tabs.closeWarningPromptMe") : null, - warnOnClose); - var reallyClose = (buttonPressed == 0); - - // don't set the prefs unless they press OK and have unchecked the box - if (aCloseTabs == this.closingTabsEnum.ALL && reallyClose && !warnOnClose.value) { - Services.prefs.setBoolPref("browser.tabs.warnOnClose", false); - Services.prefs.setBoolPref("browser.tabs.warnOnCloseOtherTabs", false); - } - return reallyClose; - ]]> - </body> - </method> - - <method name="getTabsToTheEndFrom"> - <parameter name="aTab"/> - <body> - <![CDATA[ - var tabsToEnd = []; - let tabs = this.visibleTabs; - for (let i = tabs.length - 1; tabs[i] != aTab && i >= 0; --i) { - tabsToEnd.push(tabs[i]); - } - return tabsToEnd.reverse(); - ]]> - </body> - </method> - - <method name="removeTabsToTheEndFrom"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab)) { - let tabs = this.getTabsToTheEndFrom(aTab); - for (let i = tabs.length - 1; i >= 0; --i) { - this.removeTab(tabs[i], {animate: true}); - } - } - ]]> - </body> - </method> - - <method name="removeAllTabsBut"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (aTab.pinned) - return; - - if (this.warnAboutClosingTabs(this.closingTabsEnum.OTHER)) { - let tabs = this.visibleTabs; - this.selectedTab = aTab; - - for (let i = tabs.length - 1; i >= 0; --i) { - if (tabs[i] != aTab && !tabs[i].pinned) - this.removeTab(tabs[i]); - } - } - ]]> - </body> - </method> - - <method name="removeCurrentTab"> - <parameter name="aParams"/> - <body> - <![CDATA[ - this.removeTab(this.mCurrentTab, aParams); - ]]> - </body> - </method> - - <field name="_removingTabs"> - [] - </field> - - <method name="removeTab"> - <parameter name="aTab"/> - <parameter name="aParams"/> - <body> - <![CDATA[ - if (aParams) { - var animate = aParams.animate; - var byMouse = aParams.byMouse; - } - - // Handle requests for synchronously removing an already - // asynchronously closing tab. - if (!animate && - aTab.closing) { - this._endRemoveTab(aTab); - return; - } - - var isLastTab = (this.tabs.length - this._removingTabs.length == 1); - - if (!this._beginRemoveTab(aTab, false, null, true)) - return; - - if (!aTab.pinned && !aTab.hidden && aTab._fullyOpen && byMouse) - this.tabContainer._lockTabSizing(aTab); - else - this.tabContainer._unlockTabSizing(); - - if (!animate /* the caller didn't opt in */ || - isLastTab || - aTab.pinned || - aTab.hidden || - this._removingTabs.length > 3 /* don't want lots of concurrent animations */ || - aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ || - window.getComputedStyle(aTab).maxWidth == "0.1px" /* fade-in transition hasn't moved yet */ || - !Services.prefs.getBoolPref("browser.tabs.animate")) { - this._endRemoveTab(aTab); - return; - } - - this.tabContainer._handleTabTelemetryStart(aTab); - - this._blurTab(aTab); - aTab.style.maxWidth = ""; // ensure that fade-out transition happens - aTab.removeAttribute("fadein"); - - if (this.tabs.length - this._removingTabs.length == 1) { - // The second tab just got closed and we will end up with a single - // one. Remove the first tab's close button immediately (if needed) - // rather than after the tabclose animation ends. - this.tabContainer.adjustTabstrip(); - } - - setTimeout(function (tab, tabbrowser) { - if (tab.parentNode && - window.getComputedStyle(tab).maxWidth == "0.1px") { - NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)"); - tabbrowser._endRemoveTab(tab); - } - }, 3000, aTab, this); - ]]> - </body> - </method> - - <!-- Tab close requests are ignored if the window is closing anyway, - e.g. when holding Ctrl+W. --> - <field name="_windowIsClosing"> - false - </field> - - <method name="_beginRemoveTab"> - <parameter name="aTab"/> - <parameter name="aTabWillBeMoved"/> - <parameter name="aCloseWindowWithLastTab"/> - <parameter name="aCloseWindowFastpath"/> - <body> - <![CDATA[ - if (aTab.closing || - aTab._pendingPermitUnload || - this._windowIsClosing) - return false; - - var browser = this.getBrowserForTab(aTab); - - if (!aTabWillBeMoved) { - let ds = browser.docShell; - if (ds && ds.contentViewer) { - // We need to block while calling permitUnload() because it - // processes the event queue and may lead to another removeTab() - // call before permitUnload() even returned. - aTab._pendingPermitUnload = true; - let permitUnload = ds.contentViewer.permitUnload(); - delete aTab._pendingPermitUnload; - - if (!permitUnload) - return false; - } - } - - var closeWindow = false; - var newTab = false; - if (this.tabs.length - this._removingTabs.length == 1) { - closeWindow = aCloseWindowWithLastTab != null ? aCloseWindowWithLastTab : - !window.toolbar.visible || - this.tabContainer._closeWindowWithLastTab; - - // Closing the tab and replacing it with a blank one is notably slower - // than closing the window right away. If the caller opts in, take - // the fast path. - if (closeWindow && - aCloseWindowFastpath && - this._removingTabs.length == 0 && - (this._windowIsClosing = window.closeWindow(true, window.warnAboutClosingWindow))) - return null; - - newTab = true; - } - - aTab.closing = true; - this._removingTabs.push(aTab); - this._visibleTabs = null; // invalidate cache - if (newTab) - this.addTab(BROWSER_NEW_TAB_URL, {skipAnimation: true}); - else - this.tabContainer.updateVisibility(); - - // We're committed to closing the tab now. - // Dispatch a notification. - // We dispatch it before any teardown so that event listeners can - // inspect the tab that's about to close. - var evt = document.createEvent("UIEvent"); - evt.initUIEvent("TabClose", true, false, window, aTabWillBeMoved ? 1 : 0); - aTab.dispatchEvent(evt); - - if (!gMultiProcessBrowser) { - // Prevent this tab from showing further dialogs, since we're closing it - var windowUtils = browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils); - windowUtils.disableDialogs(); - } - - // Remove the tab's filter and progress listener. - const filter = this.mTabFilters[aTab._tPos]; - - browser.webProgress.removeProgressListener(filter); - - filter.removeProgressListener(this.mTabListeners[aTab._tPos]); - this.mTabListeners[aTab._tPos].destroy(); - - if (browser.registeredOpenURI && !aTabWillBeMoved) { - this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI); - delete browser.registeredOpenURI; - } - - // We are no longer the primary content area. - browser.setAttribute("type", "content-targetable"); - - // Remove this tab as the owner of any other tabs, since it's going away. - Array.forEach(this.tabs, function (tab) { - if ("owner" in tab && tab.owner == aTab) - // |tab| is a child of the tab we're removing, make it an orphan - tab.owner = null; - }); - - aTab._endRemoveArgs = [closeWindow, newTab]; - return true; - ]]> - </body> - </method> - - <method name="_endRemoveTab"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (!aTab || !aTab._endRemoveArgs) - return; - - var [aCloseWindow, aNewTab] = aTab._endRemoveArgs; - aTab._endRemoveArgs = null; - - if (this._windowIsClosing) { - aCloseWindow = false; - aNewTab = false; - } - - this._lastRelatedTab = null; - - // update the UI early for responsiveness - aTab.collapsed = true; - this.tabContainer._fillTrailingGap(); - this._blurTab(aTab); - - this._removingTabs.splice(this._removingTabs.indexOf(aTab), 1); - - if (aCloseWindow) { - this._windowIsClosing = true; - while (this._removingTabs.length) - this._endRemoveTab(this._removingTabs[0]); - } else if (!this._windowIsClosing) { - if (aNewTab) - focusAndSelectUrlBar(); - - // workaround for bug 345399 - this.tabContainer.mTabstrip._updateScrollButtonsDisabledState(); - } - - // We're going to remove the tab and the browser now. - // Clean up mTabFilters and mTabListeners now rather than in - // _beginRemoveTab, so that their size is always in sync with the - // number of tabs and browsers (the xbl destructor depends on this). - this.mTabFilters.splice(aTab._tPos, 1); - this.mTabListeners.splice(aTab._tPos, 1); - - var browser = this.getBrowserForTab(aTab); - this._outerWindowIDBrowserMap.delete(browser.outerWindowID); - - // Because of the way XBL works (fields just set JS - // properties on the element) and the code we have in place - // to preserve the JS objects for any elements that have - // JS properties set on them, the browser element won't be - // destroyed until the document goes away. So we force a - // cleanup ourselves. - // This has to happen before we remove the child so that the - // XBL implementation of nsIObserver still works. - browser.destroy(); - - if (browser == this.mCurrentBrowser) - this.mCurrentBrowser = null; - - var wasPinned = aTab.pinned; - - // Invalidate browsers cache, as the tab is removed from the - // tab container. - this._browsers = null; - - // Remove the tab ... - this.tabContainer.removeChild(aTab); - - // ... and fix up the _tPos properties immediately. - for (let i = aTab._tPos; i < this.tabs.length; i++) - this.tabs[i]._tPos = i; - - if (!this._windowIsClosing) { - if (wasPinned) - this.tabContainer._positionPinnedTabs(); - - // update tab close buttons state - this.tabContainer.adjustTabstrip(); - - setTimeout(function(tabs) { - tabs._lastTabClosedByMouse = false; - }, 0, this.tabContainer); - } - - // Pale Moon: if resizing immediately, select the tab immediately to the left - // instead of the right (if not leftmost) to prevent focus swap and - // "selected tab not under cursor" - // FIXME: Tabs must be sliding in from the left for this, or it'd unfocus - // in the other direction! Disabled for now. Is there an easier way? :hover? - // Is this even needed when resizing immediately?... - - //if (Services.prefs.getBoolPref("browser.tabs.resize_immediately")) { - // if (this.selectedTab._tPos > 1) { - // let newPos = this.selectedTab._tPos - 1; - // this.selectedTab = this.tabs[newPos]; - // } - //} - - // update tab positional properties and attributes - this.selectedTab._selected = true; - this.tabContainer._setPositionalAttributes(); - - // Removing the panel requires fixing up selectedPanel immediately - // (see below), which would be hindered by the potentially expensive - // browser removal. So we remove the browser and the panel in two - // steps. - - var panel = this.getNotificationBox(browser); - - // This will unload the document. An unload handler could remove - // dependant tabs, so it's important that the tabbrowser is now in - // a consistent state (tab removed, tab positions updated, etc.). - browser.parentNode.removeChild(browser); - - // Release the browser in case something is erroneously holding a - // reference to the tab after its removal. - this._tabForBrowser.delete(aTab.linkedBrowser); - aTab.linkedBrowser = null; - - // As the browser is removed, the removal of a dependent document can - // cause the whole window to close. So at this point, it's possible - // that the binding is destructed. - if (this.mTabBox) { - let selectedPanel = this.mTabBox.selectedPanel; - - this.mPanelContainer.removeChild(panel); - - // Under the hood, a selectedIndex attribute controls which panel - // is displayed. Removing a panel A which precedes the selected - // panel B makes selectedIndex point to the panel next to B. We - // need to explicitly preserve B as the selected panel. - this.mTabBox.selectedPanel = selectedPanel; - } - - if (aCloseWindow) - this._windowIsClosing = closeWindow(true, window.warnAboutClosingWindow); - ]]> - </body> - </method> - - <method name="_blurTab"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (!aTab.selected) - return; - - if (aTab.owner && - !aTab.owner.hidden && - !aTab.owner.closing && - Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")) { - this.selectedTab = aTab.owner; - return; - } - - // Switch to a visible tab unless there aren't any others remaining - let remainingTabs = this.visibleTabs; - let numTabs = remainingTabs.length; - if (numTabs == 0 || numTabs == 1 && remainingTabs[0] == aTab) { - remainingTabs = Array.filter(this.tabs, function(tab) { - return !tab.closing; - }, this); - } - - // Try to find a remaining tab that comes after the given tab - var tab = aTab; - do { - tab = tab.nextSibling; - } while (tab && remainingTabs.indexOf(tab) == -1); - - if (!tab) { - tab = aTab; - - do { - tab = tab.previousSibling; - } while (tab && remainingTabs.indexOf(tab) == -1); - } - - this.selectedTab = tab; - ]]> - </body> - </method> - - <method name="swapNewTabWithBrowser"> - <parameter name="aNewTab"/> - <parameter name="aBrowser"/> - <body> - <![CDATA[ - // The browser must be standalone. - if (aBrowser.getTabBrowser()) - throw Cr.NS_ERROR_INVALID_ARG; - - // The tab is definitely not loading. - aNewTab.removeAttribute("busy"); - if (aNewTab.selected) { - this.mIsBusy = false; - } - - this._swapBrowserDocShells(aNewTab, aBrowser); - - // Update the new tab's title. - this.setTabTitle(aNewTab); - - if (aNewTab.selected) { - this.updateCurrentBrowser(true); - } - ]]> - </body> - </method> - - <method name="swapBrowsersAndCloseOther"> - <parameter name="aOurTab"/> - <parameter name="aOtherTab"/> - <body> - <![CDATA[ - // Do not allow transfering a private tab to a non-private window - // and vice versa. - if (PrivateBrowsingUtils.isWindowPrivate(window) != - PrivateBrowsingUtils.isWindowPrivate(aOtherTab.ownerDocument.defaultView)) - return; - - // That's gBrowser for the other window, not the tab's browser! - var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser; - var isPending = aOtherTab.hasAttribute("pending"); - - // First, start teardown of the other browser. Make sure to not - // fire the beforeunload event in the process. Close the other - // window if this was its last tab. - if (!remoteBrowser._beginRemoveTab(aOtherTab, true, true)) - return; - - let ourBrowser = this.getBrowserForTab(aOurTab); - let otherBrowser = aOtherTab.linkedBrowser; - - // If the other tab is pending (i.e. has not been restored, yet) - // then do not switch docShells but retrieve the other tab's state - // and apply it to our tab. - if (isPending) { - let ss = Cc["@mozilla.org/browser/sessionstore;1"] - .getService(Ci.nsISessionStore) - ss.setTabState(aOurTab, ss.getTabState(aOtherTab)); - - // Make sure to unregister any open URIs. - this._swapRegisteredOpenURIs(ourBrowser, otherBrowser); - } else { - // Workarounds for bug 458697 - // Icon might have been set on DOMLinkAdded, don't override that. - if (!ourBrowser.mIconURL && otherBrowser.mIconURL) - this.setIcon(aOurTab, otherBrowser.mIconURL); - var isBusy = aOtherTab.hasAttribute("busy"); - if (isBusy) { - aOurTab.setAttribute("busy", "true"); - this._tabAttrModified(aOurTab); - if (aOurTab.selected) - this.mIsBusy = true; - } - - this._swapBrowserDocShells(aOurTab, otherBrowser); - } - - // Finish tearing down the tab that's going away. - remoteBrowser._endRemoveTab(aOtherTab); - - if (isBusy) - this.setTabTitleLoading(aOurTab); - else - this.setTabTitle(aOurTab); - - // If the tab was already selected (this happpens in the scenario - // of replaceTabWithWindow), notify onLocationChange, etc. - if (aOurTab.selected) - this.updateCurrentBrowser(true); - ]]> - </body> - </method> - - <method name="_swapBrowserDocShells"> - <parameter name="aOurTab"/> - <parameter name="aOtherBrowser"/> - <body> - <![CDATA[ - // Unhook our progress listener - let index = aOurTab._tPos; - const filter = this.mTabFilters[index]; - let tabListener = this.mTabListeners[index]; - let ourBrowser = this.getBrowserForTab(aOurTab); - ourBrowser.webProgress.removeProgressListener(filter); - filter.removeProgressListener(tabListener); - - // Make sure to unregister any open URIs. - this._swapRegisteredOpenURIs(ourBrowser, aOtherBrowser); - - // Unmap old outerWindowIDs. - this._outerWindowIDBrowserMap.delete(ourBrowser.outerWindowID); - let remoteBrowser = aOtherBrowser.ownerDocument.defaultView.gBrowser; - if (remoteBrowser) { - remoteBrowser._outerWindowIDBrowserMap.delete(aOtherBrowser.outerWindowID); - } - // Swap the docshells - ourBrowser.swapDocShells(aOtherBrowser); - - // Register new outerWindowIDs. - this._outerWindowIDBrowserMap.set(ourBrowser.outerWindowID, ourBrowser); - if (remoteBrowser) { - remoteBrowser._outerWindowIDBrowserMap.set(aOtherBrowser.outerWindowID, aOtherBrowser); - } - // Restore the progress listener - this.mTabListeners[index] = tabListener = - this.mTabProgressListener(aOurTab, ourBrowser, false); - - const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL; - filter.addProgressListener(tabListener, notifyAll); - ourBrowser.webProgress.addProgressListener(filter, notifyAll); - ]]> - </body> - </method> - - <method name="_swapRegisteredOpenURIs"> - <parameter name="aOurBrowser"/> - <parameter name="aOtherBrowser"/> - <body> - <![CDATA[ - // If the current URI is registered as open remove it from the list. - if (aOurBrowser.registeredOpenURI) { - this._placesAutocomplete.unregisterOpenPage(aOurBrowser.registeredOpenURI); - delete aOurBrowser.registeredOpenURI; - } - - // If the other/new URI is registered as open then copy it over. - if (aOtherBrowser.registeredOpenURI) { - aOurBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI; - delete aOtherBrowser.registeredOpenURI; - } - ]]> - </body> - </method> - - <method name="reloadAllTabs"> - <body> - <![CDATA[ - let tabs = this.visibleTabs; - let l = tabs.length; - for (var i = 0; i < l; i++) { - try { - this.getBrowserForTab(tabs[i]).reload(); - } catch (e) { - // ignore failure to reload so others will be reloaded - } - } - ]]> - </body> - </method> - - <method name="reloadTab"> - <parameter name="aTab"/> - <body> - <![CDATA[ - this.getBrowserForTab(aTab).reload(); - ]]> - </body> - </method> - - <method name="addProgressListener"> - <parameter name="aListener"/> - <body> - <![CDATA[ - if (arguments.length != 1) { - Components.utils.reportError("gBrowser.addProgressListener was " + - "called with a second argument, " + - "which is not supported. See bug " + - "608628."); - } - - this.mProgressListeners.push(aListener); - ]]> - </body> - </method> - - <method name="removeProgressListener"> - <parameter name="aListener"/> - <body> - <![CDATA[ - this.mProgressListeners = - this.mProgressListeners.filter(function (l) l != aListener); - ]]> - </body> - </method> - - <method name="addTabsProgressListener"> - <parameter name="aListener"/> - <body> - this.mTabsProgressListeners.push(aListener); - </body> - </method> - - <method name="removeTabsProgressListener"> - <parameter name="aListener"/> - <body> - <![CDATA[ - this.mTabsProgressListeners = - this.mTabsProgressListeners.filter(function (l) l != aListener); - ]]> - </body> - </method> - - <method name="getBrowserForTab"> - <parameter name="aTab"/> - <body> - <![CDATA[ - return aTab.linkedBrowser; - ]]> - </body> - </method> - - <method name="showOnlyTheseTabs"> - <parameter name="aTabs"/> - <body> - <![CDATA[ - Array.forEach(this.tabs, function(tab) { - if (aTabs.indexOf(tab) == -1) - this.hideTab(tab); - else - this.showTab(tab); - }, this); - - this.tabContainer._handleTabSelect(false); - ]]> - </body> - </method> - - <method name="showTab"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (aTab.hidden) { - aTab.removeAttribute("hidden"); - this._visibleTabs = null; // invalidate cache - - this.tabContainer.adjustTabstrip(); - - this.tabContainer._setPositionalAttributes(); - - let event = document.createEvent("Events"); - event.initEvent("TabShow", true, false); - aTab.dispatchEvent(event); - } - ]]> - </body> - </method> - - <method name="hideTab"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (!aTab.hidden && !aTab.pinned && !aTab.selected && - !aTab.closing) { - aTab.setAttribute("hidden", "true"); - this._visibleTabs = null; // invalidate cache - - this.tabContainer.adjustTabstrip(); - - this.tabContainer._setPositionalAttributes(); - - let event = document.createEvent("Events"); - event.initEvent("TabHide", true, false); - aTab.dispatchEvent(event); - } - ]]> - </body> - </method> - - <method name="selectTabAtIndex"> - <parameter name="aIndex"/> - <parameter name="aEvent"/> - <body> - <![CDATA[ - let tabs = this.visibleTabs; - - // count backwards for aIndex < 0 - if (aIndex < 0) - aIndex += tabs.length; - - if (aIndex >= 0 && aIndex < tabs.length) - this.selectedTab = tabs[aIndex]; - - if (aEvent) { - aEvent.preventDefault(); - aEvent.stopPropagation(); - } - ]]> - </body> - </method> - - <property name="selectedTab"> - <getter> - return this.mCurrentTab; - </getter> - <setter> - <![CDATA[ - if (gNavToolbox.collapsed) { - return this.mTabBox.selectedTab; - } - // Update the tab - this.mTabBox.selectedTab = val; - return val; - ]]> - </setter> - </property> - - <property name="selectedBrowser" - onget="return this.mCurrentBrowser;" - readonly="true"/> - - <property name="browsers" readonly="true"> - <getter> - <![CDATA[ - return this._browsers || - (this._browsers = Array.map(this.tabs, function (tab) tab.linkedBrowser)); - ]]> - </getter> - </property> - <field name="_browsers">null</field> - - <!-- Moves a tab to a new browser window, unless it's already the only tab - in the current window, in which case this will do nothing. --> - <method name="replaceTabWithWindow"> - <parameter name="aTab"/> - <parameter name="aOptions"/> - <body> - <![CDATA[ - if (this.tabs.length == 1) - return null; - - var options = "chrome,dialog=no,all"; - for (var name in aOptions) - options += "," + name + "=" + aOptions[name]; - - // tell a new window to take the "dropped" tab - return window.openDialog(getBrowserURL(), "_blank", options, aTab); - ]]> - </body> - </method> - - <method name="moveTabTo"> - <parameter name="aTab"/> - <parameter name="aIndex"/> - <body> - <![CDATA[ - var oldPosition = aTab._tPos; - if (oldPosition == aIndex) - return; - - // Don't allow mixing pinned and unpinned tabs. - if (aTab.pinned) - aIndex = Math.min(aIndex, this._numPinnedTabs - 1); - else - aIndex = Math.max(aIndex, this._numPinnedTabs); - if (oldPosition == aIndex) - return; - - this._lastRelatedTab = null; - - this.mTabFilters.splice(aIndex, 0, this.mTabFilters.splice(aTab._tPos, 1)[0]); - this.mTabListeners.splice(aIndex, 0, this.mTabListeners.splice(aTab._tPos, 1)[0]); - - let wasFocused = (document.activeElement == this.mCurrentTab); - - aIndex = aIndex < aTab._tPos ? aIndex: aIndex+1; - this.mCurrentTab._selected = false; - - // invalidate caches - this._browsers = null; - this._visibleTabs = null; - - // use .item() instead of [] because dragging to the end of the strip goes out of - // bounds: .item() returns null (so it acts like appendChild), but [] throws - this.tabContainer.insertBefore(aTab, this.tabs.item(aIndex)); - - for (let i = 0; i < this.tabs.length; i++) { - this.tabs[i]._tPos = i; - this.tabs[i]._selected = false; - } - this.mCurrentTab._selected = true; - - if (wasFocused) - this.mCurrentTab.focus(); - - this.tabContainer._handleTabSelect(false); - - if (aTab.pinned) - this.tabContainer._positionPinnedTabs(); - - this.tabContainer._setPositionalAttributes(); - - var evt = document.createEvent("UIEvents"); - evt.initUIEvent("TabMove", true, false, window, oldPosition); - aTab.dispatchEvent(evt); - ]]> - </body> - </method> - - <method name="moveTabForward"> - <body> - <![CDATA[ - let nextTab = this.mCurrentTab.nextSibling; - while (nextTab && nextTab.hidden) - nextTab = nextTab.nextSibling; - - if (nextTab) - this.moveTabTo(this.mCurrentTab, nextTab._tPos); - else if (this.arrowKeysShouldWrap) - this.moveTabToStart(); - ]]> - </body> - </method> - - <method name="moveTabBackward"> - <body> - <![CDATA[ - let previousTab = this.mCurrentTab.previousSibling; - while (previousTab && previousTab.hidden) - previousTab = previousTab.previousSibling; - - if (previousTab) - this.moveTabTo(this.mCurrentTab, previousTab._tPos); - else if (this.arrowKeysShouldWrap) - this.moveTabToEnd(); - ]]> - </body> - </method> - - <method name="moveTabToStart"> - <body> - <![CDATA[ - var tabPos = this.mCurrentTab._tPos; - if (tabPos > 0) - this.moveTabTo(this.mCurrentTab, 0); - ]]> - </body> - </method> - - <method name="moveTabToEnd"> - <body> - <![CDATA[ - var tabPos = this.mCurrentTab._tPos; - if (tabPos < this.browsers.length - 1) - this.moveTabTo(this.mCurrentTab, this.browsers.length - 1); - ]]> - </body> - </method> - - <method name="moveTabOver"> - <parameter name="aEvent"/> - <body> - <![CDATA[ - var direction = window.getComputedStyle(this.parentNode, null).direction; - if ((direction == "ltr" && aEvent.keyCode == KeyEvent.DOM_VK_RIGHT) || - (direction == "rtl" && aEvent.keyCode == KeyEvent.DOM_VK_LEFT)) - this.moveTabForward(); - else - this.moveTabBackward(); - ]]> - </body> - </method> - - <method name="duplicateTab"> - <parameter name="aTab"/><!-- can be from a different window as well --> - <body> - <![CDATA[ - return Cc["@mozilla.org/browser/sessionstore;1"] - .getService(Ci.nsISessionStore) - .duplicateTab(window, aTab); - ]]> - </body> - </method> - - <!-- BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT - MAKE SURE TO ADD IT HERE AS WELL. --> - <property name="canGoBack" - onget="return this.mCurrentBrowser.canGoBack;" - readonly="true"/> - - <property name="canGoForward" - onget="return this.mCurrentBrowser.canGoForward;" - readonly="true"/> - - <method name="goBack"> - <body> - <![CDATA[ - return this.mCurrentBrowser.goBack(); - ]]> - </body> - </method> - - <method name="goForward"> - <body> - <![CDATA[ - return this.mCurrentBrowser.goForward(); - ]]> - </body> - </method> - - <method name="reload"> - <body> - <![CDATA[ - return this.mCurrentBrowser.reload(); - ]]> - </body> - </method> - - <method name="reloadWithFlags"> - <parameter name="aFlags"/> - <body> - <![CDATA[ - return this.mCurrentBrowser.reloadWithFlags(aFlags); - ]]> - </body> - </method> - - <method name="stop"> - <body> - <![CDATA[ - return this.mCurrentBrowser.stop(); - ]]> - </body> - </method> - - <!-- throws exception for unknown schemes --> - <method name="loadURI"> - <parameter name="aURI"/> - <parameter name="aReferrerURI"/> - <parameter name="aCharset"/> - <body> - <![CDATA[ - return this.mCurrentBrowser.loadURI(aURI, aReferrerURI, aCharset); - ]]> - </body> - </method> - - <!-- throws exception for unknown schemes --> - <method name="loadURIWithFlags"> - <parameter name="aURI"/> - <parameter name="aFlags"/> - <parameter name="aReferrerURI"/> - <parameter name="aCharset"/> - <parameter name="aPostData"/> - <body> - <![CDATA[ - return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData); - ]]> - </body> - </method> - - <method name="goHome"> - <body> - <![CDATA[ - return this.mCurrentBrowser.goHome(); - ]]> - </body> - </method> - - <property name="homePage"> - <getter> - <![CDATA[ - return this.mCurrentBrowser.homePage; - ]]> - </getter> - <setter> - <![CDATA[ - this.mCurrentBrowser.homePage = val; - return val; - ]]> - </setter> - </property> - - <method name="gotoIndex"> - <parameter name="aIndex"/> - <body> - <![CDATA[ - return this.mCurrentBrowser.gotoIndex(aIndex); - ]]> - </body> - </method> - - <method name="attachFormFill"> - <body><![CDATA[ - for (var i = 0; i < this.mPanelContainer.childNodes.length; ++i) { - var cb = this.getBrowserAtIndex(i); - cb.attachFormFill(); - } - ]]></body> - </method> - - <method name="detachFormFill"> - <body><![CDATA[ - for (var i = 0; i < this.mPanelContainer.childNodes.length; ++i) { - var cb = this.getBrowserAtIndex(i); - cb.detachFormFill(); - } - ]]></body> - </method> - - <property name="currentURI" - onget="return this.mCurrentBrowser.currentURI;" - readonly="true"/> - - <field name="_fastFind">null</field> - <property name="fastFind" - readonly="true"> - <getter> - <![CDATA[ - if (!this._fastFind) { - this._fastFind = Components.classes["@mozilla.org/typeaheadfind;1"] - .createInstance(Components.interfaces.nsITypeAheadFind); - this._fastFind.init(this.docShell); - } - return this._fastFind; - ]]> - </getter> - </property> - - <field name="_lastSearchString">null</field> - <field name="_lastSearchHighlight">false</field> - - <field name="finder"><![CDATA[ - ({ - mTabBrowser: this, - mListeners: new Set(), - get finder() { - return this.mTabBrowser.mCurrentBrowser.finder; - }, - addResultListener: function(aListener) { - this.mListeners.add(aListener); - this.finder.addResultListener(aListener); - }, - removeResultListener: function(aListener) { - this.mListeners.delete(aListener); - this.finder.removeResultListener(aListener); - }, - get searchString() { - return this.finder.searchString; - }, - get clipboardSearchString() { - return this.finder.clipboardSearchString; - }, - set clipboardSearchString(val) { - return this.finder.clipboardSearchString = val; - }, - set caseSensitive(val) { - return this.finder.caseSensitive = val; - }, - fastFind: function(aSearchString, aLinksOnly, aDrawOutline) { - this.finder.fastFind(aSearchString, aLinksOnly, aDrawOutline); - }, - findAgain: function(aFindBackwards, aLinksOnly, aDrawOutline) { - this.finder.findAgain(aFindBackwards, aLinksOnly, aDrawOutline); - }, - setSearchStringToSelection: function() { - return this.finder.setSearchStringToSelection(); - }, - highlight: function(aHighlight, aWord) { - this.finder.highlight(aHighlight, aWord); - }, - getInitialSelection: function() { - this.finder.getInitialSelection(); - }, - enableSelection: function() { - this.finder.enableSelection(); - }, - removeSelection: function() { - this.finder.removeSelection(); - }, - focusContent: function() { - this.finder.focusContent(); - }, - keyPress: function(aEvent) { - this.finder.keyPress(aEvent); - }, - requestMatchesCount: function(aWord, aMatchLimit, aLinksOnly) { - this.finder.requestMatchesCount(aWord, aMatchLimit, aLinksOnly); - } - }) - ]]></field> - - <property name="docShell" - onget="return this.mCurrentBrowser.docShell" - readonly="true"/> - - <property name="webNavigation" - onget="return this.mCurrentBrowser.webNavigation" - readonly="true"/> - - <property name="webBrowserFind" - readonly="true" - onget="return this.mCurrentBrowser.webBrowserFind"/> - - <property name="webProgress" - readonly="true" - onget="return this.mCurrentBrowser.webProgress"/> - - <property name="contentWindow" - readonly="true" - onget="return this.mCurrentBrowser.contentWindow"/> - - <property name="sessionHistory" - onget="return this.mCurrentBrowser.sessionHistory;" - readonly="true"/> - - <property name="markupDocumentViewer" - onget="return this.mCurrentBrowser.markupDocumentViewer;" - readonly="true"/> - - <property name="contentViewerEdit" - onget="return this.mCurrentBrowser.contentViewerEdit;" - readonly="true"/> - - <property name="contentViewerFile" - onget="return this.mCurrentBrowser.contentViewerFile;" - readonly="true"/> - - <property name="contentDocument" - onget="return this.mCurrentBrowser.contentDocument;" - readonly="true"/> - - <property name="contentTitle" - onget="return this.mCurrentBrowser.contentTitle;" - readonly="true"/> - - <property name="contentPrincipal" - onget="return this.mCurrentBrowser.contentPrincipal;" - readonly="true"/> - - <property name="securityUI" - onget="return this.mCurrentBrowser.securityUI;" - readonly="true"/> - - <property name="fullZoom" - onget="return this.mCurrentBrowser.fullZoom;" - onset="this.mCurrentBrowser.fullZoom = val;"/> - - <property name="textZoom" - onget="return this.mCurrentBrowser.textZoom;" - onset="this.mCurrentBrowser.textZoom = val;"/> - - <property name="isSyntheticDocument" - onget="return this.mCurrentBrowser.isSyntheticDocument;" - readonly="true"/> - - <method name="_handleKeyEvent"> - <parameter name="aEvent"/> - <body><![CDATA[ - if (!aEvent.isTrusted) { - // Don't let untrusted events mess with tabs. - return; - } - - if (aEvent.altKey) - return; - - if (aEvent.ctrlKey && aEvent.shiftKey && !aEvent.metaKey) { - switch (aEvent.keyCode) { - case aEvent.DOM_VK_PAGE_UP: - this.moveTabBackward(); - aEvent.stopPropagation(); - aEvent.preventDefault(); - return; - case aEvent.DOM_VK_PAGE_DOWN: - this.moveTabForward(); - aEvent.stopPropagation(); - aEvent.preventDefault(); - return; - } - } - - // We need to take care of FAYT-watching as long as the findbar - // isn't initialized. The checks on aEvent are copied from - // _shouldFastFind (see findbar.xml). - if (!gFindBarInitialized && - !(aEvent.ctrlKey || aEvent.metaKey) && - !aEvent.defaultPrevented) { - let charCode = aEvent.charCode; - if (charCode) { - let char = String.fromCharCode(charCode); - if (char == "'" || char == "/" || - Services.prefs.getBoolPref("accessibility.typeaheadfind")) { - gFindBar._onBrowserKeypress(aEvent); - return; - } - } - } - -#ifdef XP_MACOSX - if (!aEvent.metaKey) - return; - - var offset = 1; - switch (aEvent.charCode) { - case '}'.charCodeAt(0): - offset = -1; - case '{'.charCodeAt(0): - if (window.getComputedStyle(this, null).direction == "ltr") - offset *= -1; - this.tabContainer.advanceSelectedTab(offset, true); - aEvent.stopPropagation(); - aEvent.preventDefault(); - } -#else - if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey && - aEvent.keyCode == KeyEvent.DOM_VK_F4 && - !this.mCurrentTab.pinned) { - this.removeCurrentTab({animate: true}); - aEvent.stopPropagation(); - aEvent.preventDefault(); - } -#endif - ]]></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;"/> - - <method name="createTooltip"> - <parameter name="event"/> - <body><![CDATA[ - event.stopPropagation(); - var tab = document.tooltipNode; - if (tab.localName != "tab") { - event.preventDefault(); - return; - } - event.target.setAttribute("label", tab.mOverCloseButton ? - tab.getAttribute("closetabtext") : - tab.getAttribute("label")); - ]]></body> - </method> - - <method name="handleEvent"> - <parameter name="aEvent"/> - <body><![CDATA[ - switch (aEvent.type) { - case "keypress": - this._handleKeyEvent(aEvent); - break; - case "sizemodechange": - if (aEvent.target == window) { - this.mCurrentBrowser.docShellIsActive = - (window.windowState != window.STATE_MINIMIZED); - } - break; - } - ]]></body> - </method> - - <method name="receiveMessage"> - <parameter name="aMessage"/> - <body><![CDATA[ - let json = aMessage.json; - let browser = aMessage.target; - - switch (aMessage.name) { - case "DOMTitleChanged": { - let tab = this.getTabForBrowser(browser); - if (!tab) - return; - let titleChanged = this.setTabTitle(tab); - if (titleChanged && !tab.selected && !tab.hasAttribute("busy")) - tab.setAttribute("titlechanged", "true"); - break; - } - case "DOMWebNotificationClicked": { - let tab = this.getTabForBrowser(browser); - if (!tab) - return; - this.selectedTab = tab; - window.focus(); - break; - } - } - ]]></body> - </method> - - <constructor> - <![CDATA[ - let browserStack = document.getAnonymousElementByAttribute(this, "anonid", "browserStack"); - this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser"); - if (Services.prefs.getBoolPref("browser.tabs.remote")) { - browserStack.removeChild(this.mCurrentBrowser); - this.mCurrentBrowser.setAttribute("remote", true); - browserStack.appendChild(this.mCurrentBrowser); - } - - this.mCurrentTab = this.tabContainer.firstChild; - document.addEventListener("keypress", this, false); - window.addEventListener("sizemodechange", this, false); - - var uniqueId = "panel" + Date.now(); - this.mPanelContainer.childNodes[0].id = uniqueId; - this.mCurrentTab.linkedPanel = uniqueId; - this.mCurrentTab._tPos = 0; - this.mCurrentTab._fullyOpen = true; - this.mCurrentTab.linkedBrowser = this.mCurrentBrowser; - this._tabForBrowser.set(this.mCurrentBrowser, this.mCurrentTab); - - // set up the shared autoscroll popup - this._autoScrollPopup = this.mCurrentBrowser._createAutoScrollPopup(); - this._autoScrollPopup.id = "autoscroller"; - this.appendChild(this._autoScrollPopup); - this.mCurrentBrowser.setAttribute("autoscrollpopup", this._autoScrollPopup.id); - this.mCurrentBrowser.droppedLinkHandler = handleDroppedLink; - this.updateWindowResizers(); - - // Hook up the event listeners to the first browser - var tabListener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, true); - const nsIWebProgress = Components.interfaces.nsIWebProgress; - const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"] - .createInstance(nsIWebProgress); - filter.addProgressListener(tabListener, nsIWebProgress.NOTIFY_ALL); - this.mTabListeners[0] = tabListener; - this.mTabFilters[0] = filter; - - try { - // We assume this can only fail because mCurrentBrowser's docShell - // hasn't been created, yet. This may be caused by code accessing - // gBrowser before the window has finished loading. - this._addProgressListenerForInitialTab(); - } catch (e) { - // The binding was constructed too early, wait until the initial - // tab's document is ready, then add the progress listener. - this._waitForInitialContentDocument(); - } - - this.style.backgroundColor = - Services.prefs.getBoolPref("browser.display.use_system_colors") ? - "-moz-default-background-color" : - Services.prefs.getCharPref("browser.display.background_color"); - - if (Services.prefs.getBoolPref("browser.tabs.remote")) { - messageManager.addMessageListener("DOMTitleChanged", this); - } else { - this._outerWindowIDBrowserMap.set(this.mCurrentBrowser.outerWindowID, - this.mCurrentBrowser); - } - messageManager.addMessageListener("DOMWebNotificationClicked", this); - ]]> - </constructor> - - <method name="_addProgressListenerForInitialTab"> - <body><![CDATA[ - this.webProgress.addProgressListener(this.mTabFilters[0], Ci.nsIWebProgress.NOTIFY_ALL); - ]]></body> - </method> - - <method name="_waitForInitialContentDocument"> - <body><![CDATA[ - let obs = (subject, topic) => { - if (this.browsers[0].contentWindow == subject) { - Services.obs.removeObserver(obs, topic); - this._addProgressListenerForInitialTab(); - } - }; - - // We use content-document-global-created as an approximation for - // "docShell is initialized". We can do this because in the - // mTabProgressListener we care most about the STATE_STOP notification - // that will reset mBlank. That means it's important to at least add - // the progress listener before the initial about:blank load stops - // if we can't do it before the load starts. - Services.obs.addObserver(obs, "content-document-global-created", false); - ]]></body> - </method> - - <destructor> - <![CDATA[ - for (var i = 0; i < this.mTabListeners.length; ++i) { - let browser = this.getBrowserAtIndex(i); - if (browser.registeredOpenURI) { - this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI); - delete browser.registeredOpenURI; - } - browser.webProgress.removeProgressListener(this.mTabFilters[i]); - this.mTabFilters[i].removeProgressListener(this.mTabListeners[i]); - this.mTabFilters[i] = null; - this.mTabListeners[i].destroy(); - this.mTabListeners[i] = null; - } - document.removeEventListener("keypress", this, false); - window.removeEventListener("sizemodechange", this, false); - - if (Services.prefs.getBoolPref("browser.tabs.remote")) - messageManager.removeMessageListener("DOMTitleChanged", this); - ]]> - </destructor> - - <!-- Deprecated stuff, implemented for backwards compatibility. --> - <method name="enterTabbedMode"> - <body> - Application.console.log("enterTabbedMode is an obsolete method and " + - "will be removed in a future release."); - </body> - </method> - <field name="mTabbedMode" readonly="true">true</field> - <method name="setStripVisibilityTo"> - <parameter name="aShow"/> - <body> - this.tabContainer.visible = aShow; - </body> - </method> - <method name="getStripVisibility"> - <body> - return this.tabContainer.visible; - </body> - </method> - <property name="mContextTab" readonly="true" - onget="return TabContextMenu.contextTab;"/> - <property name="mPrefs" readonly="true" - onget="return Services.prefs;"/> - <property name="mTabContainer" readonly="true" - onget="return this.tabContainer;"/> - <property name="mTabs" readonly="true" - onget="return this.tabs;"/> - <!-- - - Compatibility hack: several extensions depend on this property to - - access the tab context menu or tab container, so keep that working for - - now. Ideally we can remove this once extensions are using - - tabbrowser.tabContextMenu and tabbrowser.tabContainer directly. - --> - <property name="mStrip" readonly="true"> - <getter> - <![CDATA[ - return ({ - self: this, - childNodes: [null, this.tabContextMenu, this.tabContainer], - firstChild: { nextSibling: this.tabContextMenu }, - getElementsByAttribute: function (attr, attrValue) { - if (attr == "anonid" && attrValue == "tabContextMenu") - return [this.self.tabContextMenu]; - return []; - }, - // Also support adding event listeners (forward to the tab container) - addEventListener: function (a,b,c) { this.self.tabContainer.addEventListener(a,b,c); }, - removeEventListener: function (a,b,c) { this.self.tabContainer.removeEventListener(a,b,c); } - }); - ]]> - </getter> - </property> - </implementation> - - <handlers> - <handler event="DOMWindowClose" phase="capturing"> - <![CDATA[ - if (!event.isTrusted) - return; - - if (this.tabs.length == 1) - return; - - var tab = this._getTabForContentWindow(event.target); - if (tab) { - this.removeTab(tab); - event.preventDefault(); - } - ]]> - </handler> - <handler event="DOMWillOpenModalDialog" phase="capturing"> - <![CDATA[ - if (!event.isTrusted) - return; - - // We're about to open a modal dialog, make sure the opening - // tab is brought to the front. - this.selectedTab = this._getTabForContentWindow(event.target.top); - ]]> - </handler> - <handler event="DOMTitleChanged"> - <![CDATA[ - if (!event.isTrusted) - return; - - var contentWin = event.target.defaultView; - if (contentWin != contentWin.top) - return; - - var tab = this._getTabForContentWindow(contentWin); - if (!tab) { - return; - } - - var titleChanged = this.setTabTitle(tab); - if (titleChanged && !tab.selected && !tab.hasAttribute("busy")) - tab.setAttribute("titlechanged", "true"); - ]]> - </handler> - </handlers> - </binding> - - <binding id="tabbrowser-tabbox" - extends="chrome://global/content/bindings/tabbox.xml#tabbox"> - <implementation> - <property name="tabs" readonly="true" - onget="return document.getBindingParent(this).tabContainer;"/> - </implementation> - </binding> - - <binding id="tabbrowser-arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox-clicktoscroll"> - <implementation> - <!-- Override scrollbox.xml method, since our scrollbox's children are - inherited from the binding parent --> - <method name="_getScrollableElements"> - <body><![CDATA[ - return Array.filter(document.getBindingParent(this).childNodes, - this._canScrollToElement, this); - ]]></body> - </method> - <method name="_canScrollToElement"> - <parameter name="tab"/> - <body><![CDATA[ - return !tab.pinned && !tab.hidden; - ]]></body> - </method> - </implementation> - - <handlers> - <handler event="underflow" phase="capturing"><![CDATA[ - if (event.detail == 0) - return; // Ignore vertical events - - var tabs = document.getBindingParent(this); - tabs.removeAttribute("overflow"); - - if (tabs._lastTabClosedByMouse) - tabs._expandSpacerBy(this._scrollButtonDown.clientWidth); - - tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab, - tabs.tabbrowser); - - tabs._positionPinnedTabs(); - ]]></handler> - <handler event="overflow"><![CDATA[ - if (event.detail == 0) - return; // Ignore vertical events - - var tabs = document.getBindingParent(this); - tabs.setAttribute("overflow", "true"); - tabs._positionPinnedTabs(); - tabs._handleTabSelect(false); - ]]></handler> - </handlers> - </binding> - - <binding id="tabbrowser-tabs" - extends="chrome://global/content/bindings/tabbox.xml#tabs"> - <resources> - <stylesheet src="chrome://browser/content/tabbrowser.css"/> - </resources> - - <content> - <xul:hbox align="end"> - <xul:image class="tab-drop-indicator" anonid="tab-drop-indicator" collapsed="true"/> - </xul:hbox> - <xul:arrowscrollbox anonid="arrowscrollbox" orient="horizontal" flex="1" - style="min-width: 1px;" -#ifndef XP_MACOSX - clicktoscroll="true" -#endif - class="tabbrowser-arrowscrollbox"> -# This is a hack to circumvent bug 472020, otherwise the tabs show up on the -# right of the newtab button. - <children includes="tab"/> -# This is to ensure anything extensions put here will go before the newtab -# button, necessary due to the previous hack. - <children/> - <xul:toolbarbutton class="tabs-newtab-button" - command="cmd_newNavigatorTab" - onclick="checkForMiddleClick(this, event);" - onmouseover="document.getBindingParent(this)._enterNewTab();" - onmouseout="document.getBindingParent(this)._leaveNewTab();" - tooltiptext="&newTabButton.tooltip;"/> - <xul:spacer class="closing-tabs-spacer" anonid="closing-tabs-spacer" - style="width: 0;"/> - </xul:arrowscrollbox> - </content> - - <implementation implements="nsIDOMEventListener"> - <constructor> - <![CDATA[ - this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth"); - this.mCloseButtons = Services.prefs.getIntPref("browser.tabs.closeButtons"); - this._closeWindowWithLastTab = Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab"); - - var tab = this.firstChild; - tab.setAttribute("label", - this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle")); - tab.setAttribute("crop", "end"); - tab.setAttribute("onerror", "this.removeAttribute('image');"); - this.adjustTabstrip(); - - Services.prefs.addObserver("browser.tabs.", this._prefObserver, false); - window.addEventListener("resize", this, false); - window.addEventListener("load", this, false); - - try { - this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled"); - } catch (ex) { - this._tabAnimationLoggingEnabled = false; - } - this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled"); - ]]> - </constructor> - - <destructor> - <![CDATA[ - Services.prefs.removeObserver("browser.tabs.", this._prefObserver); - ]]> - </destructor> - - <field name="tabbrowser" readonly="true"> - document.getElementById(this.getAttribute("tabbrowser")); - </field> - - <field name="tabbox" readonly="true"> - this.tabbrowser.mTabBox; - </field> - - <field name="contextMenu" readonly="true"> - document.getElementById("tabContextMenu"); - </field> - - <field name="mTabstripWidth">0</field> - - <field name="mTabstrip"> - document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox"); - </field> - - <field name="_firstTab">null</field> - <field name="_lastTab">null</field> - <field name="_afterSelectedTab">null</field> - <field name="_beforeHoveredTab">null</field> - <field name="_afterHoveredTab">null</field> - - <method name="_setPositionalAttributes"> - <body><![CDATA[ - let visibleTabs = this.tabbrowser.visibleTabs; - - if (!visibleTabs.length) - return; - - let selectedIndex = visibleTabs.indexOf(this.selectedItem); - - let lastVisible = visibleTabs.length - 1; - - if (this._afterSelectedTab) - this._afterSelectedTab.removeAttribute("afterselected-visible"); - if (this.selectedItem.closing || selectedIndex == lastVisible) { - this._afterSelectedTab = null; - } else { - this._afterSelectedTab = visibleTabs[selectedIndex + 1]; - this._afterSelectedTab.setAttribute("afterselected-visible", - "true"); - } - - if (this._firstTab) - this._firstTab.removeAttribute("first-visible-tab"); - this._firstTab = visibleTabs[0]; - this._firstTab.setAttribute("first-visible-tab", "true"); - if (this._lastTab) - this._lastTab.removeAttribute("last-visible-tab"); - this._lastTab = visibleTabs[lastVisible]; - this._lastTab.setAttribute("last-visible-tab", "true"); - ]]></body> - </method> - - <field name="_prefObserver"><![CDATA[({ - tabContainer: this, - - observe: function (subject, topic, data) { - switch (data) { - case "browser.tabs.closeButtons": - this.tabContainer.mCloseButtons = Services.prefs.getIntPref(data); - this.tabContainer.adjustTabstrip(); - break; - case "browser.tabs.autoHide": - this.tabContainer.updateVisibility(); - break; - case "browser.tabs.closeWindowWithLastTab": - this.tabContainer._closeWindowWithLastTab = Services.prefs.getBoolPref(data); - this.tabContainer.adjustTabstrip(); - break; - } - } - });]]></field> - <field name="_blockDblClick">false</field> - - <field name="_tabDropIndicator"> - document.getAnonymousElementByAttribute(this, "anonid", "tab-drop-indicator"); - </field> - - <field name="_dragOverDelay">350</field> - <field name="_dragTime">0</field> - - <field name="_container" readonly="true"><![CDATA[ - this.parentNode && this.parentNode.localName == "toolbar" ? this.parentNode : this; - ]]></field> - - <field name="_propagatedVisibilityOnce">false</field> - - <property name="visible" - onget="return !this._container.collapsed;"> - <setter><![CDATA[ - if (val == this.visible && - this._propagatedVisibilityOnce) - return val; - - this._container.collapsed = !val; - - this._propagateVisibility(); - this._propagatedVisibilityOnce = true; - - return val; - ]]></setter> - </property> - - <method name="_enterNewTab"> - <body><![CDATA[ - let visibleTabs = this.tabbrowser.visibleTabs; - let candidate = visibleTabs[visibleTabs.length - 1]; - if (!candidate.selected) { - this._beforeHoveredTab = candidate; - candidate.setAttribute("beforehovered", "true"); - } - ]]></body> - </method> - - <method name="_leaveNewTab"> - <body><![CDATA[ - if (this._beforeHoveredTab) { - this._beforeHoveredTab.removeAttribute("beforehovered"); - this._beforeHoveredTab = null; - } - ]]></body> - </method> - - <method name="_propagateVisibility"> - <body><![CDATA[ - let visible = this.visible; - - document.getElementById("menu_closeWindow").hidden = !visible; - document.getElementById("menu_close").setAttribute("label", - this.tabbrowser.mStringBundle.getString(visible ? "tabs.closeTab" : "tabs.close")); - - goSetCommandEnabled("cmd_ToggleTabsOnTop", visible); - - TabsOnTop.syncUI(); - - TabsInTitlebar.allowedBy("tabs-visible", visible); - ]]></body> - </method> - - <method name="updateVisibility"> - <body><![CDATA[ - if (this.childNodes.length - this.tabbrowser._removingTabs.length == 1) - this.visible = window.toolbar.visible && - !Services.prefs.getBoolPref("browser.tabs.autoHide"); - else - this.visible = true; - ]]></body> - </method> - - <method name="adjustTabstrip"> - <body><![CDATA[ - let numTabs = this.childNodes.length - - this.tabbrowser._removingTabs.length; - // modes for tabstrip - // 0 - button on active tab only - // 1 - close buttons on all tabs, if available space allows - // 2 - no close buttons at all - // 3 - close button at the end of the tabstrip - switch (this.mCloseButtons) { - case 0: - // If we decide we want to hide the close tab button on the last tab - // when closing the window with the last tab, then we should check - // if (numTabs == 1 && this._closeWindowWithLastTab) here and set - // this.setAttribute("closebuttons", "hidden") appropriately - this.setAttribute("closebuttons", "activetab"); - break; - case 1: - if (numTabs == 1) { - // See remark about potentially hiding the close tab button, above. - this.setAttribute("closebuttons", "alltabs"); - } else if (numTabs == 2) { - // This is an optimization to avoid layout flushes by calling - // getBoundingClientRect() when we just opened a second tab. In - // this case it's highly unlikely that the tab width is smaller - // than mTabClipWidth and the tab close button obscures too much - // of the tab's label. In the edge case of the window being too - // narrow (or if tabClipWidth has been set to a way higher value), - // we'll correct the 'closebuttons' attribute after the tabopen - // animation has finished. - this.setAttribute("closebuttons", "alltabs"); - } else { - let tab = this.tabbrowser.visibleTabs[this.tabbrowser._numPinnedTabs]; - if (tab && tab.getBoundingClientRect().width > this.mTabClipWidth) - this.setAttribute("closebuttons", "alltabs"); - else - this.setAttribute("closebuttons", "activetab"); - } - break; - case 2: - case 3: - this.setAttribute("closebuttons", "never"); - break; - } - var tabstripClosebutton = document.getElementById("tabs-closebutton"); - if (tabstripClosebutton && tabstripClosebutton.parentNode == this._container) - tabstripClosebutton.collapsed = this.mCloseButtons != 3; - ]]></body> - </method> - - <method name="_handleTabSelect"> - <parameter name="aSmoothScroll"/> - <body><![CDATA[ - if (this.getAttribute("overflow") == "true") - this.mTabstrip.ensureElementIsVisible(this.selectedItem, aSmoothScroll); - ]]></body> - </method> - - <method name="_fillTrailingGap"> - <body><![CDATA[ - try { - // if we're at the right side (and not the logical end, - // which is why this works for both LTR and RTL) - // of the tabstrip, we need to ensure that we stay - // completely scrolled to the right side - var tabStrip = this.mTabstrip; - if (tabStrip.scrollPosition + tabStrip.scrollClientSize > - tabStrip.scrollSize) - tabStrip.scrollByPixels(-1); - } catch (e) {} - ]]></body> - </method> - - <field name="_closingTabsSpacer"> - document.getAnonymousElementByAttribute(this, "anonid", "closing-tabs-spacer"); - </field> - - <field name="_tabDefaultMaxWidth">NaN</field> - <field name="_lastTabClosedByMouse">false</field> - <field name="_hasTabTempMaxWidth">false</field> - - <!-- Try to keep the active tab's close button under the mouse cursor --> - <method name="_lockTabSizing"> - <parameter name="aTab"/> - <body><![CDATA[ - var tabs = this.tabbrowser.visibleTabs; - if (!tabs.length) - return; - - var isEndTab = (aTab._tPos > tabs[tabs.length-1]._tPos); - var tabWidth = aTab.getBoundingClientRect().width; - - if (!this._tabDefaultMaxWidth) - this._tabDefaultMaxWidth = - parseFloat(window.getComputedStyle(aTab).maxWidth); - this._lastTabClosedByMouse = true; - - if (this.getAttribute("overflow") == "true") { -#ifdef XP_WIN - // Don't need to do anything if we're in overflow mode and we're closing - // the last tab. - if (isEndTab) -#else - // Don't need to do anything if we're in overflow mode and aren't scrolled - // all the way to the right, or if we're closing the last tab. - if (isEndTab || !this.mTabstrip._scrollButtonDown.disabled) -#endif - return; - - // If the tab has an owner that will become the active tab, the owner will - // be to the left of it, so we actually want the left tab to slide over. - // This can't be done as easily in non-overflow mode, so we don't bother. - if (aTab.owner) - return; - - // Resize immediately if preffed - // XXX: we may want to make this a three-state pref to disable this early - // exit if people prefer a mix of behavior (don't resize in overflow, - // but resize if not overflowing) - if (Services.prefs.getBoolPref("browser.tabs.resize_immediately")) - return; - - this._expandSpacerBy(tabWidth); - } else { // non-overflow mode - // Locking is neither in effect nor needed, so let tabs expand normally. - if (isEndTab && !this._hasTabTempMaxWidth) - return; - - // Resize immediately if preffed - // XXX: we may want to make this a three-state pref to disable this early - // exit if people prefer a mix of behavior (don't resize in overflow, - // but resize if not overflowing) - if (Services.prefs.getBoolPref("browser.tabs.resize_immediately")) - return; - - let numPinned = this.tabbrowser._numPinnedTabs; - // Force tabs to stay the same width, unless we're closing the last tab, - // which case we need to let them expand just enough so that the overall - // tabbar width is the same. - if (isEndTab) { - let numNormalTabs = tabs.length - numPinned; - tabWidth = tabWidth * (numNormalTabs + 1) / numNormalTabs; - if (tabWidth > this._tabDefaultMaxWidth) - tabWidth = this._tabDefaultMaxWidth; - } - tabWidth += "px"; - for (let i = numPinned; i < tabs.length; i++) { - let tab = tabs[i]; - tab.style.setProperty("max-width", tabWidth, "important"); - if (!isEndTab) { // keep tabs the same width - tab.style.transition = "none"; - tab.clientTop; // flush styles to skip animation; see bug 649247 - tab.style.transition = ""; - } - } - this._hasTabTempMaxWidth = true; - this.tabbrowser.addEventListener("mousemove", this, false); - window.addEventListener("mouseout", this, false); - } - ]]></body> - </method> - - <method name="_expandSpacerBy"> - <parameter name="pixels"/> - <body><![CDATA[ - let spacer = this._closingTabsSpacer; - spacer.style.width = parseFloat(spacer.style.width) + pixels + "px"; - this.setAttribute("using-closing-tabs-spacer", "true"); - this.tabbrowser.addEventListener("mousemove", this, false); - window.addEventListener("mouseout", this, false); - ]]></body> - </method> - - <method name="_unlockTabSizing"> - <body><![CDATA[ - this.tabbrowser.removeEventListener("mousemove", this, false); - window.removeEventListener("mouseout", this, false); - - if (this._hasTabTempMaxWidth) { - this._hasTabTempMaxWidth = false; - let tabs = this.tabbrowser.visibleTabs; - for (let i = 0; i < tabs.length; i++) - tabs[i].style.maxWidth = ""; - } - - if (this.hasAttribute("using-closing-tabs-spacer")) { - this.removeAttribute("using-closing-tabs-spacer"); - this._closingTabsSpacer.style.width = 0; - } - ]]></body> - </method> - - <field name="_lastNumPinned">0</field> - <method name="_positionPinnedTabs"> - <body><![CDATA[ - var numPinned = this.tabbrowser._numPinnedTabs; - var doPosition = this.getAttribute("overflow") == "true" && - numPinned > 0; - - if (doPosition) { - this.setAttribute("positionpinnedtabs", "true"); - - let scrollButtonWidth = this.mTabstrip._scrollButtonDown.getBoundingClientRect().width; - let paddingStart = this.mTabstrip.scrollboxPaddingStart; - let width = 0; - - for (let i = numPinned - 1; i >= 0; i--) { - let tab = this.childNodes[i]; - width += tab.getBoundingClientRect().width; - tab.style.MozMarginStart = - (width + scrollButtonWidth + paddingStart) + "px"; - } - - this.style.MozPaddingStart = width + paddingStart + "px"; - - } else { - this.removeAttribute("positionpinnedtabs"); - - for (let i = 0; i < numPinned; i++) { - let tab = this.childNodes[i]; - tab.style.MozMarginStart = ""; - } - - this.style.MozPaddingStart = ""; - } - - if (this._lastNumPinned != numPinned) { - this._lastNumPinned = numPinned; - this._handleTabSelect(false); - } - ]]></body> - </method> - - <method name="_animateTabMove"> - <parameter name="event"/> - <body><![CDATA[ - let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0); - - if (this.getAttribute("movingtab") != "true") { - this.setAttribute("movingtab", "true"); - this.selectedItem = draggedTab; - } - - if (!("animLastScreenX" in draggedTab._dragData)) - draggedTab._dragData.animLastScreenX = draggedTab._dragData.screenX; - - let screenX = event.screenX; - if (screenX == draggedTab._dragData.animLastScreenX) - return; - - let draggingRight = screenX > draggedTab._dragData.animLastScreenX; - draggedTab._dragData.animLastScreenX = screenX; - - let rtl = (window.getComputedStyle(this).direction == "rtl"); - let pinned = draggedTab.pinned; - let numPinned = this.tabbrowser._numPinnedTabs; - let tabs = this.tabbrowser.visibleTabs - .slice(pinned ? 0 : numPinned, - pinned ? numPinned : undefined); - if (rtl) - tabs.reverse(); - let tabWidth = draggedTab.getBoundingClientRect().width; - - // Move the dragged tab based on the mouse position. - - let leftTab = tabs[0]; - let rightTab = tabs[tabs.length - 1]; - let tabScreenX = draggedTab.boxObject.screenX; - let translateX = screenX - draggedTab._dragData.screenX; - if (!pinned) - translateX += this.mTabstrip.scrollPosition - draggedTab._dragData.scrollX; - let leftBound = leftTab.boxObject.screenX - tabScreenX; - let rightBound = (rightTab.boxObject.screenX + rightTab.boxObject.width) - - (tabScreenX + tabWidth); - translateX = Math.max(translateX, leftBound); - translateX = Math.min(translateX, rightBound); - draggedTab.style.transform = "translateX(" + translateX + "px)"; - - // Determine what tab we're dragging over. - // * Point of reference is the center of the dragged tab. If that - // point touches a background tab, the dragged tab would take that - // tab's position when dropped. - // * We're doing a binary search in order to reduce the amount of - // tabs we need to check. - - let tabCenter = tabScreenX + translateX + tabWidth / 2; - let newIndex = -1; - let oldIndex = "animDropIndex" in draggedTab._dragData ? - draggedTab._dragData.animDropIndex : draggedTab._tPos; - let low = 0; - let high = tabs.length - 1; - while (low <= high) { - let mid = Math.floor((low + high) / 2); - if (tabs[mid] == draggedTab && - ++mid > high) - break; - let boxObject = tabs[mid].boxObject; - let screenX = boxObject.screenX + getTabShift(tabs[mid], oldIndex); - if (screenX > tabCenter) { - high = mid - 1; - } else if (screenX + boxObject.width < tabCenter) { - low = mid + 1; - } else { - newIndex = tabs[mid]._tPos; - break; - } - } - if (newIndex >= oldIndex) - newIndex++; - if (newIndex < 0 || newIndex == oldIndex) - return; - draggedTab._dragData.animDropIndex = newIndex; - - // Shift background tabs to leave a gap where the dragged tab - // would currently be dropped. - - for (let tab of tabs) { - if (tab != draggedTab) { - let shift = getTabShift(tab, newIndex); - tab.style.transform = shift ? "translateX(" + shift + "px)" : ""; - } - } - - function getTabShift(tab, dropIndex) { - if (tab._tPos < draggedTab._tPos && tab._tPos >= dropIndex) - return rtl ? -tabWidth : tabWidth; - if (tab._tPos > draggedTab._tPos && tab._tPos < dropIndex) - return rtl ? tabWidth : -tabWidth; - return 0; - } - ]]></body> - </method> - - <method name="_finishAnimateTabMove"> - <body><![CDATA[ - if (this.getAttribute("movingtab") != "true") - return; - - for (let tab of this.tabbrowser.visibleTabs) - tab.style.transform = ""; - - this.removeAttribute("movingtab"); - - this._handleTabSelect(); - ]]></body> - </method> - - <method name="handleEvent"> - <parameter name="aEvent"/> - <body><![CDATA[ - switch (aEvent.type) { - case "load": - this.updateVisibility(); - break; - case "resize": - if (aEvent.target != window) - break; - - let sizemode = document.documentElement.getAttribute("sizemode"); - TabsInTitlebar.allowedBy("sizemode", - sizemode == "maximized" || sizemode == "fullscreen"); - - var width = this.mTabstrip.boxObject.width; - if (width != this.mTabstripWidth) { - this.adjustTabstrip(); - this._fillTrailingGap(); - this._handleTabSelect(); - this.mTabstripWidth = width; - } - - this.tabbrowser.updateWindowResizers(); - break; - case "mouseout": - // If the "related target" (the node to which the pointer went) is not - // a child of the current document, the mouse just left the window. - let relatedTarget = aEvent.relatedTarget; - if (relatedTarget && relatedTarget.ownerDocument == document) - break; - case "mousemove": - if (document.getElementById("tabContextMenu").state != "open") - this._unlockTabSizing(); - break; - } - ]]></body> - </method> - - <field name="_animateElement"> - this.mTabstrip._scrollButtonDown; - </field> - - <method name="_notifyBackgroundTab"> - <parameter name="aTab"/> - <body><![CDATA[ - if (aTab.pinned) - return; - - var scrollRect = this.mTabstrip.scrollClientRect; - var tab = aTab.getBoundingClientRect(); - - // Is the new tab already completely visible? - if (scrollRect.left <= tab.left && tab.right <= scrollRect.right) - return; - - if (this.mTabstrip.smoothScroll) { - let selected = !this.selectedItem.pinned && - this.selectedItem.getBoundingClientRect(); - - // Can we make both the new tab and the selected tab completely visible? - if (!selected || - Math.max(tab.right - selected.left, selected.right - tab.left) <= - scrollRect.width) { - this.mTabstrip.ensureElementIsVisible(aTab); - return; - } - - this.mTabstrip._smoothScrollByPixels(this.mTabstrip._isRTLScrollbox ? - selected.right - scrollRect.right : - selected.left - scrollRect.left); - } - - if (!this._animateElement.hasAttribute("notifybgtab")) { - this._animateElement.setAttribute("notifybgtab", "true"); - setTimeout(function (ele) { - ele.removeAttribute("notifybgtab"); - }, 150, this._animateElement); - } - ]]></body> - </method> - - <method name="_getDragTargetTab"> - <parameter name="event"/> - <body><![CDATA[ - let tab = event.target.localName == "tab" ? event.target : null; - if (tab && - (event.type == "drop" || event.type == "dragover") && - event.dataTransfer.dropEffect == "link") { - let boxObject = tab.boxObject; - if (event.screenX < boxObject.screenX + boxObject.width * .25 || - event.screenX > boxObject.screenX + boxObject.width * .75) - return null; - } - return tab; - ]]></body> - </method> - - <method name="_getDropIndex"> - <parameter name="event"/> - <body><![CDATA[ - var tabs = this.childNodes; - var tab = this._getDragTargetTab(event); - if (window.getComputedStyle(this, null).direction == "ltr") { - for (let i = tab ? tab._tPos : 0; i < tabs.length; i++) - if (event.screenX < tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2) - return i; - } else { - for (let i = tab ? tab._tPos : 0; i < tabs.length; i++) - if (event.screenX > tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2) - return i; - } - return tabs.length; - ]]></body> - </method> - - <method name="_setEffectAllowedForDataTransfer"> - <parameter name="event"/> - <body><![CDATA[ - var dt = event.dataTransfer; - // Disallow dropping multiple items - if (dt.mozItemCount > 1) - return dt.effectAllowed = "none"; - - var types = dt.mozTypesAt(0); - var sourceNode = null; - // tabs are always added as the first type - if (types[0] == TAB_DROP_TYPE) { - var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0); - if (sourceNode instanceof XULElement && - sourceNode.localName == "tab" && - sourceNode.ownerDocument.defaultView instanceof ChromeWindow && - sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser" && - sourceNode.ownerDocument.defaultView.gBrowser.tabContainer == sourceNode.parentNode) { - // Do not allow transfering a private tab to a non-private window - // and vice versa. - if (PrivateBrowsingUtils.isWindowPrivate(window) != - PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerDocument.defaultView)) - return dt.effectAllowed = "none"; - -#ifdef XP_MACOSX - return dt.effectAllowed = event.altKey ? "copy" : "move"; -#else - return dt.effectAllowed = event.ctrlKey ? "copy" : "move"; -#endif - } - } - - if (browserDragAndDrop.canDropLink(event)) { - // Here we need to do this manually - return dt.effectAllowed = dt.dropEffect = "link"; - } - return dt.effectAllowed = "none"; - ]]></body> - </method> - - <method name="_handleNewTab"> - <parameter name="tab"/> - <body><![CDATA[ - if (tab.parentNode != this) - return; - tab._fullyOpen = true; - - this.adjustTabstrip(); - - if (tab.getAttribute("selected") == "true") { - this._fillTrailingGap(); - this._handleTabSelect(); - } else { - this._notifyBackgroundTab(tab); - } - - // XXXmano: this is a temporary workaround for bug 345399 - // We need to manually update the scroll buttons disabled state - // if a tab was inserted to the overflow area or removed from it - // without any scrolling and when the tabbar has already - // overflowed. - this.mTabstrip._updateScrollButtonsDisabledState(); - ]]></body> - </method> - - <method name="_canAdvanceToTab"> - <parameter name="aTab"/> - <body> - <![CDATA[ - return !aTab.closing; - ]]> - </body> - </method> - - <method name="_handleTabTelemetryStart"> - <parameter name="aTab"/> - <parameter name="aURI"/> - <body> - <![CDATA[ - // Animation-smoothness telemetry/logging - if (this._tabAnimationLoggingEnabled) { - if (aURI == "about:newtab" && (aTab._tPos == 1 || aTab._tPos == 2)) { - // Indicate newtab page animation where other tabs are unaffected - // (for which case, the 2nd or 3rd tabs are good representatives, even if not absolute) - aTab._recordingTabOpenPlain = true; - } - aTab._recordingHandle = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .startFrameTimeRecording(); - } - - // Overall animation duration - aTab._animStartTime = Date.now(); - ]]> - </body> - </method> - - <method name="_handleTabTelemetryEnd"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (!aTab._animStartTime) { - return; - } - - aTab._animStartTime = 0; - - // Handle tab animation smoothness telemetry/logging of frame intervals and paint times - if (!("_recordingHandle" in aTab)) { - return; - } - - let paints = {}; - let intervals = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .stopFrameTimeRecording(aTab._recordingHandle, paints); - delete aTab._recordingHandle; - paints = paints.value; // The result array itself. - let frameCount = intervals.length; - - if (this._tabAnimationLoggingEnabled) { - let msg = "Tab " + (aTab.closing ? "close" : "open") + " (Frame-interval / paint-processing):\n"; - for (let i = 0; i < frameCount; i++) { - msg += Math.round(intervals[i]) + " / " + Math.round(paints[i]) + "\n"; - } - Services.console.logStringMessage(msg); - } - - // For telemetry, the first frame interval is not useful since it may represent an interval - // to a relatively old frame (prior to recording start). So we'll ignore it for the average. - // But if we recorded only 1 frame (very rare), then the first paint duration is a good - // representative of the first frame interval for our cause (indicates very bad animation). - // First paint duration is always useful for us. - if (frameCount > 0) { - let averageInterval = 0; - let averagePaint = paints[0]; - for (let i = 1; i < frameCount; i++) { - averageInterval += intervals[i]; - averagePaint += paints[i]; - }; - averagePaint /= frameCount; - averageInterval = (frameCount == 1) - ? averagePaint - : averageInterval / (frameCount - 1); - - if (aTab._recordingTabOpenPlain) { - delete aTab._recordingTabOpenPlain; - } - } - ]]> - </body> - </method> - - <!-- Deprecated stuff, implemented for backwards compatibility. --> - <property name="mTabstripClosebutton" readonly="true" - onget="return document.getElementById('tabs-closebutton');"/> - <property name="mAllTabsPopup" readonly="true" - onget="return document.getElementById('alltabs-popup');"/> - </implementation> - - <handlers> - <handler event="TabSelect" action="this._handleTabSelect();"/> - - <handler event="transitionend"><![CDATA[ - if (event.propertyName != "max-width") - return; - - var tab = event.target; - - this._handleTabTelemetryEnd(tab); - - if (tab.getAttribute("fadein") == "true") { - if (tab._fullyOpen) - this.adjustTabstrip(); - else - this._handleNewTab(tab); - } else if (tab.closing) { - this.tabbrowser._endRemoveTab(tab); - } - ]]></handler> - - <handler event="dblclick"><![CDATA[ -#ifndef XP_MACOSX - // When the tabbar has an unified appearance with the titlebar - // and menubar, a double-click in it should have the same behavior - // as double-clicking the titlebar - if (TabsInTitlebar.enabled || - (TabsOnTop.enabled && this.parentNode._dragBindingAlive)) - return; -#endif - - if (event.button != 0 || - event.originalTarget.localName != "box") - return; - - // See hack note in the tabbrowser-close-tab-button binding - if (!this._blockDblClick) - BrowserOpenTab(); - - event.preventDefault(); - ]]></handler> - - <handler event="click"><![CDATA[ - if (event.button != 1) - return; - - if (event.target.localName == "tab") { - if (this.childNodes.length > 1 || !this._closeWindowWithLastTab) - this.tabbrowser.removeTab(event.target, {animate: true, byMouse: true}); - } else if (event.originalTarget.localName == "box") { - BrowserOpenTab(); - } else { - return; - } - - event.stopPropagation(); - ]]></handler> - - <handler event="keypress"><![CDATA[ - if (event.altKey || event.shiftKey || -#ifdef XP_MACOSX - !event.metaKey) -#else - !event.ctrlKey || event.metaKey) -#endif - return; - - switch (event.keyCode) { - case KeyEvent.DOM_VK_UP: - this.tabbrowser.moveTabBackward(); - break; - case KeyEvent.DOM_VK_DOWN: - this.tabbrowser.moveTabForward(); - break; - case KeyEvent.DOM_VK_RIGHT: - case KeyEvent.DOM_VK_LEFT: - this.tabbrowser.moveTabOver(event); - break; - case KeyEvent.DOM_VK_HOME: - this.tabbrowser.moveTabToStart(); - break; - case KeyEvent.DOM_VK_END: - this.tabbrowser.moveTabToEnd(); - break; - default: - // Stop the keypress event for the above keyboard - // shortcuts only. - return; - } - event.stopPropagation(); - event.preventDefault(); - ]]></handler> - - <handler event="dragstart"><![CDATA[ - var tab = this._getDragTargetTab(event); - if (!tab) - return; - - let dt = event.dataTransfer; - dt.mozSetDataAt(TAB_DROP_TYPE, tab, 0); - let browser = tab.linkedBrowser; - - // We must not set text/x-moz-url or text/plain data here, - // otherwise trying to deatch the tab by dropping it on the desktop - // may result in an "internet shortcut" - dt.mozSetDataAt("text/x-moz-text-internal", browser.currentURI.spec, 0); - - // Set the cursor to an arrow during tab drags. - dt.mozCursor = "default"; - - // Create a canvas to which we capture the current tab. - // Until canvas is HiDPI-aware (bug 780362), we need to scale the desired - // canvas size (in CSS pixels) to the window's backing resolution in order - // to get a full-resolution drag image for use on HiDPI displays. - let windowUtils = window.getInterface(Ci.nsIDOMWindowUtils); - let scale = windowUtils.screenPixelsPerCSSPixel / windowUtils.fullZoom; - let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); - canvas.mozOpaque = true; - canvas.width = 160 * scale; - canvas.height = 90 * scale; - PageThumbs.captureToCanvas(browser, canvas); - dt.setDragImage(canvas, -16 * scale, -16 * scale); - - // _dragData.offsetX/Y give the coordinates that the mouse should be - // positioned relative to the corner of the new window created upon - // dragend such that the mouse appears to have the same position - // relative to the corner of the dragged tab. - function clientX(ele) ele.getBoundingClientRect().left; - let tabOffsetX = clientX(tab) - clientX(this); - tab._dragData = { - offsetX: event.screenX - window.screenX - tabOffsetX, - offsetY: event.screenY - window.screenY, - scrollX: this.mTabstrip.scrollPosition, - screenX: event.screenX - }; - - event.stopPropagation(); - ]]></handler> - - <handler event="dragover"><![CDATA[ - var effects = this._setEffectAllowedForDataTransfer(event); - - var ind = this._tabDropIndicator; - if (effects == "" || effects == "none") { - ind.collapsed = true; - return; - } - event.preventDefault(); - event.stopPropagation(); - - var tabStrip = this.mTabstrip; - var ltr = (window.getComputedStyle(this, null).direction == "ltr"); - - // autoscroll the tab strip if we drag over the scroll - // buttons, even if we aren't dragging a tab, but then - // return to avoid drawing the drop indicator - var pixelsToScroll = 0; - if (this.getAttribute("overflow") == "true") { - var targetAnonid = event.originalTarget.getAttribute("anonid"); - switch (targetAnonid) { - case "scrollbutton-up": - pixelsToScroll = tabStrip.scrollIncrement * -1; - break; - case "scrollbutton-down": - pixelsToScroll = tabStrip.scrollIncrement; - break; - } - if (pixelsToScroll) - tabStrip.scrollByPixels((ltr ? 1 : -1) * pixelsToScroll); - } - - if (effects == "move" && - this == event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0).parentNode) { - ind.collapsed = true; - this._animateTabMove(event); - return; - } - - this._finishAnimateTabMove(); - - if (effects == "link") { - let tab = this._getDragTargetTab(event); - if (tab) { - if (!this._dragTime) - this._dragTime = Date.now(); - if (Date.now() >= this._dragTime + this._dragOverDelay) - this.selectedItem = tab; - ind.collapsed = true; - return; - } - } - - var rect = tabStrip.getBoundingClientRect(); - var newMargin; - if (pixelsToScroll) { - // if we are scrolling, put the drop indicator at the edge - // so that it doesn't jump while scrolling - let scrollRect = tabStrip.scrollClientRect; - let minMargin = scrollRect.left - rect.left; - let maxMargin = Math.min(minMargin + scrollRect.width, - scrollRect.right); - if (!ltr) - [minMargin, maxMargin] = [this.clientWidth - maxMargin, - this.clientWidth - minMargin]; - newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin; - } - else { - let newIndex = this._getDropIndex(event); - if (newIndex == this.childNodes.length) { - let tabRect = this.childNodes[newIndex-1].getBoundingClientRect(); - if (ltr) - newMargin = tabRect.right - rect.left; - else - newMargin = rect.right - tabRect.left; - } - else { - let tabRect = this.childNodes[newIndex].getBoundingClientRect(); - if (ltr) - newMargin = tabRect.left - rect.left; - else - newMargin = rect.right - tabRect.right; - } - } - - ind.collapsed = false; - - newMargin += ind.clientWidth / 2; - if (!ltr) - newMargin *= -1; - - ind.style.transform = "translate(" + Math.round(newMargin) + "px)"; - ind.style.MozMarginStart = (-ind.clientWidth) + "px"; - ]]></handler> - - <handler event="drop"><![CDATA[ - var dt = event.dataTransfer; - var dropEffect = dt.dropEffect; - var draggedTab; - if (dropEffect != "link") { // copy or move - draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0); - // not our drop then - if (!draggedTab) - return; - } - - this._tabDropIndicator.collapsed = true; - event.stopPropagation(); - if (draggedTab && dropEffect == "copy") { - // copy the dropped tab (wherever it's from) - let newIndex = this._getDropIndex(event); - let newTab = this.tabbrowser.duplicateTab(draggedTab); - this.tabbrowser.moveTabTo(newTab, newIndex); - if (draggedTab.parentNode != this || event.shiftKey) - this.selectedItem = newTab; - } else if (draggedTab && draggedTab.parentNode == this) { - this._finishAnimateTabMove(); - - // actually move the dragged tab - if ("animDropIndex" in draggedTab._dragData) { - let newIndex = draggedTab._dragData.animDropIndex; - if (newIndex > draggedTab._tPos) - newIndex--; - this.tabbrowser.moveTabTo(draggedTab, newIndex); - } - } else if (draggedTab) { - // swap the dropped tab with a new one we create and then close - // it in the other window (making it seem to have moved between - // windows) - let newIndex = this._getDropIndex(event); - let newTab = this.tabbrowser.addTab("about:blank"); - let newBrowser = this.tabbrowser.getBrowserForTab(newTab); - // Stop the about:blank load - newBrowser.stop(); - // make sure it has a docshell - newBrowser.docShell; - - let numPinned = this.tabbrowser._numPinnedTabs; - if (newIndex < numPinned || draggedTab.pinned && newIndex == numPinned) - this.tabbrowser.pinTab(newTab); - this.tabbrowser.moveTabTo(newTab, newIndex); - - // We need to select the tab before calling swapBrowsersAndCloseOther - // so that window.content in chrome windows points to the right tab - // when pagehide/show events are fired. - this.tabbrowser.selectedTab = newTab; - - draggedTab.parentNode._finishAnimateTabMove(); - this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab); - - // Call updateCurrentBrowser to make sure the URL bar is up to date - // for our new tab after we've done swapBrowsersAndCloseOther. - this.tabbrowser.updateCurrentBrowser(true); - } else { - // Pass true to disallow dropping javascript: or data: urls - let url; - try { - url = browserDragAndDrop.drop(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 - return; - - let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); - - if (event.shiftKey) - bgLoad = !bgLoad; - - 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 - } - } - } - - if (draggedTab) { - delete draggedTab._dragData; - } - ]]></handler> - - <handler event="dragend"><![CDATA[ - // Note: while this case is correctly handled here, this event - // isn't dispatched when the tab is moved within the tabstrip, - // see bug 460801. - - this._finishAnimateTabMove(); - - var dt = event.dataTransfer; - var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0); - if (dt.mozUserCancelled || dt.dropEffect != "none") { - delete draggedTab._dragData; - return; - } - - // Disable detach within the browser toolbox - var eX = event.screenX; - var eY = event.screenY; - var wX = window.screenX; - // check if the drop point is horizontally within the window - if (eX > wX && eX < (wX + window.outerWidth)) { - let bo = this.mTabstrip.boxObject; - // also avoid detaching if the the tab was dropped too close to - // the tabbar (half a tab) - let endScreenY = bo.screenY + 1.5 * bo.height; - if (eY < endScreenY && eY > window.screenY) - return; - } - - // screen.availLeft et. al. only check the screen that this window is on, - // but we want to look at the screen the tab is being dropped onto. - var sX = {}, sY = {}, sWidth = {}, sHeight = {}; - Cc["@mozilla.org/gfx/screenmanager;1"] - .getService(Ci.nsIScreenManager) - .screenForRect(eX, eY, 1, 1) - .GetAvailRect(sX, sY, sWidth, sHeight); - // ensure new window entirely within screen - var winWidth = Math.min(window.outerWidth, sWidth.value); - var winHeight = Math.min(window.outerHeight, sHeight.value); - var left = Math.min(Math.max(eX - draggedTab._dragData.offsetX, sX.value), - sX.value + sWidth.value - winWidth); - var top = Math.min(Math.max(eY - draggedTab._dragData.offsetY, sY.value), - sY.value + sHeight.value - winHeight); - - delete draggedTab._dragData; - - if (this.tabbrowser.tabs.length == 1) { - // resize _before_ move to ensure the window fits the new screen. if - // the window is too large for its screen, the window manager may do - // automatic repositioning. - window.resizeTo(winWidth, winHeight); - window.moveTo(left, top); - window.focus(); - } else { - this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: left, - screenY: top, -#ifndef XP_WIN - outerWidth: winWidth, - outerHeight: winHeight -#endif - }); - } - event.stopPropagation(); - ]]></handler> - - <handler event="dragexit"><![CDATA[ - this._dragTime = 0; - - // This does not work at all (see bug 458613) - var target = event.relatedTarget; - while (target && target != this) - target = target.parentNode; - if (target) - return; - - this._tabDropIndicator.collapsed = true; - event.stopPropagation(); - ]]></handler> - </handlers> - </binding> - - <!-- close-tab-button binding - This binding relies on the structure of the tabbrowser binding. - Therefore it should only be used as a child of the tab or the tabs - element (in both cases, when they are anonymous nodes of <tabbrowser>). - --> - <binding id="tabbrowser-close-tab-button" - extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image"> - <handlers> - <handler event="click" button="0"><![CDATA[ - var bindingParent = document.getBindingParent(this); - var tabContainer = bindingParent.parentNode; - /* The only sequence in which a second click event (i.e. dblclik) - * can be dispatched on an in-tab close button is when it is shown - * after the first click (i.e. the first click event was dispatched - * on the tab). This happens when we show the close button only on - * the active tab. (bug 352021) - * The only sequence in which a third click event can be dispatched - * on an in-tab close button is when the tab was opened with a - * double click on the tabbar. (bug 378344) - * In both cases, it is most likely that the close button area has - * been accidentally clicked, therefore we do not close the tab. - * - * We don't want to ignore processing of more than one click event, - * though, since the user might actually be repeatedly clicking to - * close many tabs at once. - */ - if (event.detail > 1 && !this._ignoredClick) { - this._ignoredClick = true; - return; - } - - // Reset the "ignored click" flag - this._ignoredClick = false; - - tabContainer.tabbrowser.removeTab(bindingParent, {animate: true, byMouse: true}); - tabContainer._blockDblClick = true; - - /* XXXmano hack (see bug 343628): - * Since we're removing the event target, if the user - * double-clicks this button, the dblclick event will be dispatched - * with the tabbar as its event target (and explicit/originalTarget), - * which treats that as a mouse gesture for opening a new tab. - * In this context, we're manually blocking the dblclick event - * (see dblclick handler). - */ - var clickedOnce = false; - function enableDblClick(event) { - var target = event.originalTarget; - if (target.className == 'tab-close-button') - target._ignoredClick = true; - if (!clickedOnce) { - clickedOnce = true; - return; - } - tabContainer._blockDblClick = false; - tabContainer.removeEventListener("click", enableDblClick, true); - } - tabContainer.addEventListener("click", enableDblClick, true); - ]]></handler> - - <handler event="dblclick" button="0" phase="capturing"> - // for the one-close-button case - event.stopPropagation(); - </handler> - - <handler event="dragstart"> - event.stopPropagation(); - </handler> - </handlers> - </binding> - - <binding id="tabbrowser-tab" display="xul:hbox" - extends="chrome://global/content/bindings/tabbox.xml#tab"> - <resources> - <stylesheet src="chrome://browser/content/tabbrowser.css"/> - </resources> - - <content context="tabContextMenu" closetabtext="&closeTab.label;"> - <xul:stack class="tab-stack" flex="1"> - <xul:hbox xbl:inherits="pinned,selected,titlechanged" - class="tab-background"> - <xul:hbox xbl:inherits="pinned,selected,titlechanged" - class="tab-background-start"/> - <xul:hbox xbl:inherits="pinned,selected,titlechanged" - class="tab-background-middle"/> - <xul:hbox xbl:inherits="pinned,selected,titlechanged" - class="tab-background-end"/> - </xul:hbox> - <xul:hbox xbl:inherits="pinned,selected,titlechanged" - class="tab-content" align="center"> - <xul:image xbl:inherits="fadein,pinned,busy,progress,selected" - class="tab-throbber" - role="presentation" - layer="true" /> - <xul:image xbl:inherits="validate,src=image,fadein,pinned,selected" - class="tab-icon-image" - role="presentation" - anonid="tab-icon"/> - <xul:label flex="1" - xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected" - class="tab-text tab-label" - role="presentation"/> - <xul:toolbarbutton anonid="close-button" - xbl:inherits="fadein,pinned,selected" - class="tab-close-button close-icon"/> - </xul:hbox> - </xul:stack> - </content> - - <implementation> - <property name="pinned" readonly="true"> - <getter> - return this.getAttribute("pinned") == "true"; - </getter> - </property> - <property name="hidden" readonly="true"> - <getter> - return this.getAttribute("hidden") == "true"; - </getter> - </property> - - <field name="mOverCloseButton">false</field> - <field name="mCorrespondingMenuitem">null</field> - <field name="closing">false</field> - <field name="lastAccessed">0</field> - </implementation> - - <handlers> - <handler event="mouseover"><![CDATA[ - let anonid = event.originalTarget.getAttribute("anonid"); - if (anonid == "close-button") - this.mOverCloseButton = true; - - let tab = event.target; - if (tab.closing) - return; - - let tabContainer = this.parentNode; - let visibleTabs = tabContainer.tabbrowser.visibleTabs; - let tabIndex = visibleTabs.indexOf(tab); - if (tabIndex == 0) { - tabContainer._beforeHoveredTab = null; - } else { - let candidate = visibleTabs[tabIndex - 1]; - if (!candidate.selected) { - tabContainer._beforeHoveredTab = candidate; - candidate.setAttribute("beforehovered", "true"); - } - } - - if (tabIndex == visibleTabs.length - 1) { - tabContainer._afterHoveredTab = null; - } else { - let candidate = visibleTabs[tabIndex + 1]; - if (!candidate.selected) { - tabContainer._afterHoveredTab = candidate; - candidate.setAttribute("afterhovered", "true"); - } - } - ]]></handler> - <handler event="mouseout"><![CDATA[ - let anonid = event.originalTarget.getAttribute("anonid"); - if (anonid == "close-button") - this.mOverCloseButton = false; - - let tabContainer = this.parentNode; - if (tabContainer._beforeHoveredTab) { - tabContainer._beforeHoveredTab.removeAttribute("beforehovered"); - tabContainer._beforeHoveredTab = null; - } - if (tabContainer._afterHoveredTab) { - tabContainer._afterHoveredTab.removeAttribute("afterhovered"); - tabContainer._afterHoveredTab = null; - } - ]]></handler> - <handler event="dragstart" phase="capturing"> - this.style.MozUserFocus = ''; - </handler> - <handler event="mousedown" phase="capturing"> - <![CDATA[ - if (this.selected) { - this.style.MozUserFocus = 'ignore'; - this.clientTop; // just using this to flush style updates - } else if (this.mOverCloseButton) { - // Prevent tabbox.xml from selecting the tab. - event.stopPropagation(); - } - ]]> - </handler> - <handler event="mouseup"> - this.style.MozUserFocus = ''; - </handler> - </handlers> - </binding> - - <binding id="tabbrowser-alltabs-popup" - extends="chrome://global/content/bindings/popup.xml#popup"> - <implementation implements="nsIDOMEventListener"> - <method name="_tabOnAttrModified"> - <parameter name="aEvent"/> - <body><![CDATA[ - var tab = aEvent.target; - if (tab.mCorrespondingMenuitem) - this._setMenuitemAttributes(tab.mCorrespondingMenuitem, tab); - ]]></body> - </method> - - <method name="_tabOnTabClose"> - <parameter name="aEvent"/> - <body><![CDATA[ - var tab = aEvent.target; - if (tab.mCorrespondingMenuitem) - this.removeChild(tab.mCorrespondingMenuitem); - ]]></body> - </method> - - <method name="handleEvent"> - <parameter name="aEvent"/> - <body><![CDATA[ - switch (aEvent.type) { - case "TabAttrModified": - this._tabOnAttrModified(aEvent); - break; - case "TabClose": - this._tabOnTabClose(aEvent); - break; - case "scroll": - this._updateTabsVisibilityStatus(); - break; - } - ]]></body> - </method> - - <method name="_updateTabsVisibilityStatus"> - <body><![CDATA[ - var tabContainer = gBrowser.tabContainer; - // We don't want menu item decoration unless there is overflow. - if (tabContainer.getAttribute("overflow") != "true") - return; - - var tabstripBO = tabContainer.mTabstrip.scrollBoxObject; - for (var i = 0; i < this.childNodes.length; i++) { - let curTab = this.childNodes[i].tab; - let curTabBO = curTab.boxObject; - if (curTabBO.screenX >= tabstripBO.screenX && - curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width) - this.childNodes[i].setAttribute("tabIsVisible", "true"); - else - this.childNodes[i].removeAttribute("tabIsVisible"); - } - ]]></body> - </method> - - <method name="_createTabMenuItem"> - <parameter name="aTab"/> - <body><![CDATA[ - var menuItem = document.createElementNS( - "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", - "menuitem"); - - menuItem.setAttribute("class", "menuitem-iconic alltabs-item menuitem-with-favicon"); - - this._setMenuitemAttributes(menuItem, aTab); - - if (!aTab.mCorrespondingMenuitem) { - aTab.mCorrespondingMenuitem = menuItem; - menuItem.tab = aTab; - - this.appendChild(menuItem); - } - ]]></body> - </method> - - <method name="_setMenuitemAttributes"> - <parameter name="aMenuitem"/> - <parameter name="aTab"/> - <body><![CDATA[ - aMenuitem.setAttribute("label", aTab.label); - aMenuitem.setAttribute("crop", aTab.getAttribute("crop")); - - if (aTab.hasAttribute("busy")) { - aMenuitem.setAttribute("busy", aTab.getAttribute("busy")); - aMenuitem.removeAttribute("image"); - } else { - aMenuitem.setAttribute("image", aTab.getAttribute("image")); - aMenuitem.removeAttribute("busy"); - } - - if (aTab.hasAttribute("pending")) - aMenuitem.setAttribute("pending", aTab.getAttribute("pending")); - else - aMenuitem.removeAttribute("pending"); - - if (aTab.selected) - aMenuitem.setAttribute("selected", "true"); - else - aMenuitem.removeAttribute("selected"); - ]]></body> - </method> - </implementation> - - <handlers> - <handler event="popupshowing"> - <![CDATA[ - var tabcontainer = gBrowser.tabContainer; - - // Listen for changes in the tab bar. - tabcontainer.addEventListener("TabAttrModified", this, false); - tabcontainer.addEventListener("TabClose", this, false); - tabcontainer.mTabstrip.addEventListener("scroll", this, false); - - let tabs = gBrowser.visibleTabs; - for (var i = 0; i < tabs.length; i++) { - if (!tabs[i].pinned) - this._createTabMenuItem(tabs[i]); - } - this._updateTabsVisibilityStatus(); - ]]></handler> - - <handler event="popuphidden"> - <![CDATA[ - // clear out the menu popup and remove the listeners - for (let i = this.childNodes.length - 1; i >= 0; i--) { - let menuItem = this.childNodes[i]; - if (menuItem.tab) { - menuItem.tab.mCorrespondingMenuitem = null; - this.removeChild(menuItem); - } - } - var tabcontainer = gBrowser.tabContainer; - tabcontainer.mTabstrip.removeEventListener("scroll", this, false); - tabcontainer.removeEventListener("TabAttrModified", this, false); - tabcontainer.removeEventListener("TabClose", this, false); - ]]></handler> - - <handler event="DOMMenuItemActive"> - <![CDATA[ - var tab = event.target.tab; - if (tab) { - let overLink = tab.linkedBrowser.currentURI.spec; - if (overLink == "about:blank") - overLink = ""; - XULBrowserWindow.setOverLink(overLink, null); - } - ]]></handler> - - <handler event="DOMMenuItemInactive"> - <![CDATA[ - XULBrowserWindow.setOverLink("", null); - ]]></handler> - - <handler event="command"><![CDATA[ - if (event.target.tab) - gBrowser.selectedTab = event.target.tab; - ]]></handler> - - </handlers> - </binding> - - <binding id="statuspanel" display="xul:hbox"> - <content> - <xul:hbox class="statuspanel-inner"> - <xul:label class="statuspanel-label" - role="status" - aria-live="off" - xbl:inherits="value=label,crop,mirror" - flex="1" - crop="end"/> - </xul:hbox> - </content> - - <implementation implements="nsIDOMEventListener"> - <constructor><![CDATA[ - window.addEventListener("resize", this, false); - ]]></constructor> - - <destructor><![CDATA[ - window.removeEventListener("resize", this, false); - MousePosTracker.removeListener(this); - ]]></destructor> - - <property name="label"> - <setter><![CDATA[ - if (!this.label) { - this.removeAttribute("mirror"); - this.removeAttribute("sizelimit"); - } - - this.style.minWidth = this.getAttribute("type") == "status" && - this.getAttribute("previoustype") == "status" - ? getComputedStyle(this).width : ""; - - if (val) { - this.setAttribute("label", val); - this.removeAttribute("inactive"); - this._calcMouseTargetRect(); - MousePosTracker.addListener(this); - } else { - this.setAttribute("inactive", "true"); - MousePosTracker.removeListener(this); - } - - return val; - ]]></setter> - <getter> - return this.hasAttribute("inactive") ? "" : this.getAttribute("label"); - </getter> - </property> - - <method name="getMouseTargetRect"> - <body><![CDATA[ - return this._mouseTargetRect; - ]]></body> - </method> - - <method name="onMouseEnter"> - <body> - this._mirror(); - </body> - </method> - - <method name="onMouseLeave"> - <body> - this._mirror(); - </body> - </method> - - <method name="handleEvent"> - <parameter name="event"/> - <body><![CDATA[ - if (!this.label) - return; - - switch (event.type) { - case "resize": - this._calcMouseTargetRect(); - break; - } - ]]></body> - </method> - - <method name="_calcMouseTargetRect"> - <body><![CDATA[ - let alignRight = false; - - if (getComputedStyle(document.documentElement).direction == "rtl") - alignRight = !alignRight; - - let rect = this.getBoundingClientRect(); - this._mouseTargetRect = { - top: rect.top, - bottom: rect.bottom, - left: alignRight ? window.innerWidth - rect.width : 0, - right: alignRight ? window.innerWidth : rect.width - }; - ]]></body> - </method> - - <method name="_mirror"> - <body> - if (this.hasAttribute("mirror")) - this.removeAttribute("mirror"); - else - this.setAttribute("mirror", "true"); - - if (!this.hasAttribute("sizelimit")) { - this.setAttribute("sizelimit", "true"); - this._calcMouseTargetRect(); - } - </body> - </method> - </implementation> - </binding> - -</bindings> diff --git a/browser/base/content/test/general/audio.ogg b/browser/base/content/test/general/audio.ogg Binary files differdeleted file mode 100644 index 7e6ef77ec..000000000 --- a/browser/base/content/test/general/audio.ogg +++ /dev/null diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml deleted file mode 100644 index c99819f0d..000000000 --- a/browser/base/content/urlbarBindings.xml +++ /dev/null @@ -1,1969 +0,0 @@ -<?xml version="1.0"?> - -# -*- Mode: HTML -*- -# 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/. - -<!DOCTYPE bindings [ -<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd"> -%notificationDTD; -<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd"> -%browserDTD; -]> - -<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl" - xmlns:html="http://www.w3.org/1999/xhtml" - xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - xmlns:xbl="http://www.mozilla.org/xbl"> - - <binding id="urlbar" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete"> - - <content sizetopopup="pref"> - <xul:hbox anonid="textbox-container" - class="autocomplete-textbox-container urlbar-textbox-container" - flex="1" xbl:inherits="focused"> - <children includes="image|deck|stack|box"> - <xul:image class="autocomplete-icon" allowevents="true"/> - </children> - <xul:hbox anonid="textbox-input-box" - class="textbox-input-box urlbar-input-box" - flex="1" xbl:inherits="tooltiptext=inputtooltiptext"> - <children/> - <html:input anonid="input" - class="autocomplete-textbox urlbar-input textbox-input uri-element-right-align" - allowevents="true" - xbl:inherits="tooltiptext=inputtooltiptext,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/> - </xul:hbox> - <children includes="hbox"/> - </xul:hbox> - <xul:dropmarker anonid="historydropmarker" - class="autocomplete-history-dropmarker urlbar-history-dropmarker" - allowevents="true" - xbl:inherits="open,enablehistory,parentfocused=focused"/> - <xul:popupset anonid="popupset" - class="autocomplete-result-popupset"/> - <children includes="toolbarbutton"/> - </content> - - <implementation implements="nsIObserver, nsIDOMEventListener"> - <constructor><![CDATA[ - this._prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService) - .getBranch("browser.urlbar."); - - this._prefs.addObserver("", this, false); - this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll"); - this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll"); - this.completeDefaultIndex = this._prefs.getBoolPref("autoFill"); - this.timeout = this._prefs.getIntPref("delay"); - this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled"); - this._mayTrimURLs = this._prefs.getBoolPref("trimURLs"); - - this.inputField.controllers.insertControllerAt(0, this._copyCutController); - this.inputField.addEventListener("mousedown", this, false); - this.inputField.addEventListener("mousemove", this, false); - this.inputField.addEventListener("mouseout", this, false); - this.inputField.addEventListener("overflow", this, false); - this.inputField.addEventListener("underflow", this, false); - - const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - var textBox = document.getAnonymousElementByAttribute(this, - "anonid", "textbox-input-box"); - var cxmenu = document.getAnonymousElementByAttribute(textBox, - "anonid", "input-box-contextmenu"); - var pasteAndGo; - cxmenu.addEventListener("popupshowing", function() { - if (!pasteAndGo) - return; - var controller = document.commandDispatcher.getControllerForCommand("cmd_paste"); - var enabled = controller.isCommandEnabled("cmd_paste"); - if (enabled) - pasteAndGo.removeAttribute("disabled"); - else - pasteAndGo.setAttribute("disabled", "true"); - }, false); - - var insertLocation = cxmenu.firstChild; - while (insertLocation.nextSibling && - insertLocation.getAttribute("cmd") != "cmd_paste") - insertLocation = insertLocation.nextSibling; - if (insertLocation) { - pasteAndGo = document.createElement("menuitem"); - let label = Services.strings.createBundle("chrome://browser/locale/browser.properties"). - GetStringFromName("pasteAndGo.label"); - pasteAndGo.setAttribute("label", label); - pasteAndGo.setAttribute("anonid", "paste-and-go"); - pasteAndGo.setAttribute("oncommand", - "gURLBar.select(); goDoCommand('cmd_paste'); gURLBar.handleCommand();"); - cxmenu.insertBefore(pasteAndGo, insertLocation.nextSibling); - } - ]]></constructor> - - <destructor><![CDATA[ - this._prefs.removeObserver("", this); - this._prefs = null; - this.inputField.controllers.removeController(this._copyCutController); - this.inputField.removeEventListener("mousedown", this, false); - this.inputField.removeEventListener("mousemove", this, false); - this.inputField.removeEventListener("mouseout", this, false); - this.inputField.removeEventListener("overflow", this, false); - this.inputField.removeEventListener("underflow", this, false); - ]]></destructor> - - <field name="_value">""</field> - - <!-- - onBeforeValueGet is called by the base-binding's .value getter. - It can return an object with a "value" property, to override the - return value of the getter. - --> - <method name="onBeforeValueGet"> - <body><![CDATA[ - if (this.hasAttribute("actiontype")) - return {value: this._value}; - return null; - ]]></body> - </method> - - <!-- - onBeforeValueSet is called by the base-binding's .value setter. - It should return the value that the setter should use. - --> - <method name="onBeforeValueSet"> - <parameter name="aValue"/> - <body><![CDATA[ - this._value = aValue; - var returnValue = aValue; - var action = this._parseActionUrl(aValue); - - if (action) { - returnValue = action.param; - } - - // Set the actiontype only if the user is not overriding actions. - if (action && this._noActionsKeys.size == 0) { - this.setAttribute("actiontype", action.type); - } else { - this.removeAttribute("actiontype"); - } - return returnValue; - ]]></body> - </method> - - <field name="_mayTrimURLs">true</field> - <method name="trimValue"> - <parameter name="aURL"/> - <body><![CDATA[ - // This method must not modify the given URL such that calling - // nsIURIFixup::createFixupURI with the result will produce a different URI. - return this._mayTrimURLs ? trimURL(aURL) : aURL; - ]]></body> - </method> - - <field name="_formattingEnabled">true</field> - <method name="formatValue"> - <body><![CDATA[ - if (!this._formattingEnabled || this.focused) - return; - - let controller = this.editor.selectionController; - let selection = controller.getSelection(controller.SELECTION_URLSECONDARY); - selection.removeAllRanges(); - - let textNode = this.editor.rootElement.firstChild; - let value = textNode.textContent; - - let protocol = value.match(/^[a-z\d.+\-]+:(?=[^\d])/); - if (protocol && - ["http:", "https:", "ftp:"].indexOf(protocol[0]) == -1) - return; - let matchedURL = value.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/); - if (!matchedURL) - return; - - let [, preDomain, domain] = matchedURL; - let baseDomain = domain; - let subDomain = ""; - // getBaseDomainFromHost doesn't recognize IPv6 literals in brackets as IPs (bug 667159) - if (domain[0] != "[") { - try { - baseDomain = Services.eTLD.getBaseDomainFromHost(domain); - if (!domain.endsWith(baseDomain)) { - // getBaseDomainFromHost converts its resultant to ACE. - let IDNService = Cc["@mozilla.org/network/idn-service;1"] - .getService(Ci.nsIIDNService); - baseDomain = IDNService.convertACEtoUTF8(baseDomain); - } - } catch (e) {} - } - if (baseDomain != domain) { - subDomain = domain.slice(0, -baseDomain.length); - } - - let rangeLength = preDomain.length + subDomain.length; - if (rangeLength) { - let range = document.createRange(); - range.setStart(textNode, 0); - range.setEnd(textNode, rangeLength); - selection.addRange(range); - } - - let startRest = preDomain.length + domain.length; - if (startRest < value.length) { - let range = document.createRange(); - range.setStart(textNode, startRest); - range.setEnd(textNode, value.length); - selection.addRange(range); - } - ]]></body> - </method> - - <method name="_clearFormatting"> - <body><![CDATA[ - if (!this._formattingEnabled) - return; - - let controller = this.editor.selectionController; - let selection = controller.getSelection(controller.SELECTION_URLSECONDARY); - selection.removeAllRanges(); - ]]></body> - </method> - - <method name="handleRevert"> - <body><![CDATA[ - var isScrolling = this.popupOpen; - - gBrowser.userTypedValue = null; - - // don't revert to last valid url unless page is NOT loading - // and user is NOT key-scrolling through autocomplete list - if (!XULBrowserWindow.isBusy && !isScrolling) { - URLBarSetURI(); - - // If the value isn't empty and the urlbar has focus, select the value. - if (this.value && this.hasAttribute("focused")) - this.select(); - } - - // tell widget to revert to last typed text only if the user - // was scrolling when they hit escape - return !isScrolling; - ]]></body> - </method> - - <method name="handleCommand"> - <parameter name="aTriggeringEvent"/> - <body><![CDATA[ - if (aTriggeringEvent instanceof MouseEvent && aTriggeringEvent.button == 2) - return; // Do nothing for right clicks - - var url = this.value; - var mayInheritPrincipal = false; - var postData = null; - - var action = this._parseActionUrl(url); - if (action) { - url = action.param; - if (this.hasAttribute("actiontype")) { - if (action.type == "switchtab") { - this.handleRevert(); - let prevTab = gBrowser.selectedTab; - if (switchToTabHavingURI(url) && - isTabEmpty(prevTab)) - gBrowser.removeTab(prevTab); - } - return; - } - } - 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); - } - - 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); - } - - // 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(); - - let isMouseEvent = aTriggeringEvent instanceof MouseEvent; - let altEnter = !isMouseEvent && aTriggeringEvent && aTriggeringEvent.altKey; - - 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(); - } - - // If the current tab is empty, ignore Alt+Enter (just reuse this tab) - altEnter = altEnter && !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 (where == "current") { - loadCurrent(); - } else { - this.handleRevert(); - let params = { allowThirdPartyFixup: true, - postData: postData, - initiatingDoc: document }; - openUILinkIn(url, where, params); - } - } else { - loadCurrent(); - } - ]]></body> - </method> - - <method name="_canonizeURL"> - <parameter name="aTriggeringEvent"/> - <body><![CDATA[ - var url = this.value; - if (!url) - return ["", null, false]; - - // 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. - if (/^\s*[^.:\/\s]+(?:\/.*|\s*)$/i.test(url) && - (aTriggeringEvent instanceof KeyEvent)) { -#ifdef XP_MACOSX - let accel = aTriggeringEvent.metaKey; -#else - let accel = aTriggeringEvent.ctrlKey; -#endif - let shift = aTriggeringEvent.shiftKey; - - let suffix = ""; - - switch (true) { - case (accel && shift): - suffix = ".org/"; - break; - case (shift): - suffix = ".net/"; - break; - case (accel): - try { - suffix = gPrefService.getCharPref("browser.fixup.alternate.suffix"); - if (suffix.charAt(suffix.length - 1) != "/") - suffix += "/"; - } catch(e) { - suffix = ".com/"; - } - break; - } - - if (suffix) { - // trim leading/trailing spaces (bug 233205) - url = url.trim(); - - // Tack www. and suffix on. If user has appended directories, insert - // suffix before them (bug 279035). Be careful not to get two slashes. - - let firstSlash = url.indexOf("/"); - - if (firstSlash >= 0) { - url = url.substring(0, firstSlash) + suffix + - url.substring(firstSlash + 1); - } else { - url = url + suffix; - } - - url = "http://www." + url; - } - } - - var postData = {}; - var mayInheritPrincipal = { value: false }; - url = getShortcutOrURI(url, postData, mayInheritPrincipal); - - return [url, postData.value, mayInheritPrincipal.value]; - ]]></body> - </method> - - <field name="_contentIsCropped">false</field> - - <method name="_initURLTooltip"> - <body><![CDATA[ - if (this.focused || !this._contentIsCropped) - return; - this.inputField.setAttribute("tooltiptext", this.value); - ]]></body> - </method> - - <method name="_hideURLTooltip"> - <body><![CDATA[ - this.inputField.removeAttribute("tooltiptext"); - ]]></body> - </method> - - <method name="onDragOver"> - <parameter name="aEvent"/> - <body> - var types = aEvent.dataTransfer.types; - if (types.contains("application/x-moz-file") || - types.contains("text/x-moz-url") || - types.contains("text/uri-list") || - types.contains("text/unicode")) - aEvent.preventDefault(); - </body> - </method> - - <method name="onDrop"> - <parameter name="aEvent"/> - <body><![CDATA[ - let url = browserDragAndDrop.drop(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) { - aEvent.preventDefault(); - this.value = url; - SetPageProxyState("invalid"); - this.focus(); - try { - urlSecurityCheck(url, - gBrowser.contentPrincipal, - Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); - } catch (ex) { - return; - } - this.handleCommand(); - // Force not showing the dropped URI immediately. - gBrowser.userTypedValue = null; - URLBarSetURI(); - } - ]]></body> - </method> - - <method name="_getSelectedValueForClipboard"> - <body><![CDATA[ - // Grab the actual input field's value, not our value, which could include moz-action: - var inputVal = this.inputField.value; - var selectedVal = inputVal.substring(this.selectionStart, this.selectionEnd); - - // If the selection doesn't start at the beginning or doesn't span the full domain or - // the URL bar is modified, nothing else to do here. - if (this.selectionStart > 0 || this.valueIsTyped) - return selectedVal; - // The selection doesn't span the full domain if it doesn't contain a slash and is - // followed by some character other than a slash. - if (!selectedVal.includes("/")) { - let remainder = inputVal.replace(selectedVal, ""); - if (remainder != "" && remainder[0] != "/") - return selectedVal; - } - - let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup); - - let uri; - try { - uri = uriFixup.createFixupURI(inputVal, Ci.nsIURIFixup.FIXUP_FLAG_NONE); - } catch (e) {} - if (!uri) - return selectedVal; - - // Only copy exposable URIs - try { - uri = uriFixup.createExposableURI(uri); - } catch (ex) {} - - // If the entire URL is selected, just use the actual loaded URI. - if (inputVal == selectedVal) { - // ... but only if isn't a javascript: or data: URI, since those - // are hard to read when encoded - if (!uri.schemeIs("javascript") && !uri.schemeIs("data")) { - // Parentheses are known to confuse third-party applications (bug 458565). - selectedVal = uri.spec.replace(/[()]/g, function (c) escape(c)); - } - - return selectedVal; - } - - // Just the beginning of the URL is selected, check for a trimmed - // value - let spec = uri.spec; - let trimmedSpec = this.trimValue(spec); - if (spec != trimmedSpec) { - // Prepend the portion that trimValue removed from the beginning. - // This assumes trimValue will only truncate the URL at - // the beginning or end (or both). - let trimmedSegments = spec.split(trimmedSpec); - selectedVal = trimmedSegments[0] + selectedVal; - } - - return selectedVal; - ]]></body> - </method> - - <field name="_copyCutController"><![CDATA[ - ({ - urlbar: this, - doCommand: function(aCommand) { - var urlbar = this.urlbar; - var val = urlbar._getSelectedValueForClipboard(); - if (!val) - return; - - if (aCommand == "cmd_cut" && this.isCommandEnabled(aCommand)) { - let start = urlbar.selectionStart; - let end = urlbar.selectionEnd; - urlbar.inputField.value = urlbar.inputField.value.substring(0, start) + - urlbar.inputField.value.substring(end); - urlbar.selectionStart = urlbar.selectionEnd = start; - urlbar.removeAttribute("actiontype"); - SetPageProxyState("invalid"); - } - - Cc["@mozilla.org/widget/clipboardhelper;1"] - .getService(Ci.nsIClipboardHelper) - .copyString(val, document); - }, - supportsCommand: function(aCommand) { - switch (aCommand) { - case "cmd_copy": - case "cmd_cut": - return true; - } - return false; - }, - isCommandEnabled: function(aCommand) { - return this.supportsCommand(aCommand) && - (aCommand != "cmd_cut" || !this.urlbar.readOnly) && - this.urlbar.selectionStart < this.urlbar.selectionEnd; - }, - onEvent: function(aEventName) {} - }) - ]]></field> - - <method name="observe"> - <parameter name="aSubject"/> - <parameter name="aTopic"/> - <parameter name="aData"/> - <body><![CDATA[ - if (aTopic == "nsPref:changed") { - switch (aData) { - case "clickSelectsAll": - case "doubleClickSelectsAll": - this[aData] = this._prefs.getBoolPref(aData); - break; - case "autoFill": - this.completeDefaultIndex = this._prefs.getBoolPref(aData); - break; - case "delay": - this.timeout = this._prefs.getIntPref(aData); - break; - case "formatting.enabled": - this._formattingEnabled = this._prefs.getBoolPref(aData); - break; - case "trimURLs": - this._mayTrimURLs = this._prefs.getBoolPref(aData); - break; - } - } - ]]></body> - </method> - - <method name="handleEvent"> - <parameter name="aEvent"/> - <body><![CDATA[ - switch (aEvent.type) { - case "mousedown": - if (this.doubleClickSelectsAll && - aEvent.button == 0 && aEvent.detail == 2) { - this.editor.selectAll(); - aEvent.preventDefault(); - } - break; - case "mousemove": - this._initURLTooltip(); - break; - case "mouseout": - this._hideURLTooltip(); - break; - case "overflow": - this._contentIsCropped = true; - break; - case "underflow": - this._contentIsCropped = false; - this._hideURLTooltip(); - break; - } - ]]></body> - </method> - - <property name="textValue" - onget="return this.value;"> - <setter> - <![CDATA[ - try { - val = losslessDecodeURI(makeURI(val)); - } catch (ex) { } - - // Trim popup selected values, but never trim results coming from - // autofill. - if (this.popup.selectedIndex == -1) - this._disableTrim = true; - this.value = val; - this._disableTrim = false; - - // Completing a result should simulate the user typing the result, so - // fire an input event. - let evt = document.createEvent("UIEvents"); - evt.initUIEvent("input", true, false, window, 0); - this.mIgnoreInput = true; - this.dispatchEvent(evt); - this.mIgnoreInput = false; - - return this.value; - ]]> - </setter> - </property> - - <method name="_parseActionUrl"> - <parameter name="aUrl"/> - <body><![CDATA[ - if (!aUrl.startsWith("moz-action:")) - return null; - - // url is in the format moz-action:ACTION,PARAM - let [, action, param] = aUrl.match(/^moz-action:([^,]+),(.*)$/); - return {type: action, param: param}; - ]]></body> - </method> - - <field name="_noActionsKeys"><![CDATA[ - new Set(); - ]]></field> - - <method name="_clearNoActions"> - <parameter name="aURL"/> - <body><![CDATA[ - this._noActionsKeys.clear(); - this.popup.removeAttribute("noactions"); - let action = this._parseActionUrl(this._value); - if (action) - this.setAttribute("actiontype", action.type); - ]]></body> - </method> - </implementation> - - <handlers> - <handler event="keydown"><![CDATA[ - if ((event.keyCode === KeyEvent.DOM_VK_ALT || - event.keyCode === KeyEvent.DOM_VK_SHIFT) && - this.popup.selectedIndex >= 0 && - !this._noActionsKeys.has(event.keyCode)) { - if (this._noActionsKeys.size == 0) { - this.popup.setAttribute("noactions", "true"); - this.removeAttribute("actiontype"); - } - this._noActionsKeys.add(event.keyCode); - } - ]]></handler> - - <handler event="keyup"><![CDATA[ - if ((event.keyCode === KeyEvent.DOM_VK_ALT || - event.keyCode === KeyEvent.DOM_VK_SHIFT) && - this._noActionsKeys.has(event.keyCode)) { - this._noActionsKeys.delete(event.keyCode); - if (this._noActionsKeys.size == 0) - this._clearNoActions(); - } - ]]></handler> - - <handler event="blur"><![CDATA[ - if (event.originalTarget != this.inputField) - return; - this._clearNoActions(); - this.formatValue(); - ]]></handler> - - <handler event="dragstart" phase="capturing"><![CDATA[ - // Drag only if the gesture starts from the input field. - if (event.originalTarget != this.inputField) - return; - - // Drag only if the entire value is selected and it's a valid URI. - var isFullSelection = this.selectionStart == 0 && - this.selectionEnd == this.textLength; - if (!isFullSelection || - this.getAttribute("pageproxystate") != "valid") - return; - - var urlString = content.location.href; - var title = content.document.title || urlString; - var htmlString = "<a href=\"" + urlString + "\">" + urlString + "</a>"; - - var dt = event.dataTransfer; - dt.setData("text/x-moz-url", urlString + "\n" + title); - dt.setData("text/unicode", urlString); - dt.setData("text/html", htmlString); - - dt.effectAllowed = "copyLink"; - event.stopPropagation(); - ]]></handler> - - <handler event="focus" phase="capturing"><![CDATA[ - if (event.originalTarget != this.inputField) - return; - this._hideURLTooltip(); - this._clearFormatting(); - ]]></handler> - - <handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/> - <handler event="drop" phase="capturing" action="this.onDrop(event, this);"/> - <handler event="select"><![CDATA[ - if (!Cc["@mozilla.org/widget/clipboard;1"] - .getService(Ci.nsIClipboard) - .supportsSelectionClipboard()) - return; - - // Check if this selection was actually user-generated, and exit if not - // to prevent copying the selection (e.g autofill) to clipboard/primary - if (!window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .isHandlingUserInput) - return; - - var val = this._getSelectedValueForClipboard(); - if (!val) - return; - - Cc["@mozilla.org/widget/clipboardhelper;1"] - .getService(Ci.nsIClipboardHelper) - .copyStringToClipboard(val, Ci.nsIClipboard.kSelectionClipboard, document); - ]]></handler> - </handlers> - - </binding> - - <!-- Note: this binding is applied to the autocomplete popup used in the Search bar and in web page content --> - <binding id="browser-autocomplete-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-result-popup"> - <implementation> - <method name="openAutocompletePopup"> - <parameter name="aInput"/> - <parameter name="aElement"/> - <body> - <![CDATA[ - // initially the panel is hidden - // to avoid impacting startup / new window performance - aInput.popup.hidden = false; - - // this method is defined on the base binding - this._openAutocompletePopup(aInput, aElement); - ]]></body> - </method> - - <method name="onPopupClick"> - <parameter name="aEvent"/> - <body><![CDATA[ - // Ignore all right-clicks - if (aEvent.button == 2) - return; - - var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController); - - // Check for unmodified left-click, and use default behavior - if (aEvent.button == 0 && !aEvent.shiftKey && !aEvent.ctrlKey && - !aEvent.altKey && !aEvent.metaKey) { - controller.handleEnter(true); - return; - } - - // Check for middle-click or modified clicks on the search bar - var searchBar = BrowserSearch.searchBar; - if (searchBar && searchBar.textbox == this.mInput) { - // Handle search bar popup clicks - var search = controller.getValueAt(this.selectedIndex); - - // close the autocomplete popup and revert the entered search term - this.closePopup(); - controller.handleEscape(); - - // Fill in the search bar's value - searchBar.value = search; - - // open the search results according to the clicking subtlety - var where = whereToOpenLink(aEvent, false, true); - searchBar.doSearch(search, where); - } - ]]></body> - </method> - </implementation> - </binding> - - <binding id="urlbar-rich-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup"> - <implementation> - <field name="_maxResults">0</field> - - <field name="_bundle" readonly="true"> - Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService). - createBundle("chrome://browser/locale/places/places.properties"); - </field> - - <property name="maxResults" readonly="true"> - <getter> - <![CDATA[ - if (!this._maxResults) { - var prefService = - Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); - this._maxResults = prefService.getIntPref("browser.urlbar.maxRichResults"); - } - return this._maxResults; - ]]> - </getter> - </property> - - <method name="openAutocompletePopup"> - <parameter name="aInput"/> - <parameter name="aElement"/> - <body> - <![CDATA[ - // initially the panel is hidden - // to avoid impacting startup / new window performance - aInput.popup.hidden = false; - - // this method is defined on the base binding - this._openAutocompletePopup(aInput, aElement); - ]]></body> - </method> - - <method name="onPopupClick"> - <parameter name="aEvent"/> - <body> - <![CDATA[ - // Ignore right-clicks - if (aEvent.button == 2) - return; - - var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController); - - // Check for unmodified left-click, and use default behavior - if (aEvent.button == 0 && !aEvent.shiftKey && !aEvent.ctrlKey && - !aEvent.altKey && !aEvent.metaKey) { - controller.handleEnter(true); - return; - } - - // Check for middle-click or modified clicks on the URL bar - if (gURLBar && this.mInput == gURLBar) { - var url = controller.getValueAt(this.selectedIndex); - - // close the autocomplete popup and revert the entered address - this.closePopup(); - controller.handleEscape(); - - // Check if this is meant to be an action - let action = this.mInput._parseActionUrl(url); - if (action) { - if (action.type == "switchtab") - url = action.param; - else - return; - } - - // respect the usual clicking subtleties - openUILink(url, aEvent); - } - ]]> - </body> - </method> - - <method name="createResultLabel"> - <parameter name="aTitle"/> - <parameter name="aUrl"/> - <parameter name="aType"/> - <body> - <![CDATA[ - var label = aTitle + " " + aUrl; - // convert aType (ex: "ac-result-type-<aType>") to text to be spoke aloud - // by screen readers. convert "tag" and "bookmark" to the localized versions, - // but don't do anything for "favicon" (the default) - if (aType != "favicon") { - label += " " + this._bundle.GetStringFromName(aType + "ResultLabel"); - } - return label; - ]]> - </body> - </method> - - </implementation> - </binding> - - <binding id="addon-progress-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification"> - <content align="start"> - <xul:image class="popup-notification-icon" - xbl:inherits="popupid,src=icon"/> - <xul:vbox flex="1"> - <xul:description class="popup-notification-description addon-progress-description" - xbl:inherits="xbl:text=label"/> - <xul:spacer flex="1"/> - <xul:hbox align="center"> - <xul:progressmeter anonid="progressmeter" flex="1" mode="undetermined" class="popup-progress-meter"/> - <xul:button anonid="cancel" class="popup-progress-cancel" oncommand="document.getBindingParent(this).cancel()"/> - </xul:hbox> - <xul:label anonid="progresstext" class="popup-progress-label"/> - <xul:hbox class="popup-notification-button-container" - pack="end" align="center"> - <xul:button anonid="button" - class="popup-notification-menubutton" - type="menu-button" - xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey"> - <xul:menupopup anonid="menupopup" - xbl:inherits="oncommand=menucommand"> - <children/> - <xul:menuitem class="menuitem-iconic popup-notification-closeitem close-icon" - label="&closeNotificationItem.label;" - xbl:inherits="oncommand=closeitemcommand"/> - </xul:menupopup> - </xul:button> - </xul:hbox> - </xul:vbox> - <xul:vbox pack="start"> - <xul:toolbarbutton anonid="closebutton" - class="messageCloseButton close-icon popup-notification-closebutton tabbable" - xbl:inherits="oncommand=closebuttoncommand" - tooltiptext="&closeNotification.tooltip;"/> - </xul:vbox> - </content> - <implementation> - <constructor><![CDATA[ - this.cancelbtn.setAttribute("tooltiptext", gNavigatorBundle.getString("addonDownloadCancelTooltip")); - - this.notification.options.installs.forEach(function(aInstall) { - aInstall.addListener(this); - }, this); - - // Calling updateProgress can sometimes cause this notification to be - // removed in the middle of refreshing the notification panel which - // makes the panel get refreshed again. Just initialise to the - // undetermined state and then schedule a proper check at the next - // opportunity - this.setProgress(0, -1); - this._updateProgressTimeout = setTimeout(this.updateProgress.bind(this), 0); - ]]></constructor> - - <destructor><![CDATA[ - this.destroy(); - ]]></destructor> - - <field name="progressmeter" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "progressmeter"); - </field> - <field name="progresstext" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "progresstext"); - </field> - <field name="cancelbtn" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "cancel"); - </field> - <field name="DownloadUtils" readonly="true"> - let utils = {}; - Components.utils.import("resource://gre/modules/DownloadUtils.jsm", utils); - utils.DownloadUtils; - </field> - - <method name="destroy"> - <body><![CDATA[ - this.notification.options.installs.forEach(function(aInstall) { - aInstall.removeListener(this); - }, this); - clearTimeout(this._updateProgressTimeout); - ]]></body> - </method> - - <method name="setProgress"> - <parameter name="aProgress"/> - <parameter name="aMaxProgress"/> - <body><![CDATA[ - if (aMaxProgress == -1) { - this.progressmeter.mode = "undetermined"; - } - else { - this.progressmeter.mode = "determined"; - this.progressmeter.value = (aProgress * 100) / aMaxProgress; - } - - let now = Date.now(); - - if (!this.notification.lastUpdate) { - this.notification.lastUpdate = now; - this.notification.lastProgress = aProgress; - return; - } - - let delta = now - this.notification.lastUpdate; - if ((delta < 400) && (aProgress < aMaxProgress)) - return; - - delta /= 1000; - - // This code is taken from nsDownloadManager.cpp - let speed = (aProgress - this.notification.lastProgress) / delta; - if (this.notification.speed) - speed = speed * 0.9 + this.notification.speed * 0.1; - - this.notification.lastUpdate = now; - this.notification.lastProgress = aProgress; - this.notification.speed = speed; - - let status = null; - [status, this.notification.last] = this.DownloadUtils.getDownloadStatus(aProgress, aMaxProgress, speed, this.notification.last); - this.progresstext.value = status; - ]]></body> - </method> - - <method name="cancel"> - <body><![CDATA[ - // Cache these as cancelling the installs will remove this - // notification which will drop these references - let browser = this.notification.browser; - let contentWindow = this.notification.options.contentWindow; - let sourceURI = this.notification.options.sourceURI; - - let installs = this.notification.options.installs; - installs.forEach(function(aInstall) { - try { - aInstall.cancel(); - } - catch (e) { - // Cancel will throw if the download has already failed - } - }, this); - - let anchorID = "addons-notification-icon"; - let notificationID = "addon-install-cancelled"; - let messageString = gNavigatorBundle.getString("addonDownloadCancelled"); - messageString = PluralForm.get(installs.length, messageString); - let buttonText = gNavigatorBundle.getString("addonDownloadRestart"); - buttonText = PluralForm.get(installs.length, buttonText); - - let action = { - label: buttonText, - accessKey: gNavigatorBundle.getString("addonDownloadRestart.accessKey"), - callback: function() { - let weblistener = Cc["@mozilla.org/addons/web-install-listener;1"]. - getService(Ci.amIWebInstallListener); - if (weblistener.onWebInstallRequested(contentWindow, sourceURI, - installs, installs.length)) { - installs.forEach(function(aInstall) { - aInstall.install(); - }); - } - } - }; - - PopupNotifications.show(browser, notificationID, messageString, - anchorID, action); - ]]></body> - </method> - - <method name="updateProgress"> - <body><![CDATA[ - let downloadingCount = 0; - let progress = 0; - let maxProgress = 0; - - this.notification.options.installs.forEach(function(aInstall) { - if (aInstall.maxProgress == -1) - maxProgress = -1; - progress += aInstall.progress; - if (maxProgress >= 0) - maxProgress += aInstall.maxProgress; - if (aInstall.state < AddonManager.STATE_DOWNLOADED) - downloadingCount++; - }); - - if (downloadingCount == 0) { - this.destroy(); - PopupNotifications.remove(this.notification); - } - else { - this.setProgress(progress, maxProgress); - } - ]]></body> - </method> - - <method name="onDownloadProgress"> - <body><![CDATA[ - this.updateProgress(); - ]]></body> - </method> - - <method name="onDownloadFailed"> - <body><![CDATA[ - this.updateProgress(); - ]]></body> - </method> - - <method name="onDownloadCancelled"> - <body><![CDATA[ - this.updateProgress(); - ]]></body> - </method> - - <method name="onDownloadEnded"> - <body><![CDATA[ - this.updateProgress(); - ]]></body> - </method> - </implementation> - </binding> - - <binding id="plugin-popupnotification-center-item"> - <content align="center"> - <xul:vbox pack="center" anonid="itemBox" class="itemBox"> - <xul:description anonid="center-item-label" class="center-item-label" /> - <xul:hbox flex="1" pack="start" align="center" anonid="center-item-warning"> - <xul:image anonid="center-item-warning-icon" class="center-item-warning-icon"/> - <xul:label anonid="center-item-warning-label"/> - <xul:label anonid="center-item-link" value="&checkForUpdates;" class="text-link"/> - </xul:hbox> - </xul:vbox> - <xul:vbox pack="center"> - <xul:menulist class="center-item-menulist" - anonid="center-item-menulist"> - <xul:menupopup> - <xul:menuitem anonid="allownow" value="allownow" - label="&pluginActivateNow.label;" /> - <xul:menuitem anonid="allowalways" value="allowalways" - label="&pluginActivateAlways.label;" /> - <xul:menuitem anonid="block" value="block" - label="&pluginBlockNow.label;" /> - </xul:menupopup> - </xul:menulist> - </xul:vbox> - </content> - <resources> - <stylesheet src="chrome://global/skin/notification.css"/> - </resources> - <implementation> - <constructor><![CDATA[ - document.getAnonymousElementByAttribute(this, "anonid", "center-item-label").value = this.action.pluginName; - - let curState = "block"; - if (this.action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) { - if (this.action.pluginPermissionType == Ci.nsIPermissionManager.EXPIRE_SESSION) { - curState = "allownow"; - } - else { - curState = "allowalways"; - } - } - document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").value = curState; - - let warningString = ""; - let linkString = ""; - - let link = document.getAnonymousElementByAttribute(this, "anonid", "center-item-link"); - - let url; - let linkHandler; - - if (this.action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED) { - document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").hidden = true; - warningString = gNavigatorBundle.getString("pluginActivateDisabled.label"); - linkString = gNavigatorBundle.getString("pluginActivateDisabled.manage"); - linkHandler = function(event) { - event.preventDefault(); - gPluginHandler.managePlugins(); - }; - document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning-icon").hidden = true; - } - else { - url = this.action.detailsLink; - - switch (this.action.blocklistState) { - case Ci.nsIBlocklistService.STATE_NOT_BLOCKED: - document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning").hidden = true; - break; - case Ci.nsIBlocklistService.STATE_BLOCKED: - document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").hidden = true; - warningString = gNavigatorBundle.getString("pluginActivateBlocked.label"); - linkString = gNavigatorBundle.getString("pluginActivate.learnMore"); - break; - case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE: - warningString = gNavigatorBundle.getString("pluginActivateOutdated.label"); - linkString = gNavigatorBundle.getString("pluginActivate.updateLabel"); - break; - case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE: - warningString = gNavigatorBundle.getString("pluginActivateVulnerable.label"); - linkString = gNavigatorBundle.getString("pluginActivate.riskLabel"); - break; - } - } - document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning-label").value = warningString; - - if (url || linkHandler) { - link.value = linkString; - if (url) { - link.href = url; - } - if (linkHandler) { - link.addEventListener("click", linkHandler, false); - } - } - else { - link.hidden = true; - } - ]]></constructor> - <property name="value"> - <getter> - return document.getAnonymousElementByAttribute(this, "anonid", - "center-item-menulist").value; - </getter> - <setter><!-- This should be used only in automated tests --> - document.getAnonymousElementByAttribute(this, "anonid", - "center-item-menulist").value = val; - </setter> - </property> - </implementation> - </binding> - - <binding id="click-to-play-plugins-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification"> - <content align="start" class="click-to-play-plugins-notification-content"> - <xul:vbox flex="1" align="stretch" class="popup-notification-main-box" - xbl:inherits="popupid"> - <xul:hbox class="click-to-play-plugins-notification-description-box" flex="1" align="start"> - <xul:description class="click-to-play-plugins-outer-description" flex="1"> - <html:span anonid="click-to-play-plugins-notification-description" /> - <xul:label class="text-link click-to-play-plugins-notification-link" anonid="click-to-play-plugins-notification-link" /> - </xul:description> - <xul:toolbarbutton anonid="closebutton" - class="messageCloseButton close-icon popup-notification-closebutton tabbable" - xbl:inherits="oncommand=closebuttoncommand" - tooltiptext="&closeNotification.tooltip;"/> - </xul:hbox> - <xul:grid anonid="click-to-play-plugins-notification-center-box" - class="click-to-play-plugins-notification-center-box"> - <xul:columns> - <xul:column flex="1"/> - <xul:column/> - </xul:columns> - <xul:rows> - <children includes="row"/> - <xul:hbox pack="start" anonid="plugin-notification-showbox"> - <xul:button label="&pluginNotification.showAll.label;" - accesskey="&pluginNotification.showAll.accesskey;" - class="plugin-notification-showbutton" - oncommand="document.getBindingParent(this)._setState(2)"/> - </xul:hbox> - </xul:rows> - </xul:grid> - <xul:hbox anonid="button-container" - class="click-to-play-plugins-notification-button-container" - pack="center" align="center"> - <xul:button anonid="primarybutton" - class="click-to-play-popup-button primary-button" - oncommand="document.getBindingParent(this)._onButton(this)" - flex="1"/> - <xul:button anonid="secondarybutton" - class="click-to-play-popup-button" - oncommand="document.getBindingParent(this)._onButton(this);" - flex="1"/> - </xul:hbox> - <xul:box hidden="true"> - <children/> - </xul:box> - </xul:vbox> - </content> - <resources> - <stylesheet src="chrome://global/skin/notification.css"/> - </resources> - <implementation> - <field name="_states"> - ({SINGLE: 0, MULTI_COLLAPSED: 1, MULTI_EXPANDED: 2}) - </field> - <field name="_primaryButton"> - document.getAnonymousElementByAttribute(this, "anonid", "primarybutton"); - </field> - <field name="_secondaryButton"> - document.getAnonymousElementByAttribute(this, "anonid", "secondarybutton") - </field> - <field name="_buttonContainer"> - document.getAnonymousElementByAttribute(this, "anonid", "button-container") - </field> - <field name="_brandShortName"> - document.getElementById("bundle_brand").getString("brandShortName") - </field> - <field name="_items">[]</field> - <constructor><![CDATA[ - const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - for (let action of this.notification.options.centerActions) { - let item = document.createElementNS(XUL_NS, "row"); - item.setAttribute("class", "plugin-popupnotification-centeritem"); - item.action = action; - this.appendChild(item); - this._items.push(item); - } - switch (this.notification.options.centerActions.length) { - case 0: - PopupNotifications._dismiss(); - break; - case 1: - this._setState(this._states.SINGLE); - break; - default: - if (this.notification.options.primaryPlugin) { - this._setState(this._states.MULTI_COLLAPSED); - } else { - this._setState(this._states.MULTI_EXPANDED); - } - } - ]]></constructor> - <method name="_setState"> - <parameter name="state" /> - <body><![CDATA[ - var grid = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-center-box"); - - if (this._states.SINGLE == state) { - grid.hidden = true; - this._setupSingleState(); - return; - } - - let host = gPluginHandler._getHostFromPrincipal(this.notification.browser.contentWindow.document.nodePrincipal); - this._setupDescription("pluginActivateMultiple.message", null, host); - - var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox"); - - var dialogStrings = Services.strings.createBundle("chrome://global/locale/dialog.properties"); - this._primaryButton.label = dialogStrings.GetStringFromName("button-accept"); - this._primaryButton.setAttribute("default", "true"); - - this._secondaryButton.label = dialogStrings.GetStringFromName("button-cancel"); - this._primaryButton.setAttribute("action", "_multiAccept"); - this._secondaryButton.setAttribute("action", "_cancel"); - - grid.hidden = false; - - if (this._states.MULTI_COLLAPSED == state) { - for (let child of this.childNodes) { - if (child.tagName != "row") { - continue; - } - child.hidden = this.notification.options.primaryPlugin != - child.action.permissionString; - } - showBox.hidden = false; - } - else { - for (let child of this.childNodes) { - if (child.tagName != "row") { - continue; - } - child.hidden = false; - } - showBox.hidden = true; - } - this._setupLink(null); - ]]></body> - </method> - <method name="_setupSingleState"> - <body><![CDATA[ - var action = this.notification.options.centerActions[0]; - var host = action.pluginPermissionHost; - - let label, linkLabel, linkUrl, button1, button2; - - if (action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) { - button1 = { - label: "pluginBlockNow.label", - accesskey: "pluginBlockNow.accesskey", - action: "_singleBlock" - }; - button2 = { - label: "pluginContinue.label", - accesskey: "pluginContinue.accesskey", - action: "_singleContinue", - default: true - }; - switch (action.blocklistState) { - case Ci.nsIBlocklistService.STATE_NOT_BLOCKED: - label = "pluginEnabled.message"; - linkLabel = "pluginActivate.learnMore"; - break; - - case Ci.nsIBlocklistService.STATE_BLOCKED: - Cu.reportError(Error("Cannot happen!")); - break; - - case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE: - label = "pluginEnabledOutdated.message"; - linkLabel = "pluginActivate.updateLabel"; - break; - - case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE: - label = "pluginEnabledVulnerable.message"; - linkLabel = "pluginActivate.riskLabel" - break; - - default: - Cu.reportError(Error("Unexpected blocklist state")); - } - } - else if (action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED) { - let linkElement = - document.getAnonymousElementByAttribute( - this, "anonid", "click-to-play-plugins-notification-link"); - linkElement.textContent = gNavigatorBundle.getString("pluginActivateDisabled.manage"); - linkElement.setAttribute("onclick", "gPluginHandler.managePlugins()"); - - let descElement = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description"); - descElement.textContent = gNavigatorBundle.getFormattedString( - "pluginActivateDisabled.message", [action.pluginName, this._brandShortName]) + " "; - this._buttonContainer.hidden = true; - return; - } - else if (action.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) { - let descElement = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description"); - descElement.textContent = gNavigatorBundle.getFormattedString( - "pluginActivateBlocked.message", [action.pluginName, this._brandShortName]) + " "; - this._setupLink("pluginActivate.learnMore", action.detailsLink); - this._buttonContainer.hidden = true; - return; - } - else { - button1 = { - label: "pluginActivateNow.label", - accesskey: "pluginActivateNow.accesskey", - action: "_singleActivateNow" - }; - button2 = { - label: "pluginActivateAlways.label", - accesskey: "pluginActivateAlways.accesskey", - action: "_singleActivateAlways" - }; - switch (action.blocklistState) { - case Ci.nsIBlocklistService.STATE_NOT_BLOCKED: - label = "pluginActivateNew.message"; - linkLabel = "pluginActivate.learnMore"; - button2.default = true; - break; - - case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE: - label = "pluginActivateOutdated.message"; - linkLabel = "pluginActivate.updateLabel"; - button1.default = true; - break; - - case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE: - label = "pluginActivateVulnerable.message"; - linkLabel = "pluginActivate.riskLabel" - button1.default = true; - break; - - default: - Cu.reportError(Error("Unexpected blocklist state")); - } - } - this._setupDescription(label, action.pluginName, host); - this._setupLink(linkLabel, action.detailsLink); - - this._primaryButton.label = gNavigatorBundle.getString(button1.label); - this._primaryButton.accesskey = gNavigatorBundle.getString(button1.accesskey); - this._primaryButton.setAttribute("action", button1.action); - - this._secondaryButton.label = gNavigatorBundle.getString(button2.label); - this._secondaryButton.accesskey = gNavigatorBundle.getString(button2.accesskey); - this._secondaryButton.setAttribute("action", button2.action); - if (button1.default) { - this._primaryButton.setAttribute("default", "true"); - } - else if (button2.default) { - this._secondaryButton.setAttribute("default", "true"); - } - ]]></body> - </method> - <method name="_setupDescription"> - <parameter name="baseString" /> - <parameter name="pluginName" /> <!-- null for the multiple-plugin case --> - <parameter name="host" /> - <body><![CDATA[ - var bsn = this._brandShortName; - var span = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description"); - while (span.lastChild) { - span.removeChild(span.lastChild); - } - - var args = ["__host__", this._brandShortName]; - if (pluginName) { - args.unshift(pluginName); - } - var bases = gNavigatorBundle.getFormattedString(baseString, args). - split("__host__", 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); - span.appendChild(document.createTextNode(bases[1] + " ")); - ]]></body> - </method> - <method name="_setupLink"> - <parameter name="linkString"/> - <parameter name="linkUrl" /> - <body><![CDATA[ - var link = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-link"); - if (!linkString || !linkUrl) { - link.hidden = true; - return; - } - - link.hidden = false; - link.textContent = gNavigatorBundle.getString(linkString); - link.href = linkUrl; - ]]></body> - </method> - <method name="_onButton"> - <parameter name="aButton" /> - <body><![CDATA[ - let methodName = aButton.getAttribute("action"); - this[methodName](); - ]]></body> - </method> - <method name="_singleActivateNow"> - <body><![CDATA[ - gPluginHandler._updatePluginPermission(this.notification, - this.notification.options.centerActions[0], - "allownow"); - this._cancel(); - ]]></body> - </method> - <method name="_singleBlock"> - <body><![CDATA[ - gPluginHandler._updatePluginPermission(this.notification, - this.notification.options.centerActions[0], - "block"); - this._cancel(); - ]]></body> - </method> - <method name="_singleActivateAlways"> - <body><![CDATA[ - gPluginHandler._updatePluginPermission(this.notification, - this.notification.options.centerActions[0], - "allowalways"); - this._cancel(); - ]]></body> - </method> - <method name="_singleContinue"> - <body><![CDATA[ - gPluginHandler._updatePluginPermission(this.notification, - this.notification.options.centerActions[0], - "continue"); - this._cancel(); - ]]></body> - </method> - <method name="_multiAccept"> - <body><![CDATA[ - for (let item of this._items) { - let action = item.action; - if (action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED || - action.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) { - continue; - } - gPluginHandler._updatePluginPermission(this.notification, - item.action, item.value); - } - this._cancel(); - ]]></body> - </method> - <method name="_cancel"> - <body><![CDATA[ - PopupNotifications._dismiss(); - ]]></body> - </method> - <method name="_accept"> - <parameter name="aEvent" /> - <body><![CDATA[ - if (aEvent.defaultPrevented) - return; - aEvent.preventDefault(); - if (this._primaryButton.getAttribute("default") == "true") { - this._primaryButton.click(); - } - else if (this._secondaryButton.getAttribute("default") == "true") { - this._secondaryButton.click(); - } - ]]></body> - </method> - </implementation> - <handlers> - <!-- The _accept method checks for .defaultPrevented so that if focus is in a button, - enter activates the button and not this default action --> - <handler event="keypress" keycode="VK_ENTER" group="system" action="this._accept(event);"/> - <handler event="keypress" keycode="VK_RETURN" group="system" action="this._accept(event);"/> - </handlers> - </binding> - - <binding id="splitmenu"> - <content> - <xul:hbox anonid="menuitem" flex="1" - class="splitmenu-menuitem" - xbl:inherits="iconic,label,disabled,onclick=oncommand,_moz-menuactive=active"/> - <xul:menu anonid="menu" class="splitmenu-menu" - xbl:inherits="disabled,_moz-menuactive=active" - oncommand="event.stopPropagation();"> - <children includes="menupopup"/> - </xul:menu> - </content> - - <implementation implements="nsIDOMEventListener"> - <constructor><![CDATA[ - this._parentMenupopup.addEventListener("DOMMenuItemActive", this, false); - this._parentMenupopup.addEventListener("popuphidden", this, false); - ]]></constructor> - - <destructor><![CDATA[ - this._parentMenupopup.removeEventListener("DOMMenuItemActive", this, false); - this._parentMenupopup.removeEventListener("popuphidden", this, false); - ]]></destructor> - - <field name="menuitem" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "menuitem"); - </field> - <field name="menu" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "menu"); - </field> - - <field name="_menuDelay">600</field> - - <field name="_parentMenupopup"><![CDATA[ - this._getParentMenupopup(this); - ]]></field> - - <method name="_getParentMenupopup"> - <parameter name="aNode"/> - <body><![CDATA[ - let node = aNode.parentNode; - while (node) { - if (node.localName == "menupopup") - break; - node = node.parentNode; - } - return node; - ]]></body> - </method> - - <method name="handleEvent"> - <parameter name="event"/> - <body><![CDATA[ - switch (event.type) { - case "DOMMenuItemActive": - if (this.getAttribute("active") == "true" && - event.target != this && - this._getParentMenupopup(event.target) == this._parentMenupopup) - this.removeAttribute("active"); - break; - case "popuphidden": - if (event.target == this._parentMenupopup) - this.removeAttribute("active"); - break; - } - ]]></body> - </method> - </implementation> - - <handlers> - <handler event="mouseover"><![CDATA[ - if (this.getAttribute("active") != "true") { - this.setAttribute("active", "true"); - - let event = document.createEvent("Events"); - event.initEvent("DOMMenuItemActive", true, false); - this.dispatchEvent(event); - - if (this.getAttribute("disabled") != "true") { - let self = this; - setTimeout(function () { - if (self.getAttribute("active") == "true") - self.menu.open = true; - }, this._menuDelay); - } - } - ]]></handler> - - <handler event="popupshowing"><![CDATA[ - if (event.target == this.firstChild && - this._parentMenupopup._currentPopup) - this._parentMenupopup._currentPopup.hidePopup(); - ]]></handler> - - <handler event="click" phase="capturing"><![CDATA[ - if (this.getAttribute("disabled") == "true") { - // Prevent the command from being carried out - event.stopPropagation(); - return; - } - - let node = event.originalTarget; - while (true) { - if (node == this.menuitem) - break; - if (node == this) - return; - node = node.parentNode; - } - - this._parentMenupopup.hidePopup(); - ]]></handler> - </handlers> - </binding> - - <binding id="menuitem-tooltip" extends="chrome://global/content/bindings/menu.xml#menuitem"> - <implementation> - <constructor><![CDATA[ - this.setAttribute("tooltiptext", this.getAttribute("acceltext")); - // TODO: Simplify this to this.setAttribute("acceltext", "") once bug - // 592424 is fixed - document.getAnonymousElementByAttribute(this, "anonid", "accel").firstChild.setAttribute("value", ""); - ]]></constructor> - </implementation> - </binding> - - <binding id="menuitem-iconic-tooltip" extends="chrome://global/content/bindings/menu.xml#menuitem-iconic"> - <implementation> - <constructor><![CDATA[ - this.setAttribute("tooltiptext", this.getAttribute("acceltext")); - // TODO: Simplify this to this.setAttribute("acceltext", "") once bug - // 592424 is fixed - document.getAnonymousElementByAttribute(this, "anonid", "accel").firstChild.setAttribute("value", ""); - ]]></constructor> - </implementation> - </binding> - - <binding id="promobox"> - <content> - <xul:hbox class="panel-promo-box" align="start" flex="1"> - <xul:hbox align="center" flex="1"> - <xul:image class="panel-promo-icon"/> - <xul:description anonid="promo-message" class="panel-promo-message" flex="1"> - <xul:description anonid="promo-link" - class="plain text-link inline-link" - onclick="document.getBindingParent(this).onLinkClick();"/> - </xul:description> - </xul:hbox> - <xul:toolbarbutton class="panel-promo-closebutton close-icon" - oncommand="document.getBindingParent(this).onCloseButtonCommand();" - tooltiptext="&closeNotification.tooltip;"/> - </xul:hbox> - </content> - - <implementation implements="nsIDOMEventListener"> - <constructor><![CDATA[ - this._panel.addEventListener("popupshowing", this, false); - ]]></constructor> - - <destructor><![CDATA[ - this._panel.removeEventListener("popupshowing", this, false); - ]]></destructor> - - <field name="_panel" readonly="true"><![CDATA[ - let node = this.parentNode; - while(node && node.localName != "panel") { - node = node.parentNode; - } - node; - ]]></field> - <field name="_promomessage" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "promo-message"); - </field> - <field name="_promolink" readonly="true"> - document.getAnonymousElementByAttribute(this, "anonid", "promo-link"); - </field> - <field name="_brandBundle" readonly="true"> - Services.strings.createBundle("chrome://branding/locale/brand.properties"); - </field> - <property name="_viewsLeftMap"> - <getter><![CDATA[ - let viewsLeftMap = {}; - try { - viewsLeftMap = JSON.parse(Services.prefs.getCharPref("browser.syncPromoViewsLeftMap")); - } catch (ex) { - // If the old preference exists, migrate it to the new one. - try { - let oldPref = Services.prefs.getIntPref("browser.syncPromoViewsLeft"); - Services.prefs.clearUserPref("browser.syncPromoViewsLeft"); - viewsLeftMap.bookmarks = oldPref; - viewsLeftMap.passwords = oldPref; - Services.prefs.setCharPref("browser.syncPromoViewsLeftMap", - JSON.stringify(viewsLeftMap)); - } catch (ex2) {} - } - return viewsLeftMap; - ]]></getter> - </property> - <property name="_viewsLeft"> - <getter><![CDATA[ - let views = 5; - let map = this._viewsLeftMap; - if (this._notificationType in map) { - views = map[this._notificationType]; - } - return views; - ]]></getter> - <setter><![CDATA[ - let map = this._viewsLeftMap; - map[this._notificationType] = val; - Services.prefs.setCharPref("browser.syncPromoViewsLeftMap", - JSON.stringify(map)); - return val; - ]]></setter> - </property> - <property name="_notificationType"> - <getter><![CDATA[ - // Use the popupid attribute to identify the notification type, - // otherwise just rely on the panel id for common arrowpanels. - let type = this._panel.firstChild.getAttribute("popupid") || - this._panel.id; - if (type.startsWith("password-")) - return "passwords"; - if (type == "editBookmarkPanel") - return "bookmarks"; - if (type == "addon-install-complete") { - if (!Services.prefs.prefHasUserValue("services.sync.username")) - return "addons"; - if (!Services.prefs.getBoolPref("services.sync.engine.addons")) - return "addons-sync-disabled"; - } - return null; - ]]></getter> - </property> - <property name="_notificationMessage"> - <getter><![CDATA[ - return gNavigatorBundle.getFormattedString( - "syncPromoNotification." + this._notificationType + ".description", - [this._brandBundle.GetStringFromName("syncBrandShortName")] - ); - ]]></getter> - </property> - <property name="_notificationLink"> - <getter><![CDATA[ - if (this._notificationType == "addons-sync-disabled") { - return "https://forum.palemoon.org/viewforum.php?f=52"; - } - return "http://www.palemoon.org/sync/"; - ]]></getter> - </property> - <method name="onCloseButtonCommand"> - <body><![CDATA[ - this._viewsLeft = 0; - this.hidden = true; - ]]></body> - </method> - <method name="onLinkClick"> - <body><![CDATA[ - // Open a new selected tab and close the current panel. - gBrowser.loadOneTab(this._promolink.getAttribute("href"), - { inBackground: false }); - this._panel.hidePopup(); - ]]></body> - </method> - <method name="handleEvent"> - <parameter name="event"/> - <body><![CDATA[ - if (event.type != "popupshowing" || event.target != this._panel) - return; - - // A previous notification may have unhidden this. - this.hidden = true; - - // Only handle supported notification panels. - if (!this._notificationType) { - return; - } - - let viewsLeft = this._viewsLeft; - if (viewsLeft) { - // XXX: Short-circuit this for now. - // TO-DO: Clean up this code for sync promotion - this._viewsLeft = 0; - viewsLeft = 0; - return; - // XXX - - if (Services.prefs.prefHasUserValue("services.sync.username") && - this._notificationType != "addons-sync-disabled") { - // If the user has already setup Sync, don't show the notification. - this._viewsLeft = 0; - // Be sure to hide the panel, in case it was visible and the user - // decided to setup Sync after noticing it. - viewsLeft = 0; - // The panel is still hidden, just bail out. - return; - } - else { - this._viewsLeft = viewsLeft - 1; - } - - this._promolink.setAttribute("href", this._notificationLink); - this._promolink.value = gNavigatorBundle.getString("syncPromoNotification.learnMoreLinkText"); - - this.hidden = false; - - // HACK: The description element doesn't wrap correctly in panels, - // thus set a width on it, based on the available space, before - // setting its textContent. Then set its height as well, to - // fix wrong height calculation on Linux (bug 659578). - this._panel.addEventListener("popupshown", function panelShown() { - this._panel.removeEventListener("popupshown", panelShown, true); - // Previous popupShown events may close the panel or change - // its contents, so ensure this is still valid. - if (this._panel.state != "open" || !this._notificationType) - return; - this._promomessage.width = this._promomessage.getBoundingClientRect().width; - this._promomessage.firstChild.textContent = this._notificationMessage; - this._promomessage.height = this._promomessage.getBoundingClientRect().height; - }.bind(this), true); - } - ]]></body> - </method> - </implementation> - </binding> - - <binding id="toolbarbutton-badged" display="xul:button" - extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton"> - <content> - <children includes="observes|template|menupopup|panel|tooltip"/> - <xul:hbox class="toolbarbutton-badge-container" align="start" pack="end" flex="1"> - <xul:hbox class="toolbarbutton-badge" xbl:inherits="badge"/> - <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/> - </xul:hbox> - <xul:label class="toolbarbutton-text" crop="right" flex="1" - xbl:inherits="value=label,accesskey,crop"/> - </content> - </binding> - -</bindings> diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js deleted file mode 100644 index b1e78d6a9..000000000 --- a/browser/base/content/utilityOverlay.js +++ /dev/null @@ -1,677 +0,0 @@ -# -*- Mode: javascript; 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/. - -// Services = object with smart getters for common XPCOM services -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); -Components.utils.import("resource:///modules/RecentWindow.jsm"); - -XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () { - const PREF = "browser.newtab.url"; - - function getNewTabPageURL() { - if (!Services.prefs.prefHasUserValue(PREF)) { - if (PrivateBrowsingUtils.isWindowPrivate(window) && - !PrivateBrowsingUtils.permanentPrivateBrowsing) - return "about:privatebrowsing"; - } - return Services.prefs.getCharPref(PREF) || "about:blank"; - } - - function update() { - BROWSER_NEW_TAB_URL = getNewTabPageURL(); - } - - Services.prefs.addObserver(PREF, update, false); - - addEventListener("unload", function onUnload() { - removeEventListener("unload", onUnload); - Services.prefs.removeObserver(PREF, update); - }); - - return getNewTabPageURL(); -}); - -var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab"; - -var gBidiUI = false; - -/** - * Determines whether the given url is considered a special URL for new tabs. - */ -function isBlankPageURL(aURL) { - // Pale Moon: Only make "about:blank", the logopage, or "about:newtab" be - // a "blank page" to fix focus issues. - // Original code: return aURL == "about:blank" || aURL == BROWSER_NEW_TAB_URL; - return aURL == "about:blank" || aURL == "about:newtab" || aURL == "about:logopage"; -} - -function getBrowserURL() -{ - return "chrome://browser/content/browser.xul"; -} - -function getTopWin(skipPopups) { - // If this is called in a browser window, use that window regardless of - // whether it's the frontmost window, since commands can be executed in - // background windows (bug 626148). - if (top.document.documentElement.getAttribute("windowtype") == "navigator:browser" && - (!skipPopups || top.toolbar.visible)) - return top; - - let isPrivate = PrivateBrowsingUtils.isWindowPrivate(window); - return RecentWindow.getMostRecentBrowserWindow({private: isPrivate, - allowPopups: !skipPopups}); -} - -function openTopWin(url) { - /* deprecated */ - openUILinkIn(url, "current"); -} - -function getBoolPref(prefname, def) -{ - try { - return Services.prefs.getBoolPref(prefname); - } - catch(er) { - return def; - } -} - -/* openUILink handles clicks on UI elements that cause URLs to load. - * - * As the third argument, you may pass an object with the same properties as - * accepted by openUILinkIn, plus "ignoreButton" and "ignoreAlt". - */ -function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup, - aPostData, aReferrerURI) { - let params; - - if (aIgnoreButton && typeof aIgnoreButton == "object") { - params = aIgnoreButton; - - // don't forward "ignoreButton" and "ignoreAlt" to openUILinkIn - aIgnoreButton = params.ignoreButton; - aIgnoreAlt = params.ignoreAlt; - delete params.ignoreButton; - delete params.ignoreAlt; - } else { - params = { - allowThirdPartyFixup: aAllowThirdPartyFixup, - postData: aPostData, - referrerURI: aReferrerURI, - initiatingDoc: event ? event.target.ownerDocument : null - }; - } - - let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt); - openUILinkIn(url, where, params); -} - - -/* whereToOpenLink() looks at an event to decide where to open a link. - * - * The event may be a mouse event (click, double-click, middle-click) or keypress event (enter). - * - * On Windows, the modifiers are: - * Ctrl new tab, selected - * Shift new window - * Ctrl+Shift new tab, in background - * Alt save - * - * Middle-clicking is the same as Ctrl+clicking (it opens a new tab). - * - * Exceptions: - * - Alt is ignored for menu items selected using the keyboard so you don't accidentally save stuff. - * (Currently, the Alt isn't sent here at all for menu items, but that will change in bug 126189.) - * - Alt is hard to use in context menus, because pressing Alt closes the menu. - * - Alt can't be used on the bookmarks toolbar because Alt is used for "treat this as something draggable". - * - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click. - */ -function whereToOpenLink( e, ignoreButton, ignoreAlt ) -{ - // This method must treat a null event like a left click without modifier keys (i.e. - // e = { shiftKey:false, ctrlKey:false, metaKey:false, altKey:false, button:0 }) - // for compatibility purposes. - if (!e) - return "current"; - - var shift = e.shiftKey; - var ctrl = e.ctrlKey; - var meta = e.metaKey; - var alt = e.altKey && !ignoreAlt; - - // ignoreButton allows "middle-click paste" to use function without always opening in a new window. - var middle = !ignoreButton && e.button == 1; - var middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true); - - // Don't do anything special with right-mouse clicks. They're probably clicks on context menu items. - -#ifdef XP_MACOSX - if (meta || (middle && middleUsesTabs)) -#else - if (ctrl || (middle && middleUsesTabs)) -#endif - return shift ? "tabshifted" : "tab"; - - if (alt && getBoolPref("browser.altClickSave", false)) - return "save"; - - if (shift || (middle && !middleUsesTabs)) - return "window"; - - return "current"; -} - -/* openUILinkIn opens a URL in a place specified by the parameter |where|. - * - * |where| can be: - * "current" current tab (if there aren't any browser windows, then in a new window instead) - * "tab" new tab (if there aren't any browser windows, then in a new window instead) - * "tabshifted" same as "tab" but in background if default is to select new tabs, and vice versa - * "window" new window - * "save" save to disk (with no filename hint!) - * - * aAllowThirdPartyFixup controls whether third party services such as Google's - * I Feel Lucky are allowed to interpret this URL. This parameter may be - * undefined, which is treated as false. - * - * Instead of aAllowThirdPartyFixup, you may also pass an object with any of - * these properties: - * allowThirdPartyFixup (boolean) - * postData (nsIInputStream) - * referrerURI (nsIURI) - * relatedToCurrent (boolean) - */ -function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) { - var params; - - if (arguments.length == 3 && typeof arguments[2] == "object") { - params = aAllowThirdPartyFixup; - } else { - params = { - allowThirdPartyFixup: aAllowThirdPartyFixup, - postData: aPostData, - referrerURI: aReferrerURI - }; - } - - params.fromChrome = true; - - openLinkIn(url, where, params); -} - -function openLinkIn(url, where, params) { - if (!where || !url) - return; - - var aFromChrome = params.fromChrome; - var aAllowThirdPartyFixup = params.allowThirdPartyFixup; - var aPostData = params.postData; - var aCharset = params.charset; - var aReferrerURI = params.referrerURI; - var aRelatedToCurrent = params.relatedToCurrent; - var aInBackground = params.inBackground; - var aDisallowInheritPrincipal = params.disallowInheritPrincipal; - var aInitiatingDoc = params.initiatingDoc; - var aIsPrivate = params.private; - var sendReferrerURI = true; - - if (where == "save") { - if (!aInitiatingDoc) { - Components.utils.reportError("openUILink/openLinkIn was called with " + - "where == 'save' but without initiatingDoc. See bug 814264."); - return; - } - 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") && - w && !w.toolbar.visible) { - w = getTopWin(true); - aRelatedToCurrent = false; - } - - if (!w || where == "window") { - // Strip referrer data when opening a new private window, to prevent - // regular browsing data from leaking into it. - if (aIsPrivate) { - sendReferrerURI = false; - } - - var sa = Cc["@mozilla.org/supports-array;1"]. - createInstance(Ci.nsISupportsArray); - - var wuri = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - wuri.data = url; - - let charset = null; - if (aCharset) { - charset = Cc["@mozilla.org/supports-string;1"] - .createInstance(Ci.nsISupportsString); - charset.data = "charset=" + aCharset; - } - - var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"]. - createInstance(Ci.nsISupportsPRBool); - allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup; - - sa.AppendElement(wuri); - sa.AppendElement(charset); - if (sendReferrerURI) - sa.AppendElement(aReferrerURI); - sa.AppendElement(aPostData); - sa.AppendElement(allowThirdPartyFixupSupports); - - let features = "chrome,dialog=no,all"; - if (aIsPrivate) { - features += ",private"; - } - - Services.ww.openWindow(w || window, getBrowserURL(), null, features, sa); - return; - } - - let loadInBackground = where == "current" ? false : aInBackground; - if (loadInBackground == null) { - loadInBackground = aFromChrome ? - false : - getBoolPref("browser.tabs.loadInBackground"); - } - - if (where == "current" && w.gBrowser.selectedTab.pinned) { - try { - let uriObj = Services.io.newURI(url, null, null); - if (!uriObj.schemeIs("javascript") && - w.gBrowser.currentURI.host != uriObj.host) { - where = "tab"; - loadInBackground = false; - } - } catch (err) { - where = "tab"; - loadInBackground = false; - } - } - - // Raise the target window before loading the URI, since loading it may - // result in a new frontmost window (e.g. "javascript:window.open('');"). - w.focus(); - - switch (where) { - case "current": - let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; - if (aAllowThirdPartyFixup) { - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - } - if (aDisallowInheritPrincipal) - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; - w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData); - break; - case "tabshifted": - loadInBackground = !loadInBackground; - // fall through - case "tab": - let browser = w.gBrowser; - browser.loadOneTab(url, { - referrerURI: aReferrerURI, - charset: aCharset, - postData: aPostData, - inBackground: loadInBackground, - allowThirdPartyFixup: aAllowThirdPartyFixup, - relatedToCurrent: aRelatedToCurrent}); - break; - } - - w.gBrowser.selectedBrowser.focus(); - - if (!loadInBackground && w.isBlankPageURL(url)) - w.focusAndSelectUrlBar(); -} - -// Used as an onclick handler for UI elements with link-like behavior. -// e.g. onclick="checkForMiddleClick(this, event);" -function checkForMiddleClick(node, event) { - // We should be using the disabled property here instead of the attribute, - // but some elements that this function is used with don't support it (e.g. - // menuitem). - if (node.getAttribute("disabled") == "true") - return; // Do nothing - - if (event.button == 1) { - /* Execute the node's oncommand or command. - * - * XXX: we should use node.oncommand(event) once bug 246720 is fixed. - */ - var target = node.hasAttribute("oncommand") ? node : - node.ownerDocument.getElementById(node.getAttribute("command")); - var fn = new Function("event", target.getAttribute("oncommand")); - fn.call(target, event); - - // If the middle-click was on part of a menu, close the menu. - // (Menus close automatically with left-click but not with middle-click.) - closeMenus(event.target); - } -} - -// Closes all popups that are ancestors of the node. -function closeMenus(node) -{ - if ("tagName" in node) { - if (node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - && (node.tagName == "menupopup" || node.tagName == "popup")) - node.hidePopup(); - - closeMenus(node.parentNode); - } -} - -// Gather all descendent text under given document node. -function gatherTextUnder ( root ) -{ - var text = ""; - var node = root.firstChild; - var depth = 1; - while ( node && depth > 0 ) { - // See if this node is text. - if ( node.nodeType == Node.TEXT_NODE ) { - // Add this text to our collection. - text += " " + node.data; - } else if ( node instanceof HTMLImageElement) { - // If it has an alt= attribute, use that. - var altText = node.getAttribute( "alt" ); - if ( altText && altText != "" ) { - text = altText; - break; - } - } - // Find next node to test. - // First, see if this node has children. - if ( node.hasChildNodes() ) { - // Go to first child. - node = node.firstChild; - depth++; - } else { - // No children, try next sibling (or parent next sibling). - while ( depth > 0 && !node.nextSibling ) { - node = node.parentNode; - depth--; - } - if ( node.nextSibling ) { - node = node.nextSibling; - } - } - } - // Strip leading whitespace. - text = text.replace( /^\s+/, "" ); - // Strip trailing whitespace. - text = text.replace( /\s+$/, "" ); - // Compress remaining whitespace. - text = text.replace( /\s+/g, " " ); - return text; -} - -function getShellService() -{ - var shell = null; - try { - shell = Components.classes["@mozilla.org/browser/shell-service;1"] - .getService(Components.interfaces.nsIShellService); - } catch (e) { - } - return shell; -} - -function isBidiEnabled() { - // first check the pref. - if (getBoolPref("bidi.browser.ui", false)) - return true; - - // if the pref isn't set, check for an RTL locale and force the pref to true - // if we find one. - var rv = false; - - try { - var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] - .getService(Components.interfaces.nsILocaleService); - var systemLocale = localeService.getSystemLocale().getCategory("NSILOCALE_CTYPE").substr(0,3); - - switch (systemLocale) { - case "ar-": - case "he-": - case "fa-": - case "ur-": - case "syr": - rv = true; - Services.prefs.setBoolPref("bidi.browser.ui", true); - } - } catch (e) {} - - return rv; -} - -function openAboutDialog() { - var enumerator = Services.wm.getEnumerator("Browser:About"); - while (enumerator.hasMoreElements()) { - // Only open one about window (Bug 599573) - let win = enumerator.getNext(); - win.focus(); - return; - } - -#ifdef XP_WIN - var features = "chrome,centerscreen,dependent"; -#elifdef XP_MACOSX - var features = "chrome,resizable=no,minimizable=no"; -#else - var features = "chrome,centerscreen,dependent,dialog=no"; -#endif - window.openDialog("chrome://browser/content/aboutDialog.xul", "", features); -} - -function openPreferences(paneID, extraArgs) -{ - var instantApply = getBoolPref("browser.preferences.instantApply", false); - var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal"); - - var win = Services.wm.getMostRecentWindow("Browser:Preferences"); - if (win) { - win.focus(); - if (paneID) { - var pane = win.document.getElementById(paneID); - win.document.documentElement.showPane(pane); - } - - if (extraArgs && extraArgs["advancedTab"]) { - var advancedPaneTabs = win.document.getElementById("advancedPrefs"); - advancedPaneTabs.selectedTab = win.document.getElementById(extraArgs["advancedTab"]); - } - - return win; - } - - return openDialog("chrome://browser/content/preferences/preferences.xul", - "Preferences", features, paneID, extraArgs); -} - -function openAdvancedPreferences(tabID) -{ - openPreferences("paneAdvanced", { "advancedTab" : tabID }); -} - -/** - * Opens the troubleshooting information (about:support) page for this version - * of the application. - */ -function openTroubleshootingPage() -{ - openUILinkIn("about:support", "tab"); -} - -/** - * Opens the feedback page for this version of the application. - */ -function openFeedbackPage() -{ - openUILinkIn(Services.prefs.getCharPref("browser.feedback.url"), "tab"); -} - -function buildHelpMenu() -{ - // Enable/disable the "Report Web Forgery" menu item. - if (typeof gSafeBrowsing != "undefined") - gSafeBrowsing.setReportPhishingMenu(); -} - -function isElementVisible(aElement) -{ - if (!aElement) - return false; - - // If aElement or a direct or indirect parent is hidden or collapsed, - // height, width or both will be 0. - var bo = aElement.boxObject; - return (bo.height > 0 && bo.width > 0); -} - -function makeURLAbsolute(aBase, aUrl) -{ - // Note: makeURI() will throw if aUri is not a valid URI - return makeURI(aUrl, null, makeURI(aBase)).spec; -} - - -/** - * openNewTabWith: opens a new tab with the given URL. - * - * @param aURL - * The URL to open (as a string). - * @param aDocument - * The document from which the URL came, or null. This is used to set the - * referrer header and to do a security check of whether the document is - * allowed to reference the URL. If null, there will be no referrer - * header and no security check. - * @param aPostData - * Form POST data, or null. - * @param aEvent - * The triggering event (for the purpose of determining whether to open - * in the background), or null. - * @param aAllowThirdPartyFixup - * If true, then we allow the URL text to be sent to third party services - * (e.g., Google's I Feel Lucky) for interpretation. This parameter may - * be undefined in which case it is treated as false. - * @param [optional] aReferrer - * If aDocument is null, then this will be used as the referrer. - * There will be no security check. - */ -function openNewTabWith(aURL, aDocument, aPostData, aEvent, - aAllowThirdPartyFixup, aReferrer) { - if (aDocument) - urlSecurityCheck(aURL, aDocument.nodePrincipal); - - // As in openNewWindowWith(), we want to pass the charset of the - // current document over to a new tab. - var originCharset = aDocument && aDocument.characterSet; - if (!originCharset && - document.documentElement.getAttribute("windowtype") == "navigator:browser") - originCharset = window.content.document.characterSet; - - openLinkIn(aURL, aEvent && aEvent.shiftKey ? "tabshifted" : "tab", - { charset: originCharset, - postData: aPostData, - allowThirdPartyFixup: aAllowThirdPartyFixup, - referrerURI: aDocument ? aDocument.documentURIObject : aReferrer }); -} - -function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aReferrer) { - if (aDocument) - urlSecurityCheck(aURL, aDocument.nodePrincipal); - - // if and only if the current window is a browser window and it has a - // document with a character set, then extract the current charset menu - // setting from the current document and use it to initialize the new browser - // window... - var originCharset = aDocument && aDocument.characterSet; - if (!originCharset && - document.documentElement.getAttribute("windowtype") == "navigator:browser") - originCharset = window.content.document.characterSet; - - openLinkIn(aURL, "window", - { charset: originCharset, - postData: aPostData, - allowThirdPartyFixup: aAllowThirdPartyFixup, - referrerURI: aDocument ? aDocument.documentURIObject : aReferrer }); -} - -/** - * isValidFeed: checks whether the given data represents a valid feed. - * - * @param aLink - * An object representing a feed with title, href and type. - * @param aPrincipal - * The principal of the document, used for security check. - * @param aIsFeed - * Whether this is already a known feed or not, if true only a security - * check will be performed. - */ -function isValidFeed(aLink, aPrincipal, aIsFeed) -{ - if (!aLink || !aPrincipal) - return false; - - var type = aLink.type.toLowerCase().replace(/^\s+|\s*(?:;.*)?$/g, ""); - if (!aIsFeed) { - aIsFeed = (type == "application/rss+xml" || - type == "application/atom+xml"); - } - - if (aIsFeed) { - try { - urlSecurityCheck(aLink.href, aPrincipal, - Components.interfaces.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); - return type || "application/rss+xml"; - } - catch(ex) { - } - } - - return null; -} - -// aCalledFromModal is optional -function openHelpLink(aHelpTopic, aCalledFromModal) { - var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] - .getService(Components.interfaces.nsIURLFormatter) - .formatURLPref("app.support.baseURL"); - url += aHelpTopic; - - var where = aCalledFromModal ? "window" : "tab"; - openUILinkIn(url, where); -} - -function openPrefsHelp() { - // non-instant apply prefwindows are usually modal, so we can't open in the topmost window, - // since its probably behind the window. - var instantApply = getBoolPref("browser.preferences.instantApply"); - - var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic; - openHelpLink(helpTopic, !instantApply); -} - -function trimURL(aURL) { - // This function must not modify the given URL such that calling - // nsIURIFixup::createFixupURI with the result will produce a different URI. - return aURL /* remove single trailing slash for http/https/ftp URLs */ - .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1") - /* remove http:// unless the host starts with "ftp\d*\." or contains "@" */ - .replace(/^http:\/\/((?!ftp\d*\.)[^\/@]+(?:\/|$))/, "$1"); -} diff --git a/browser/base/content/viewSourceOverlay.xul b/browser/base/content/viewSourceOverlay.xul deleted file mode 100644 index 8b40ddfd2..000000000 --- a/browser/base/content/viewSourceOverlay.xul +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0"?> -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -<?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?> - -<overlay id="viewSourceOverlay" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - -<window id="viewSource"> - <commandset id="baseMenuCommandSet"/> - <keyset id="baseMenuKeyset"/> - <stringbundleset id="stringbundleset"/> -</window> - -<menubar id="viewSource-main-menubar"> -#ifdef XP_MACOSX - <menu id="windowMenu"/> - <menupopup id="menu_ToolsPopup"/> -#endif - <menu id="helpMenu"/> -</menubar> - -</overlay> diff --git a/browser/base/content/web-panels.js b/browser/base/content/web-panels.js deleted file mode 100644 index 6e2bf5bc4..000000000 --- a/browser/base/content/web-panels.js +++ /dev/null @@ -1,102 +0,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/. */ - -const NS_ERROR_MODULE_NETWORK = 2152398848; -const NS_NET_STATUS_READ_FROM = NS_ERROR_MODULE_NETWORK + 8; -const NS_NET_STATUS_WROTE_TO = NS_ERROR_MODULE_NETWORK + 9; - -function getPanelBrowser() -{ - return document.getElementById("web-panels-browser"); -} - -var panelProgressListener = { - onProgressChange : function (aWebProgress, aRequest, - aCurSelfProgress, aMaxSelfProgress, - aCurTotalProgress, aMaxTotalProgress) { - }, - - onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) - { - if (!aRequest) - return; - - //ignore local/resource:/chrome: files - if (aStatus == NS_NET_STATUS_READ_FROM || aStatus == NS_NET_STATUS_WROTE_TO) - return; - - if (aStateFlags & Ci.nsIWebProgressListener.STATE_START && - aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) { - window.parent.document.getElementById('sidebar-throbber').setAttribute("loading", "true"); - } - else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && - aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) { - window.parent.document.getElementById('sidebar-throbber').removeAttribute("loading"); - } - }, - - onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { - UpdateBackForwardCommands(getPanelBrowser().webNavigation); - }, - - onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { - }, - - onSecurityChange : function(aWebProgress, aRequest, aState) { - }, - - QueryInterface : function(aIID) - { - if (aIID.equals(Ci.nsIWebProgressListener) || - aIID.equals(Ci.nsISupportsWeakReference) || - aIID.equals(Ci.nsISupports)) - return this; - throw Cr.NS_NOINTERFACE; - } -}; - -var gLoadFired = false; -function loadWebPanel(aURI) { - var panelBrowser = getPanelBrowser(); - if (gLoadFired) { - panelBrowser.webNavigation - .loadURI(aURI, nsIWebNavigation.LOAD_FLAGS_NONE, - null, null, null); - } - panelBrowser.setAttribute("cachedurl", aURI); -} - -function load() -{ - var panelBrowser = getPanelBrowser(); - panelBrowser.webProgress.addProgressListener(panelProgressListener, - Ci.nsIWebProgress.NOTIFY_ALL); - var cachedurl = panelBrowser.getAttribute("cachedurl") - if (cachedurl) { - panelBrowser.webNavigation - .loadURI(cachedurl, nsIWebNavigation.LOAD_FLAGS_NONE, null, - null, null); - } - - gLoadFired = true; -} - -function unload() -{ - getPanelBrowser().webProgress.removeProgressListener(panelProgressListener); -} - -function PanelBrowserStop() -{ - getPanelBrowser().webNavigation.stop(nsIWebNavigation.STOP_ALL) -} - -function PanelBrowserReload() -{ - getPanelBrowser().webNavigation - .sessionHistory - .QueryInterface(nsIWebNavigation) - .reload(nsIWebNavigation.LOAD_FLAGS_NONE); -} diff --git a/browser/base/content/web-panels.xul b/browser/base/content/web-panels.xul deleted file mode 100644 index ea1e2eba7..000000000 --- a/browser/base/content/web-panels.xul +++ /dev/null @@ -1,84 +0,0 @@ -<?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/. - -<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?> -<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> -<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?> - -<!DOCTYPE page [ -<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd"> -%browserDTD; -<!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd"> -%textcontextDTD; -]> - -<page id="webpanels-window" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" - onload="load()" onunload="unload()"> - <script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/> - <script type="application/javascript" src="chrome://browser/content/browser.js"/> - <script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/> - <script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/> - <script type="application/javascript" src="chrome://browser/content/web-panels.js"/> - - <stringbundleset id="stringbundleset"> - <stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/> - </stringbundleset> - - <broadcasterset id="mainBroadcasterSet"> - <broadcaster id="isFrameImage"/> - </broadcasterset> - - <commandset id="mainCommandset"> - <command id="Browser:Back" - oncommand="getPanelBrowser().webNavigation.goBack();" - disabled="true"/> - <command id="Browser:Forward" - oncommand="getPanelBrowser().webNavigation.goForward();" - disabled="true"/> - <command id="Browser:Stop" oncommand="PanelBrowserStop();"/> - <command id="Browser:Reload" oncommand="PanelBrowserReload();"/> - <command id="Browser:BackOrBackDuplicate" - oncommand="getPanelBrowser().webNavigation.goBack(event);" - disabled="true"> - <observes element="Browser:Back" attribute="disabled"/> - </command> - <command id="Browser:ForwardOrForwardDuplicate" - oncommand="getPanelBrowser().webNavigation.goForward(event);" - disabled="true"> - <observes element="Browser:Forward" attribute="disabled"/> - </command> - <command id="Browser:ReloadOrDuplicate" - oncommand="PanelBrowserReload(event)" - disabled="true"> - <observes element="Browser:Reload" attribute="disabled"/> - </command> - </commandset> - - <popupset id="mainPopupSet"> - <tooltip id="aHTMLTooltip" page="true"/> - <menupopup id="contentAreaContextMenu" pagemenu="start" - onpopupshowing="if (event.target != this) - return true; - gContextMenu = new nsContextMenu(this, event.shiftKey); - if (gContextMenu.shouldDisplay) - document.popupNode = this.triggerNode; - return gContextMenu.shouldDisplay;" - onpopuphiding="if (event.target != this) - return; - gContextMenu.hiding(); - gContextMenu = null;"> -#include browser-context.inc - </menupopup> - </popupset> - - <commandset id="editMenuCommands"/> - <browser id="web-panels-browser" persist="cachedurl" type="content" flex="1" - context="contentAreaContextMenu" tooltip="aHTMLTooltip" - onclick="window.parent.contentAreaClick(event, true);"/> -</page> diff --git a/browser/base/content/win6BrowserOverlay.xul b/browser/base/content/win6BrowserOverlay.xul deleted file mode 100644 index a69e3f6bd..000000000 --- a/browser/base/content/win6BrowserOverlay.xul +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> - -<!-- -*- Mode: HTML -*- --> -<!-- 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/. --> - -<overlay id="win6-browser-overlay" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <toolbar id="toolbar-menubar" - autohide="true"/> -</overlay> |