diff options
author | Thomas Groman <tgroman@nuegia.net> | 2020-04-20 20:49:37 -0700 |
---|---|---|
committer | Thomas Groman <tgroman@nuegia.net> | 2020-04-20 20:49:37 -0700 |
commit | f9cab004186edb425a9b88ad649726605080a17c (patch) | |
tree | e2dae51d3144e83d097a12e7a1499e3ea93f90be /base/content | |
parent | f428692de8b59ab89a66502c079e1823dfda8aeb (diff) | |
download | webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.gz webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.lz webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.xz webbrowser-f9cab004186edb425a9b88ad649726605080a17c.zip |
move browser to webbrowser/
Diffstat (limited to 'base/content')
77 files changed, 0 insertions, 34235 deletions
diff --git a/base/content/aboutDialog.css b/base/content/aboutDialog.css deleted file mode 100644 index d96eba5..0000000 --- a/base/content/aboutDialog.css +++ /dev/null @@ -1,74 +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/. */ - -#aboutPMDialogContainer { - width: 700px; - height: 410px; -} - -#aboutVersionBox { - font-family: Arial, helvetica; - height: 38 px; -} - -#aboutVersion { - text-align: center; - font-size: 18px; - font-weight: bold; - margin: 4px; -} - -#distribution, -#distributionId { - text-align: center; - font-size: 14px; - font-weight: bold; - display: none; - margin-top: 0; - margin-bottom: 0; -} - -#aboutTextBox { - font-family: Arial, helvetica; - font-size: 14px; - margin: 5px 20px; - padding: 4px 10px 0px; - border-radius: 3px; - color: black; - background-color: rgba(240, 240, 240, .6); -} - -#aboutLinkBox { - font-family: Arial, helvetica; -} - -.text-credits { - margin: 5px 0px; -} - -.text-center { - text-align: center; -} - -.text-link, -.text-link:focus { - margin: 0px; - padding: 0px; -} - -.bottom-link, -.bottom-link:focus { - text-align: center; - text-decoration: none !important; - padding: 4px; - border-radius: 3px; - color: #244C8A; - background-color: rgba(240, 240, 240, .7); - margin: 0 40px; - transition: background-color 0.5s ease-out; -} - -.bottom-link:hover { - background-color: rgba(240, 240, 255, .95); -} diff --git a/base/content/aboutDialog.js b/base/content/aboutDialog.js deleted file mode 100644 index e4e18f2..0000000 --- a/base/content/aboutDialog.js +++ /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/. - -// 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("aboutVersion").textContent += " (" + buildDate + ")"; - } - -#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); - } -} diff --git a/base/content/aboutDialog.xul b/base/content/aboutDialog.xul deleted file mode 100644 index 91fa81e..0000000 --- a/base/content/aboutDialog.xul +++ /dev/null @@ -1,86 +0,0 @@ -<?xml version="1.0"?> <!-- -*- Mode: HTML -*- --> - -<?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 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" flex="1"> - <vbox id="aboutHeaderBox" /> - <vbox id="aboutVersionBox" flex="3"> -#ifdef HAVE_64BIT_BUILD -#expand <label id="aboutVersion">Version: __MOZ_APP_VERSION__ (64-bit)</label> -#else -#expand <label id="aboutVersion">Version: __MOZ_APP_VERSION__ (32-bit)</label> -#endif - <label id="distribution" class="text-blurb"/> - <label id="distributionId" class="text-blurb"/> - - </vbox> - <vbox id="aboutTextBox" flex="1"> - <description class="text-credits text-center"> -#if defined(MOZ_OFFICIAL_BRANDING) || defined(MC_OFFICIAL) -#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 - <label class="text-link" href="http://www.palemoon.org">Pale Moon</label> is released by <label class="text-link" href="http://www.moonchildproductions.info">Moonchild Productions</label>. - </description> - <description class="text-credits text-center"> - Special thanks to all our supporters and donors for making this browser possible! - </description> - <description class="text-credits"> - 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 -#else - &brandFullName; is released by &vendorShortName;. - </description> - <description class="text-credits"> - This is an experimental build of Web Browser. -#endif - </description> - </vbox> - <vbox id="aboutLinkBox"> - <hbox pack="center"> - <label class="text-link bottom-link" href="about:rights">End-user rights</label> - <label class="text-link bottom-link" href="about:license">Licensing information</label> - <label class="text-link bottom-link" id="releaseNotesURL">Release notes</label> - </hbox> - <description id="aboutPMtrademark">&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/base/content/autocomplete.css b/base/content/autocomplete.css deleted file mode 100644 index 960bdc4..0000000 --- a/base/content/autocomplete.css +++ /dev/null @@ -1,17 +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"); - -/* Apply crisp rendering for favicons at exactly 2dppx resolution */ -@media (resolution: 2dppx) { - .ac-site-icon { - image-rendering: -moz-crisp-edges; - } -} - -richlistitem > .ac-title-box > .ac-title > .ac-comment:not([selected]) > html|span.ac-selected-text { - display: none; -} diff --git a/base/content/autocomplete.xml b/base/content/autocomplete.xml deleted file mode 100644 index bd09284..0000000 --- a/base/content/autocomplete.xml +++ /dev/null @@ -1,2128 +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="privateAutocompleteBindings" - 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="private-autocomplete" role="xul:combobox" - extends="chrome://global/content/bindings/textbox.xml#textbox"> - <resources> - <stylesheet src="chrome://browser/content/autocomplete.css"/> - <stylesheet src="chrome://browser/skin/autocomplete.css"/> - </resources> - - <content sizetopopup="pref"> - <xul:hbox class="private-autocomplete-textbox-container" flex="1" xbl:inherits="focused"> - <children includes="image|deck|stack|box"> - <xul:image class="private-autocomplete-icon" allowevents="true"/> - </children> - - <xul:hbox anonid="textbox-input-box" class="textbox-input-box" flex="1" xbl:inherits="tooltiptext=inputtooltiptext"> - <children/> - <html:input anonid="input" class="private-autocomplete-textbox textbox-input" - allowevents="true" - xbl:inherits="tooltiptext=inputtooltiptext,value,type=inputtype,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint"/> - </xul:hbox> - <children includes="hbox"/> - </xul:hbox> - - <xul:dropmarker anonid="historydropmarker" class="private-autocomplete-history-dropmarker" - allowevents="true" - xbl:inherits="open,enablehistory,parentfocused=focused"/> - - <xul:popupset anonid="popupset" class="private-autocomplete-result-popupset"/> - - <children includes="toolbarbutton"/> - </content> - - <implementation implements="nsIAutoCompleteInput, nsIDOMXULMenuListElement"> - <field name="mController">null</field> - <field name="mSearchNames">null</field> - <field name="mIgnoreInput">false</field> - <field name="mEnterEvent">null</field> - - <field name="_searchBeginHandler">null</field> - <field name="_searchCompleteHandler">null</field> - <field name="_textEnteredHandler">null</field> - <field name="_textRevertedHandler">null</field> - - <constructor><![CDATA[ - this.mController = Components.classes["@mozilla.org/autocomplete/controller;1"]. - getService(Components.interfaces.nsIAutoCompleteController); - - this._searchBeginHandler = this.initEventHandler("searchbegin"); - this._searchCompleteHandler = this.initEventHandler("searchcomplete"); - this._textEnteredHandler = this.initEventHandler("textentered"); - this._textRevertedHandler = this.initEventHandler("textreverted"); - - // For security reasons delay searches on pasted values. - this.inputField.controllers.insertControllerAt(0, this._pasteController); - ]]></constructor> - - <destructor><![CDATA[ - this.inputField.controllers.removeController(this._pasteController); - ]]></destructor> - - <!-- =================== nsIAutoCompleteInput =================== --> - - <field name="popup"><![CDATA[ - // Wrap in a block so that the let statements don't - // create properties on 'this' (bug 635252). - { - let popup = null; - let popupId = this.getAttribute("autocompletepopup"); - if (popupId) - popup = document.getElementById(popupId); - if (!popup) { - popup = document.createElement("panel"); - popup.setAttribute("type", "autocomplete"); - popup.setAttribute("noautofocus", "true"); - - let popupset = document.getAnonymousElementByAttribute(this, "anonid", "popupset"); - popupset.appendChild(popup); - } - popup.mInput = this; - popup; - } - ]]></field> - - <property name="controller" onget="return this.mController;" readonly="true"/> - - <property name="popupOpen" - onget="return this.popup.popupOpen;" - onset="if (val) this.openPopup(); else this.closePopup();"/> - - <property name="disableAutoComplete" - onset="this.setAttribute('disableautocomplete', val); return val;" - onget="return this.getAttribute('disableautocomplete') == 'true';"/> - - <property name="completeDefaultIndex" - onset="this.setAttribute('completedefaultindex', val); return val;" - onget="return this.getAttribute('completedefaultindex') == 'true';"/> - - <property name="completeSelectedIndex" - onset="this.setAttribute('completeselectedindex', val); return val;" - onget="return this.getAttribute('completeselectedindex') == 'true';"/> - - <property name="forceComplete" - onset="this.setAttribute('forcecomplete', val); return val;" - onget="return this.getAttribute('forcecomplete') == 'true';"/> - - <property name="minResultsForPopup" - onset="this.setAttribute('minresultsforpopup', val); return val;" - onget="var m = parseInt(this.getAttribute('minresultsforpopup')); return isNaN(m) ? 1 : m;"/> - - <property name="showCommentColumn" - onset="this.setAttribute('showcommentcolumn', val); return val;" - onget="return this.getAttribute('showcommentcolumn') == 'true';"/> - - <property name="showImageColumn" - onset="this.setAttribute('showimagecolumn', val); return val;" - onget="return this.getAttribute('showimagecolumn') == 'true';"/> - - <property name="timeout" - onset="this.setAttribute('timeout', val); return val;"> - <getter><![CDATA[ - // For security reasons delay searches on pasted values. - if (this._valueIsPasted) { - let t = parseInt(this.getAttribute('pastetimeout')); - return isNaN(t) ? 1000 : t; - } - - let t = parseInt(this.getAttribute('timeout')); - return isNaN(t) ? 50 : t; - ]]></getter> - </property> - - <property name="searchParam" - onget="return this.getAttribute('autocompletesearchparam') || '';" - onset="this.setAttribute('autocompletesearchparam', val); return val;"/> - - <property name="searchCount" readonly="true" - onget="this.initSearchNames(); return this.mSearchNames.length;"/> - - <field name="shrinkDelay" readonly="true"> - parseInt(this.getAttribute("shrinkdelay")) || 0 - </field> - - <field name="PrivateBrowsingUtils" readonly="true"> - { - let utils = {}; - Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm", utils); - utils.PrivateBrowsingUtils - } - </field> - - <property name="inPrivateContext" readonly="true" - onget="return this.PrivateBrowsingUtils.isWindowPrivate(window);"/> - - <property name="noRollupOnCaretMove" readonly="true" - onget="return this.popup.getAttribute('norolluponanchor') == 'true'"/> - - <!-- This is the maximum number of drop-down rows we get when we - hit the drop marker beside fields that have it (like the URLbar).--> - <field name="maxDropMarkerRows" readonly="true">14</field> - - <method name="getSearchAt"> - <parameter name="aIndex"/> - <body><![CDATA[ - this.initSearchNames(); - return this.mSearchNames[aIndex]; - ]]></body> - </method> - - <property name="textValue" - onget="return this.value;"> - <setter><![CDATA[ - // Completing a result should simulate the user typing the result, - // so fire an input event. - // 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; - - var 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="selectTextRange"> - <parameter name="aStartIndex"/> - <parameter name="aEndIndex"/> - <body><![CDATA[ - this.inputField.setSelectionRange(aStartIndex, aEndIndex); - ]]></body> - </method> - - <method name="onSearchBegin"> - <body><![CDATA[ - if (this.popup && typeof this.popup.onSearchBegin == "function") - this.popup.onSearchBegin(); - if (this._searchBeginHandler) - this._searchBeginHandler(); - ]]></body> - </method> - - <method name="onSearchComplete"> - <body><![CDATA[ - if (this.mController.matchCount == 0) - this.setAttribute("nomatch", "true"); - else - this.removeAttribute("nomatch"); - - if (this.ignoreBlurWhileSearching && !this.focused) { - this.handleEnter(); - this.detachController(); - } - - if (this._searchCompleteHandler) - this._searchCompleteHandler(); - ]]></body> - </method> - - <method name="onTextEntered"> - <body><![CDATA[ - let rv = false; - if (this._textEnteredHandler) - rv = this._textEnteredHandler(this.mEnterEvent); - this.mEnterEvent = null; - return rv; - ]]></body> - </method> - - <method name="onTextReverted"> - <body><![CDATA[ - if (this._textRevertedHandler) - return this._textRevertedHandler(); - return false; - ]]></body> - </method> - - <!-- =================== nsIDOMXULMenuListElement =================== --> - - <property name="editable" readonly="true" - onget="return true;" /> - - <property name="crop" - onset="this.setAttribute('crop',val); return val;" - onget="return this.getAttribute('crop');"/> - - <property name="open" - onget="return this.getAttribute('open') == 'true';"> - <setter><![CDATA[ - if (val) - this.showHistoryPopup(); - else - this.closePopup(); - ]]></setter> - </property> - - <!-- =================== PUBLIC MEMBERS =================== --> - - <field name="valueIsTyped">false</field> - <field name="_disableTrim">false</field> - <property name="value"> - <getter><![CDATA[ - if (typeof this.onBeforeValueGet == "function") { - var result = this.onBeforeValueGet(); - if (result) - return result.value; - } - return this.inputField.value; - ]]></getter> - <setter><![CDATA[ - this.mIgnoreInput = true; - - if (typeof this.onBeforeValueSet == "function") - val = this.onBeforeValueSet(val); - - if (typeof this.trimValue == "function" && !this._disableTrim) - val = this.trimValue(val); - - this.valueIsTyped = false; - this.inputField.value = val; - - if (typeof this.formatValue == "function") - this.formatValue(); - - this.mIgnoreInput = false; - var event = document.createEvent('Events'); - event.initEvent('ValueChange', true, true); - this.inputField.dispatchEvent(event); - return val; - ]]></setter> - </property> - - <property name="focused" readonly="true" - onget="return this.getAttribute('focused') == 'true';"/> - - <!-- maximum number of rows to display at a time --> - <property name="maxRows" - onset="this.setAttribute('maxrows', val); return val;" - onget="return parseInt(this.getAttribute('maxrows')) || 0;"/> - - <!-- option to allow scrolling through the list via the tab key, rather than - tab moving focus out of the textbox --> - <property name="tabScrolling" - onset="this.setAttribute('tabscrolling', val); return val;" - onget="return this.getAttribute('tabscrolling') == 'true';"/> - - <!-- option to completely ignore any blur events while searches are - still going on. --> - <property name="ignoreBlurWhileSearching" - onset="this.setAttribute('ignoreblurwhilesearching', val); return val;" - onget="return this.getAttribute('ignoreblurwhilesearching') == 'true';"/> - - <!-- disable key navigation handling in the popup results --> - <property name="disableKeyNavigation" - onset="this.setAttribute('disablekeynavigation', val); return val;" - onget="return this.getAttribute('disablekeynavigation') == 'true';"/> - - <!-- option to highlight entries that don't have any matches --> - <property name="highlightNonMatches" - onset="this.setAttribute('highlightnonmatches', val); return val;" - onget="return this.getAttribute('highlightnonmatches') == 'true';"/> - - <!-- =================== PRIVATE MEMBERS =================== --> - - <!-- ::::::::::::: autocomplete controller ::::::::::::: --> - - <method name="attachController"> - <body><![CDATA[ - this.mController.input = this; - ]]></body> - </method> - - <method name="detachController"> - <body><![CDATA[ - if (this.mController.input == this) - this.mController.input = null; - ]]></body> - </method> - - <!-- ::::::::::::: popup opening ::::::::::::: --> - - <method name="openPopup"> - <body><![CDATA[ - if (this.focused) - this.popup.openAutocompletePopup(this, this); - ]]></body> - </method> - - <method name="closePopup"> - <body><![CDATA[ - this.popup.closePopup(); - ]]></body> - </method> - - <method name="showHistoryPopup"> - <body><![CDATA[ - // history dropmarker pushed state - function cleanup(popup) { - popup.removeEventListener("popupshowing", onShow, false); - } - function onShow(event) { - var popup = event.target, input = popup.input; - cleanup(popup); - input.setAttribute("open", "true"); - function onHide() { - input.removeAttribute("open"); - popup.removeEventListener("popuphiding", onHide, false); - } - popup.addEventListener("popuphiding", onHide, false); - } - this.popup.addEventListener("popupshowing", onShow, false); - setTimeout(cleanup, 1000, this.popup); - - // Store our "normal" maxRows on the popup, so that it can reset the - // value when the popup is hidden. - this.popup._normalMaxRows = this.maxRows; - - // Increase our maxRows temporarily, since we want the dropdown to - // be bigger in this case. The popup's popupshowing/popuphiding - // handlers will take care of resetting this. - this.maxRows = this.maxDropMarkerRows; - - // Ensure that we have focus. - if (!this.focused) - this.focus(); - this.attachController(); - this.mController.startSearch(""); - ]]></body> - </method> - - <method name="toggleHistoryPopup"> - <body><![CDATA[ - // If this method is called on the same event tick as the popup gets - // hidden, do nothing to avoid re-opening the popup when the drop - // marker is clicked while the popup is still open. - if (!this.popup.isPopupHidingTick && !this.popup.popupOpen) - this.showHistoryPopup(); - else - this.closePopup(); - ]]></body> - </method> - - <!-- ::::::::::::: event dispatching ::::::::::::: --> - - <method name="initEventHandler"> - <parameter name="aEventType"/> - <body><![CDATA[ - let handlerString = this.getAttribute("on" + aEventType); - if (handlerString) { - return (new Function("eventType", "param", handlerString)).bind(this, aEventType); - } - return null; - ]]></body> - </method> - - <!-- ::::::::::::: key handling ::::::::::::: --> - - <field name="_selectionDetails">null</field> - <method name="onKeyPress"> - <parameter name="aEvent"/> - <body><![CDATA[ - return this.handleKeyPress(aEvent); - ]]></body> - </method> - - <method name="handleKeyPress"> - <parameter name="aEvent"/> - <body><![CDATA[ - if (aEvent.target.localName != "textbox") - return true; // Let child buttons of autocomplete take input - - //XXXpch this is so bogus... - if (aEvent.defaultPrevented) - return false; - - var cancel = false; - - let { AppConstants } = - Components.utils.import("resource://gre/modules/AppConstants.jsm", {}); - // Catch any keys that could potentially move the caret. Ctrl can be - // used in combination with these keys on Windows and Linux; and Alt - // can be used on OS X, so make sure the unused one isn't used. - let metaKey = AppConstants.platform == "macosx" ? aEvent.ctrlKey : aEvent.altKey; - if (!this.disableKeyNavigation && !metaKey) { - switch (aEvent.keyCode) { - case KeyEvent.DOM_VK_LEFT: - case KeyEvent.DOM_VK_RIGHT: - case KeyEvent.DOM_VK_HOME: - cancel = this.mController.handleKeyNavigation(aEvent.keyCode); - break; - } - } - - // Handle keys that are not part of a keyboard shortcut (no Ctrl or Alt) - if (!this.disableKeyNavigation && !aEvent.ctrlKey && !aEvent.altKey) { - switch (aEvent.keyCode) { - case KeyEvent.DOM_VK_TAB: - if (this.tabScrolling && this.popup.popupOpen) - cancel = this.mController.handleKeyNavigation(aEvent.shiftKey ? - KeyEvent.DOM_VK_UP : - KeyEvent.DOM_VK_DOWN); - else if (this.forceComplete && this.mController.matchCount >= 1) - this.mController.handleTab(); - break; - case KeyEvent.DOM_VK_UP: - case KeyEvent.DOM_VK_DOWN: - case KeyEvent.DOM_VK_PAGE_UP: - case KeyEvent.DOM_VK_PAGE_DOWN: - cancel = this.mController.handleKeyNavigation(aEvent.keyCode); - break; - } - } - - // Handle keys we know aren't part of a shortcut, even with Alt or - // Ctrl. - switch (aEvent.keyCode) { - case KeyEvent.DOM_VK_ESCAPE: - cancel = this.mController.handleEscape(); - break; - case KeyEvent.DOM_VK_RETURN: - if (AppConstants.platform == "macosx") { - // Prevent the default action, since it will beep on Mac - if (aEvent.metaKey) - aEvent.preventDefault(); - } - this.mEnterEvent = aEvent; - if (this.mController.selection) { - this._selectionDetails = { - index: this.mController.selection.currentIndex, - kind: "key" - }; - } - cancel = this.handleEnter(); - break; - case KeyEvent.DOM_VK_DELETE: - if (AppConstants.platform == "macosx" && !aEvent.shiftKey) { - break; - } - cancel = this.handleDelete(); - break; - case KeyEvent.DOM_VK_BACK_SPACE: - if (AppConstants.platform == "macosx" && aEvent.shiftKey) { - cancel = this.handleDelete(); - } - break; - case KeyEvent.DOM_VK_DOWN: - case KeyEvent.DOM_VK_UP: - if (aEvent.altKey) - this.toggleHistoryPopup(); - break; - case KeyEvent.DOM_VK_F4: - if (AppConstants.platform != "macosx") { - this.toggleHistoryPopup(); - } - break; - } - - if (cancel) { - aEvent.stopPropagation(); - aEvent.preventDefault(); - } - - return true; - ]]></body> - </method> - - <method name="handleEnter"> - <body><![CDATA[ - return this.mController.handleEnter(false); - ]]></body> - </method> - - <method name="handleDelete"> - <body><![CDATA[ - return this.mController.handleDelete(); - ]]></body> - </method> - - <!-- ::::::::::::: miscellaneous ::::::::::::: --> - - <method name="initSearchNames"> - <body><![CDATA[ - if (!this.mSearchNames) { - var names = this.getAttribute("autocompletesearch"); - if (!names) - this.mSearchNames = []; - else - this.mSearchNames = names.split(" "); - } - ]]></body> - </method> - - <method name="_focus"> - <!-- doesn't reset this.mController --> - <body><![CDATA[ - this._dontBlur = true; - this.focus(); - this._dontBlur = false; - ]]></body> - </method> - - <method name="resetActionType"> - <body><![CDATA[ - if (this.mIgnoreInput) - return; - this.removeAttribute("actiontype"); - ]]></body> - </method> - - <field name="_valueIsPasted">false</field> - <field name="_pasteController"><![CDATA[ - ({ - _autocomplete: this, - _kGlobalClipboard: Components.interfaces.nsIClipboard.kGlobalClipboard, - supportsCommand: aCommand => aCommand == "cmd_paste", - doCommand: function(aCommand) { - this._autocomplete._valueIsPasted = true; - this._autocomplete.editor.paste(this._kGlobalClipboard); - this._autocomplete._valueIsPasted = false; - }, - isCommandEnabled: function(aCommand) { - return this._autocomplete.editor.isSelectionEditable && - this._autocomplete.editor.canPaste(this._kGlobalClipboard); - }, - onEvent: function() {} - }) - ]]></field> - - <method name="onInput"> - <parameter name="aEvent"/> - <body><![CDATA[ - if (!this.mIgnoreInput && this.mController.input == this) { - this.valueIsTyped = true; - this.mController.handleText(); - } - this.resetActionType(); - ]]></body> - </method> - </implementation> - - <handlers> - <handler event="input"><![CDATA[ - this.onInput(event); - ]]></handler> - - <handler event="keypress" phase="capturing" - action="return this.onKeyPress(event);"/> - - <handler event="compositionstart" phase="capturing" - action="if (this.mController.input == this) this.mController.handleStartComposition();"/> - - <handler event="compositionend" phase="capturing" - action="if (this.mController.input == this) this.mController.handleEndComposition();"/> - - <handler event="focus" phase="capturing" - action="this.attachController();"/> - - <handler event="blur" phase="capturing"><![CDATA[ - if (!this._dontBlur) { - if (this.forceComplete && this.mController.matchCount >= 1) { - // mousemove sets selected index. Don't blindly use that selected - // index in this blur handler since if the popup is open you can - // easily "select" another match just by moving the mouse over it. - let filledVal = this.value.replace(/.+ >> /, "").toLowerCase(); - let selectedVal = null; - if (this.popup.selectedIndex >= 0) { - selectedVal = this.mController.getFinalCompleteValueAt( - this.popup.selectedIndex); - } - if (selectedVal && filledVal != selectedVal.toLowerCase()) { - for (let i = 0; i < this.mController.matchCount; i++) { - let matchVal = this.mController.getFinalCompleteValueAt(i); - if (matchVal.toLowerCase() == filledVal) { - this.popup.selectedIndex = i; - break; - } - } - } - this.mController.handleEnter(false); - } - if (!this.ignoreBlurWhileSearching) - this.detachController(); - } - ]]></handler> - </handlers> - </binding> - - <binding id="private-autocomplete-result-popup" extends="chrome://browser/content/autocomplete.xml#private-autocomplete-base-popup"> - <resources> - <stylesheet src="chrome://browser/content/autocomplete.css"/> - <stylesheet src="chrome://global/skin/tree.css"/> - <stylesheet src="chrome://browser/skin/autocomplete.css"/> - </resources> - - <content ignorekeys="true" level="top" consumeoutsideclicks="never"> - <xul:tree anonid="tree" class="private-autocomplete-tree plain" hidecolumnpicker="true" flex="1" seltype="single"> - <xul:treecols anonid="treecols"> - <xul:treecol id="treecolAutoCompleteValue" class="private-autocomplete-treecol" flex="1" overflow="true"/> - </xul:treecols> - <xul:treechildren class="private-autocomplete-treebody"/> - </xul:tree> - </content> - - <implementation> - <field name="mShowCommentColumn">false</field> - <field name="mShowImageColumn">false</field> - - <property name="showCommentColumn" - onget="return this.mShowCommentColumn;"> - <setter> - <![CDATA[ - if (!val && this.mShowCommentColumn) { - // reset the flex on the value column and remove the comment column - document.getElementById("treecolAutoCompleteValue").setAttribute("flex", 1); - this.removeColumn("treecolAutoCompleteComment"); - } else if (val && !this.mShowCommentColumn) { - // reset the flex on the value column and add the comment column - document.getElementById("treecolAutoCompleteValue").setAttribute("flex", 2); - this.addColumn({id: "treecolAutoCompleteComment", flex: 1}); - } - this.mShowCommentColumn = val; - return val; - ]]> - </setter> - </property> - - <property name="showImageColumn" - onget="return this.mShowImageColumn;"> - <setter> - <![CDATA[ - if (!val && this.mShowImageColumn) { - // remove the image column - this.removeColumn("treecolAutoCompleteImage"); - } else if (val && !this.mShowImageColumn) { - // add the image column - this.addColumn({id: "treecolAutoCompleteImage", flex: 1}); - } - this.mShowImageColumn = val; - return val; - ]]> - </setter> - </property> - - - <method name="addColumn"> - <parameter name="aAttrs"/> - <body> - <![CDATA[ - var col = document.createElement("treecol"); - col.setAttribute("class", "private-autocomplete-treecol"); - for (var name in aAttrs) - col.setAttribute(name, aAttrs[name]); - this.treecols.appendChild(col); - return col; - ]]> - </body> - </method> - - <method name="removeColumn"> - <parameter name="aColId"/> - <body> - <![CDATA[ - return this.treecols.removeChild(document.getElementById(aColId)); - ]]> - </body> - </method> - - <property name="selectedIndex" - onget="return this.tree.currentIndex;"> - <setter> - <![CDATA[ - this.tree.view.selection.select(val); - if (this.tree.treeBoxObject.height > 0) - this.tree.treeBoxObject.ensureRowIsVisible(val < 0 ? 0 : val); - // Fire select event on xul:tree so that accessibility API - // support layer can fire appropriate accessibility events. - var event = document.createEvent('Events'); - event.initEvent("select", true, true); - this.tree.dispatchEvent(event); - return val; - ]]></setter> - </property> - - <method name="adjustHeight"> - <body> - <![CDATA[ - // detect the desired height of the tree - var bx = this.tree.treeBoxObject; - var view = this.tree.view; - if (!view) - return; - var rows = this.maxRows; - if (!view.rowCount || (rows && view.rowCount < rows)) - rows = view.rowCount; - - var height = rows * bx.rowHeight; - - if (height == 0) { - this.tree.setAttribute("collapsed", "true"); - } else { - if (this.tree.hasAttribute("collapsed")) - this.tree.removeAttribute("collapsed"); - - this.tree.setAttribute("height", height); - } - this.tree.setAttribute("hidescrollbar", view.rowCount <= rows); - ]]> - </body> - </method> - - <method name="openAutocompletePopup"> - <parameter name="aInput"/> - <parameter name="aElement"/> - <body><![CDATA[ - // until we have "baseBinding", (see bug #373652) this allows - // us to override openAutocompletePopup(), but still call - // the method on the base class - this._openAutocompletePopup(aInput, aElement); - ]]></body> - </method> - - <method name="_openAutocompletePopup"> - <parameter name="aInput"/> - <parameter name="aElement"/> - <body><![CDATA[ - if (!this.mPopupOpen) { - this.mInput = aInput; - this.view = aInput.controller.QueryInterface(Components.interfaces.nsITreeView); - this.invalidate(); - - this.showCommentColumn = this.mInput.showCommentColumn; - this.showImageColumn = this.mInput.showImageColumn; - - var rect = aElement.getBoundingClientRect(); - var nav = aElement.ownerDocument.defaultView.QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsIWebNavigation); - var docShell = nav.QueryInterface(Components.interfaces.nsIDocShell); - var docViewer = docShell.contentViewer; - var width = (rect.right - rect.left) * docViewer.fullZoom; - this.setAttribute("width", width > 100 ? width : 100); - - // Adjust the direction of the autocomplete popup list based on the textbox direction, bug 649840 - var popupDirection = aElement.ownerDocument.defaultView.getComputedStyle(aElement).direction; - this.style.direction = popupDirection; - - this.openPopup(aElement, "after_start", 0, 0, false, false); - } - ]]></body> - </method> - - <method name="invalidate"> - <body><![CDATA[ - this.adjustHeight(); - this.tree.treeBoxObject.invalidate(); - ]]></body> - </method> - - <method name="selectBy"> - <parameter name="aReverse"/> - <parameter name="aPage"/> - <body><![CDATA[ - try { - var amount = aPage ? 5 : 1; - this.selectedIndex = this.getNextIndex(aReverse, amount, this.selectedIndex, this.tree.view.rowCount-1); - if (this.selectedIndex == -1) { - this.input._focus(); - } - } catch (ex) { - // do nothing - occasionally timer-related js errors happen here - // e.g. "this.selectedIndex has no properties", when you type fast and hit a - // navigation key before this popup has opened - } - ]]></body> - </method> - - <!-- =================== PUBLIC MEMBERS =================== --> - - <field name="tree"> - document.getAnonymousElementByAttribute(this, "anonid", "tree"); - </field> - - <field name="treecols"> - document.getAnonymousElementByAttribute(this, "anonid", "treecols"); - </field> - - <property name="view" - onget="return this.mView;"> - <setter><![CDATA[ - // We must do this by hand because the tree binding may not be ready yet - this.mView = val; - this.tree.boxObject.view = val; - ]]></setter> - </property> - - </implementation> - </binding> - - <binding id="private-autocomplete-base-popup" role="none" -extends="chrome://global/content/bindings/popup.xml#popup"> - <implementation implements="nsIAutoCompletePopup"> - <field name="mInput">null</field> - <field name="mPopupOpen">false</field> - <field name="mIsPopupHidingTick">false</field> - - <!-- =================== nsIAutoCompletePopup =================== --> - - <property name="input" readonly="true" - onget="return this.mInput"/> - - <property name="overrideValue" readonly="true" - onget="return null;"/> - - <property name="popupOpen" readonly="true" - onget="return this.mPopupOpen;"/> - - <property name="isPopupHidingTick" readonly="true" - onget="return this.mIsPopupHidingTick;"/> - - <method name="closePopup"> - <body> - <![CDATA[ - if (this.mPopupOpen) { - this.hidePopup(); - this.removeAttribute("width"); - } - ]]> - </body> - </method> - - <!-- This is the default number of rows that we give the autocomplete - popup when the textbox doesn't have a "maxrows" attribute - for us to use. --> - <field name="defaultMaxRows" readonly="true">6</field> - - <!-- In some cases (e.g. when the input's dropmarker button is clicked), - the input wants to display a popup with more rows. In that case, it - should increase its maxRows property and store the "normal" maxRows - in this field. When the popup is hidden, we restore the input's - maxRows to the value stored in this field. - - This field is set to -1 between uses so that we can tell when it's - been set by the input and when we need to set it in the popupshowing - handler. --> - <field name="_normalMaxRows">-1</field> - - <property name="maxRows" readonly="true"> - <getter> - <![CDATA[ - return (this.mInput && this.mInput.maxRows) || this.defaultMaxRows; - ]]> - </getter> - </property> - - <method name="getNextIndex"> - <parameter name="aReverse"/> - <parameter name="aAmount"/> - <parameter name="aIndex"/> - <parameter name="aMaxRow"/> - <body><![CDATA[ - if (aMaxRow < 0) - return -1; - - var newIdx = aIndex + (aReverse?-1:1)*aAmount; - if (aReverse && aIndex == -1 || newIdx > aMaxRow && aIndex != aMaxRow) - newIdx = aMaxRow; - else if (!aReverse && aIndex == -1 || newIdx < 0 && aIndex != 0) - newIdx = 0; - - if (newIdx < 0 && aIndex == 0 || newIdx > aMaxRow && aIndex == aMaxRow) - aIndex = -1; - else - aIndex = newIdx; - - return aIndex; - ]]></body> - </method> - - <method name="onPopupClick"> - <parameter name="aEvent"/> - <body><![CDATA[ - var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController); - controller.handleEnter(true); - ]]></body> - </method> - </implementation> - - <handlers> - <handler event="popupshowing"><![CDATA[ - // If normalMaxRows wasn't already set by the input, then set it here - // so that we restore the correct number when the popup is hidden. - - // Null-check this.mInput; see bug 1017914 - if (this._normalMaxRows < 0 && this.mInput) { - this._normalMaxRows = this.mInput.maxRows; - } - - // Set an attribute for styling the popup based on the input. - let inputID = ""; - if (this.mInput && this.mInput.ownerDocument && - this.mInput.ownerDocument.documentURIObject.schemeIs("chrome")) { - inputID = this.mInput.id; - // Take care of elements with no id that are inside xbl bindings - if (!inputID) { - let bindingParent = this.mInput.ownerDocument.getBindingParent(this.mInput); - if (bindingParent) { - inputID = bindingParent.id; - } - } - } - this.setAttribute("autocompleteinput", inputID); - - this.mPopupOpen = true; - ]]></handler> - - <handler event="popuphiding"><![CDATA[ - var isListActive = true; - if (this.selectedIndex == -1) - isListActive = false; - var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController); - controller.stopSearch(); - - this.removeAttribute("autocompleteinput"); - this.mPopupOpen = false; - - // Prevent opening popup from historydropmarker mousedown handler - // on the same event tick the popup is hidden by the same mousedown - // event. - this.mIsPopupHidingTick = true; - setTimeout(() => { - this.mIsPopupHidingTick = false; - }, 0); - - // Reset the maxRows property to the cached "normal" value, and reset - // _normalMaxRows so that we can detect whether it was set by the input - // when the popupshowing handler runs. - - // Null-check this.mInput; see bug 1017914 - if (this.mInput) - this.mInput.maxRows = this._normalMaxRows; - this._normalMaxRows = -1; - // If the list was being navigated and then closed, make sure - // we fire accessible focus event back to textbox - - // Null-check this.mInput; see bug 1017914 - if (isListActive && this.mInput) { - this.mInput.mIgnoreFocus = true; - this.mInput._focus(); - this.mInput.mIgnoreFocus = false; - } - ]]></handler> - </handlers> - </binding> - - <binding id="private-autocomplete-rich-result-popup" extends="chrome://browser/content/autocomplete.xml#private-autocomplete-base-popup"> - <resources> - <stylesheet src="chrome://browser/content/autocomplete.css"/> - <stylesheet src="chrome://browser/skin/autocomplete.css"/> - </resources> - - <content ignorekeys="true" level="top" consumeoutsideclicks="never"> - <xul:richlistbox anonid="richlistbox" class="private-autocomplete-richlistbox" flex="1"/> - <xul:hbox> - <children/> - </xul:hbox> - </content> - - <implementation implements="nsIAutoCompletePopup"> - <field name="_currentIndex">0</field> - <field name="_rowHeight">0</field> - <field name="_rlbAnimated">false</field> - - <!-- =================== nsIAutoCompletePopup =================== --> - - <property name="selectedIndex" - onget="return this.richlistbox.selectedIndex;"> - <setter> - <![CDATA[ - this.richlistbox.selectedIndex = val; - - // when clearing the selection (val == -1, so selectedItem will be - // null), we want to scroll back to the top. see bug #406194 - this.richlistbox.ensureElementIsVisible( - this.richlistbox.selectedItem || this.richlistbox.firstChild); - - return val; - ]]> - </setter> - </property> - - <method name="onSearchBegin"> - <body><![CDATA[ - this.richlistbox.mouseSelectedIndex = -1; - ]]></body> - </method> - - <method name="openAutocompletePopup"> - <parameter name="aInput"/> - <parameter name="aElement"/> - <body> - <![CDATA[ - // until we have "baseBinding", (see bug #373652) this allows - // us to override openAutocompletePopup(), but still call - // the method on the base class - this._openAutocompletePopup(aInput, aElement); - ]]> - </body> - </method> - - <method name="_openAutocompletePopup"> - <parameter name="aInput"/> - <parameter name="aElement"/> - <body> - <![CDATA[ - if (!this.mPopupOpen) { - this.mInput = aInput; - // clear any previous selection, see bugs 400671 and 488357 - this.selectedIndex = -1; - - var width = aElement.getBoundingClientRect().width; - this.setAttribute("width", width > 100 ? width : 100); - // invalidate() depends on the width attribute - this._invalidate(); - - this.openPopup(aElement, "after_start", 0, 0, false, false); - } - ]]> - </body> - </method> - - <method name="invalidate"> - <parameter name="reason"/> - <body> - <![CDATA[ - // Don't bother doing work if we're not even showing - if (!this.mPopupOpen) - return; - - this._invalidate(reason); - ]]> - </body> - </method> - - <method name="_invalidate"> - <parameter name="reason"/> - <body> - <![CDATA[ - // collapsed if no matches - this.richlistbox.collapsed = (this._matchCount == 0); - - // Update the richlistbox height. - if (this._adjustHeightTimeout) { - clearTimeout(this._adjustHeightTimeout); - } - if (this._shrinkTimeout) { - clearTimeout(this._shrinkTimeout); - } - this._adjustHeightTimeout = setTimeout(() => this.adjustHeight(), 0); - - this._currentIndex = 0; - if (this._appendResultTimeout) { - clearTimeout(this._appendResultTimeout); - } - this._appendCurrentResult(reason); - ]]> - </body> - </method> - - <property name="maxResults" readonly="true"> - <getter> - <![CDATA[ - // this is how many richlistitems will be kept around - // (note, this getter may be overridden) - return 20; - ]]> - </getter> - </property> - - <property name="_matchCount" readonly="true"> - <getter> - <![CDATA[ - return Math.min(this.mInput.controller.matchCount, this.maxResults); - ]]> - </getter> - </property> - - <method name="_collapseUnusedItems"> - <body> - <![CDATA[ - let existingItemsCount = this.richlistbox.childNodes.length; - for (let i = this._matchCount; i < existingItemsCount; ++i) { - this.richlistbox.childNodes[i].collapsed = true; - } - ]]> - </body> - </method> - - <method name="adjustHeight"> - <body> - <![CDATA[ - // Figure out how many rows to show - let rows = this.richlistbox.childNodes; - let numRows = Math.min(this._matchCount, this.maxRows, rows.length); - - this.removeAttribute("height"); - - // Default the height to 0 if we have no rows to show - let height = 0; - if (numRows) { - if (!this._rowHeight) { - let firstRowRect = rows[0].getBoundingClientRect(); - this._rowHeight = firstRowRect.height; - - let transition = - window.getComputedStyle(this.richlistbox).transitionProperty; - this._rlbAnimated = transition && transition != "none"; - - // Set a fixed max-height to avoid flicker when growing the panel. - this.richlistbox.style.maxHeight = (this._rowHeight * this.maxRows) + "px"; - } - - // Calculate the height to have the first row to last row shown - height = this._rowHeight * numRows; - } - - let animate = this._rlbAnimated && - this.getAttribute("dontanimate") != "true"; - let currentHeight = this.richlistbox.getBoundingClientRect().height; - if (height > currentHeight) { - // Grow immediately. - if (animate) { - this.richlistbox.removeAttribute("height"); - this.richlistbox.style.height = height + "px"; - } else { - this.richlistbox.style.removeProperty("height"); - this.richlistbox.height = height; - } - } else { - // Delay shrinking to avoid flicker. - this._shrinkTimeout = setTimeout(() => { - this._collapseUnusedItems(); - if (animate) { - this.richlistbox.removeAttribute("height"); - this.richlistbox.style.height = height + "px"; - } else { - this.richlistbox.style.removeProperty("height"); - this.richlistbox.height = height; - } - }, this.mInput.shrinkDelay); - } - ]]> - </body> - </method> - - <method name="_appendCurrentResult"> - <parameter name="invalidateReason"/> - <body> - <![CDATA[ - var controller = this.mInput.controller; - var matchCount = this._matchCount; - var existingItemsCount = this.richlistbox.childNodes.length; - - // Process maxRows per chunk to improve performance and user experience - for (let i = 0; i < this.maxRows; i++) { - if (this._currentIndex >= matchCount) - break; - - var item; - - // trim the leading/trailing whitespace - var trimmedSearchString = controller.searchString.replace(/^\s+/, "").replace(/\s+$/, ""); - - let url = controller.getValueAt(this._currentIndex); - - if (this._currentIndex < existingItemsCount) { - // re-use the existing item - item = this.richlistbox.childNodes[this._currentIndex]; - - // Completely reuse the existing richlistitem for invalidation - // due to new results, but only when: the item is the same, *OR* - // we are about to replace the currently mouse-selected item, to - // avoid surprising the user. - let iface = Components.interfaces.nsIAutoCompletePopup; - if (item.getAttribute("text") == trimmedSearchString && - invalidateReason == iface.INVALIDATE_REASON_NEW_RESULT && - (item.getAttribute("url") == url || - this.richlistbox.mouseSelectedIndex === this._currentIndex)) { - item.collapsed = false; - this._currentIndex++; - continue; - } - } - else { - // need to create a new item - item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "richlistitem"); - } - - // set these attributes before we set the class - // so that we can use them from the constructor - let iconURI = controller.getImageAt(this._currentIndex); - item.setAttribute("image", iconURI); - item.setAttribute("url", url); - item.setAttribute("title", controller.getCommentAt(this._currentIndex)); - item.setAttribute("type", controller.getStyleAt(this._currentIndex)); - item.setAttribute("text", trimmedSearchString); - - if (this._currentIndex < existingItemsCount) { - // re-use the existing item - item._adjustAcItem(); - item.collapsed = false; - } - else { - // set the class at the end so we can use the attributes - // in the xbl constructor - item.className = "private-autocomplete-richlistitem"; - this.richlistbox.appendChild(item); - } - - this._currentIndex++; - } - - if (typeof this.onResultsAdded == "function") - this.onResultsAdded(); - - if (this._currentIndex < matchCount) { - // yield after each batch of items so that typing the url bar is - // responsive - this._appendResultTimeout = setTimeout(() => this._appendCurrentResult(), 0); - } - ]]> - </body> - </method> - - <method name="selectBy"> - <parameter name="aReverse"/> - <parameter name="aPage"/> - <body> - <![CDATA[ - try { - var amount = aPage ? 5 : 1; - - // because we collapsed unused items, we can't use this.richlistbox.getRowCount(), we need to use the matchCount - this.selectedIndex = this.getNextIndex(aReverse, amount, this.selectedIndex, this._matchCount - 1); - if (this.selectedIndex == -1) { - this.input._focus(); - } - } catch (ex) { - // do nothing - occasionally timer-related js errors happen here - // e.g. "this.selectedIndex has no properties", when you type fast and hit a - // navigation key before this popup has opened - } - ]]> - </body> - </method> - - <field name="richlistbox"> - document.getAnonymousElementByAttribute(this, "anonid", "richlistbox"); - </field> - - <property name="view" - onget="return this.mInput.controller;" - onset="return val;"/> - - </implementation> - </binding> - - <binding id="private-autocomplete-richlistitem" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem"> - <content> - <xul:hbox align="center" class="ac-title-box"> - <xul:image xbl:inherits="src=image" class="ac-site-icon"/> - <xul:hbox anonid="title-box" class="ac-title" flex="1" - onunderflow="_doUnderflow('_title');" - onoverflow="_doOverflow('_title');"> - <xul:description anonid="title" class="ac-normal-text ac-comment" xbl:inherits="selected"/> - </xul:hbox> - <xul:label anonid="title-overflow-ellipsis" xbl:inherits="selected" - class="ac-ellipsis-after ac-comment"/> - <xul:hbox anonid="extra-box" class="ac-extra" align="center" hidden="true"> - <xul:image class="ac-result-type-tag"/> - <xul:label class="ac-normal-text ac-comment" xbl:inherits="selected" value=":"/> - <xul:description anonid="extra" class="ac-normal-text ac-comment" xbl:inherits="selected"/> - </xul:hbox> - <xul:image anonid="type-image" class="ac-type-icon" xbl:inherits="selected"/> - </xul:hbox> - <xul:hbox align="center" class="ac-url-box"> - <xul:spacer class="ac-site-icon"/> - <xul:image class="ac-action-icon"/> - <xul:hbox anonid="url-box" class="ac-url" flex="1" - onunderflow="_doUnderflow('_url');" - onoverflow="_doOverflow('_url');"> - <xul:description anonid="url" class="ac-normal-text ac-url-text" - xbl:inherits="selected type"/> - <xul:description anonid="action" class="ac-normal-text ac-action-text" - xbl:inherits="selected type"/> - </xul:hbox> - <xul:label anonid="url-overflow-ellipsis" xbl:inherits="selected" - class="ac-ellipsis-after ac-url-text"/> - <xul:spacer class="ac-type-icon"/> - </xul:hbox> - </content> - <implementation implements="nsIDOMXULSelectControlItemElement"> - <constructor> - <![CDATA[ - let ellipsis = "\u2026"; - try { - ellipsis = Components.classes["@mozilla.org/preferences-service;1"]. - getService(Components.interfaces.nsIPrefBranch). - getComplexValue("intl.ellipsis", - Components.interfaces.nsIPrefLocalizedString).data; - } catch (ex) { - // Do nothing.. we already have a default - } - - this._urlOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "url-overflow-ellipsis"); - this._titleOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "title-overflow-ellipsis"); - - this._urlOverflowEllipsis.value = ellipsis; - this._titleOverflowEllipsis.value = ellipsis; - - this._typeImage = document.getAnonymousElementByAttribute(this, "anonid", "type-image"); - - this._urlBox = document.getAnonymousElementByAttribute(this, "anonid", "url-box"); - this._url = document.getAnonymousElementByAttribute(this, "anonid", "url"); - this._action = document.getAnonymousElementByAttribute(this, "anonid", "action"); - - this._titleBox = document.getAnonymousElementByAttribute(this, "anonid", "title-box"); - this._title = document.getAnonymousElementByAttribute(this, "anonid", "title"); - - this._extraBox = document.getAnonymousElementByAttribute(this, "anonid", "extra-box"); - this._extra = document.getAnonymousElementByAttribute(this, "anonid", "extra"); - - this._adjustAcItem(); - ]]> - </constructor> - - <property name="label" readonly="true"> - <getter> - <![CDATA[ - // This property is a string that is read aloud by screen readers, - // so it must not contain anything that should not be user-facing. - - let parts = [ - this.getAttribute("title"), - this.getAttribute("displayurl"), - ]; - let label = parts.filter(str => str).join(" ") - - // allow consumers that have extended popups to override - // the label values for the richlistitems - let panel = this.parentNode.parentNode; - if (panel.createResultLabel) { - return panel.createResultLabel(this, label); - } - - return label; - ]]> - </getter> - </property> - - <property name="_stringBundle"> - <getter><![CDATA[ - if (!this.__stringBundle) { - this.__stringBundle = Services.strings.createBundle("chrome://global/locale/autocomplete.properties"); - } - return this.__stringBundle; - ]]></getter> - </property> - - <field name="_boundaryCutoff">null</field> - - <property name="boundaryCutoff" readonly="true"> - <getter> - <![CDATA[ - if (!this._boundaryCutoff) { - this._boundaryCutoff = - Components.classes["@mozilla.org/preferences-service;1"]. - getService(Components.interfaces.nsIPrefBranch). - getIntPref("toolkit.autocomplete.richBoundaryCutoff"); - } - return this._boundaryCutoff; - ]]> - </getter> - </property> - - <method name="_getBoundaryIndices"> - <parameter name="aText"/> - <parameter name="aSearchTokens"/> - <body> - <![CDATA[ - // Short circuit for empty search ([""] == "") - if (aSearchTokens == "") - return [0, aText.length]; - - // Find which regions of text match the search terms - let regions = []; - for (let search of Array.prototype.slice.call(aSearchTokens)) { - let matchIndex = -1; - let searchLen = search.length; - - // Find all matches of the search terms, but stop early for perf - let lowerText = aText.substr(0, this.boundaryCutoff).toLowerCase(); - while ((matchIndex = lowerText.indexOf(search, matchIndex + 1)) >= 0) { - regions.push([matchIndex, matchIndex + searchLen]); - } - } - - // Sort the regions by start position then end position - regions = regions.sort((a, b) => { - let start = a[0] - b[0]; - return (start == 0) ? a[1] - b[1] : start; - }); - - // Generate the boundary indices from each region - let start = 0; - let end = 0; - let boundaries = []; - let len = regions.length; - for (let i = 0; i < len; i++) { - // We have a new boundary if the start of the next is past the end - let region = regions[i]; - if (region[0] > end) { - // First index is the beginning of match - boundaries.push(start); - // Second index is the beginning of non-match - boundaries.push(end); - - // Track the new region now that we've stored the previous one - start = region[0]; - } - - // Push back the end index for the current or new region - end = Math.max(end, region[1]); - } - - // Add the last region - boundaries.push(start); - boundaries.push(end); - - // Put on the end boundary if necessary - if (end < aText.length) - boundaries.push(aText.length); - - // Skip the first item because it's always 0 - return boundaries.slice(1); - ]]> - </body> - </method> - - <method name="_getSearchTokens"> - <parameter name="aSearch"/> - <body> - <![CDATA[ - let search = aSearch.toLowerCase(); - return search.split(/\s+/); - ]]> - </body> - </method> - - <method name="_setUpDescription"> - <parameter name="aDescriptionElement"/> - <parameter name="aText"/> - <parameter name="aNoEmphasis"/> - <body> - <![CDATA[ - // Get rid of all previous text - while (aDescriptionElement.hasChildNodes()) - aDescriptionElement.removeChild(aDescriptionElement.firstChild); - - // If aNoEmphasis is specified, don't add any emphasis - if (aNoEmphasis) { - aDescriptionElement.appendChild(document.createTextNode(aText)); - return; - } - - // Get the indices that separate match and non-match text - let search = this.getAttribute("text"); - let tokens = this._getSearchTokens(search); - let indices = this._getBoundaryIndices(aText, tokens); - - let next; - let start = 0; - let len = indices.length; - // Even indexed boundaries are matches, so skip the 0th if it's empty - for (let i = indices[0] == 0 ? 1 : 0; i < len; i++) { - next = indices[i]; - let text = aText.substr(start, next - start); - start = next; - - if (i % 2 == 0) { - // Emphasize the text for even indices - let span = aDescriptionElement.appendChild( - document.createElementNS("http://www.w3.org/1999/xhtml", "span")); - span.className = "ac-emphasize-text"; - span.textContent = text; - } else { - // Otherwise, it's plain text - aDescriptionElement.appendChild(document.createTextNode(text)); - } - } - ]]> - </body> - </method> - - <!-- - This will generate an array of emphasis pairs for use with - _setUpEmphasisedSections(). Each pair is a tuple (array) that - represents a block of text - containing the text of that block, and a - boolean for whether that block should have an emphasis styling applied - to it. - - These pairs are generated by parsing a localised string (aSourceString) - with parameters, in the format that is used by - nsIStringBundle.formatStringFromName(): - - "textA %1$S textB textC %2$S" - - Or: - - "textA %S" - - Where "%1$S", "%2$S", and "%S" are intended to be replaced by provided - replacement strings. These are specified an array of tuples - (aReplacements), each containing the replacement text and a boolean for - whether that text should have an emphasis styling applied. This is used - as a 1-based array - ie, "%1$S" is replaced by the item in the first - index of aReplacements, "%2$S" by the second, etc. "%S" will always - match the first index. - --> - <method name="_generateEmphasisPairs"> - <parameter name="aSourceString"/> - <parameter name="aReplacements"/> - <body> - <![CDATA[ - let pairs = []; - - // Split on %S, %1$S, %2$S, etc. ie: - // "textA %S" - // becomes ["textA ", "%S"] - // "textA %1$S textB textC %2$S" - // becomes ["textA ", "%1$S", " textB textC ", "%2$S"] - let parts = aSourceString.split(/(%(?:[0-9]+\$)?S)/); - - for (let part of parts) { - // The above regex will actually give us an empty string at the - // end - we don't want that, as we don't want to later generate an - // empty text node for it. - if (part.length === 0) - continue; - - // Determine if this token is a replacement token or a normal text - // token. If it is a replacement token, we want to extract the - // numerical number. However, we still want to match on "$S". - let match = part.match(/^%(?:([0-9]+)\$)?S$/); - - if (match) { - // "%S" doesn't have a numerical number in it, but will always - // be assumed to be 1. Furthermore, the input string specifies - // these with a 1-based index, but we want a 0-based index. - let index = (match[1] || 1) - 1; - - if (index >= 0 && index < aReplacements.length) { - pairs.push([...aReplacements[index]]); - } - } else { - pairs.push([part]); - } - } - - return pairs; - ]]> - </body> - </method> - - <!-- - _setUpEmphasisedSections() has the same use as _setUpDescription, - except instead of taking a string and highlighting given tokens, it takes - an array of pairs generated by _generateEmphasisPairs(). This allows - control over emphasising based on specific blocks of text, rather than - search for substrings. - --> - <method name="_setUpEmphasisedSections"> - <parameter name="aDescriptionElement"/> - <parameter name="aTextPairs"/> - <body> - <![CDATA[ - // Get rid of all previous text - while (aDescriptionElement.hasChildNodes()) - aDescriptionElement.firstChild.remove(); - - for (let [text, emphasise] of aTextPairs) { - if (emphasise) { - let span = aDescriptionElement.appendChild( - document.createElementNS("http://www.w3.org/1999/xhtml", "span")); - span.textContent = text; - switch(emphasise) { - case "match": - span.className = "ac-emphasize-text"; - break; - case "selected": - span.className = "ac-selected-text"; - break; - } - } else { - aDescriptionElement.appendChild(document.createTextNode(text)); - } - } - ]]> - </body> - </method> - - <field name="_textToSubURI">null</field> - <method name="_unescapeUrl"> - <parameter name="url"/> - <body> - <![CDATA[ - if (!this._textToSubURI) { - this._textToSubURI = - Components.classes["@mozilla.org/intl/texttosuburi;1"] - .getService(Components.interfaces.nsITextToSubURI); - } - return this._textToSubURI.unEscapeURIForUI("UTF-8", url); - ]]> - </body> - </method> - - <method name="_adjustAcItem"> - <body> - <![CDATA[ - let originalUrl = this.getAttribute("url"); - let title = this.getAttribute("title"); - let type = this.getAttribute("type"); - - let displayUrl; - let emphasiseTitle = true; - let emphasiseUrl = true; - - // Hide the title's extra box by default, until we find out later if - // we need extra stuff. - this._extraBox.hidden = true; - this._titleBox.flex = 1; - this._typeImage.hidden = false; - - this.removeAttribute("actiontype"); - this.classList.remove("overridable-action"); - - // The ellipses are hidden via their visibility so that they always - // take up space and don't pop in on top of text when shown. For - // keyword searches, however, the title ellipsis should not take up - // space when hidden. Setting the hidden property accomplishes that. - this._titleOverflowEllipsis.hidden = false; - - let types = new Set(type.split(/\s+/)); - - // Remove types that should ultimately not be in the `type` string. - let initialTypes = new Set(types); - types.delete("action"); - types.delete("autofill"); - types.delete("heuristic"); - types.delete("search"); - - type = [...types][0] || ""; - - // If the type includes an action, set up the item appropriately. - if (initialTypes.has("action")) { - let action = this._parseActionUrl(originalUrl); - this.setAttribute("actiontype", action.type); - - if (action.type == "switchtab") { - this.classList.add("overridable-action"); - displayUrl = this._unescapeUrl(action.params.url); - let desc = this._stringBundle.GetStringFromName("switchToTab"); - this._setUpDescription(this._action, desc, true); - } else if (action.type == "remotetab") { - displayUrl = this._unescapeUrl(action.params.url); - let desc = action.params.deviceName; - this._setUpDescription(this._action, desc, true); - } else if (action.type == "searchengine") { - emphasiseUrl = false; - - // The order here is not localizable, we default to appending - // "- Search with Engine" to the search string, to be able to - // properly generate emphasis pairs. That said, no localization - // changed the order while it was possible, so doesn't look like - // there's a strong need for that. - let {engineName, searchSuggestion, searchQuery} = action.params; - let engineStr = " - " + - this._stringBundle.formatStringFromName("searchWithEngine", - [engineName], 1); - - // Make the title by generating an array of pairs and its - // corresponding interpolation string (e.g., "%1$S") to pass to - // _generateEmphasisPairs. - let pairs; - if (searchSuggestion) { - // Check if the search query appears in the suggestion. It may - // not. If it does, then emphasize the query in the suggestion - // and otherwise just include the suggestion without emphasis. - let idx = searchSuggestion.indexOf(searchQuery); - if (idx >= 0) { - pairs = [ - [searchSuggestion.substring(0, idx), ""], - [searchQuery, "match"], - [searchSuggestion.substring(idx + searchQuery.length), ""], - ]; - } else { - pairs = [ - [searchSuggestion, ""], - ]; - } - } else { - pairs = [ - [searchQuery, ""], - ]; - } - pairs.push([engineStr, "selected"]); - let interpStr = pairs.map((pair, i) => `%${i + 1}$S`).join(""); - title = this._generateEmphasisPairs(interpStr, pairs); - - // If this is a default search match, we remove the image so we - // can style it ourselves with a generic search icon. - // We don't do this when matching an aliased search engine, - // because the icon helps with recognising which engine will be - // used (when using the default engine, we don't need that - // recognition). - if (!action.params.alias) { - this.removeAttribute("image"); - } - } else if (action.type == "visiturl") { - emphasiseUrl = false; - displayUrl = this._unescapeUrl(action.params.url); - let sourceStr = this._stringBundle.GetStringFromName("visitURL"); - title = this._generateEmphasisPairs(sourceStr, [ - [displayUrl, "match"], - ]); - } - } - - // Check if we have a search engine name - if (initialTypes.has("search")) { - emphasiseUrl = false; - - const TITLE_SEARCH_ENGINE_SEPARATOR = " \u00B7\u2013\u00B7 "; - - let searchEngine = ""; - [title, searchEngine] = title.split(TITLE_SEARCH_ENGINE_SEPARATOR); - displayUrl = this._stringBundle.formatStringFromName("searchWithEngine", [searchEngine], 1); - } - - if (!displayUrl) { - let input = this.parentNode.parentNode.input; - let url = typeof(input.trimValue) == "function" ? - input.trimValue(originalUrl) : - originalUrl; - displayUrl = this._unescapeUrl(url); - } - this.setAttribute("displayurl", displayUrl); - - // Check if we have an auto-fill URL - if (initialTypes.has("autofill")) { - emphasiseUrl = false; - - let sourceStr = this._stringBundle.GetStringFromName("visitURL"); - title = this._generateEmphasisPairs(sourceStr, [ - [displayUrl, "match"], - ]); - } - - // If we have a tag match, show the tags and icon - if (type == "tag" || type == "bookmark-tag") { - // Configure the extra box for tags display - this._extraBox.hidden = false; - this._extraBox.childNodes[0].hidden = false; - this._extraBox.childNodes[1].hidden = true; - this._extraBox.pack = "end"; - this._titleBox.flex = 1; - - // The title is separated from the tags by an endash - let tags; - [, title, tags] = title.match(/^(.+) \u2013 (.+)$/); - - // Each tag is split by a comma in an undefined order, so sort it - let sortedTags = tags.split(",").sort().join(", "); - - // Emphasize the matching text in the tags - this._setUpDescription(this._extra, sortedTags); - - // If we're suggesting bookmarks, then treat tagged matches as - // bookmarks for the star. - if (type == "bookmark-tag") { - type = "bookmark"; - } else { - this._typeImage.hidden = true; - } - // keyword and favicon type results for search engines - // have an extra magnifying glass icon after them - } else if (type == "keyword" || (initialTypes.has("search") && - initialTypes.has("favicon"))) { - // Configure the extra box for keyword display - this._extraBox.hidden = false; - this._extraBox.childNodes[0].hidden = true; - // The second child node is ":" and it should be hidden for non keyword types - this._extraBox.childNodes[1].hidden = type == "keyword" ? false : true; - this._extraBox.pack = "start"; - this._titleBox.flex = 0; - - // Hide the ellipsis so it doesn't take up space. - this._titleOverflowEllipsis.hidden = true; - - if (type == "keyword") { - // Put the parameters next to the title if we have any - let search = this.getAttribute("text"); - let params = ""; - let paramsIndex = search.indexOf(" "); - if (paramsIndex != -1) - params = search.substr(paramsIndex + 1); - - // Emphasize the keyword parameters - this._setUpDescription(this._extra, params); - - // Don't emphasize keyword searches in the title or url - emphasiseUrl = false; - emphasiseTitle = false; - } else { - // Don't show any description for non keyword types. - this._setUpDescription(this._extra, "", true); - } - // If the result has the type favicon and a known search provider, - // customize it the same way as a keyword result. - type = "keyword"; - } - - // Give the image the icon style and a special one for the type - this._typeImage.className = "ac-type-icon" + - (type ? " ac-result-type-" + type : ""); - - // Show the domain as the title if we don't have a title. - if (title == "") { - title = displayUrl; - try { - let uri = Services.io.newURI(originalUrl, null, null); - // Not all valid URLs have a domain. - if (uri.host) - title = uri.host; - } catch (e) {} - } - - // Emphasize the matching search terms for the description - if (Array.isArray(title)) - this._setUpEmphasisedSections(this._title, title); - else - this._setUpDescription(this._title, title, !emphasiseTitle); - - this._setUpDescription(this._url, displayUrl, !emphasiseUrl); - - // Set up overflow on a timeout because the contents of the box - // might not have a width yet even though we just changed them - setTimeout(this._setUpOverflow, 0, this._titleBox, this._titleOverflowEllipsis); - setTimeout(this._setUpOverflow, 0, this._urlBox, this._urlOverflowEllipsis); - ]]> - </body> - </method> - - <method name="_parseActionUrl"> - <parameter name="aUrl"/> - <body><![CDATA[ - if (!aUrl.startsWith("moz-action:")) - return null; - - // URL is in the format moz-action:ACTION,PARAMS - // Where PARAMS is a JSON encoded object. - let [, type, params] = aUrl.match(/^moz-action:([^,]+),(.*)$/); - - let action = { - type: type, - }; - - try { - action.params = JSON.parse(params); - for (let key in action.params) { - action.params[key] = decodeURIComponent(action.params[key]); - } - } catch (e) { - // If this failed, we assume that params is not a JSON object, and - // is instead just a flat string. This will happen when - // UnifiedComplete is disabled - in which case, the param is always - // a URL. - action.params = { - url: params, - } - } - - return action; - ]]></body> - </method> - - <method name="_setUpOverflow"> - <parameter name="aParentBox"/> - <parameter name="aEllipsis"/> - <body> - <![CDATA[ - // Hide the ellipsis incase there's just enough to not underflow - aEllipsis.style.visibility = "hidden"; - - // Start with the parent's width and subtract off its children - let tooltip = []; - let children = aParentBox.childNodes; - let widthDiff = aParentBox.boxObject.width; - - for (let i = 0; i < children.length; i++) { - // Only consider a child if it actually takes up space - let childWidth = children[i].boxObject.width; - if (childWidth > 0) { - // Subtract a little less to account for subpixel rounding - widthDiff -= childWidth - .5; - - // Add to the tooltip if it's not hidden and has text - let childText = children[i].textContent; - if (childText) - tooltip.push(childText); - } - } - - // If the children take up more space than the parent.. overflow! - if (widthDiff < 0) { - // Re-show the ellipsis now that we know it's needed - aEllipsis.style.visibility = "visible"; - - // Separate text components with a ndash -- - aParentBox.tooltipText = tooltip.join(" \u2013 "); - } - ]]> - </body> - </method> - - <method name="_doUnderflow"> - <parameter name="aName"/> - <body> - <![CDATA[ - // Hide the ellipsis right when we know we're underflowing instead of - // waiting for the timeout to trigger the _setUpOverflow calculations - this[aName + "Box"].tooltipText = ""; - this[aName + "OverflowEllipsis"].style.visibility = "hidden"; - ]]> - </body> - </method> - - <method name="_doOverflow"> - <parameter name="aName"/> - <body> - <![CDATA[ - this._setUpOverflow(this[aName + "Box"], - this[aName + "OverflowEllipsis"]); - ]]> - </body> - </method> - - </implementation> - </binding> - - <binding id="private-autocomplete-tree" extends="chrome://global/content/bindings/tree.xml#tree"> - <content> - <children includes="treecols"/> - <xul:treerows class="private-autocomplete-treerows tree-rows" xbl:inherits="hidescrollbar" flex="1"> - <children/> - </xul:treerows> - </content> - </binding> - - <binding id="private-autocomplete-richlistbox" extends="chrome://global/content/bindings/richlistbox.xml#richlistbox"> - <implementation> - <field name="mLastMoveTime">Date.now()</field> - <field name="mouseSelectedIndex">-1</field> - </implementation> - <handlers> - <handler event="mouseup"> - <![CDATA[ - // don't call onPopupClick for the scrollbar buttons, thumb, slider, etc. - let item = event.originalTarget; - while (item && item.localName != "richlistitem") { - item = item.parentNode; - } - - if (!item) - return; - - this.parentNode.onPopupClick(event); - ]]> - </handler> - - <handler event="mousemove"> - <![CDATA[ - if (Date.now() - this.mLastMoveTime > 30) { - let item = event.target; - while (item && item.localName != "richlistitem") { - item = item.parentNode; - } - - if (!item) - return; - - let index = this.getIndexOfItem(item); - if (index != this.selectedIndex) { - this.mouseSelectedIndex = this.selectedIndex = index; - } - - this.mLastMoveTime = Date.now(); - } - ]]> - </handler> - </handlers> - </binding> - - <binding id="private-autocomplete-treebody"> - <implementation> - <field name="mLastMoveTime">Date.now()</field> - </implementation> - - <handlers> - <handler event="mouseup" action="this.parentNode.parentNode.onPopupClick(event);"/> - - <handler event="mousedown"><![CDATA[ - var rc = this.parentNode.treeBoxObject.getRowAt(event.clientX, event.clientY); - if (rc != this.parentNode.currentIndex) - this.parentNode.view.selection.select(rc); - ]]></handler> - - <handler event="mousemove"><![CDATA[ - if (Date.now() - this.mLastMoveTime > 30) { - var rc = this.parentNode.treeBoxObject.getRowAt(event.clientX, event.clientY); - if (rc != this.parentNode.currentIndex) - this.parentNode.view.selection.select(rc); - this.mLastMoveTime = Date.now(); - } - ]]></handler> - </handlers> - </binding> - - <binding id="private-autocomplete-treerows"> - <content> - <xul:hbox flex="1" class="tree-bodybox"> - <children/> - </xul:hbox> - <xul:scrollbar xbl:inherits="collapsed=hidescrollbar" orient="vertical" class="tree-scrollbar"/> - </content> - </binding> - - <binding id="private-history-dropmarker" extends="chrome://global/content/bindings/general.xml#dropmarker"> - <handlers> - <handler event="mousedown" button="0"><![CDATA[ - document.getBindingParent(this).toggleHistoryPopup(); - ]]></handler> - </handlers> - </binding> - -</bindings> diff --git a/base/content/autorecovery.js b/base/content/autorecovery.js deleted file mode 100644 index 01a092f..0000000 --- a/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. - */ - -var Cc = Components.classes; -var Ci = Components.interfaces; -var 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/base/content/autorecovery.xul b/base/content/autorecovery.xul deleted file mode 100644 index 866bdf2..0000000 --- a/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/base/content/baseMenuOverlay.xul b/base/content/baseMenuOverlay.xul deleted file mode 100644 index bccdec2..0000000 --- a/base/content/baseMenuOverlay.xul +++ /dev/null @@ -1,114 +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="helpSafeMode" - accesskey="&helpSafeMode.accesskey;" - label="&helpSafeMode.label;" - oncommand="restart(true);"/> - <menuseparator/> - <menuitem id="releaseNotes" - accesskey="&helpReleaseNotes.accesskey;" - label="&helpReleaseNotes.label;" - oncommand="openReleaseNotes();" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="feedbackPage" - accesskey="&helpFeedbackPage.accesskey;" - label="&helpFeedbackPage.label;" - oncommand="openFeedbackPage()" - onclick="checkForMiddleClick(this, event);"/> - <menuseparator id="updatesSeparator"/> - <menuitem id="checkForUpdates" class="menuitem-iconic" -#ifdef MOZ_UPDATER - label="&updateCmd.label;" - oncommand="checkForUpdates();"/> -#else - hidden="true"/> -#endif - <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/base/content/browser-addons.js b/base/content/browser-addons.js deleted file mode 100644 index 630a0cf..0000000 --- a/base/content/browser-addons.js +++ /dev/null @@ -1,537 +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. - */ -var 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(), -}; - -#ifdef MOZ_PERSONAS -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. - */ -var 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 + ")"); - }, -}; -#endif diff --git a/base/content/browser-appmenu.inc b/base/content/browser-appmenu.inc deleted file mode 100644 index 9d202c9..0000000 --- a/base/content/browser-appmenu.inc +++ /dev/null @@ -1,381 +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" - label="&appMenuWebDeveloper.label;"> - <menupopup id="appmenu_webDeveloper_popup"> -#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();"/> - <menuseparator/> - <menuitem id="appmenu_pageSource" - observes="devtoolsMenuBroadcaster_PageSource"/> - <menuitem id="appmenu_javascriptConsole" - observes="devtoolsMenuBroadcaster_ErrorConsole"/> - </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" onpopupshowing="buildHelpMenu();"> - <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_safeMode" - label="&appMenuSafeMode.label;" - oncommand="restart(true);"/> - <menuseparator/> - <menuitem id="appmenu_releaseNotes" - accesskey="&helpReleaseNotes.accesskey;" - label="&helpReleaseNotes.label;" - oncommand="openReleaseNotes();" - onclick="checkForMiddleClick(this, event);"/> - <menuitem id="appmenu_feedbackPage" - label="&helpFeedbackPage.label;" - oncommand="openFeedbackPage()" - onclick="checkForMiddleClick(this, event);"/> -#ifdef MOZ_UPDATER - <menuseparator/> - <menuitem id="appmenu_checkForUpdates" - class="menuitem-iconic" - label="&updateCmd.label;" - oncommand="checkForUpdates();"/> -#endif - <menuseparator/> - <menuitem id="appmenu_about" - label="&aboutProduct.label;" - oncommand="openAboutDialog();"/> - </menupopup> - </splitmenu> - </vbox> - </hbox> -</menupopup> diff --git a/base/content/browser-charsetmenu.inc b/base/content/browser-charsetmenu.inc deleted file mode 100644 index 628de13..0000000 --- a/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/base/content/browser-context.inc b/base/content/browser-context.inc deleted file mode 100644 index 38c4725..0000000 --- a/base/content/browser-context.inc +++ /dev/null @@ -1,384 +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="&mediaPlaybackRate2.label;" accesskey="&mediaPlaybackRate2.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-loop" - label="&mediaLoop.label;" - accesskey="&mediaLoop.accesskey;" - type="checkbox" - oncommand="gContextMenu.mediaCommand('loop');"/> - <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/base/content/browser-devtools-theme.js b/base/content/browser-devtools-theme.js deleted file mode 100644 index 7b21dde..0000000 --- a/base/content/browser-devtools-theme.js +++ /dev/null @@ -1,91 +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/. */ - -/** - * Listeners for the DevTools theme. - */ -var DevToolsTheme = { - _devtoolsThemePrefName: "devtools.theme", - styleSheet: null, - initialized: false, - - get isStyleSheetEnabled() { - return this.styleSheet && !this.styleSheet.sheet.disabled; - }, - - init: function () { - this.initialized = true; - Services.prefs.addObserver(this._devtoolsThemePrefName, this, false); - Services.obs.addObserver(this, "lightweight-theme-styling-update", false); - Services.obs.addObserver(this, "lightweight-theme-window-updated", false); - this._updateDevtoolsThemeAttribute(); - }, - - observe: function (subject, topic, data) { - if (topic == "lightweight-theme-styling-update") { - let newTheme = JSON.parse(data); - this._toggleStyleSheet(); - } - - if (topic == "nsPref:changed" && data == this._devtoolsThemePrefName) { - this._updateDevtoolsThemeAttribute(); - } - }, - - _inferBrightness: function() { - ToolbarIconColor.inferFromText(); - // Get an inverted full screen button if the dark theme is applied. - if (this.isStyleSheetEnabled && - document.documentElement.getAttribute("devtoolstheme") == "dark") { - document.documentElement.setAttribute("brighttitlebarforeground", "true"); - } else { - document.documentElement.removeAttribute("brighttitlebarforeground"); - } - }, - - _updateDevtoolsThemeAttribute: function() { - // Set an attribute on root element to make it possible - // to change colors based on the selected devtools theme. - let devtoolsTheme = Services.prefs.getCharPref(this._devtoolsThemePrefName); - if (devtoolsTheme != "dark") { - devtoolsTheme = "light"; - } - document.documentElement.setAttribute("devtoolstheme", devtoolsTheme); - this._inferBrightness(); - }, - - handleEvent: function(e) { - if (e.type === "load") { - this.styleSheet.removeEventListener("load", this); - this.refreshBrowserDisplay(); - } - }, - - refreshBrowserDisplay: function() { - // Don't touch things on the browser if gBrowserInit.onLoad hasn't - // yet fired. - if (this.initialized) { - gBrowser.tabContainer._positionPinnedTabs(); - this._inferBrightness(); - } - }, - - _toggleStyleSheet: function() { - let wasEnabled = this.isStyleSheetEnabled; - if (wasEnabled) { - this.styleSheet.sheet.disabled = true; - this.refreshBrowserDisplay(); - } - }, - - uninit: function () { - Services.prefs.removeObserver(this._devtoolsThemePrefName, this); - Services.obs.removeObserver(this, "lightweight-theme-styling-update", false); - Services.obs.removeObserver(this, "lightweight-theme-window-updated", false); - if (this.styleSheet) { - this.styleSheet.removeEventListener("load", this); - } - this.styleSheet = null; - } -}; diff --git a/base/content/browser-doctype.inc b/base/content/browser-doctype.inc deleted file mode 100644 index 6ee6384..0000000 --- a/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/base/content/browser-feeds.js b/base/content/browser-feeds.js deleted file mode 100644 index c678772..0000000 --- a/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/base/content/browser-fullScreen.js b/base/content/browser-fullScreen.js deleted file mode 100644 index e816ce5..0000000 --- a/base/content/browser-fullScreen.js +++ /dev/null @@ -1,462 +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", - - toggle: function () { - var enterFS = window.fullScreen; - - // 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 - - if (!this._fullScrToggler) { - this._fullScrToggler = document.getElementById("fullscr-toggler"); - this._fullScrToggler.addEventListener("mouseover", this._expandCallback, false); - this._fullScrToggler.addEventListener("dragenter", this._expandCallback, false); - } - - // On OS X Lion we don't want to hide toolbars when entering fullscreen, unless - // we're entering DOM fullscreen, in which case we should hide the toolbars. - // If we're leaving fullscreen, then we'll go through the exit code below to - // 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) { - document.addEventListener("keypress", this._keyToggleCallback, false); - document.addEventListener("popupshown", this._setPopupOpen, false); - document.addEventListener("popuphidden", this._setPopupOpen, false); - this._shouldAnimate = true; - if (gPrefService.getBoolPref("browser.fullscreen.autohide")) { - gBrowser.mPanelContainer.addEventListener("mousemove", - this._collapseCallback, 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.hideNavToolbox(document.mozFullScreen); - } - else { - this.showNavToolbox(false); - // 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 "MozDOMFullscreen:NewOrigin" event for a document - // which is not a subdocument of a currently active (ie. visible) browser - // or iframe, we know that we've switched to a different frame since the - // request to enter full-screen was made, so we should exit full-screen - // 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.hideNavToolbox(true); - }, - - 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); - - 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; - } - }, - - // Event callbacks - _expandCallback: function() - { - FullScreen.showNavToolbox(); - }, - _collapseCallback: function() - { - FullScreen.hideNavToolbox(); - }, - _keyToggleCallback: function(aEvent) - { - // if we can use the keyboard (eg Ctrl+L or Ctrl+E) to open the toolbars, we - // should provide a way to collapse them too. - if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) { - FullScreen.hideNavToolbox(true); - } - // F6 is another shortcut to the address bar, but its not covered in OpenLocation() - else if (aEvent.keyCode == aEvent.DOM_VK_F6) - FullScreen.showNavToolbox(); - }, - - // 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, - - 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 = null; - }, - - warningBox: null, - warningFadeOutTimeout: null, - fullscreenDoc: null, - - // Shows a warning that the site has entered fullscreen for a short duration. - showWarning: function(targetDoc) { - let timeout = gPrefService.getIntPref("full-screen-api.warning.timeout"); - if (!document.mozFullScreen || timeout <= 0) - return; - - // Set the strings on the fullscreen warning 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"); - if (host) { - // Document's principal's URI has a host. Display a warning including the hostname. - let utils = {}; - Cu.import("resource://gre/modules/DownloadUtils.jsm", utils); - let displayHost = utils.DownloadUtils.getURIHost(uri.spec)[0]; - let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); - - hostLabel.textContent = bundle.formatStringFromName("fullscreen.entered", [displayHost], 1); - hostLabel.removeAttribute("hidden"); - } else { - hostLabel.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"); - } - - // Set a timeout to fade the warning out after a few moments. - this.warningFadeOutTimeout = setTimeout(() => { - if (this.warningBox) { - this.warningBox.setAttribute("fade-warning-out", "true"); - } - }, timeout); - }, - - showNavToolbox: function(trackMouse = true) { - this._fullScrToggler.hidden = true; - gNavToolbox.removeAttribute("fullscreenShouldAnimate"); - gNavToolbox.style.marginTop = ""; - - if (!this._isChromeCollapsed) { - return; - } - - // Track whether mouse is near the toolbox - this._isChromeCollapsed = false; - if (trackMouse) { - gBrowser.mPanelContainer.addEventListener("mousemove", - this._collapseCallback, false); - } - }, - - hideNavToolbox: function(forceHide = false) { - this._fullScrToggler.hidden = document.mozFullScreen; - if (this._isChromeCollapsed) { - if (forceHide) { - gNavToolbox.removeAttribute("fullscreenShouldAnimate"); - } - return; - } - if (!this._safeToCollapse(forceHide)) { - this._fullScrToggler.hidden = true; - return; - } - - // browser.fullscreen.animateUp - // 0 - never animate up - // 1 - animate only for first collapse after entering fullscreen (default for perf's sake) - // 2 - animate every time it collapses - let animateUp = gPrefService.getIntPref("browser.fullscreen.animateUp"); - if (animateUp == 0) { - this._shouldAnimate = false; - } else if (animateUp == 2) { - this._shouldAnimate = true; - } - if (this._shouldAnimate && !forceHide) { - gNavToolbox.setAttribute("fullscreenShouldAnimate", true); - this._shouldAnimate = false; - // Hide the fullscreen toggler until the transition ends. - let listener = () => { - gNavToolbox.removeEventListener("transitionend", listener, true); - if (this._isChromeCollapsed) - this._fullScrToggler.hidden = false; - }; - gNavToolbox.addEventListener("transitionend", listener, true); - this._fullScrToggler.hidden = true; - } - - gNavToolbox.style.marginTop = - -gNavToolbox.getBoundingClientRect().height + "px"; - this._isChromeCollapsed = true; - gBrowser.mPanelContainer.removeEventListener("mousemove", - this._collapseCallback, false); - }, - - 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/base/content/browser-fullZoom.js b/base/content/browser-fullZoom.js deleted file mode 100644 index 890cd84..0000000 --- a/base/content/browser-fullZoom.js +++ /dev/null @@ -1,526 +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/. */ - -/** - * 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() { - gBrowser.addEventListener("ZoomChangeUsingMouseWheel", this); - - // 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 = null; - }, - - destroy: function FullZoom_destroy() { - gPrefService.removeObserver("browser.zoom.", this); - this._cps2.removeObserverForName(this.name, this); - gBrowser.removeEventListener("ZoomChangeUsingMouseWheel", this); - }, - - - // Event Handlers - - // nsIDOMEventListener - - handleEvent: function FullZoom_handleEvent(event) { - switch (event.type) { - case "ZoomChangeUsingMouseWheel": - let browser = this._getTargetedBrowser(event); - this._ignorePendingZoomAccesses(browser); - this._applyZoomToPref(browser); - break; - } - }, - - // 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, aIsPrivate) { - this._onContentPrefChanged(aGroup, aValue, aIsPrivate); - }, - - onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName, aIsPrivate) { - this._onContentPrefChanged(aGroup, undefined, aIsPrivate); - }, - - /** - * 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, aIsPrivate) { - 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 ctxt = this._loadContextFromBrowser(browser); - let domain = this._cps2.extractDomain(browser.currentURI.spec); - if (aGroup) { - if (aGroup == domain && ctxt.usePrivateBrowsing == aIsPrivate) - 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 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(browser); - return; - } - - // Avoid the cps roundtrip and apply the default/global pref. - if (aURI.spec == "about:blank") { - this._applyPrefToZoom(undefined, browser, - this._notifyOnLocationChange.bind(this, browser)); - 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(browser); - 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, browser)); - 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(browser); - return; - } - this._applyPrefToZoom(value, browser, - this._notifyOnLocationChange.bind(this, browser)); - }.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 for the given browser to the given floating - * point value, where 1 is the default zoom level. - */ - setZoom: function (value, browser = gBrowser.selectedBrowser) { - ZoomManager.setZoomForBrowser(browser, value); - this._ignorePendingZoomAccesses(browser); - this._applyZoomToPref(browser); - }, - - /** - * Sets the zoom level of the page in the given browser to the global zoom - * level. - * - * @return A promise which resolves when the zoom reset has been applied. - */ - reset: function FullZoom_reset(browser = gBrowser.selectedBrowser) { - let token = this._getBrowserToken(browser); - let result = this._getGlobalValue(browser).then(value => { - if (token.isCurrent) { - ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value); - this._ignorePendingZoomAccesses(browser); - Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset", ""); - } - }); - this._removePref(browser); - return result; - }, - - /** - * 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).then(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) { - Services.obs.notifyObservers(browser, "browser-fullZoom:zoomChange", ""); - 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) { - Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset", ""); - 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; - }, - }; - }, - - /** - * Returns the browser that the supplied zoom event is associated with. - * @param event The ZoomChangeUsingMouseWheel event. - * @return The associated browser element, if one exists, otherwise null. - */ - _getTargetedBrowser: function FullZoom__getTargetedBrowser(event) { - let target = event.originalTarget; - - // With remote content browsers, the event's target is the browser - // we're looking for. - const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - if (target instanceof window.XULElement && - target.localName == "browser" && - target.namespaceURI == XUL_NS) - return target; - - // With in-process content browsers, the event's target is the content - // document. - if (target.nodeType == Node.DOCUMENT_NODE) - return gBrowser.getBrowserForDocument(target); - - throw new Error("Unexpected ZoomChangeUsingMouseWheel event source"); - }, - - /** - * 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. - * - * @param browser The browser pertaining to the zoom. - * @returns Promise<prefValue> - * Resolves to the preference value when done. - */ - _getGlobalValue: function FullZoom__getGlobalValue(browser) { - // * !("_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. - return new Promise(resolve => { - if ("_globalValue" in this) { - resolve(this._globalValue); - return; - } - let value = undefined; - this._cps2.getGlobal(this.name, this._loadContextFromBrowser(browser), { - handleResult: function (pref) { value = pref.value; }, - handleCompletion: (reason) => { - this._globalValue = this._ensureValid(value); - resolve(this._globalValue); - } - }); - }); - }, - - /** - * Gets the load context from the given 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 "browser-fullZoom:location-change" so that - * listeners can 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(browser) { - this._executeSoon(function () { - Services.obs.notifyObservers(browser, "browser-fullZoom:location-change", ""); - }); - }, - - _executeSoon: function FullZoom__executeSoon(callback) { - if (!callback) - return; - Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL); - }, -}; diff --git a/base/content/browser-gestureSupport.js b/base/content/browser-gestureSupport.js deleted file mode 100644 index 13eb71b..0000000 --- a/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. - -var 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) -var 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/base/content/browser-menubar.inc b/base/content/browser-menubar.inc deleted file mode 100644 index fc6bc76..0000000 --- a/base/content/browser-menubar.inc +++ /dev/null @@ -1,564 +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"> - <menuitem id="menu_pageSource" - observes="devtoolsMenuBroadcaster_PageSource" - accesskey="&pageSourceCmd.accesskey;"/> - <menuitem id="javascriptConsole" - observes="devtoolsMenuBroadcaster_ErrorConsole" - accesskey="&errorConsoleCmd.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/base/content/browser-menudragging.js b/base/content/browser-menudragging.js deleted file mode 100644 index f3f00d7..0000000 --- a/base/content/browser-menudragging.js +++ /dev/null @@ -1,340 +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 = - Services.prefs.getBoolPref('browser.menu.dragging.stayOpen', false); - this.DEBUG = - Services.prefs.getBoolPref('browser.menu.dragging.debug', 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); - }, - - 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/base/content/browser-menudragging.xul b/base/content/browser-menudragging.xul deleted file mode 100644 index f5cabe5..0000000 --- a/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/base/content/browser-places.js b/base/content/browser-places.js deleted file mode 100644 index 590fe7e..0000000 --- a/base/content/browser-places.js +++ /dev/null @@ -1,1316 +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(); - - let onPanelReady = fn => { - let target = this.panel; - if (target.parentNode) { - // By targeting the panel's parent and using a capturing listener, we - // can have our listener called before others waiting for the panel to - // be shown (which probably expect the panel to be fully initialized) - target = target.parentNode; - } - target.addEventListener("popupshown", function(event) { - fn(); - }, {"capture": true, "once": true}); - }; - gEditItemOverlay.initPanel(this._itemId, - { onPanelReady, - hiddenRows: ["description", "location", - "loadInSidebar", "keyword"] }); - - this.panel.openPopup(aAnchorElement, aPosition); - }, - - 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. - */ -var 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. - */ - -var 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/base/content/browser-plugins.js b/base/content/browser-plugins.js deleted file mode 100644 index 8382682..0000000 --- a/base/content/browser-plugins.js +++ /dev/null @@ -1,781 +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; - } - }, - - _makeCenterActions: function PH_makeCenterActions(notification) { - let contentWindow = notification.browser.contentWindow; - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - - let principal = contentWindow.document.nodePrincipal; - - 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.pluginPermissionPrePath = permissionObj.principal.originNoSuffix; - pluginInfo.pluginPermissionType = permissionObj.expireType; - } - else { - pluginInfo.pluginPermissionPrePath = principal.originNoSuffix; - 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/base/content/browser-sets.inc b/base/content/browser-sets.inc deleted file mode 100644 index 78fce26..0000000 --- a/base/content/browser-sets.inc +++ /dev/null @@ -1,357 +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_toggleMute" oncommand="gBrowser.selectedTab.toggleMuteAudio()"/> - <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="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();"/> - <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/> - <command id="Tools:Permissions" oncommand="BrowserOpenPermissionsMgr();"/> - <command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/> - <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"/> - - <broadcaster id="devtoolsMenuBroadcaster_PageSource" - label="&pageSourceCmd.label;" - key="key_viewSource" - command="View:PageSource"/> - <broadcaster id="devtoolsMenuBroadcaster_ErrorConsole" - label="&errorConsoleCmd.label;" - command="Tools:ErrorConsole"/> - </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"/> - <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_toggleMute" key="&toggleMuteCmd.key;" command="cmd_toggleMute" modifiers="control"/> - <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 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/base/content/browser-syncui.js b/base/content/browser-syncui.js deleted file mode 100644 index 86f6f48..0000000 --- a/base/content/browser-syncui.js +++ /dev/null @@ -1,472 +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 -var 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 = Services.prefs.getCharPref("services.sync.firstSync", ""); - 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"); - button.setAttribute("label", this._stringBundle.GetStringFromName("setupsync.label")); - } else { - button.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label")); - } - }, - - - // Functions called by observers - onActivityStart: function SUI_onActivityStart() { - if (!gBrowser) - return; - - let button = document.getElementById("sync-button"); - if (!button) - return; - - button.setAttribute("status", "active"); - button.setAttribute("label", this._stringBundle.GetStringFromName("syncing2.label")); - }, - - 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 = Services.prefs.getCharPref("services.sync.lastSync", ""); - 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/base/content/browser-tabPreviews.js b/base/content/browser-tabPreviews.js deleted file mode 100644 index e0755b8..0000000 --- a/base/content/browser-tabPreviews.js +++ /dev/null @@ -1,1058 +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"); - - aPreview.removeAttribute("soundplaying"); - aPreview.removeAttribute("muted"); - if (aPreview._tab.hasAttribute("muted")) - aPreview.setAttribute("muted", "true"); - else if (aPreview._tab.hasAttribute("soundplaying")) - aPreview.setAttribute("soundplaying", "true"); - - 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/base/content/browser-tabPreviews.xml b/base/content/browser-tabPreviews.xml deleted file mode 100644 index 4f54321..0000000 --- a/base/content/browser-tabPreviews.xml +++ /dev/null @@ -1,78 +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:hbox align="center"> - <xul:image xbl:inherits="soundplaying,muted" class="allTabs-endimage"/> - <xul:label flex="1" xbl:inherits="value=label,crop" class="allTabs-preview-label plain"/> - </xul:hbox> - </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/base/content/browser-thumbnails.js b/base/content/browser-thumbnails.js deleted file mode 100644 index 079b0ac..0000000 --- a/base/content/browser-thumbnails.js +++ /dev/null @@ -1,203 +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. - */ -var 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) { - // Tycho: aCallback([browser.currentURI.spec for (browser of gBrowser.browsers)]); - let result = []; - for (let browser of gBrowser.browsers) { - result.push(browser.currentURI.spec); - } - aCallback(result); - }, - - /** - * 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 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/base/content/browser-title.css b/base/content/browser-title.css deleted file mode 100644 index 5f7e775..0000000 --- a/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; -} - -/* 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; - } - } - -} - -/* Lightweight Themes */ - -#main-window:-moz-lwtheme::after { - color: inherit; - text-shadow: inherit; -} - - -/* 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/base/content/browser-uacompat.js b/base/content/browser-uacompat.js deleted file mode 100644 index 933aa55..0000000 --- a/base/content/browser-uacompat.js +++ /dev/null @@ -1,45 +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/. */ - -var UserAgentCompatibility = { - PREF_UA_COMPAT: "general.useragent.compatMode", - PREF_UA_COMPAT_GECKO: "general.useragent.compatMode.gecko", - PREF_UA_COMPAT_FIREFOX: "general.useragent.compatMode.firefox", - - init: function() { - this.checkPreferences(); - Services.prefs.addObserver(this.PREF_UA_COMPAT, this, false); - Services.prefs.addObserver(this.PREF_UA_COMPAT_GECKO, this, false); - Services.prefs.addObserver(this.PREF_UA_COMPAT_FIREFOX, this, false); - }, - - uninit: function() { - Services.prefs.removeObserver(this.PREF_UA_COMPAT, this, false); - Services.prefs.removeObserver(this.PREF_UA_COMPAT_GECKO, this, false); - Services.prefs.removeObserver(this.PREF_UA_COMPAT_FIREFOX, this, false); - }, - - observe: function() { - this.checkPreferences(); - }, - - checkPreferences: function() { - var compatMode = Services.prefs.getIntPref(this.PREF_UA_COMPAT); - - switch(compatMode) { - case 0: - Services.prefs.setBoolPref(this.PREF_UA_COMPAT_GECKO, false); - Services.prefs.setBoolPref(this.PREF_UA_COMPAT_FIREFOX, false); - break; - case 1: - Services.prefs.setBoolPref(this.PREF_UA_COMPAT_GECKO, true); - Services.prefs.setBoolPref(this.PREF_UA_COMPAT_FIREFOX, false); - break; - case 2: - Services.prefs.setBoolPref(this.PREF_UA_COMPAT_GECKO, true); - Services.prefs.setBoolPref(this.PREF_UA_COMPAT_FIREFOX, true); - break; - } - } -}; diff --git a/base/content/browser-webrtcUI.js b/base/content/browser-webrtcUI.js deleted file mode 100644 index d59134c..0000000 --- a/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/. - -var 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/base/content/browser.css b/base/content/browser.css deleted file mode 100644 index a2970ae..0000000 --- a/base/content/browser.css +++ /dev/null @@ -1,759 +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"); - -moz-window-dragging: drag; -} - -%ifdef XP_WIN -#main-window[tabsontop="true"] #TabsToolbar, -#main-window[tabsontop="true"] #toolbar-menubar, -#main-window[tabsontop="true"] #navigator-toolbox > toolbar:-moz-lwtheme { - -moz-window-dragging: drag; -} -%endif - -#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"); -} - -#DateTimePickerPanel[active="true"] { - -moz-binding: url("chrome://global/content/bindings/datetimepopup.xml#datetime-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; -} - -/* Private Autocomplete */ -textbox[type="private-autocomplete"] { - -moz-binding: url("chrome://browser/content/autocomplete.xml#autocomplete"); -} - -panel[type="private-autocomplete"] { - -moz-binding: url("chrome://browser/content/autocomplete.xml#autocomplete-result-popup"); -} - -panel[type="private-autocomplete-richlistbox"] { - -moz-binding: url("chrome://browser/content/autocomplete.xml#private-autocomplete-rich-result-popup"); -} - -.private-autocomplete-tree { - -moz-binding: url("chrome://browser/content/autocomplete.xml#private-autocomplete-tree"); - -moz-user-focus: ignore; -} - -.private-autocomplete-treebody { - -moz-binding: url("chrome://browser/content/autocomplete.xml#private-autocomplete-treebody"); -} - -.private-autocomplete-richlistbox { - -moz-binding: url("chrome://browser/content/autocomplete.xml#private-autocomplete-richlistbox"); - -moz-user-focus: ignore; -} - -.private-autocomplete-richlistbox > scrollbox { - overflow-x: hidden !important; -} - -.private-autocomplete-richlistitem { - -moz-binding: url("chrome://browser/content/autocomplete.xml#private-autocomplete-richlistitem"); - -moz-box-orient: vertical; - overflow: -moz-hidden-unscrollable; -} - -.private-autocomplete-treerows { - -moz-binding: url("chrome://browser/content/autocomplete.xml#private-autocomplete-treerows"); -} - -.private-autocomplete-history-dropmarker { - display: none; -} - -.private-autocomplete-history-dropmarker[enablehistory="true"] { - display: -moz-box; - -moz-binding: url("chrome://browser/content/autocomplete.xml#private-history-dropmarker"); -} - -.ac-ellipsis-after { - visibility: hidden; -} - -.ac-url-text[type~="action"], -.ac-action-text:not([type~="action"]) { - visibility: collapse; -} - - -/* ::::: 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; - pointer-events: none; -} - -#full-screen-warning-container[fade-warning-out] { - transition-property: opacity !important; - transition-duration: 500ms !important; - opacity: 0.0; -} - -#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 { - 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; -} - -.popup-anchor { - /* should occupy space but not be visible */ - opacity: 0; - pointer-events: none; - -moz-stack-sizing: ignore; -} - -#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; -} - -/* 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-stack > .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; -} - -#navigator-toolbox[fullscreenShouldAnimate] { - transition: 0.7s margin-top ease-out; - transition-delay: 0.8s; -} diff --git a/base/content/browser.js b/base/content/browser.js deleted file mode 100644 index 7615bc9..0000000 --- a/base/content/browser.js +++ /dev/null @@ -1,7440 +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 Ci = Components.interfaces; -var Cu = Components.utils; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource:///modules/RecentWindow.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu", - "resource:///modules/CharsetMenu.jsm"); - -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.mCurrentBrowser; - window.gFindBarInitialized = true; - return findbar; -}); - -XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils", - "resource://gre/modules/BrowserUtils.jsm"); - -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; -}); - -XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", - "resource://gre/modules/PluralForm.jsm"); - -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; - } -}); - -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"); - -var 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-uacompat.js - -#ifdef MOZ_WEBRTC -#include browser-webrtcUI.js -#endif - -#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 gFindBarSettings = { - messageName: "Findbar:Keypress", - prefName: "accessibility.typeaheadfind", - findAsYouType: null, - - init: function() { - window.messageManager.addMessageListener(this.messageName, this); - - gPrefService.addObserver(this.prefName, this, false); - this.writeFindAsYouType(); - }, - - uninit: function() { - window.messageManager.removeMessageListener(this.messageName, this); - - try { - gPrefService.removeObserver(this.prefName, this); - } catch (ex) { - Cu.reportError(ex); - } - }, - - observe: function(aSubject, aTopic, aData) { - if (aTopic != "nsPref:changed") { - return; - } - - this.writeFindAsYouType(); - }, - - writeFindAsYouType: function() { - this.findAsYouType = gPrefService.getBoolPref(this.prefName); - }, - - receiveMessage: function(aMessage) { - switch (aMessage.name) { - case this.messageName: - // If the find bar for chrome window's context is not yet alive, - // only initialize it if there's a possibility FindAsYouType - // will be used. - // There's no point in doing it for most random keypresses. - if (!gFindBarInitialized && aMessage.data.shouldFastFind) { - let shouldFastFind = this.findAsYouType; - if (!shouldFastFind) { - // Please keep in sync with toolkit/content/widgets/findbar.xml - const FAYT_LINKS_KEY = "'"; - const FAYT_TEXT_KEY = "/"; - let charCode = aMessage.data.fakeEvent.charCode; - let key = charCode ? String.fromCharCode(charCode) : null; - shouldFastFind = key == FAYT_LINKS_KEY || key == FAYT_TEXT_KEY; - } - if (shouldFastFind) { - // Make sure we return the result. - return gFindBar.receiveMessage(aMessage); - } - } - break; - } - } -}; - -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() { - if (!gURLBar) { - return; - } - - 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 || - !gBrowser.selectedBrowser.blockedPopups.length) { - // 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"); - - let blockedPopupDontShowMessage = document.getElementById("blockedPopupDontShowMessage"); - let 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")); - } - - let blockedPopupsSeparator = - document.getElementById("blockedPopupsSeparator"); - blockedPopupsSeparator.setAttribute("hidden", true); - - gBrowser.selectedBrowser.retrieveListOfBlockedPopups().then(blockedPopups => { - let foundUsablePopupURI = false; - 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.popupWindowURIspec) - continue; - - var popupURIspec = blockedPopup.popupWindowURIspec; - - // 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 == "<self>" || - 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("oncommand", "gPopupBlockerObserver.showBlockedPopup(event);"); - menuitem.setAttribute("popupReportIndex", i); - menuitem.popupReportBrowser = browser; - aEvent.target.appendChild(menuitem); - } - } - - // Show the separator if we added any - // showable popup addresses to the menu. - if (foundUsablePopupURI) - blockedPopupsSeparator.removeAttribute("hidden"); - }, null); - }, - - 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 = { - delayedStartupFinished: false, - - 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); - - // These routines add message listeners. They must run before - // loading the frame script to ensure that we don't miss any - // message sent between when the frame script is loaded and when - // the listener is registered. -#ifdef MOZ_DEVTOOLS - DevToolsTheme.init(); -#endif - gFindBarSettings.init(); - - 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(); - AudioIndicator.init(); - gPrivateBrowsingUI.init(); - TabsInTitlebar.init(); - retrieveToolbarIconsizesFromTheme(); - ToolbarIconColor.init(); - UserAgentCompatibility.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 | string) - // [3]: postData (nsIInputStream) - // [4]: allowThirdPartyFixup (bool) - // [5]: referrerPolicy (int) - // [6]: originPrincipal (nsIPrincipal) - // [7]: triggeringPrincipal (nsIPrincipal) - else if (window.arguments.length >= 3) { - let referrerURI = window.arguments[2]; - if (typeof(referrerURI) == "string") { - try { - referrerURI = makeURI(referrerURI); - } catch (e) { - referrerURI = null; - } - } - let referrerPolicy = (window.arguments[5] != undefined ? - window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT); - loadURI(uriToLoad, referrerURI, window.arguments[3] || null, - window.arguments[4] || false, referrerPolicy, - // pass the origin principal (if any) and force its use to create - // an initial about:blank viewer if present: - window.arguments[6], !!window.arguments[6], window.arguments[7]); - 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); -#ifdef MOZ_WEBRTC - WebrtcIndicator.init(); -#endif - - // 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 (!Services.prefs.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 - -#ifdef MOZ_PERSONAS - gBrowser.mPanelContainer.addEventListener("InstallBrowserTheme", LightWeightThemeWebInstaller, false, true); - gBrowser.mPanelContainer.addEventListener("PreviewBrowserTheme", LightWeightThemeWebInstaller, false, true); - gBrowser.mPanelContainer.addEventListener("ResetBrowserThemePreview", LightWeightThemeWebInstaller, false, true); -#endif - - // 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("MozDOMFullscreen:NewOrigin", 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(); - }); - - // 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 - - 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); - }); - - this.delayedStartupFinished = true; - - 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; - - // 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(); - - AudioIndicator.uninit(); - - TabsInTitlebar.uninit(); - - ToolbarIconColor.uninit(); - -#ifdef MOZ_DEVTOOLS - DevToolsTheme.uninit(); -#endif - gFindBarSettings.uninit(); - - UserAgentCompatibility.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 = Services.prefs.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.showNavToolbox(); - - 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, referrerPolicy, - originPrincipal, forceAboutBlankViewerInCurrent, - triggeringPrincipal) { - 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: flags, - referrerURI: referrer, - referrerPolicy: referrerPolicy, - postData: postData, - originPrincipal: originPrincipal, - triggeringPrincipal: triggeringPrincipal, - forceAboutBlankViewerInCurrent: forceAboutBlankViewerInCurrent, - }); - } catch (e) {} -} - -/** - * Given a urlbar value, discerns between URIs, keywords and aliases. - * - * @param url - * The urlbar value. - * @param callback (optional, deprecated) - * The callback function invoked when done. This parameter is - * deprecated, please use the Promise that is returned. - * - * @return Promise<{ postData, url, mayInheritPrincipal }> - */ -function getShortcutOrURIAndPostData(url, callback = null) { - if (callback) { - Deprecated.warning("Please use the Promise returned by " + - "getShortcutOrURIAndPostData() instead of passing a " + - "callback", - "https://bugzilla.mozilla.org/show_bug.cgi?id=1100294"); - } - - return Task.spawn(function* () { - let mayInheritPrincipal = false; - let postData = null; - let shortcutURL = null; - let keyword = url; - let param = ""; - - let offset = url.indexOf(" "); - if (offset > 0) { - keyword = url.substr(0, offset); - param = url.substr(offset + 1); - } - - let engine = Services.search.getEngineByAlias(keyword); - if (engine) { - let submission = engine.getSubmission(param, null, "keyword"); - postData = submission.postData; - return { postData: submission.postData, url: submission.uri.spec, - mayInheritPrincipal }; - } - - let entry = yield PlacesUtils.keywords.fetch(keyword); - if (entry) { - shortcutURL = entry.url.href; - postData = entry.postData; - } - - if (!shortcutURL) { - return { postData, url, mayInheritPrincipal }; - } - - let escapedPostData = ""; - if (postData) - escapedPostData = unescape(postData); - - if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { - let charset = ""; - const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; - let matches = shortcutURL.match(re); - - if (matches) { - [, shortcutURL, charset] = matches; - } else { - let uri; - try { - // makeURI() throws if URI is invalid. - uri = makeURI(shortcutURL); - } catch (ex) {} - - if (uri) { - // Try to get the saved character-set. - // Will return an empty string if character-set is not found. - charset = yield PlacesUtils.getCharsetForURI(uri); - } - } - - // encodeURIComponent produces UTF-8, and cannot be used for other charsets. - // escape() works in those cases, but it doesn't uri-encode +, @, and /. - // Therefore we need to manually replace these ASCII characters by their - // encodeURIComponent result, to match the behavior of nsEscape() with - // url_XPAlphas - let encodedParam = ""; - if (charset && charset != "UTF-8") - encodedParam = escape(convertFromUnicode(charset, param)). - replace(/[+@\/]+/g, encodeURIComponent); - else // Default charset is UTF-8 - encodedParam = encodeURIComponent(param); - - shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); - - if (/%s/i.test(escapedPostData)) // POST keyword - postData = getPostDataStream(escapedPostData, param, encodedParam, - "application/x-www-form-urlencoded"); - - // This URL came from a bookmark, so it's safe to let it inherit the current - // document's principal. - mayInheritPrincipal = true; - - return { postData, url: shortcutURL, mayInheritPrincipal }; - } - - if (param) { - // This keyword doesn't take a parameter, but one was provided. Just return - // the original URL. - postData = null; - - return { postData, url, mayInheritPrincipal }; - } - - // This URL came from a bookmark, so it's safe to let it inherit the current - // document's principal. - mayInheritPrincipal = true; - - return { postData, url: shortcutURL, mayInheritPrincipal }; - }).then(data => { - if (callback) { - callback(data); - } - - return data; - }); -} - -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(aArgsOrDocument) -{ - let args; - - if (aArgsOrDocument instanceof Document) { - let doc = aArgsOrDocument; - - let requestor = doc.defaultView - .QueryInterface(Ci.nsIInterfaceRequestor); - let browser = requestor.getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler; - let outerWindowID = requestor.getInterface(Ci.nsIDOMWindowUtils) - .outerWindowID; - let URL = browser.currentURI.spec; - args = { browser, outerWindowID, URL }; - } else { - args = aArgsOrDocument; - } - - let viewInternal = () => { - top.gViewSourceUtils.viewSource(args); - } - - // Check if external view source is enabled. If so, try it. If it fails, - // fallback to internal view source. - if (Services.prefs.getBoolPref("view_source.editor.external")) { - top.gViewSourceUtils - .openInExternalEditor(args, null, null, null, result => { - if (!result) { - viewInternal(); - } - }); - } else { - // Display using internal view source - viewInternal(); - } -} - -// 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) { - - /* === about:home === */ - - if (doc.documentURI.toLowerCase() == "about:home") { - if (!PrivateBrowsingUtils.isWindowPrivate(window)) { - let wrapper = {}; - Cu.import("resource:///modules/sessionstore/SessionStore.jsm", wrapper); - let ss = wrapper.SessionStore; - ss.promiseInitialized.then(function() { - if (ss.canRestoreLastSession) { - doc.getElementById("launcher").setAttribute("session", "true"); - } - }).then(null, function onError(x) { - Cu.reportError("Error in SessionStore init while processing 'about:home': " + x); - }); - } - - // Inject search engine and snippets URL. - let docElt = doc.documentElement; - 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); - } - - function updateSearchEngine() { - let engine = AboutHomeUtils.defaultSearchEngine; - docElt.setAttribute("searchEngineName", engine.name); - docElt.setAttribute("searchEnginePostData", engine.postDataString || ""); - docElt.setAttribute("searchEngineURL", engine.searchURL); - } - Services.search.init(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); - } - - /* === about:newtab === */ - - if (doc.documentURI.toLowerCase() == "about:newtab") { - - let docElt = doc.documentElement; - - function updateSearchEngine() { - let engine = AboutHomeUtils.defaultSearchEngine; - docElt.setAttribute("searchEngineName", engine.name); - docElt.setAttribute("searchEnginePostData", engine.postDataString || ""); - docElt.setAttribute("searchEngineURL", engine.searchURL); - } - Services.search.init(updateSearchEngine); - - // Listen for the event that's triggered when the user changes search engine. - // At this point we simply reload about:newtab 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 - */ -var 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() { - FullScreen.toggle(); -} - -function onMozEnteredDomFullscreen(event) { - FullScreen.enterDomFullscreen(event); -} - -function getWebNavigation() -{ - return gBrowser.webNavigation; -} - -function BrowserReloadWithFlags(reloadFlags) { - - // Reset DOS mitigation for auth prompts when user initiates a reload. - let browser = gBrowser.selectedBrowser; - delete browser.authPromptCounter; - - /* 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(); - } - }, - - dropLinks: function (aEvent, aDisallowInherit) { - return Services.droppedLinkHandler.dropLinks(aEvent, aDisallowInherit); - } -}; - -var homeButtonObserver = { - onDrop: function (aEvent) - { - // disallow setting home pages that inherit the principal - let links = browserDragAndDrop.dropLinks(aEvent, true); - if (links.length) { - setTimeout(openHomeDialog, 0, links.map(link => link.url).join("|")); - } - }, - - onDragOver: function (aEvent) - { - browserDragAndDrop.dragOver(aEvent); - aEvent.dropEffect = "link"; - }, - onDragExit: function (aEvent) - { - } -} - -function openHomeDialog(aURL) -{ - var promptTitle = gNavigatorBundle.getString("droponhometitle"); - var promptMsg; - if (aURL.includes("|")) { - promptMsg = gNavigatorBundle.getString("droponhomemsgMultiple"); - } else { - promptMsg = gNavigatorBundle.getString("droponhomemsg"); - } - - var pressedVal = Services.prompt.confirmEx(window, promptTitle, promptMsg, - Services.prompt.STD_YES_NO_BUTTONS, - null, null, null, null, {value:0}); - - if (pressedVal == 0) { - try { - var homepageStr = Components.classes["@mozilla.org/supports-string;1"] - .createInstance(Components.interfaces.nsISupportsString); - homepageStr.data = aURL; - gPrefService.setComplexValue("browser.startup.homepage", - Components.interfaces.nsISupportsString, homepageStr); - } 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 links = browserDragAndDrop.dropLinks(aEvent); - Task.spawn(function*() { - for (let link of links) { - let data = yield getShortcutOrURIAndPostData(link.url); - if (data.url) { - // allow third-party services to fixup this URL - openNewTabWith(data.url, null, data.postData, aEvent, true); - } - } - }); - } -} - -var newWindowButtonObserver = { - onDragOver: function (aEvent) - { - browserDragAndDrop.dragOver(aEvent); - }, - onDragExit: function (aEvent) - { - }, - onDrop: function (aEvent) - { - let links = browserDragAndDrop.dropLinks(aEvent); - Task.spawn(function*() { - for (let link of links) { - let data = yield getShortcutOrURIAndPostData(link.url); - if (data.url) { - // allow third-party services to fixup this URL - openNewWindowWith(data.url, null, data.postData, true); - } - } - }); - } -} - -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, link.ownerDocument.nodePrincipal); - 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 }; - Services.search.init(function () { - 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.showNavToolbox(); - 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); - }, -}; - -XPCOMUtils.defineConstant(this, "BrowserSearch", BrowserSearch); - -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 = Services.prefs.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) { - gURLBarSettings.writePlaceholder(); - 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 (!Services.prefs.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"); - } - } -} - -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 && BrowserUtils.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 && BrowserUtils.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(); - } - - // XXX - // See: https://github.com/MoonchildProductions/Pale-Moon/issues/364 - // An actual preference: findbar.highlightAll - /* - 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 (aOpener && isExternal) { - Cu.reportError("nsBrowserAccess.openURI did not expect an opener to be " + - "passed if the context is OPEN_EXTERNAL."); - throw Cr.NS_ERROR_FAILURE; - } - - 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"); - } - - let referrer = aOpener ? makeURI(aOpener.location.href) : null; - let triggeringPrincipal = null; - let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT; - if (aOpener && aOpener.document) { - referrerPolicy = aOpener.document.referrerPolicy; - triggeringPrincipal = aOpener.document.nodePrincipal; - } - - 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 openerWindow = (aContext & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener; - - let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", { - triggeringPrincipal: triggeringPrincipal, - referrerURI: referrer, - referrerPolicy: referrerPolicy, - fromExternal: isExternal, - inBackground: loadInBackground, - opener: openerWindow }); - 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 loadflags = isExternal ? - Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL : - Ci.nsIWebNavigation.LOAD_FLAGS_NONE; - gBrowser.loadURIWithFlags(aURI.spec, { - flags: loadflags, - triggeringPrincipal: triggeringPrincipal, - referrerURI: referrer, - referrerPolicy: referrerPolicy, - }); - } - 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 AudioIndicator = { - init: function () { - Services.prefs.addObserver(this._prefName, this, false); - this.syncUI(); - }, - - uninit: function () { - Services.prefs.removeObserver(this._prefName, this); - }, - - toggle: function () { - this.enabled = !Services.prefs.getBoolPref(this._prefName); - }, - - syncUI: function () { - document.getElementById("context_toggleMuteTab").setAttribute("hidden", this.enabled); - document.getElementById("key_toggleMute").setAttribute("disabled", this.enabled); - }, - - get enabled () { - return !Services.prefs.getBoolPref(this._prefName); - }, - - 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.showAudioPlayingIcon" -} - -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, - referrerPolicy: doc.referrerPolicy, - originPrincipal: doc.nodePrincipal, - triggeringPrincipal: doc.nodePrincipal }); - 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, ""); - - // if it's not the current tab, we don't need to do anything because the - // browser doesn't exist. - let where = whereToOpenLink(event, true, false); - let lastLocationChange; - if (where == "current") { - lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - } - - getShortcutOrURIAndPostData(clipboard).then(data => { - try { - makeURI(data.url); - } catch (ex) { - // Not a valid URI. - return; - } - - try { - addToUrlbarHistory(data.url); - } catch (ex) { - // Things may go wrong when adding url to session history, - // but don't let that interfere with the loading of the url. - Cu.reportError(ex); - } - - if (where != "current" || - lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) { - openUILink(data.url, event, - { ignoreButton: true, - disallowInheritPrincipal: !data.mayInheritPrincipal, - initiatingDoc: event ? event.target.ownerDocument : null }); - } - }); - - event.stopPropagation(); -} - -// handleDroppedLink has the following 2 overloads: -// handleDroppedLink(event, url, name) -// handleDroppedLink(event, links) -function handleDroppedLink(event, urlOrLinks, name) -{ - let links; - if (Array.isArray(urlOrLinks)) { - links = urlOrLinks; - } else { - links = [{ url: urlOrLinks, name, type: "" }]; - } - - let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - - let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); - if (event.shiftKey) - inBackground = !inBackground; - - Task.spawn(function*() { - let urls = []; - let postDatas = []; - for (let link of links) { - let data = yield getShortcutOrURIAndPostData(link.url); - urls.push(data.url); - postDatas.push(data.postData); - } - if (lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) { - gBrowser.loadTabs(urls, { - inBackground, - replace: true, - allowThirdPartyFixup: false, - postDatas, - }); - } - }); - - // 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; - -var 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, - _updateToggleMuteMenuItem(aTab, aConditionFn) { - ["muted", "soundplaying"].forEach(attr => { - if (!aConditionFn || aConditionFn(attr)) { - if (aTab.hasAttribute(attr)) { - aTab.toggleMuteMenuItem.setAttribute(attr, "true"); - } else { - aTab.toggleMuteMenuItem.removeAttribute(attr); - } - } - }); - }, - 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(); - - // Adjust the state of the toggle mute menu item. - let toggleMute = document.getElementById("context_toggleMuteTab"); - if (this.contextTab.hasAttribute("muted")) { - toggleMute.label = gNavigatorBundle.getString("unmuteTab.label"); - toggleMute.accessKey = gNavigatorBundle.getString("unmuteTab.accesskey"); - } else { - toggleMute.label = gNavigatorBundle.getString("muteTab.label"); - toggleMute.accessKey = gNavigatorBundle.getString("muteTab.accesskey"); - } - - this.contextTab.toggleMuteMenuItem = toggleMute; - this._updateToggleMuteMenuItem(this.contextTab); - - this.contextTab.addEventListener("TabAttrModified", this, false); - aPopupMenu.addEventListener("popuphiding", this, false); - }, - handleEvent(aEvent) { - switch (aEvent.type) { - case "popuphiding": - gBrowser.removeEventListener("TabAttrModified", this); - aEvent.target.removeEventListener("popuphiding", this); - break; - case "TabAttrModified": - let tab = aEvent.target; - this._updateToggleMuteMenuItem(tab, - attr => aEvent.detail.changed.indexOf(attr) >= 0); - break; - } - } -}; - -#ifdef MOZ_DEVTOOLS -// Note: Do not delete! It is used for: base/content/nsContextMenu.js -XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", - "resource://devtools/client/framework/gDevTools.jsm"); -#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); -} - -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(); - } - } -}; - -var 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; - } -}; - -var 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/base/content/browser.xul b/base/content/browser.xul deleted file mode 100644 index 0a249af..0000000 --- a/base/content/browser.xul +++ /dev/null @@ -1,1046 +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://devtools/skin/devtools-browser.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;" -#ifdef MOZ_PERSONAS - lightweightthemes="true" - lightweightthemesfooter="browser-bottombox" -#endif - windowtype="navigator:browser" - macanimationtype="document" - screenX="4" screenY="4" - fullscreenbutton="true" - retargetdocumentfocus="urlbar" - 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 -#ifdef MOZ_DEVTOOLS -#include global-devtools-theme-scripts.inc -#endif -<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);"/> - <menuitem id="context_toggleMuteTab" oncommand="TabContextMenu.contextTab.toggleMuteAudio();"/> - <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"/> - <panel type="private-autocomplete" id="PopupAutoComplete" noautofocus="true" hidden="true"/> - - <!-- for url bar autocomplete --> - <panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/> - <panel type="private-autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/> - - <!-- for date/time picker. consumeoutsideclicks is set to never, so that - clicks on the anchored input box are never consumed. --> - <panel id="DateTimePickerPanel" - type="arrow" - hidden="true" - orient="vertical" - noautofocus="true" - norolluponanchor="true" - consumeoutsideclicks="never" - level="parent" - tabspecific="true"> - <iframe id="dateTimePopupFrame"/> - </panel> - - <!-- 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" - 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 -#ifndef XP_MACOSX - <spacer id="titlebar-spacer" flex="1"/> -#endif - <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="private-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="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"/> -#ifdef MOZ_WEBRTC - <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/> - <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/> -#endif - <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> -#ifdef MOZ_WEBRTC - <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> -#endif - <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" hidden="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" - datetimepicker="DateTimePickerPanel" - authdosprotected="true"/> - <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> - </hbox> - </hbox> - - <vbox id="browser-bottombox" layer="true"> - <notificationbox id="global-notificationbox"/> - <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/base/content/browserMountPoints.inc b/base/content/browserMountPoints.inc deleted file mode 100644 index e4315b0..0000000 --- a/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/base/content/content.js b/base/content/content.js deleted file mode 100644 index 211a24a..0000000 --- a/base/content/content.js +++ /dev/null @@ -1,177 +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 Cc = Components.classes; -var Ci = Components.interfaces; -var 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, "LoginFormFactory", - "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) { - LoginManagerContent.onDOMFormHasPassword(event, content); - let formLike = LoginFormFactory.createFromForm(event.target); - InsecurePasswordUtils.reportInsecurePasswords(formLike); -}); -addEventListener("DOMAutoComplete", function(event) { - LoginManagerContent.onUsernameInput(event); -}); -addEventListener("blur", function(event) { - LoginManagerContent.onUsernameInput(event); -}); - -// Provide gContextMenuContentData for 'sdk/context-menu' -var handleContentContextMenu = function (event) { - let defaultPrevented = event.defaultPrevented; - if (!Services.prefs.getBoolPref("dom.event.contextmenu.enabled")) { - let plugin = null; - try { - plugin = event.target.QueryInterface(Ci.nsIObjectLoadingContent); - } catch (e) {} - if (plugin && plugin.displayedType == Ci.nsIObjectLoadingContent.TYPE_PLUGIN) { - // Don't open a context menu for plugins. - return; - } - - defaultPrevented = false; - } - - if (defaultPrevented) - return; - - let addonInfo = {}; - let subject = { - event: event, - addonInfo: addonInfo, - }; - subject.wrappedJSObject = subject; - Services.obs.notifyObservers(subject, "content-contextmenu", null); - - let doc = event.target.ownerDocument; - let docLocation = doc.mozDocumentURIIfNotForErrorPages; - docLocation = docLocation && docLocation.spec; - let charSet = doc.characterSet; - let baseURI = doc.baseURI; - let referrer = doc.referrer; - let referrerPolicy = doc.referrerPolicy; - let frameOuterWindowID = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .outerWindowID; - let loginFillInfo = LoginManagerContent.getFieldContext(event.target); - - // The same-origin check will be done in nsContextMenu.openLinkInTab. - let parentAllowsMixedContent = !!docShell.mixedContentChannel; - - // get referrer attribute from clicked link and parse it - // if per element referrer is enabled, the element referrer overrules - // the document wide referrer - if (Services.prefs.getBoolPref("network.http.enablePerElementReferrer")) { - let referrerAttrValue = Services.netUtils.parseAttributePolicyString(event.target. - getAttribute("referrerpolicy")); - if (referrerAttrValue !== Ci.nsIHttpChannel.REFERRER_POLICY_UNSET) { - referrerPolicy = referrerAttrValue; - } - } - - // Media related cache info parent needs for saving - let contentType = null; - let contentDisposition = null; - if (event.target.nodeType == Ci.nsIDOMNode.ELEMENT_NODE && - event.target instanceof Ci.nsIImageLoadingContent && - event.target.currentURI) { - - try { - let imageCache = - Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) - .getImgCacheForDocument(doc); - let props = - imageCache.findEntryProperties(event.target.currentURI, doc); - try { - contentType = props.get("type", Ci.nsISupportsCString).data; - } catch (e) {} - try { - contentDisposition = - props.get("content-disposition", Ci.nsISupportsCString).data; - } catch (e) {} - } catch (e) {} - } - - let selectionInfo = BrowserUtils.getSelectionDetails(content); - - let loadContext = docShell.QueryInterface(Ci.nsILoadContext); - - let browser = docShell.chromeEventHandler; - let mainWin = browser.ownerGlobal; - - mainWin.gContextMenuContentData = { - isRemote: false, - event: event, - popupNode: event.target, - browser: browser, - addonInfo: addonInfo, - documentURIObject: doc.documentURIObject, - docLocation: docLocation, - charSet: charSet, - referrer: referrer, - referrerPolicy: referrerPolicy, - contentType: contentType, - contentDisposition: contentDisposition, - selectionInfo: selectionInfo, - loginFillInfo, - parentAllowsMixedContent, - }; -} - -Cc["@mozilla.org/eventlistenerservice;1"] - .getService(Ci.nsIEventListenerService) - .addSystemEventListener(global, "contextmenu", handleContentContextMenu, false); - -// 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/base/content/downloadManagerOverlay.xul b/base/content/downloadManagerOverlay.xul deleted file mode 100644 index 9987820..0000000 --- a/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/base/content/global-devtools-theme-scripts.inc b/base/content/global-devtools-theme-scripts.inc deleted file mode 100644 index 408728e..0000000 --- a/base/content/global-devtools-theme-scripts.inc +++ /dev/null @@ -1,6 +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://browser/content/browser-devtools-theme.js"/> diff --git a/base/content/global-scripts.inc b/base/content/global-scripts.inc deleted file mode 100644 index b4de574..0000000 --- a/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/base/content/hiddenWindow.xul b/base/content/hiddenWindow.xul deleted file mode 100644 index bf201fd..0000000 --- a/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/base/content/highlighter.css b/base/content/highlighter.css deleted file mode 100644 index 8fb9d80..0000000 --- a/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/base/content/jsConsoleOverlay.xul b/base/content/jsConsoleOverlay.xul deleted file mode 100644 index 1bc518d..0000000 --- a/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/base/content/macBrowserOverlay.xul b/base/content/macBrowserOverlay.xul deleted file mode 100644 index b1ae838..0000000 --- a/base/content/macBrowserOverlay.xul +++ /dev/null @@ -1,67 +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 -#ifdef MOZ_DEVTOOLS -#include global-devtools-theme-scripts.inc -#endif - -<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/base/content/nsContextMenu.js b/base/content/nsContextMenu.js deleted file mode 100644 index 916dd26..0000000 --- a/base/content/nsContextMenu.js +++ /dev/null @@ -1,1603 +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"); - -var gContextMenuContentData = null; - -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() { - gContextMenuContentData = null; - 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 (BrowserUtils.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-loop", 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); - this.setItemAttr("context-media-loop", "checked", this.target.loop); - 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://devtools/shared/Loader.jsm", {}); - let gBrowser = this.browser.ownerDocument.defaultView.gBrowser; - let target = devtools.TargetFactory.forTab(gBrowser.selectedTab); - - return gDevTools.showToolbox(target, "inspector").then(function(toolbox) { - let inspector = toolbox.getCurrentPanel(); - - this.browser.messageManager.sendAsyncMessage("debug:inspect", {}, {node: this.target}); - inspector.walker.findInspectingNode().then(nodeFront => { - inspector.selection.setNodeFront(nodeFront, "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, - referrerPolicy: doc.referrerPolicy, - originPrincipal: doc.nodePrincipal, - triggeringPrincipal: doc.nodePrincipal }); - }, - - // 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, - referrerPolicy: doc.referrerPolicy, - originPrincipal: doc.nodePrincipal, - triggeringPrincipal: doc.nodePrincipal, - 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, - referrerPolicy: doc.referrerPolicy, - originPrincipal: doc.nodePrincipal, - triggeringPrincipal: doc.nodePrincipal }); - }, - - // 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, - originPrincipal: doc.nodePrincipal, - triggeringPrincipal: doc.nodePrincipal }); - }, - - // 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) { - let target = aContext == "mathml" ? this.target : null; - top.gViewSourceUtils.viewPartialSourceInBrowser(gBrowser.selectedBrowser, target); - }, - - // 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, - forceAllowDataURI: true }); - } - }, - - saveVideoFrameAsImage: function () { - let referrerURI = document.documentURIObject; - let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser); - - 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, referrerURI, null, null, null, - isPrivate); - }, - - 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; - } - } - - // setting up a new channel for 'right click - save link as ...' - var channel = NetUtil.newChannel({ - uri: makeURI(linkURL), - loadingPrincipal: this.target.ownerDocument.nodePrincipal, - contentPolicyType: Ci.nsIContentPolicy.TYPE_SAVEAS_DOWNLOAD, - securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS, - }); - - 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.asyncOpen2(new saveAsListener()); - }, - - // 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; - let referrerURI = doc.documentURIObject; - let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser); - 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, referrerURI, null, null, null, - isPrivate); - }, Components.utils.reportError); - } - } else if (this.onImage) { - urlSecurityCheck(this.mediaURL, doc.nodePrincipal); - saveImageURL(this.mediaURL, null, "SaveImageTitle", - false, false, referrerURI, doc, null, null, - isPrivate); - } 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 "loop": - media.loop = !media.loop; - 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/base/content/openLocation.js b/base/content/openLocation.js deleted file mode 100644 index 7ad2f7c..0000000 --- a/base/content/openLocation.js +++ /dev/null @@ -1,150 +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; -var 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); -var 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 openData = { - "url": null, - "postData": null, - "mayInheritPrincipal": false - }; - if (browser) { - browser.getShortcutOrURIAndPostData(dialog.input.value).then(data => { - openData.url = data.url; - openData.postData = data.postData; - openData.mayInheritPrincipal = data.mayInheritPrincipal; - - openLocation(openData); - }); - } else { - openData.url = dialog.input.value; - - openLocation(openData); - } - - return false; -} - -function openLocation(openData) -{ - try { - // Whichever target we use for the load, we allow third-party services to - // fix up 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 (!openData.mayInheritPrincipal) - flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL; - browser.gBrowser.loadURIWithFlags( - openData.url, flags, null, null, openData.postData); - break; - case "1": - window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no", - openData.url, openData.postData, - null, null, true); - break; - case "3": - browser.delayedOpenTab( - openData.url, null, null, openData.postData, true); - break; - } - } catch (ex) {} - - if (pref) { - gOpenLocationLastURL.value = dialog.input.value; - pref.setIntPref( - "general.open_location.last_window_choice", dialog.openWhereList.value); - } - - window.close(); -} - -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/base/content/openLocation.xul b/base/content/openLocation.xul deleted file mode 100644 index 7bafed0..0000000 --- a/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/base/content/overrides/app-license.html b/base/content/overrides/app-license.html deleted file mode 100644 index 2d2e3d5..0000000 --- a/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/base/content/padlock.css b/base/content/padlock.css deleted file mode 100644 index 649cb27..0000000 --- a/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/base/content/padlock.js b/base/content/padlock.js deleted file mode 100644 index 9c29524..0000000 --- a/base/content/padlock.js +++ /dev/null @@ -1,234 +0,0 @@ -var Cc = Components.classes; -var Ci = Components.interfaces; -var 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/base/content/padlock.xul b/base/content/padlock.xul deleted file mode 100644 index e820c19..0000000 --- a/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/base/content/padlock_classic_broken.png b/base/content/padlock_classic_broken.png Binary files differdeleted file mode 100644 index 437036f..0000000 --- a/base/content/padlock_classic_broken.png +++ /dev/null diff --git a/base/content/padlock_classic_ev.png b/base/content/padlock_classic_ev.png Binary files differdeleted file mode 100644 index b3f80c0..0000000 --- a/base/content/padlock_classic_ev.png +++ /dev/null diff --git a/base/content/padlock_classic_https.png b/base/content/padlock_classic_https.png Binary files differdeleted file mode 100644 index 86026c0..0000000 --- a/base/content/padlock_classic_https.png +++ /dev/null diff --git a/base/content/padlock_classic_low.png b/base/content/padlock_classic_low.png Binary files differdeleted file mode 100644 index 652ad09..0000000 --- a/base/content/padlock_classic_low.png +++ /dev/null diff --git a/base/content/padlock_mod_broken.png b/base/content/padlock_mod_broken.png Binary files differdeleted file mode 100644 index 33a6c06..0000000 --- a/base/content/padlock_mod_broken.png +++ /dev/null diff --git a/base/content/padlock_mod_ev.png b/base/content/padlock_mod_ev.png Binary files differdeleted file mode 100644 index 3dfdcbd..0000000 --- a/base/content/padlock_mod_ev.png +++ /dev/null diff --git a/base/content/padlock_mod_https.png b/base/content/padlock_mod_https.png Binary files differdeleted file mode 100644 index d494b42..0000000 --- a/base/content/padlock_mod_https.png +++ /dev/null diff --git a/base/content/padlock_mod_low.png b/base/content/padlock_mod_low.png Binary files differdeleted file mode 100644 index 29179ef..0000000 --- a/base/content/padlock_mod_low.png +++ /dev/null diff --git a/base/content/palemoon.xhtml b/base/content/palemoon.xhtml deleted file mode 100644 index f145550..0000000 --- a/base/content/palemoon.xhtml +++ /dev/null @@ -1,66 +0,0 @@ -<!DOCTYPE html -[ - <!ENTITY % mozillaDTD SYSTEM "chrome://browser/locale/palemoon.dtd" > - %mozillaDTD; - <!ENTITY % directionDTD SYSTEM "chrome://global/locale/global.dtd" > - %directionDTD; -]> - -<!-- 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"> - <head> - <meta charset='utf-8' /> - <title>&chronicles.title.66.1;</title> - -<style type="text/css"> -html { - background: #333399 radial-gradient( circle at 75% 25%, #6666b0 0%, #333399 40%, #111177 80%) center center / cover no-repeat; - color: white; - font-style: italic; - text-rendering: optimizeLegibility; - min-height: 100%; -} - -#moztext { - margin-top: 15%; - font-size: 1.1em; - font-family: serif; - text-align: center; - line-height: 1.5; -} - -#from { - font-size: 1.95em; - font-family: serif; - text-align: right; -} - -em { - font-size: 1.3em; - line-height: 0; -} - -a { - text-decoration: none; - color: white; -} -</style> -</head> - -<body dir="&locale.dir;"> - -<section> - <p id="moztext"> - &chronicles.quote.66.1; - </p> - - <p id="from"> - &chronicles.from.66.1; - </p> -</section> - -</body> -</html> diff --git a/base/content/popup-notifications.inc b/base/content/popup-notifications.inc deleted file mode 100644 index 31a72b4..0000000 --- a/base/content/popup-notifications.inc +++ /dev/null @@ -1,104 +0,0 @@ -# to be included inside a popupset element - - <panel id="notification-popup" - type="arrow" - 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> - -#ifdef MOZ_WEBRTC - <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> -#endif - <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="password-notification" hidden="true"> - <popupnotificationcontent orient="vertical"> - <textbox id="password-notification-username"/> - <textbox id="password-notification-password" type="password" show-content=""/> - <checkbox id="password-notification-visibilityToggle" hidden="true"/> - </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/base/content/safeMode.css b/base/content/safeMode.css deleted file mode 100644 index 4f093a4..0000000 --- a/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/base/content/safeMode.js b/base/content/safeMode.js deleted file mode 100644 index e1e5c72..0000000 --- a/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/base/content/safeMode.xul b/base/content/safeMode.xul deleted file mode 100644 index 656df6e..0000000 --- a/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/base/content/sanitize.js b/base/content/sanitize.js deleted file mode 100644 index b4d13d8..0000000 --- a/base/content/sanitize.js +++ /dev/null @@ -1,534 +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://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "console", - "resource://gre/modules/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, cookie.originAttributes); - } - } - 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.removeVisitsByFilter({ - beginDate: new Date(this.range[0] / 1000), - endDate: new Date(this.range[1] / 1000) - }).catch(Components.utils.reportError);; - } else { - // Remove everything. - PlacesUtils.history.clear() - .catch(Components.utils.reportError); - } - - 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/base/content/sanitize.xul b/base/content/sanitize.xul deleted file mode 100644 index 691be92..0000000 --- a/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/base/content/sanitizeDialog.css b/base/content/sanitizeDialog.css deleted file mode 100644 index 27c3c08..0000000 --- a/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/base/content/sanitizeDialog.js b/base/content/sanitizeDialog.js deleted file mode 100644 index 7861132..0000000 --- a/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/. */ - -var Cc = Components.classes; -var 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/base/content/softwareUpdateOverlay.xul b/base/content/softwareUpdateOverlay.xul deleted file mode 100644 index 01170e4..0000000 --- a/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/base/content/tabbrowser.css b/base/content/tabbrowser.css deleted file mode 100644 index 43536b2..0000000 --- a/base/content/tabbrowser.css +++ /dev/null @@ -1,77 +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, -.tab-icon-sound:not([soundplaying]):not([muted]):not([blocked]), -.tab-icon-sound[pinned], -.tab-icon-overlay { - display: none; -} - -.tab-icon-overlay[soundplaying][pinned], -.tab-icon-overlay[muted][pinned], -.tab-icon-overlay[blocked][pinned] { - display: -moz-box; -} - -.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/base/content/tabbrowser.xml b/base/content/tabbrowser.xml deleted file mode 100644 index b5edd54..0000000 --- a/base/content/tabbrowser.xml +++ /dev/null @@ -1,5403 +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,datetimepicker,authdosprotected"/> - </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="popupAnchor" readonly="true"> - <getter><![CDATA[ - if (this.mCurrentTab._popupAnchor) { - return this.mCurrentTab._popupAnchor; - } - let stack = this.mCurrentBrowser.parentNode; - // Create an anchor for the popup - const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let popupAnchor = document.createElementNS(NS_XUL, "hbox"); - popupAnchor.className = "popup-anchor"; - popupAnchor.hidden = true; - stack.appendChild(popupAnchor); - return this.mCurrentTab._popupAnchor = popupAnchor; - ]]></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="getBrowserForContentWindow"> - <parameter name="aWindow"/> - <body> - <![CDATA[ - var tab = this._getTabForContentWindow(aWindow); - 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); - stack.insertBefore(newPrompt, browser.nextSibling); - browser.setAttribute("tabmodalPromptShowing", true); - - newPrompt.clientTop; // style flush to assure binding is attached - - let prompts = this.listPrompts(); - if (prompts.length > 1) { - // Let's hide ourself behind the current prompt. - newPrompt.hidden = true; - } - - 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.hidden = false; - 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="getTabFromAudioEvent"> - <parameter name="aEvent"/> - <body> - <![CDATA[ - if (!Services.prefs.getBoolPref("browser.tabs.showAudioPlayingIcon") || - !aEvent.isTrusted) { - return null; - } - - var browser = aEvent.originalTarget; - var tab = this.getTabForBrowser(browser); - return tab; - ]]> - </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; - let location, originalLocation; - try { - aRequest.QueryInterface(nsIChannel) - location = aRequest.URI; - originalLocation = aRequest.originalURI; - } catch (ex) {} - - 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) { - if (aWebProgress.isTopLevel) - this.mBrowser.urlbarChangeTracker.startedLoad(); - - 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, ["busy"]); - if (!this.mTab.selected) - this.mTab.setAttribute("unread", "true"); - } - this.mTab.removeAttribute("progress"); - - if (aWebProgress.isTopLevel) { - let isSuccessful = Components.isSuccessCode(aStatus); - if (!isSuccessful && !isTabEmpty(this.mTab)) { - // Restore the current document's location in case the - // request was stopped (possibly from a content script) - // before the location changed. - - this.mBrowser.userTypedValue = null; - - if (this.mTab.selected && gURLBar) - URLBarSetURI(); - } else if (isSuccessful) { - this.mBrowser.urlbarChangeTracker.finishedLoad(); - } - - if (!this.mBrowser.mIconURL) - this.mTabBrowser.useDefaultIcon(this.mTab); - } - - if (this.mBlank) - this.mBlank = false; - - // 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) { - let isSameDocument = - !!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT); - // We need to clear the typed value - // if the document failed to load, to make sure the urlbar reflects the - // failed URI (particularly for SSL errors). However, don't clear the value - // if the error page's URI is about:blank, because that causes complete - // loss of urlbar contents for invalid URI errors (see bug 867957). - if (this.mBrowser.didStartLoadSinceLastUserTyping() || - ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) && - aLocation.spec != "about:blank")) - this.mBrowser.userTypedValue = null; - - // If the browser was playing audio, we should remove the playing state. - if (this.mTab.hasAttribute("soundplaying") && !isSameDocument) { - clearTimeout(this.mTab._soundPlayingAttrRemovalTimer); - this.mTab._soundPlayingAttrRemovalTimer = 0; - this.mTab.removeAttribute("soundplaying"); - this.mTabBrowser._tabAttrModified(this.mTab, ["soundplaying"]); - } - - // If the browser was previously muted, we should restore the muted state. - if (this.mTab.hasAttribute("muted")) { - this.mTab.linkedBrowser.mute(); - } - - // 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; - this.mBrowser.lastLocationChange = Date.now(); - } - }, - - 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"/> - <parameter name="aLoadingPrincipal"/> - <body> - <![CDATA[ - let 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); - } - // We do not serialize the principal from within SessionStore.jsm, - // hence if aLoadingPrincipal is null we default to the - // systemPrincipal which will allow the favicon to load. - let loadingPrincipal = aLoadingPrincipal - ? aLoadingPrincipal - : Services.scriptSecurityManager.getSystemPrincipal(); - let loadType = PrivateBrowsingUtils.isWindowPrivate(window) - ? this.mFaviconService.FAVICON_LOAD_PRIVATE - : this.mFaviconService.FAVICON_LOAD_NON_PRIVATE; - - this.mFaviconService.setAndFetchFaviconForPage( - browser.currentURI, aURI, false, loadType, null, loadingPrincipal); - } - - let sizedIconUrl = browser.mIconURL || ""; - if (sizedIconUrl != aTab.getAttribute("image")) { - if (sizedIconUrl) - aTab.setAttribute("image", sizedIconUrl); - else - aTab.removeAttribute("image"); - this._tabAttrModified(aTab, ["image"]); - } - - if (Services.prefs.getBoolPref("browser.chrome.favicons.process")) { - let favImage = new Image; - favImage.src = browser.mIconURL; - var tabBrowser = this; - favImage.onload = function () { - try { - // Draw the icon 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(favImage, 0, 0, w, h); - icon = canvas.toDataURL(); - browser.mIconURL = icon; - aTab.setAttribute("image", icon); - } - catch (e) { - console.warn("Processing of favicon failed."); - // Canvas failed: icon remains as it was - } - tabBrowser._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]); - } - } - - 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, browser.contentPrincipal); - ]]> - </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; - - // Update global findbar with new content browser - if (gFindBarInitialized) { - gFindBar.browser = newBrowser; - } - - 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, ["selected"]); - this._tabAttrModified(this.mCurrentTab, ["selected"]); - - // 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"/> - <parameter name="aChanged"/> - <body><![CDATA[ - if (aTab.closing) - return; - - let event = new CustomEvent("TabAttrModified", { - bubbles: true, - cancelable: false, - detail: { - changed: aChanged, - } - }); - 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, ["label", "crop"]); - ]]> - </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, ["label", "crop"]); - - 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 aTriggeringPrincipal; - var aReferrerPolicy; - var aFromExternal; - var aRelatedToCurrent; - var aOriginPrincipal; - var aOpener; - if (arguments.length == 2 && - typeof arguments[1] == "object" && - !(arguments[1] instanceof Ci.nsIURI)) { - let params = arguments[1]; - aTriggeringPrincipal = params.triggeringPrincipal; - aReferrerURI = params.referrerURI; - aReferrerPolicy = params.referrerPolicy; - aCharset = params.charset; - aPostData = params.postData; - aLoadInBackground = params.inBackground; - aAllowThirdPartyFixup = params.allowThirdPartyFixup; - aFromExternal = params.fromExternal; - aRelatedToCurrent = params.relatedToCurrent; - aOriginPrincipal = params.originPrincipal; - aOpener = params.opener; - } - - var bgLoad = (aLoadInBackground != null) ? aLoadInBackground : - Services.prefs.getBoolPref("browser.tabs.loadInBackground"); - var owner = bgLoad ? null : this.selectedTab; - var tab = this.addTab(aURI, { - triggeringPrincipal: aTriggeringPrincipal, - referrerURI: aReferrerURI, - referrerPolicy: aReferrerPolicy, - charset: aCharset, - postData: aPostData, - ownerTab: owner, - allowThirdPartyFixup: aAllowThirdPartyFixup, - fromExternal: aFromExternal, - originPrincipal: aOriginPrincipal, - relatedToCurrent: aRelatedToCurrent, - opener: aOpener }); - if (!bgLoad) - this.selectedTab = tab; - - return tab; - ]]> - </body> - </method> - - <method name="loadTabs"> - <parameter name="aURIs"/> - <parameter name="aLoadInBackground"/> - <parameter name="aReplace"/> - <body><![CDATA[ - let aAllowThirdPartyFixup; - let aTargetTab; - let aNewIndex = -1; - let aPostDatas = []; - if (arguments.length == 2 && - typeof arguments[1] == "object") { - let params = arguments[1]; - aLoadInBackground = params.inBackground; - aReplace = params.replace; - aAllowThirdPartyFixup = params.allowThirdPartyFixup; - aTargetTab = params.targetTab; - aNewIndex = typeof params.newIndex === "number" ? - params.newIndex : aNewIndex; - aPostDatas = params.postDatas || aPostDatas; - } - - 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; - var targetTabIndex = -1; - - if (aReplace) { - let browser; - if (aTargetTab) { - browser = this.getBrowserForTab(aTargetTab); - targetTabIndex = aTargetTab._tPos; - } else { - browser = this.mCurrentBrowser; - targetTabIndex = this.tabContainer.selectedIndex; - } - let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; - if (aAllowThirdPartyFixup) { - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - } - try { - browser.loadURIWithFlags(aURIs[0], { - flags, postData: aPostDatas[0] - }); - } catch (e) { - // Ignore failure in case a URI is wrong, so we can continue - // opening the next ones. - } - } else { - firstTabAdded = this.addTab(aURIs[0], { - ownerTab: owner, - skipAnimation: multiple, - allowThirdPartyFixup: aAllowThirdPartyFixup, - postData: aPostDatas[0] - }); - if (aNewIndex !== -1) { - this.moveTabTo(firstTabAdded, aNewIndex); - targetTabIndex = firstTabAdded._tPos; - } - } - - let tabNum = targetTabIndex; - for (let i = 1; i < aURIs.length; ++i) { - let tab = this.addTab(aURIs[i], { - skipAnimation: true, - allowThirdPartyFixup: aAllowThirdPartyFixup, - postData: aPostDatas[i] - }); - if (targetTabIndex !== -1) - 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 aTriggeringPrincipal; - var aReferrerPolicy; - var aFromExternal; - var aRelatedToCurrent; - var aSkipAnimation; - var aOriginPrincipal; - var aSkipBackgroundNotify; - var aOpener; - if (arguments.length == 2 && - typeof arguments[1] == "object" && - !(arguments[1] instanceof Ci.nsIURI)) { - let params = arguments[1]; - aTriggeringPrincipal = params.triggeringPrincipal; - aReferrerURI = params.referrerURI; - aReferrerPolicy = params.referrerPolicy; - aCharset = params.charset; - aPostData = params.postData; - aOwner = params.ownerTab; - aAllowThirdPartyFixup = params.allowThirdPartyFixup; - aFromExternal = params.fromExternal; - aRelatedToCurrent = params.relatedToCurrent; - aSkipAnimation = params.skipAnimation; - aOriginPrincipal = params.originPrincipal; - aOpener = params.opener; - aSkipBackgroundNotify = params.skipBackgroundNotify; - } - - // 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"); - - let aURIObject = null; - try { - aURIObject = Services.io.newURI(aURI || "about:blank"); - } catch (ex) { /* we'll try to fix up this URL later */ } - - 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');"); - - if (aSkipBackgroundNotify) { - t.setAttribute("skipbackgroundnotify", true); - } - - 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 (aOpener) { - b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aOpener); - } - - if (this.hasAttribute("autocompletepopup")) - b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup")); - b.setAttribute("autoscrollpopup", this._autoScrollPopup.id); - - if (this.hasAttribute("datetimepicker")) { - b.setAttribute("datetimepicker", this.getAttribute("datetimepicker")); - } - - if (this.hasAttribute("authdosprotected")) { - b.setAttribute("authdosprotected", this.getAttribute("authdosprotected")); - } - - // 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 (aOriginPrincipal && aURI) { - let {URI_INHERITS_SECURITY_CONTEXT} = Ci.nsIProtocolHandler; - // Unless we know for sure we're not inheriting principals, - // force the about:blank viewer to have the right principal: - if (!aURIObject || - (Services.io.getProtocolFlags(aURIObject.scheme) & URI_INHERITS_SECURITY_CONTEXT)) { - b.createAboutBlankContentViewer(aOriginPrincipal); - } - } - - // 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: flags, - triggeringPrincipal: aTriggeringPrincipal, - referrerURI: aReferrerURI, - referrerPolicy: aReferrerPolicy, - charset: aCharset, - postData: 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) { - requestAnimationFrame(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: - // If there are multiple windows, pinned tabs will be closed, so - // we warn about them, too; if there is just one window, pinned - // tabs should come back on restart, so exclude them from warning. - var numberOfWindows = 0; - var browserEnum = Services.wm.getEnumerator("navigator:browser"); - while (browserEnum.hasMoreElements() && numberOfWindows < 2) { - numberOfWindows++; - browserEnum.getNext(); - } - if (numberOfWindows > 1) { - tabsToClose = this.tabs.length - this._removingTabs.length - } - else { - 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"); - - // Expedite the removal of the icon if it was already scheduled. - if (aOtherTab._soundPlayingAttrRemovalTimer) { - clearTimeout(aOtherTab._soundPlayingAttrRemovalTimer); - aOtherTab._soundPlayingAttrRemovalTimer = 0; - aOtherTab.removeAttribute("soundplaying"); - remoteBrowser._tabAttrModified(aOtherTab, ["soundplaying"]); - } - - // 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; - - let modifiedAttrs = []; - if (aOtherTab.hasAttribute("muted")) { - aOurTab.setAttribute("muted", "true"); - aOurTab.muteReason = aOtherTab.muteReason; - ourBrowser.mute(); - modifiedAttrs.push("muted"); - } - if (aOtherTab.hasAttribute("soundplaying")) { - aOurTab.setAttribute("soundplaying", "true"); - modifiedAttrs.push("soundplaying"); - } - - // 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, otherBrowser.contentPrincipal); - var isBusy = aOtherTab.hasAttribute("busy"); - if (isBusy) { - aOurTab.setAttribute("busy", "true"); - modifiedAttrs.push("busy"); - 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); - - if (modifiedAttrs.length) { - this._tabAttrModified(aOurTab, modifiedAttrs); - } - ]]> - </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[ - let browser = this.getBrowserForTab(aTab); - // Reset DOS mitigation for basic auth prompt - delete browser.authPromptCounter; - browser.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[ - // Note - the callee understands both: - // (a) loadURIWithFlags(aURI, aFlags, ...) - // (b) loadURIWithFlags(aURI, { flags: aFlags, ... }) - // Forwarding it as (a) here actually supports both (a) and (b), - // so you can call us either way too. - return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData); - ]]> - </body> - </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; - }, - destroy: function() { - this.finder.destroy(); - }, - 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; - }, - set entireWord(val) { - return this.finder.entireWord = val; - }, - get highlighter() { - return this.finder.highlighter; - }, - get matchesCountLimit() { - return this.finder.matchesCountLimit; - }, - fastFind: function(...args) { - this.finder.fastFind(...args); - }, - findAgain: function(...args) { - this.finder.findAgain(...args); - }, - setSearchStringToSelection: function() { - return this.finder.setSearchStringToSelection(); - }, - highlight: function(...args) { - this.finder.highlight(...args); - }, - getInitialSelection: function() { - this.finder.getInitialSelection(); - }, - getActiveSelectionText: function() { - return this.finder.getActiveSelectionText(); - }, - enableSelection: function() { - this.finder.enableSelection(); - }, - removeSelection: function() { - this.finder.removeSelection(); - }, - focusContent: function() { - this.finder.focusContent(); - }, - onFindbarClose: function() { - this.finder.onFindbarClose(); - }, - onFindbarOpen: function() { - this.finder.onFindbarOpen(); - }, - onModalHighlightChange: function(...args) { - return this.finder.onModalHighlightChange(...args); - }, - onHighlightAllChange: function(...args) { - return this.finder.onHighlightAllChange(...args); - }, - keyPress: function(aEvent) { - this.finder.keyPress(aEvent); - }, - requestMatchesCount: function(...args) { - this.finder.requestMatchesCount(...args); - }, - onIteratorRangeFound: function(...args) { - this.finder.onIteratorRangeFound(...args); - }, - onIteratorReset: function() { - this.finder.onIteratorReset(); - }, - onIteratorRestart: function(...args) { - this.finder.onIteratorRestart(...args); - }, - onIteratorStart: function(...args) { - this.finder.onIteratorStart(...args); - }, - onLocationChange: function(...args) { - this.finder.onLocationChange(...args); - } - }) - ]]></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="contentWindowAsCPOW" - 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="contentDocumentAsCPOW" - 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; - } - } - -#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="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; - } - - var stringID, label; - if (tab.mOverCloseButton) { - stringID = "tabs.closeTab"; - } else if (tab._overPlayingIcon) { - if (tab.linkedBrowser.audioBlocked) { - stringID = "tabs.unblockAudio.tooltip"; - } else { - stringID = tab.linkedBrowser.audioMuted ? - "tabs.unmuteAudio.tooltip" : - "tabs.muteAudio.tooltip"; - } - } else { - label = tab.getAttribute("label"); - } - if (stringID && !label) { - label = this.mStringBundle.getString(stringID); - } - event.target.setAttribute("label", 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> - <field name="_soundPlayingAttrRemovalTimer">0</field> - </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> - <handler event="DOMAudioPlaybackStarted"> - <![CDATA[ - var tab = getTabFromAudioEvent(event) - if (!tab) { - return; - } - - clearTimeout(tab._soundPlayingAttrRemovalTimer); - tab._soundPlayingAttrRemovalTimer = 0; - - let modifiedAttrs = []; - if (tab.hasAttribute("soundplaying-scheduledremoval")) { - tab.removeAttribute("soundplaying-scheduledremoval"); - modifiedAttrs.push("soundplaying-scheduledremoval"); - } - - if (!tab.hasAttribute("soundplaying")) { - tab.setAttribute("soundplaying", true); - modifiedAttrs.push("soundplaying"); - } - - this._tabAttrModified(tab, modifiedAttrs); - ]]> - </handler> - <handler event="DOMAudioPlaybackStopped"> - <![CDATA[ - var tab = getTabFromAudioEvent(event) - if (!tab) { - return; - } - - if (tab.hasAttribute("soundplaying")) { - let removalDelay = Services.prefs.getIntPref("browser.tabs.delayHidingAudioPlayingIconMS"); - - tab.style.setProperty("--soundplaying-removal-delay", `${removalDelay - 300}ms`); - tab.setAttribute("soundplaying-scheduledremoval", "true"); - this._tabAttrModified(tab, ["soundplaying-scheduledremoval"]); - - tab._soundPlayingAttrRemovalTimer = setTimeout(() => { - tab.removeAttribute("soundplaying-scheduledremoval"); - tab.removeAttribute("soundplaying"); - this._tabAttrModified(tab, ["soundplaying", "soundplaying-scheduledremoval"]); - }, removalDelay); - } - ]]> - </handler> - <handler event="DOMAudioPlaybackBlockStarted"> - <![CDATA[ - var tab = getTabFromAudioEvent(event) - if (!tab) { - return; - } - - if (!tab.hasAttribute("blocked")) { - tab.setAttribute("blocked", true); - this._tabAttrModified(tab, ["blocked"]); - } - ]]> - </handler> - <handler event="DOMAudioPlaybackBlockStopped"> - <![CDATA[ - var tab = getTabFromAudioEvent(event) - if (!tab) { - return; - } - - if (tab.hasAttribute("blocked")) { - tab.removeAttribute("blocked"); - this._tabAttrModified(tab, ["blocked"]); - } - ]]> - </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); - - this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled", 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 { - if (tab.hasAttribute("skipbackgroundnotify")) { - tab.removeAttribute("skipbackgroundnotify"); - } 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 comments in the "mousedown" and "click" event handlers of the - // tabbrowser-tabs binding. - if (!this._blockDblClick) - BrowserOpenTab(); - - event.preventDefault(); - ]]></handler> - - <!-- Consider that the in-tab close button is only shown on the active - tab. When clicking on an inactive tab at the position where the - close button will appear during the click, no "click" event will be - dispatched, because the mousedown and mouseup events don't have the - same event target. For that reason use "mousedown" instead of "click" - to implement in-tab close button behavior. (Pale Moon UXP issue #775) - --> - <handler event="mousedown" button="0" phase="capturing"><![CDATA[ - /* 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. - * - * Also prevent errant doubleclick on the close button from opening - * a new tab (bug 343628): - * Since we're removing the event target, if the user double-clicks - * the 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. - */ - - // Reset flags at the beginning of a series of clicks: - if (event.detail == 1) { - this.flagClickOnCloseButton = false; - this.flagActivateTabOrClickOnTabbar = false; - } - - this.blockCloseButtonOnDblclick = this.flagActivateTabOrClickOnTabbar; - this._blockDblClick = this.flagClickOnCloseButton; - - // Set flags: - let eventTargetIsCloseButton = - event.originalTarget.classList.contains("tab-close-button"); - this.flagClickOnCloseButton = eventTargetIsCloseButton; - this.flagActivateTabOrClickOnTabbar = - ((!eventTargetIsCloseButton && event.detail == 1) || - event.originalTarget.localName == "box"); - ]]></handler> - - <handler event="click" button="0"><![CDATA[ - // See comment in the "mousedown" event handler of the - // tabbrowser-tabs binding. - if (event.originalTarget.classList.contains("tab-close-button") && - !this.blockCloseButtonOnDblclick) { - gBrowser.removeTab(document.getBindingParent(event.originalTarget), - {animate: true, byMouse: true,}); - this._blockDblClick = true; - } - ]]></handler> - - <handler event="click" button="1"><![CDATA[ - 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 links; - try { - links = browserDragAndDrop.dropLinks(event, true); - } catch (ex) {} - -// // valid urls don't contain spaces ' '; if we have a space it isn't a valid url. -// if (!url || url.includes(" ")) //PMed - if (!links || links.length === 0) //FF - return; - - let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); - - if (event.shiftKey) - inBackground = !inBackground; - - let targetTab = this._getDragTargetTab(event); - let replace = !(!targetTab || dropEffect == "copy"); - let newIndex = this._getDropIndex(event); - let urls = links.map(link => link.url); - this.tabbrowser.loadTabs(urls, { - inBackground, - replace, - allowThirdPartyFixup: true, - targetTab, - newIndex, - }); - } - - 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="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:image xbl:inherits="busy,soundplaying,soundplaying-scheduledremoval,pinned,muted,blocked,selected" - anonid="overlay-icon" - class="tab-icon-overlay" - role="presentation"/> - <xul:label flex="1" - xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected" - class="tab-text tab-label" - role="presentation"/> - <xul:image xbl:inherits="soundplaying,soundplaying-scheduledremoval,pinned,muted,blocked,selected" - anonid="soundplaying-icon" - class="tab-icon-sound" - 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> - <property name="_overPlayingIcon" readonly="true"> - <getter><![CDATA[ - let iconVisible = this.hasAttribute("soundplaying") || - this.hasAttribute("muted") || - this.hasAttribute("blocked"); - let soundPlayingIcon = - document.getAnonymousElementByAttribute(this, "anonid", "soundplaying-icon"); - let overlayIcon = - document.getAnonymousElementByAttribute(this, "anonid", "overlay-icon"); - - return soundPlayingIcon && soundPlayingIcon.matches(":hover") || - (overlayIcon && overlayIcon.matches(":hover") && iconVisible); - ]]></getter> - </property> - <field name="mCorrespondingMenuitem">null</field> - <field name="closing">false</field> - <field name="lastAccessed">0</field> - - <method name="toggleMuteAudio"> - <parameter name="aMuteReason"/> - <body> - <![CDATA[ - let tabContainer = this.parentNode; - let browser = this.linkedBrowser; - let modifiedAttrs = []; - if (browser.audioBlocked) { - this.removeAttribute("blocked"); - modifiedAttrs.push("blocked"); - - // We don't want sound icon flickering between "blocked", "none" and - // "sound-playing", here adding the "soundplaying" is to keep the - // transition smoothly. - if (!this.hasAttribute("soundplaying")) { - this.setAttribute("soundplaying", true); - modifiedAttrs.push("soundplaying"); - } - - browser.resumeMedia(); - } else { - if (browser.audioMuted) { - browser.unmute(); - this.removeAttribute("muted"); - } else { - browser.mute(); - this.setAttribute("muted", "true"); - } - this.muteReason = aMuteReason || null; - modifiedAttrs.push("muted"); - } - tabContainer.tabbrowser._tabAttrModified(this, modifiedAttrs); - ]]> - </body> - </method> - </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 || - this._overPlayingIcon) { - // Prevent tabbox.xml from selecting the tab. - event.stopPropagation(); - } - ]]> - </handler> - <handler event="mouseup"> - this.style.MozUserFocus = ''; - </handler> - <handler event="click"> - <![CDATA[ - if (event.button != 0) { - return; - } - - if (this._overPlayingIcon) { - this.toggleMuteAudio(); - } - ]]> - </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"); - - function addEndImage() { - let endImage = document.createElement("image"); - endImage.setAttribute("class", "allTabs-endimage"); - let endImageContainer = document.createElement("hbox"); - endImageContainer.setAttribute("align", "center"); - endImageContainer.setAttribute("pack", "center"); - endImageContainer.appendChild(endImage); - aMenuitem.appendChild(endImageContainer); - return endImage; - } - - if (aMenuitem.firstChild) - aMenuitem.firstChild.remove(); - if (aTab.hasAttribute("muted")) - addEndImage().setAttribute("muted", "true"); - else if (aTab.hasAttribute("soundplaying")) - addEndImage().setAttribute("soundplaying", "true"); - ]]></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/base/content/test/general/audio.ogg b/base/content/test/general/audio.ogg Binary files differdeleted file mode 100644 index 7e6ef77..0000000 --- a/base/content/test/general/audio.ogg +++ /dev/null diff --git a/base/content/urlbarBindings.xml b/base/content/urlbarBindings.xml deleted file mode 100644 index d2d9cc7..0000000 --- a/base/content/urlbarBindings.xml +++ /dev/null @@ -1,1800 +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://browser/content/autocomplete.xml#private-autocomplete"> - - <content sizetopopup="pref"> - <xul:hbox anonid="textbox-container" - class="private-autocomplete-textbox-container urlbar-textbox-container" - flex="1" xbl:inherits="focused"> - <children includes="image|deck|stack|box"> - <xul:image class="private-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="private-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="private-autocomplete-history-dropmarker urlbar-history-dropmarker" - allowevents="true" - xbl:inherits="open,enablehistory,parentfocused=focused"/> - <xul:popupset anonid="popupset" - class="private-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); - let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - - let matchLastLocationChange = true; - 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; - } - continueOperation.call(this); - } - else { - this._canonizeURL(aTriggeringEvent, response => { - [url, postData, mayInheritPrincipal] = response; - if (url) { - matchLastLocationChange = (lastLocationChange == - gBrowser.selectedBrowser.lastLocationChange); - continueOperation.call(this); - } - }); - } - - function continueOperation() - { - this.value = url; - gBrowser.userTypedValue = url; - try { - addToUrlbarHistory(url); - } catch (ex) { - // Things may go wrong when adding url to session history, - // but don't let that interfere with the loading of the url. - Cu.reportError(ex); - } - - // Reset DOS mitigations for the basic auth prompt. - let browser = gBrowser.selectedBrowser; - delete browser.authPromptCounter; - - function loadCurrent() { - let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; - // Pass LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL to prevent any loads from - // inheriting the currently loaded document's principal, unless this - // URL is marked as safe to inherit (e.g. came from a bookmark - // keyword). - if (!mayInheritPrincipal) - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL; - // If the value wasn't typed, we know that we decoded the value as - // UTF-8 (see losslessDecodeURI) - if (!this.valueIsTyped) - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_URI_IS_UTF8; - gBrowser.loadURIWithFlags(url, flags, null, null, postData); - } - - // 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; - - // If the current tab is empty, ignore Alt+Enter (just reuse this tab) - let altEnter = !isMouseEvent && aTriggeringEvent && - aTriggeringEvent.altKey && !isTabEmpty(gBrowser.selectedTab); - - if (isMouseEvent || altEnter) { - // Use the standard UI link behaviors for clicks or Alt+Enter - let where = "tab"; - if (isMouseEvent) - where = whereToOpenLink(aTriggeringEvent, false, false); - - if (where == "current") { - if (matchLastLocationChange) { - loadCurrent(); - } - } else { - this.handleRevert(); - let params = { allowThirdPartyFixup: true, - postData: postData, - initiatingDoc: document }; - if (!this.valueIsTyped) - params.isUTF8 = true; - openUILinkIn(url, where, params); - } - } else { - if (matchLastLocationChange) { - loadCurrent(); - } - } - } - ]]></body> - </method> - - <method name="_canonizeURL"> - <parameter name="aTriggeringEvent"/> - <parameter name="aCallback"/> - <body><![CDATA[ - var url = this.value; - if (!url) { - aCallback(["", null, false]); - return; - } - - // Only add the suffix when the URL bar value isn't already "URL-like", - // and only if we get a keyboard event, to match user expectations. - 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; - } - } - - getShortcutOrURIAndPostData(url).then(data => { - aCallback([data.url, data.postData, data.mayInheritPrincipal]); - }); - ]]></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 links = browserDragAndDrop.dropLinks(aEvent); - - // The URL bar automatically handles inputs with newline characters, - // so we can get away with treating text/x-moz-url flavours as text/plain. - if (links.length > 0 && links[0].url) { - let url = links[0].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://browser/content/autocomplete.xml#private-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 prePath = this.notification.browser.contentWindow.document.nodePrincipal.URI.prePath; - this._setupDescription("pluginActivateMultiple.message", null, prePath); - - 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 prePath = action.pluginPermissionPrePath; - - 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, prePath); - 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="prePath" /> - <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 = ["__prepath__", this._brandShortName]; - if (pluginName) { - args.unshift(pluginName); - } - var bases = gNavigatorBundle.getFormattedString(baseString, args). - split("__prepath__", 2); - - span.appendChild(document.createTextNode(bases[0])); - var prePathSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em"); - prePathSpan.appendChild(document.createTextNode(prePath)); - span.appendChild(prePathSpan); - span.appendChild(document.createTextNode(bases[1] + " ")); - ]]></body> - </method> - <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="toolbarbutton-badged" display="xul:button" - extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton"> - <content> - <children includes="observes|template|menupopup|panel|tooltip"/> - <xul:stack class="toolbarbutton-badge-stack"> - <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/> - <xul:label class="toolbarbutton-badge" xbl:inherits="value=badge" top="0" end="0"/> - </xul:stack> - <xul:label class="toolbarbutton-text" crop="right" flex="1" - xbl:inherits="value=label,accesskey,crop"/> - </content> - </binding> - -</bindings> diff --git a/base/content/utilityOverlay.js b/base/content/utilityOverlay.js deleted file mode 100644 index 1d284ba..0000000 --- a/base/content/utilityOverlay.js +++ /dev/null @@ -1,901 +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.defineLazyModuleGetter(this, "ShellService", - "resource:///modules/ShellService.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "Deprecated", - "resource://gre/modules/Deprecated.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 getBoolPref(pref, defaultValue) { - Deprecated.warning("getBoolPref is deprecated and will be removed in a future release. " + - "You should use Services.pref.getBoolPref (Services.jsm).", - "https://github.com/MoonchildProductions/UXP/issues/989"); - return Services.prefs.getBoolPref(pref, defaultValue); -} - - -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"); -} - -/* 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, - referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT, - 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 = Services.prefs.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 && Services.prefs.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, - referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT, - }; - } - - params.fromChrome = true; - - openLinkIn(url, where, params); -} - -/* eslint-disable complexity */ -function openLinkIn(url, where, params) { - if (!where || !url) - return; - const Cc = Components.classes; - const Ci = Components.interfaces; - - var aFromChrome = params.fromChrome; - var aAllowThirdPartyFixup = params.allowThirdPartyFixup; - var aPostData = params.postData; - var aCharset = params.charset; - var aReferrerURI = params.referrerURI; - var aReferrerPolicy = ('referrerPolicy' in params ? - params.referrerPolicy : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT); - var aRelatedToCurrent = params.relatedToCurrent; - var aForceAllowDataURI = params.forceAllowDataURI; - var aInBackground = params.inBackground; - var aDisallowInheritPrincipal = params.disallowInheritPrincipal; - var aInitiatingDoc = params.initiatingDoc; - var aIsPrivate = params.private; - var aPrincipal = params.originPrincipal; - var aTriggeringPrincipal = params.triggeringPrincipal; - var aForceAboutBlankViewerInCurrent = - params.forceAboutBlankViewerInCurrent; - 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; - } - // TODO(1073187): propagate referrerPolicy. - saveURL(url, null, null, true, null, aReferrerURI, aInitiatingDoc); - return; - } - - var w = getTopWin(); - if ((where == "tab" || where == "tabshifted") && - w && !w.toolbar.visible) { - w = getTopWin(true); - aRelatedToCurrent = false; - } - - // We can only do this after we're sure of what |w| will be the rest of this function. - // Note that if |w| is null we might have no current browser (we'll open a new window). - var aCurrentBrowser = params.currentBrowser || (w && w.gBrowser.selectedBrowser); - - // Teach the principal about the right OA to use, e.g. in case when - // opening a link in a new private window. - // Please note we do not have to do that for SystemPrincipals and we - // can not do it for NullPrincipals since NullPrincipals are only - // identical if they actually are the same object (See Bug: 1346759) - function useOAForPrincipal(principal) { - if (principal && principal.isCodebasePrincipal) { - let attrs = { - privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)), - }; - return Services.scriptSecurityManager.createCodebasePrincipal(principal.URI, attrs); - } - return principal; - } - aPrincipal = useOAForPrincipal(aPrincipal); - aTriggeringPrincipal = useOAForPrincipal(aTriggeringPrincipal); - - if (!w || where == "window") { - // This propagates to window.arguments. - // Strip referrer data when opening a new private window, to prevent - // regular browsing data from leaking into it. - if (aIsPrivate) { - 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; - - var referrerURISupports = null; - if (aReferrerURI && sendReferrerURI) { - referrerURISupports = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - referrerURISupports.data = aReferrerURI.spec; - } - - var referrerPolicySupports = Cc["@mozilla.org/supports-PRUint32;1"]. - createInstance(Ci.nsISupportsPRUint32); - referrerPolicySupports.data = aReferrerPolicy; - - sa.AppendElement(wuri); - sa.AppendElement(charset); - sa.AppendElement(referrerURISupports); - sa.AppendElement(aPostData); - sa.AppendElement(allowThirdPartyFixupSupports); - sa.AppendElement(referrerPolicySupports); - sa.AppendElement(aPrincipal); - sa.AppendElement(aTriggeringPrincipal); - - 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 : - Services.prefs.getBoolPref("browser.tabs.loadInBackground"); - } - - let uriObj; - if (where == "current") { - try { - uriObj = Services.io.newURI(url, null, null); - } catch (e) {} - } - - if (where == "current" && w.gBrowser.selectedTab.pinned) { - try { - // nsIURI.host can throw for non-nsStandardURL nsIURIs. - if (!uriObj || !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(); - - let browserUsedForLoad = null; - 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_PRINCIPAL; - if (aForceAllowDataURI) { - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI; - } - let {URI_INHERITS_SECURITY_CONTEXT} = Ci.nsIProtocolHandler; - if (aForceAboutBlankViewerInCurrent && - (!uriObj || - (Services.io.getProtocolFlags(uriObj.scheme) & URI_INHERITS_SECURITY_CONTEXT))) { - // Unless we know for sure we're not inheriting principals, - // force the about:blank viewer to have the right principal: - w.gBrowser.selectedBrowser.createAboutBlankContentViewer(aPrincipal); - } - - w.gBrowser.loadURIWithFlags(url, { - flags: flags, - triggeringPrincipal: aTriggeringPrincipal, - referrerURI: aReferrerURI, - referrerPolicy: aReferrerPolicy, - postData: aPostData, - originPrincipal: aPrincipal, - }); - browserUsedForLoad = aCurrentBrowser; - break; - case "tabshifted": - loadInBackground = !loadInBackground; - // fall through - case "tab": - let browser = w.gBrowser; - let tabUsedForLoad = browser.loadOneTab(url, { - referrerURI: aReferrerURI, - referrerPolicy: aReferrerPolicy, - charset: aCharset, - postData: aPostData, - inBackground: loadInBackground, - allowThirdPartyFixup: aAllowThirdPartyFixup, - relatedToCurrent: aRelatedToCurrent, - originPrincipal: aPrincipal, - triggeringPrincipal: aTriggeringPrincipal }); - browserUsedForLoad = tabUsedForLoad.linkedBrowser; - break; - } - - // Focus the content, but only if the browser used for the load is selected. - if (browserUsedForLoad && - browserUsedForLoad == browserUsedForLoad.getTabBrowser().selectedBrowser) { - browserUsedForLoad.focus(); - } - - if (!loadInBackground && w.isBlankPageURL(url)) - if (!w.focusAndSelectUrlBar()) { - console.error("Unable to focus and select address bar.") - } -} - -// 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; -} - -// This function exists for legacy reasons. -function getShellService() -{ - return ShellService; -} - -function isBidiEnabled() { - // first check the pref. - if (Services.prefs.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; -} - -#ifdef MOZ_UPDATER -/** - * Opens the update manager and checks for updates to the application. - */ -function checkForUpdates() -{ - var um = - Components.classes["@mozilla.org/updates/update-manager;1"]. - getService(Components.interfaces.nsIUpdateManager); - var prompter = - Components.classes["@mozilla.org/updates/update-prompt;1"]. - createInstance(Components.interfaces.nsIUpdatePrompt); - - // If there's an update ready to be applied, show the "Update Downloaded" - // UI instead and let the user know they have to restart the application for - // the changes to be applied. - if (um.activeUpdate && ["pending", "pending-elevate", "applied"].includes(um.activeUpdate.state)) - prompter.showUpdateDownloaded(um.activeUpdate); - else - prompter.checkForUpdates(); -} -#endif - -/** - * Set up the help menu software update items to show proper status, - * also disabling the items if update is disabled. - */ -function buildHelpMenu() -{ -#ifdef MOZ_UPDATER - var updates = - Components.classes["@mozilla.org/updates/update-service;1"]. - getService(Components.interfaces.nsIApplicationUpdateService); - var um = - Components.classes["@mozilla.org/updates/update-manager;1"]. - getService(Components.interfaces.nsIUpdateManager); - - // Disable the UI if the update enabled pref has been locked by the - // administrator or if we cannot update for some other reason. - var checkForUpdates = document.getElementById("checkForUpdates"); - var appMenuCheckForUpdates = document.getElementById("appmenu_checkForUpdates"); - var canCheckForUpdates = updates.canCheckForUpdates; - - checkForUpdates.setAttribute("disabled", !canCheckForUpdates); - - if (appMenuCheckForUpdates) { - appMenuCheckForUpdates.setAttribute("disabled", !canCheckForUpdates); - } - - if (!canCheckForUpdates) { - return; - } - - var strings = document.getElementById("bundle_browser"); - var activeUpdate = um.activeUpdate; - - // If there's an active update, substitute its name into the label - // we show for this item, otherwise display a generic label. - function getStringWithUpdateName(key) { - if (activeUpdate && activeUpdate.name) - return strings.getFormattedString(key, [activeUpdate.name]); - return strings.getString(key + "Fallback"); - } - - // By default, show "Check for Updates..." from updatesItem_default or - // updatesItem_defaultFallback - var key = "default"; - if (activeUpdate) { - switch (activeUpdate.state) { - case "downloading": - // If we're downloading an update at present, show the text: - // "Downloading Thunderbird x.x..." from updatesItem_downloading or - // updatesItem_downloadingFallback, otherwise we're paused, and show - // "Resume Downloading Thunderbird x.x..." from updatesItem_resume or - // updatesItem_resumeFallback - key = updates.isDownloading ? "downloading" : "resume"; - break; - case "pending": - // If we're waiting for the user to restart, show: "Apply Downloaded - // Updates Now..." from updatesItem_pending or - // updatesItem_pendingFallback - key = "pending"; - break; - } - } - - checkForUpdates.label = getStringWithUpdateName("updatesItem_" + key); - - if (appMenuCheckForUpdates) { - appMenuCheckForUpdates.label = getStringWithUpdateName("updatesItem_" + key); - } - - // updatesItem_default.accesskey, updatesItem_downloading.accesskey, - // updatesItem_resume.accesskey or updatesItem_pending.accesskey - checkForUpdates.accessKey = strings.getString("updatesItem_" + key + - ".accesskey"); - - if (appMenuCheckForUpdates) { - appMenuCheckForUpdates.accessKey = strings.getString("updatesItem_" + key + - ".accesskey"); - } - - if (um.activeUpdate && updates.isDownloading) { - checkForUpdates.setAttribute("loading", "true"); - if (appMenuCheckForUpdates) { - appMenuCheckForUpdates.setAttribute("loading", "true"); - } - } else { - checkForUpdates.removeAttribute("loading"); - if (appMenuCheckForUpdates) { - appMenuCheckForUpdates.removeAttribute("loading"); - } - } -#else -#ifndef XP_MACOSX - // Some extensions may rely on these being present so only hide the about - // separator when there are no elements besides the check for updates menuitem - // in between the about separator and the updates separator. - var updatesSeparator = document.getElementById("updatesSeparator"); - var aboutSeparator = document.getElementById("aboutSeparator"); - var checkForUpdates = document.getElementById("checkForUpdates"); - if (updatesSeparator.nextSibling === checkForUpdates && - checkForUpdates.nextSibling === aboutSeparator) - updatesSeparator.hidden = true; -#endif -#endif -} - - -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 = Services.prefs.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 release notes page for this version of the application. - */ -function openReleaseNotes() -{ - var relnotesURL = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] - .getService(Components.interfaces.nsIURLFormatter) - .formatURLPref("app.releaseNotesURL"); - - openUILinkIn(relnotesURL, "tab"); -} - -/** - * 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 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. - * @param [optional] aReferrerPolicy - * Referrer policy - Ci.nsIHttpChannel.REFERRER_POLICY_*. - */ -function openNewTabWith(aURL, aDocument, aPostData, aEvent, - aAllowThirdPartyFixup, aReferrer, aReferrerPolicy) { - 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, - referrerPolicy: aReferrerPolicy, - }); -} - -function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, - aReferrer, aReferrerPolicy) { - 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, - referrerPolicy: aReferrerPolicy, - }); -} - -/** - * 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 = Services.prefs.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/base/content/viewSourceOverlay.xul b/base/content/viewSourceOverlay.xul deleted file mode 100644 index 8b40ddf..0000000 --- a/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/base/content/web-panels.js b/base/content/web-panels.js deleted file mode 100644 index 6e2bf5b..0000000 --- a/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/base/content/web-panels.xul b/base/content/web-panels.xul deleted file mode 100644 index ea1e2eb..0000000 --- a/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/base/content/win6BrowserOverlay.xul b/base/content/win6BrowserOverlay.xul deleted file mode 100644 index a69e3f6..0000000 --- a/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> |