diff options
Diffstat (limited to 'browser')
226 files changed, 1265 insertions, 11016 deletions
diff --git a/browser/LICENSE b/browser/LICENSE index 99d9d6bcd..f1b2067a7 100644 --- a/browser/LICENSE +++ b/browser/LICENSE @@ -2,6 +2,10 @@ Please see the file ../toolkit/content/license.html for the copyright licensing conditions attached to this codebase, including copies of the licenses concerned. -You are not granted rights or licenses to the trademarks of the -Mozilla Foundation or any party, including without limitation the -Firefox name or logo. +You are not granted rights or licenses to the trademarks of Moonchild +Productions or any other party, including without limitation the +Basilisk name or logo. + +The Serpent logo in branding/unofficial is derived from "Sea Serpent" +by Lorc, licensed under the Creative Commons license CC-BY 3.0 + diff --git a/browser/app/blocklist.xml b/browser/app/blocklist.xml index 1c71bcd61..239fe43a4 100644 --- a/browser/app/blocklist.xml +++ b/browser/app/blocklist.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> -<blocklist lastupdate="1511452800000" xmlns="http://www.mozilla.org/2006/addons-blocklist"> +<blocklist lastupdate="1521130300000" xmlns="http://www.mozilla.org/2006/addons-blocklist"> <emItems> <emItem blockID="i988" id="{b12785f5-d8d0-4530-a3ea-5c4263b85bef}"> <prefs/> @@ -2087,6 +2087,10 @@ <prefs/> <versionRange minVersion="0" maxVersion="15.0.5" severity="1"/> </emItem> + <emItem blockID="2447476f-043b-4d0b-9d3c-8e859c97d950" id="{44e4b2cf-77ba-4f76-aca7-f3fcbc2dda2f}"> + <prefs/> + <versionRange minVersion="0" maxVersion="*" severity="3"/> + </emItem> </emItems> <pluginItems> <pluginItem blockID="p416"> diff --git a/browser/app/macbuild/Contents/Info.plist.in b/browser/app/macbuild/Contents/Info.plist.in index 6212e886d..d6902fffd 100644 --- a/browser/app/macbuild/Contents/Info.plist.in +++ b/browser/app/macbuild/Contents/Info.plist.in @@ -205,6 +205,11 @@ <true/> <key>LSApplicationCategoryType</key> <string>public.app-category.productivity</string> + <key>LSEnvironment</key> + <dict> + <key>MallocNanoZone</key> + <string>0</string> + </dict> <key>LSFileQuarantineEnabled</key> <true/> <key>LSMinimumSystemVersion</key> diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp index ac2e85ea3..184b1fc2e 100644 --- a/browser/app/nsBrowserApp.cpp +++ b/browser/app/nsBrowserApp.cpp @@ -24,11 +24,6 @@ #include "nsStringGlue.h" #ifdef XP_WIN -#ifdef MOZ_ASAN -// ASAN requires basilisk.exe to be built with -MD, and it's OK if we don't -// support Windows XP SP2 in ASAN builds. -#define XRE_DONT_SUPPORT_XPSP2 -#endif #define XRE_WANT_ENVIRON #define strcasecmp _stricmp #ifdef MOZ_SANDBOX diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index b46d944e8..0ef9d4ab5 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -229,11 +229,6 @@ pref("browser.slowStartup.notificationDisabled", false); pref("browser.slowStartup.timeThreshold", 40000); pref("browser.slowStartup.maxSamples", 5); -// This url, if changed, MUST continue to point to an https url. Pulling arbitrary content to inject into -// this page over http opens us up to a man-in-the-middle attack that we'd rather not face. If you are a downstream -// repackager of this code using an alternate snippet url, please keep your users safe -pref("browser.aboutHomeSnippets.updateUrl", "https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/"); - pref("browser.enable_automatic_image_resizing", true); pref("browser.casting.enabled", false); pref("browser.chrome.site_icons", true); @@ -1061,7 +1056,6 @@ pref("services.sync.prefs.sync.browser.download.useDownloadDir", true); pref("services.sync.prefs.sync.browser.formfill.enable", true); pref("services.sync.prefs.sync.browser.link.open_newwindow", true); pref("services.sync.prefs.sync.browser.newtabpage.enabled", true); -pref("services.sync.prefs.sync.browser.newtabpage.enhanced", true); pref("services.sync.prefs.sync.browser.newtabpage.pinned", true); pref("services.sync.prefs.sync.browser.offline-apps.notify", true); pref("services.sync.prefs.sync.browser.safebrowsing.phishing.enabled", true); @@ -1156,7 +1150,7 @@ pref("browser.newtabpage.introShown", false); pref("browser.newtabpage.enabled", true); // Toggles the enhanced content of 'about:newtab'. Shows sponsored tiles. -sticky_pref("browser.newtabpage.enhanced", true); +sticky_pref("browser.newtabpage.enhanced", false); // enables Activity Stream inspired layout pref("browser.newtabpage.compact", false); @@ -1330,20 +1324,21 @@ pref("identity.fxaccounts.migrateToDevEdition", false); pref("ui.key.menuAccessKeyFocuses", true); #endif +#ifdef MOZ_EME // Encrypted media extensions. -#ifdef XP_LINUX -// On Linux EME is visible but disabled by default. This is so that the -// "Play DRM content" checkbox in the Firefox UI is unchecked by default. +// EME is visible but disabled by default. This is so that the +// "Play DRM content" checkbox in the browser UI is unchecked by default. // DRM requires downloading and installing proprietary binaries, which -// users on an open source operating systems didn't opt into. The first -// time a site using EME is encountered, the user will be prompted to -// enable DRM, whereupon the EME plugin binaries will be downloaded if -// permission is granted. +// users didn't necessarily opt-in to by installing the browser. +// The first time a site using EME is encountered, the user will be +// prompted to enable DRM, whereupon the EME plugin binaries will be +// downloaded if permission is granted. pref("media.eme.enabled", false); +pref("media.eme.apiVisible", true); #else -pref("media.eme.enabled", true); +// Disable redundant interfaces +pref("media.eme.apiVisible", false); #endif -pref("media.eme.apiVisible", true); // Decode using Gecko Media Plugins in <video>, if a system decoder is not // availble and the preferred GMP is available. @@ -1397,13 +1392,6 @@ pref("browser.translation.engine", "bing"); // Determines if Telemetry pings can be archived locally. pref("toolkit.telemetry.archive.enabled", true); -// Telemetry experiments settings. -pref("experiments.enabled", true); -pref("experiments.manifest.fetchIntervalSeconds", 86400); -pref("experiments.manifest.uri", "https://telemetry-experiment.cdn.mozilla.net/manifest/v1/firefox/%VERSION%/%CHANNEL%"); -// Whether experiments are supported by the current application profile. -pref("experiments.supported", true); - // Enable GMP support in the addon manager. pref("media.gmp-provider.enabled", true); diff --git a/browser/base/content/aboutDialog.js b/browser/base/content/aboutDialog.js index b024d2d52..f9571621f 100644 --- a/browser/base/content/aboutDialog.js +++ b/browser/base/content/aboutDialog.js @@ -40,16 +40,23 @@ function init(aEvent) // Pref is unset } - // Include the build ID and display warning if this is an "a#" (nightly or aurora) build + // Include the build ID let versionField = document.getElementById("version"); let version = Services.appinfo.version; + let buildID = Services.appinfo.appBuildID; + let year = buildID.slice(0, 4); + let month = buildID.slice(4, 6); + let day = buildID.slice(6, 8); + let hour = buildID.slice(8, 10); + let minute = buildID.slice(10, 12); + if (Services.prefs.getBoolPref("general.useragent.appVersionIsBuildID")) { + versionField.textContent = `${year}.${month}.${day}`; + } else { + versionField.textContent = `v` + version + ` (${year}-${month}-${day})`; + } + + // Display warning if this is an "a#" (nightly or aurora) build if (/a\d+$/.test(version)) { - let buildID = Services.appinfo.appBuildID; - let year = buildID.slice(0, 4); - let month = buildID.slice(4, 6); - let day = buildID.slice(6, 8); - versionField.textContent += ` (${year}-${month}-${day})`; - document.getElementById("experimental").hidden = false; document.getElementById("communityDesc").hidden = true; } diff --git a/browser/base/content/aboutDialog.xul b/browser/base/content/aboutDialog.xul index ef2804f31..5780e5ec1 100644 --- a/browser/base/content/aboutDialog.xul +++ b/browser/base/content/aboutDialog.xul @@ -45,7 +45,7 @@ <vbox id="leftBox" flex="1"/> <vbox id="rightBox" flex="1"> <hbox align="baseline"> -#expand <label id="version">__MOZ_APP_VERSION_DISPLAY__</label> +#expand <label id="version"></label> #ifndef NIGHTLY_BUILD <label id="releasenotes" class="text-link">&releaseNotes.link;</label> #endif @@ -120,20 +120,20 @@ <vbox id="experimental" hidden="true"> <description class="text-blurb" id="warningDesc"> &warningDesc.version; -#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT - &warningDesc.telemetryDesc; -#endif - </description> - <description class="text-blurb" id="communityExperimentalDesc"> - &community.exp.start;<label class="text-link" href="http://www.mozilla.org/">&community.exp.mozillaLink;</label>&community.exp.middle;<label class="text-link" useoriginprincipal="true" href="about:credits">&community.exp.creditsLink;</label>&community.exp.end; </description> </vbox> +#ifdef MC_PRIVATE_BUILD +<description class="text-blurb" id="communityDesc"> + This is a private build of Basilisk. 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.basilisk-browser.org/">Basilisk website</label>. + </description> +#else <description class="text-blurb" id="communityDesc"> - &community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" useoriginprincipal="true" href="about:credits">&community.creditsLink;</label>&community.end3; + Basilisk is community software released by <label class="text-link" href="http://www.palemoon.org/">the Pale Moon team</label> and Mozilla developers. Learn <label class="text-link" useoriginprincipal="true" href="about:credits">who contributed</label> to this software. </description> <description class="text-blurb" id="contributeDesc"> - &helpus.start;<label class="text-link" href="https://sendto.mozilla.org/page/contribute/Give-Now?source=mozillaorg_default_footer&ref=firefox_about&utm_campaign=firefox_about&tm_source=firefox&tm_medium=referral&utm_content=20140929_FireFoxAbout">&helpus.donateLink;</label>&helpus.middle;<label class="text-link" href="http://www.mozilla.org/contribute/">&helpus.getInvolvedLink;</label>&helpus.end; + Want to help? Please consider <label class="text-link" href="https://www.palemoon.org/donations.shtml">donating</label> or get involved with our <label class="text-link" href="https://github.com/MoonchildProductions/UXP">development</label> of the Unified XUL Platform. </description> +#endif </vbox> </vbox> </hbox> @@ -141,7 +141,7 @@ <hbox pack="center"> <label class="text-link bottom-link" useoriginprincipal="true" href="about:license">&bottomLinks.license;</label> <label class="text-link bottom-link" useoriginprincipal="true" href="about:rights">&bottomLinks.rights;</label> - <label class="text-link bottom-link" href="https://www.mozilla.org/privacy/">&bottomLinks.privacy;</label> + <label class="text-link bottom-link" href="https://www.palemoon.org/privacy.shtml">&bottomLinks.privacy;</label> </hbox> <description id="trademark">&trademarkInfo.part1;</description> </vbox> diff --git a/browser/base/content/abouthome/aboutHome.css b/browser/base/content/abouthome/aboutHome.css index c0b02e257..bc3f9882c 100644 --- a/browser/base/content/abouthome/aboutHome.css +++ b/browser/base/content/abouthome/aboutHome.css @@ -49,8 +49,7 @@ a { background-repeat: no-repeat; } -#searchIconAndTextContainer, -#snippets { +#searchIconAndTextContainer { width: 470px; } @@ -168,48 +167,6 @@ a { transition-duration: 0ms; } -#defaultSnippet1, -#defaultSnippet2, -#rightsSnippet { - display: block; - min-height: 38px; - background: 0 center no-repeat; - padding: 6px 0; - padding-inline-start: 49px; -} - -#rightsSnippet[hidden] { - display: none; -} - -#defaultSnippet1:dir(rtl), -#defaultSnippet2:dir(rtl), -#rightsSnippet:dir(rtl) { - background-position: right 0 center; -} - -#defaultSnippet1 { - background-image: url("chrome://browser/content/abouthome/snippet1.png"); -} - -#defaultSnippet2 { - background-image: url("chrome://browser/content/abouthome/snippet2.png"); -} - -#snippets { - display: inline-block; - text-align: start; - margin: 12px 0; - color: #3c3c3c; - font-size: 75%; - /* 12px is the computed font size, 15px the computed line height of the snippets - with Segoe UI on a default Windows 7 setup. The 15/12 multiplier approximately - converts em from units of font-size to units of line-height. The goal is to - preset the height of a three-line snippet to avoid visual moving/flickering as - the snippets load. */ - min-height: calc(15/12 * 3em); -} - #launcher { display: -moz-box; -moz-box-align: center; @@ -385,20 +342,6 @@ body[narrow] #restorePreviousSession::before { background-image: url("chrome://branding/content/about-logo@2x.png"); } - #defaultSnippet1, - #defaultSnippet2, - #rightsSnippet { - background-size: 40px; - } - - #defaultSnippet1 { - background-image: url("chrome://browser/content/abouthome/snippet1@2x.png"); - } - - #defaultSnippet2 { - background-image: url("chrome://browser/content/abouthome/snippet2@2x.png"); - } - .launchButton::before, #aboutMozilla::before { transform: scale(.5); diff --git a/browser/base/content/abouthome/aboutHome.js b/browser/base/content/abouthome/aboutHome.js index 50f3e01cd..0cbcc835a 100644 --- a/browser/base/content/abouthome/aboutHome.js +++ b/browser/base/content/abouthome/aboutHome.js @@ -6,23 +6,10 @@ /* import-globals-from ../contentSearchUI.js */ -// The process of adding a new default snippet involves: -// * add a new entity to aboutHome.dtd -// * add a <span/> for it in aboutHome.xhtml -// * add an entry here in the proper ordering (based on spans) -// The <a/> part of the snippet will be linked to the corresponding url. -const DEFAULT_SNIPPETS_URLS = [ - "https://www.mozilla.org/firefox/features/?utm_source=snippet&utm_medium=snippet&utm_campaign=default+feature+snippet" -, "https://addons.mozilla.org/firefox/?utm_source=snippet&utm_medium=snippet&utm_campaign=addons" -]; - -const SNIPPETS_UPDATE_INTERVAL_MS = 14400000; // 4 hours. - // IndexedDB storage constants. const DATABASE_NAME = "abouthome"; const DATABASE_VERSION = 1; const DATABASE_STORAGE = "persistent"; -const SNIPPETS_OBJECTSTORE_NAME = "snippets"; var searchText; // This global tracks if the page has been set up before, to prevent double inits @@ -33,13 +20,6 @@ var gObserver = new MutationObserver(function (mutations) { if (mutation.attributeName == "session") { fitToWidth(); } - if (mutation.attributeName == "snippetsVersion") { - if (!gInitialized) { - ensureSnippetsMapThen(loadSnippets); - gInitialized = true; - } - return; - } } }); @@ -90,126 +70,6 @@ window.addEventListener("keypress", ev => { searchText.value += ev.key; }); -// This object has the same interface as Map and is used to store and retrieve -// the snippets data. It is lazily initialized by ensureSnippetsMapThen(), so -// be sure its callback returned before trying to use it. -var gSnippetsMap; -var gSnippetsMapCallbacks = []; - -/** - * Ensure the snippets map is properly initialized. - * - * @param aCallback - * Invoked once the map has been initialized, gets the map as argument. - * @note Snippets should never directly manage the underlying storage, since - * it may change inadvertently. - */ -function ensureSnippetsMapThen(aCallback) -{ - if (gSnippetsMap) { - aCallback(gSnippetsMap); - return; - } - - // Handle multiple requests during the async initialization. - gSnippetsMapCallbacks.push(aCallback); - if (gSnippetsMapCallbacks.length > 1) { - // We are already updating, the callbacks will be invoked when done. - return; - } - - let invokeCallbacks = function () { - if (!gSnippetsMap) { - gSnippetsMap = Object.freeze(new Map()); - } - - for (let callback of gSnippetsMapCallbacks) { - callback(gSnippetsMap); - } - gSnippetsMapCallbacks.length = 0; - } - - let openRequest = indexedDB.open(DATABASE_NAME, {version: DATABASE_VERSION, - storage: DATABASE_STORAGE}); - - openRequest.onerror = function (event) { - // Try to delete the old database so that we can start this process over - // next time. - indexedDB.deleteDatabase(DATABASE_NAME); - invokeCallbacks(); - }; - - openRequest.onupgradeneeded = function (event) { - let db = event.target.result; - if (!db.objectStoreNames.contains(SNIPPETS_OBJECTSTORE_NAME)) { - db.createObjectStore(SNIPPETS_OBJECTSTORE_NAME); - } - } - - openRequest.onsuccess = function (event) { - let db = event.target.result; - - db.onerror = function (event) { - invokeCallbacks(); - } - - db.onversionchange = function (event) { - event.target.close(); - invokeCallbacks(); - } - - let cache = new Map(); - let cursorRequest; - try { - cursorRequest = db.transaction(SNIPPETS_OBJECTSTORE_NAME) - .objectStore(SNIPPETS_OBJECTSTORE_NAME).openCursor(); - } catch (ex) { - console.error(ex); - invokeCallbacks(); - return; - } - - cursorRequest.onerror = function (event) { - invokeCallbacks(); - } - - cursorRequest.onsuccess = function(event) { - let cursor = event.target.result; - - // Populate the cache from the persistent storage. - if (cursor) { - cache.set(cursor.key, cursor.value); - cursor.continue(); - return; - } - - // The cache has been filled up, create the snippets map. - gSnippetsMap = Object.freeze({ - get: (aKey) => cache.get(aKey), - set: function (aKey, aValue) { - db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite") - .objectStore(SNIPPETS_OBJECTSTORE_NAME).put(aValue, aKey); - return cache.set(aKey, aValue); - }, - has: (aKey) => cache.has(aKey), - delete: function (aKey) { - db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite") - .objectStore(SNIPPETS_OBJECTSTORE_NAME).delete(aKey); - return cache.delete(aKey); - }, - clear: function () { - db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite") - .objectStore(SNIPPETS_OBJECTSTORE_NAME).clear(); - return cache.clear(); - }, - get size() { return cache.size; }, - }); - - setTimeout(invokeCallbacks, 0); - } - } -} - function onSearchSubmit(aEvent) { gContentSearchController.search(aEvent); @@ -246,146 +106,6 @@ function setupSearch() */ function loadCompleted() { - var event = new CustomEvent("AboutHomeLoadSnippetsCompleted", {bubbles:true}); - document.dispatchEvent(event); -} - -/** - * Update the local snippets from the remote storage, then show them through - * showSnippets. - */ -function loadSnippets() -{ - if (!gSnippetsMap) - throw new Error("Snippets map has not properly been initialized"); - - // Allow tests to modify the snippets map before using it. - var event = new CustomEvent("AboutHomeLoadSnippets", {bubbles:true}); - document.dispatchEvent(event); - - // Check cached snippets version. - let cachedVersion = gSnippetsMap.get("snippets-cached-version") || 0; - let currentVersion = document.documentElement.getAttribute("snippetsVersion"); - if (cachedVersion < currentVersion) { - // The cached snippets are old and unsupported, restart from scratch. - gSnippetsMap.clear(); - } - - // Check last snippets update. - let lastUpdate = gSnippetsMap.get("snippets-last-update"); - let updateURL = document.documentElement.getAttribute("snippetsURL"); - let shouldUpdate = !lastUpdate || - Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS; - if (updateURL && shouldUpdate) { - // Try to update from network. - let xhr = new XMLHttpRequest(); - xhr.timeout = 5000; - // Even if fetching should fail we don't want to spam the server, thus - // set the last update time regardless its results. Will retry tomorrow. - gSnippetsMap.set("snippets-last-update", Date.now()); - xhr.onloadend = function (event) { - if (xhr.status == 200) { - gSnippetsMap.set("snippets", xhr.responseText); - gSnippetsMap.set("snippets-cached-version", currentVersion); - } - showSnippets(); - loadCompleted(); - }; - try { - xhr.open("GET", updateURL, true); - xhr.send(null); - } catch (ex) { - showSnippets(); - loadCompleted(); - return; - } - } else { - showSnippets(); - loadCompleted(); - } -} - -/** - * Shows locally cached remote snippets, or default ones when not available. - * - * @note: snippets should never invoke showSnippets(), or they may cause - * a "too much recursion" exception. - */ -var _snippetsShown = false; -function showSnippets() -{ - let snippetsElt = document.getElementById("snippets"); - - // Show about:rights notification, if needed. - let showRights = document.documentElement.getAttribute("showKnowYourRights"); - if (showRights) { - let rightsElt = document.getElementById("rightsSnippet"); - let anchor = rightsElt.getElementsByTagName("a")[0]; - anchor.href = "about:rights"; - snippetsElt.appendChild(rightsElt); - rightsElt.removeAttribute("hidden"); - return; - } - - if (!gSnippetsMap) - throw new Error("Snippets map has not properly been initialized"); - if (_snippetsShown) { - // There's something wrong with the remote snippets, just in case fall back - // to the default snippets. - showDefaultSnippets(); - throw new Error("showSnippets should never be invoked multiple times"); - } - _snippetsShown = true; - - let snippets = gSnippetsMap.get("snippets"); - // If there are remotely fetched snippets, try to to show them. - if (snippets) { - // Injecting snippets can throw if they're invalid XML. - try { - snippetsElt.innerHTML = snippets; - // Scripts injected by innerHTML are inactive, so we have to relocate them - // through DOM manipulation to activate their contents. - Array.forEach(snippetsElt.getElementsByTagName("script"), function(elt) { - let relocatedScript = document.createElement("script"); - relocatedScript.type = "text/javascript;version=1.8"; - relocatedScript.text = elt.text; - elt.parentNode.replaceChild(relocatedScript, elt); - }); - return; - } catch (ex) { - // Bad content, continue to show default snippets. - } - } - - showDefaultSnippets(); -} - -/** - * Clear snippets element contents and show default snippets. - */ -function showDefaultSnippets() -{ - // Clear eventual contents... - let snippetsElt = document.getElementById("snippets"); - snippetsElt.innerHTML = ""; - - // ...then show default snippets. - let defaultSnippetsElt = document.getElementById("defaultSnippets"); - let entries = defaultSnippetsElt.querySelectorAll("span"); - // Choose a random snippet. Assume there is always at least one. - let randIndex = Math.floor(Math.random() * entries.length); - let entry = entries[randIndex]; - // Inject url in the eventual link. - if (DEFAULT_SNIPPETS_URLS[randIndex]) { - let links = entry.getElementsByTagName("a"); - // Default snippets can have only one link, otherwise something is messed - // up in the translation. - if (links.length == 1) { - links[0].href = DEFAULT_SNIPPETS_URLS[randIndex]; - } - } - // Move the default snippet to the snippets element. - snippetsElt.appendChild(entry); } function fitToWidth() { diff --git a/browser/base/content/abouthome/aboutHome.xhtml b/browser/base/content/abouthome/aboutHome.xhtml index c288e732e..22bf2e7e8 100644 --- a/browser/base/content/abouthome/aboutHome.xhtml +++ b/browser/base/content/abouthome/aboutHome.xhtml @@ -46,15 +46,6 @@ <input id="searchSubmit" type="button" onclick="onSearchSubmit(event)" title="&contentSearchSubmit.tooltip;"/> </div> - - <div id="snippetContainer"> - <div id="defaultSnippets" hidden="true"> - <span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span> - <span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span> - </div> - <span id="rightsSnippet" hidden="true">&abouthome.rightsSnippet;</span> - <div id="snippets"/> - </div> </div> <div class="spacer"/> @@ -73,7 +64,5 @@ <button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button> </div> - <a id="aboutMozilla" href="https://www.mozilla.org/about/?utm_source=about-home&utm_medium=Referral" - aria-label="&abouthome.aboutMozilla.label;"/> </body> </html> diff --git a/browser/base/content/browser-context.inc b/browser/base/content/browser-context.inc index 51b14d152..3061cccdd 100644 --- a/browser/base/content/browser-context.inc +++ b/browser/base/content/browser-context.inc @@ -456,12 +456,14 @@ oncommand="gContextMenu.openPasswordManager();"/> </menupopup> </menu> +#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 <menuseparator id="context-media-eme-separator" hidden="true"/> <menuitem id="context-media-eme-learnmore" class="menuitem-iconic" diff --git a/browser/base/content/browser-media.js b/browser/base/content/browser-media.js index 81e7faf17..bd5c5b227 100644 --- a/browser/base/content/browser-media.js +++ b/browser/base/content/browser-media.js @@ -5,12 +5,16 @@ var gEMEHandler = { get uiEnabled() { +#ifdef MOZ_EME let emeUIEnabled = Services.prefs.getBoolPref("browser.eme.ui.enabled"); // Force-disable on WinXP: if (navigator.platform.toLowerCase().startsWith("win")) { emeUIEnabled = emeUIEnabled && parseFloat(Services.sysinfo.get("version")) >= 6; } return emeUIEnabled; +#else + return false; +#endif }, ensureEMEEnabled: function(browser, keySystem) { Services.prefs.setBoolPref("media.eme.enabled", true); @@ -41,11 +45,23 @@ var gEMEHandler = { } return true; }, - getLearnMoreLink: function(msgId) { - let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel"); + getEMEDisabledFragment: function(msgId) { + let mainMessage = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.message"); + let [prefix, suffix] = mainMessage.split(/%(?:\$\d)?S/).map(s => document.createTextNode(s)); + let text = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.learnMoreLabel"); let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); - return "<label class='text-link' href='" + baseURL + "drm-content'>" + - text + "</label>"; + let link = document.createElement("label"); + link.className = "text-link"; + link.setAttribute("href", baseURL + "drm-content"); + link.textContent = text; + + let fragment = document.createDocumentFragment(); + [prefix, link, suffix].forEach(n => fragment.appendChild(n)); + return fragment; + }, + getMessageWithBrandName: function(notificationId) { + let msgId = "emeNotifications." + notificationId + ".message"; + return gNavigatorBundle.getFormattedString(msgId, [this._brandShortName]); }, receiveMessage: function({target: browser, data: data}) { let parsedData; @@ -63,7 +79,8 @@ var gEMEHandler = { let notificationId; let buttonCallback; - let params = []; + // Notification message can be either a string or a DOM fragment. + let notificationMessage; switch (status) { case "available": case "cdm-created": @@ -78,17 +95,17 @@ var gEMEHandler = { case "cdm-disabled": notificationId = "drmContentDisabled"; buttonCallback = gEMEHandler.ensureEMEEnabled.bind(gEMEHandler, browser, keySystem) - params = [this.getLearnMoreLink(notificationId)]; + notificationMessage = this.getEMEDisabledFragment(); break; case "cdm-insufficient-version": notificationId = "drmContentCDMInsufficientVersion"; - params = [this._brandShortName]; + notificationMessage = this.getMessageWithBrandName(notificationId); break; case "cdm-not-installed": notificationId = "drmContentCDMInstalling"; - params = [this._brandShortName]; + notificationMessage = this.getMessageWithBrandName(notificationId); break; case "cdm-not-supported": @@ -100,44 +117,29 @@ var gEMEHandler = { return; } - this.showNotificationBar(browser, notificationId, keySystem, params, buttonCallback); - }, - showNotificationBar: function(browser, notificationId, keySystem, labelParams, callback) { + // Now actually create the notification + let box = gBrowser.getNotificationBox(browser); if (box.getNotificationWithValue(notificationId)) { return; } - let msgPrefix = "emeNotifications." + notificationId + "."; - let msgId = msgPrefix + "message"; - - let message = labelParams.length ? - gNavigatorBundle.getFormattedString(msgId, labelParams) : - gNavigatorBundle.getString(msgId); - let buttons = []; - if (callback) { + if (buttonCallback) { + let msgPrefix = "emeNotifications." + notificationId + "."; let btnLabelId = msgPrefix + "button.label"; let btnAccessKeyId = msgPrefix + "button.accesskey"; buttons.push({ label: gNavigatorBundle.getString(btnLabelId), accessKey: gNavigatorBundle.getString(btnAccessKeyId), - callback: callback + callback: buttonCallback }); } let iconURL = "chrome://browser/skin/drm-icon.svg#chains-black"; - // Do a little dance to get rich content into the notification: - let fragment = document.createDocumentFragment(); - let descriptionContainer = document.createElement("description"); - descriptionContainer.innerHTML = message; - while (descriptionContainer.childNodes.length) { - fragment.appendChild(descriptionContainer.childNodes[0]); - } - - box.appendNotification(fragment, notificationId, iconURL, box.PRIORITY_WARNING_MEDIUM, - buttons); + box.appendNotification(notificationMessage, notificationId, iconURL, + box.PRIORITY_WARNING_MEDIUM, buttons); }, showPopupNotificationForSuccess: function(browser, keySystem) { // We're playing EME content! Remove any "we can't play because..." messages. @@ -201,29 +203,16 @@ let gDecoderDoctorHandler = { getLabelForNotificationBox(type) { if (type == "adobe-cdm-not-found" && AppConstants.platform == "win") { - if (AppConstants.isPlatformAndVersionAtMost("win", "5.9")) { - // We supply our own Learn More button so we don't need to populate the message here. - return gNavigatorBundle.getFormattedString("emeNotifications.drmContentDisabled.message", [""]); - } return gNavigatorBundle.getString("decoder.noCodecs.message"); } if (type == "adobe-cdm-not-activated" && AppConstants.platform == "win") { - if (AppConstants.isPlatformAndVersionAtMost("win", "5.9")) { - return gNavigatorBundle.getString("decoder.noCodecsXP.message"); - } - if (!AppConstants.isPlatformAndVersionAtLeast("win", "6.1")) { - return gNavigatorBundle.getString("decoder.noCodecsVista.message"); - } return gNavigatorBundle.getString("decoder.noCodecs.message"); } if (type == "platform-decoder-not-found") { - if (AppConstants.isPlatformAndVersionAtLeast("win", "6.1")) { + if (AppConstants.platform == "win") { return gNavigatorBundle.getString("decoder.noHWAcceleration.message"); } - if (AppConstants.isPlatformAndVersionAtLeast("win", "6")) { - return gNavigatorBundle.getString("decoder.noHWAccelerationVista.message"); - } if (AppConstants.platform == "linux") { return gNavigatorBundle.getString("decoder.noCodecsLinux.message"); } diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc index e952bc3ca..41734711c 100644 --- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -34,12 +34,6 @@ accesskey="&newPrivateWindow.accesskey;" command="Tools:PrivateBrowsing" key="key_privatebrowsing"/> -#ifdef E10S_TESTING_ONLY - <menuitem id="menu_newNonRemoteWindow" - label="&newNonRemoteWindow.label;" - hidden="true" - command="Tools:NonRemoteWindow"/> -#endif #ifdef MAC_NON_BROWSER_WINDOW <menuitem id="menu_openLocation" label="&openLocationCmd.label;" @@ -179,15 +173,6 @@ label="&bidiSwitchTextDirectionItem.label;" accesskey="&bidiSwitchTextDirectionItem.accesskey;" hidden="true"/> -#ifdef XP_UNIX -#ifndef XP_MACOSX - <menuseparator/> - <menuitem id="menu_preferences" - label="&preferencesCmdUnix.label;" - accesskey="&preferencesCmdUnix.accesskey;" - oncommand="openPreferences();"/> -#endif -#endif </menupopup> </menu> @@ -521,13 +506,11 @@ <menupopup id="menu_mirrorTab-popup" onpopupshowing="populateMirrorTabMenu(this)"/> </menu> -#ifndef XP_UNIX <menuseparator id="prefSep"/> <menuitem id="menu_preferences" label="&preferencesCmd2.label;" accesskey="&preferencesCmd2.accesskey;" oncommand="openPreferences();"/> -#endif </menupopup> </menu> diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index 3a9fb9d96..83c737977 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -1554,6 +1554,10 @@ var BookmarkingUI = { // so kill current view and let popupshowing generate a new one. if (this.button._placesView) this.button._placesView.uninit(); + // ...and do the same for the menu bar. + let menubar = document.getElementById("bookmarksMenu"); + if (menubar && menubar._placesView) + menubar._placesView.uninit(); // We have to do the same thing for the "special" views underneath the // the bookmarks menu. diff --git a/browser/base/content/browser-plugins.js b/browser/base/content/browser-plugins.js index ad070df12..c1bc65860 100644 --- a/browser/base/content/browser-plugins.js +++ b/browser/base/content/browser-plugins.js @@ -63,9 +63,7 @@ var gPluginHandler = { msg.data.pluginID); break; case "PluginContent:SubmitReport": - if (AppConstants.MOZ_CRASHREPORTER) { - this.submitReport(msg.data.runID, msg.data.keyVals, msg.data.submitURLOptIn); - } + // Nothing to do here break; case "PluginContent:LinkClickCallback": switch (msg.data.name) { @@ -98,11 +96,8 @@ var gPluginHandler = { }, submitReport: function submitReport(runID, keyVals, submitURLOptIn) { - if (!AppConstants.MOZ_CRASHREPORTER) { - return; - } - Services.prefs.setBoolPref("dom.ipc.plugins.reportCrashURL", submitURLOptIn); - PluginCrashReporter.submitCrashReport(runID, keyVals); + /*** STUB ***/ + return; }, // Callback for user clicking a "reload page" link @@ -461,18 +456,7 @@ var gPluginHandler = { // If we don't have a minidumpID, we can't (or didn't) submit anything. // This can happen if the plugin is killed from the task manager. - let state; - if (!AppConstants.MOZ_CRASHREPORTER || !gCrashReporter.enabled) { - // This state tells the user that crash reporting is disabled, so we - // cannot send a report. - state = "noSubmit"; - } else if (!pluginDumpID) { - // This state tells the user that there is no crash report available. - state = "noReport"; - } else { - // This state asks the user to submit a crash report. - state = "please"; - } + let state = "noSubmit"; let mm = window.getGroupMessageManager("browsers"); mm.broadcastAsyncMessage("BrowserPlugins:NPAPIPluginProcessCrashed", @@ -513,22 +497,6 @@ var gPluginHandler = { callback: function() { browser.reload(); }, }]; - if (AppConstants.MOZ_CRASHREPORTER && - PluginCrashReporter.hasCrashReport(pluginID)) { - let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label"); - let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey"); - let submitButton = { - label: submitLabel, - accessKey: submitKey, - popup: null, - callback: () => { - PluginCrashReporter.submitCrashReport(pluginID); - }, - }; - - buttons.push(submitButton); - } - notification = notificationBox.appendNotification(messageString, "plugin-crashed", iconURL, priority, buttons); diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc index a5a4ae8aa..0c753520f 100644 --- a/browser/base/content/browser-sets.inc +++ b/browser/base/content/browser-sets.inc @@ -103,10 +103,6 @@ oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/> <command id="Tools:PrivateBrowsing" oncommand="OpenBrowserWindow({private: true});" reserved="true"/> -#ifdef E10S_TESTING_ONLY - <command id="Tools:NonRemoteWindow" - oncommand="OpenBrowserWindow({remote: false});"/> -#endif <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/> <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/> <command id="Social:SharePage" oncommand="SocialShare.sharePage();"/> diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index d813a55cc..696a2871a 100755 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -53,19 +53,16 @@ Cu.import("resource://gre/modules/NotificationDB.jsm"); ["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"], ["Weave", "resource://services-sync/main.js"], ["fxAccounts", "resource://gre/modules/FxAccounts.jsm"], +#ifdef MOZ_DEVTOOLS + // Note: Do not delete! It is used for: base/content/nsContextMenu.js ["gDevTools", "resource://devtools/client/framework/gDevTools.jsm"], - ["gDevToolsBrowser", "resource://devtools/client/framework/gDevTools.jsm"], +#endif ["webrtcUI", "resource:///modules/webrtcUI.jsm", ] ].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource)); XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing", "resource://gre/modules/SafeBrowsing.jsm"); -if (AppConstants.MOZ_CRASHREPORTER) { - XPCOMUtils.defineLazyModuleGetter(this, "PluginCrashReporter", - "resource:///modules/ContentCrashHandlers.jsm"); -} - // lazy service getters [ ["Favicons", "@mozilla.org/browser/favicon-service;1", "mozIAsyncFavicons"], @@ -74,13 +71,6 @@ if (AppConstants.MOZ_CRASHREPORTER) { ["gDNSService", "@mozilla.org/network/dns-service;1", "nsIDNSService"], ].forEach(([name, cc, ci]) => XPCOMUtils.defineLazyServiceGetter(this, name, cc, ci)); -if (AppConstants.MOZ_CRASHREPORTER) { - XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter", - "@mozilla.org/xre/app-info;1", - "nsICrashReporter"); -} - - XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function() { let tmp = {}; Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm", tmp); @@ -97,11 +87,6 @@ XPCOMUtils.defineLazyGetter(this, "gCustomizeMode", function() { return new scope.CustomizeMode(window); }); -XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () { - // Only show resizers on Windows 2000 and XP - return AppConstants.isPlatformAndVersionAtMost("win", "5.9"); -}); - XPCOMUtils.defineLazyGetter(this, "gPrefService", function() { return Services.prefs; }); @@ -219,7 +204,8 @@ var gInitialPages = [ "about:home", "about:privatebrowsing", "about:welcomeback", - "about:sessionrestore" + "about:sessionrestore", + "about:logopage" ]; function* browserWindows() { @@ -473,9 +459,7 @@ var gPopupBlockerObserver = { var brandShortName = brandBundle.getString("brandShortName"); var popupCount = gBrowser.selectedBrowser.blockedPopups.length; - var stringKey = AppConstants.platform == "win" - ? "popupWarningButton" - : "popupWarningButtonUnix"; + var stringKey = "popupWarningButton"; var popupButtonText = gNavigatorBundle.getString(stringKey); var popupButtonAccesskey = gNavigatorBundle.getString(stringKey + ".accesskey"); @@ -1224,9 +1208,6 @@ var gBrowserInit = { BrowserOffline.init(); IndexedDBPromptHelper.init(); - if (AppConstants.E10S_TESTING_ONLY) - gRemoteTabsUI.init(); - // 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. @@ -1658,10 +1639,6 @@ if (AppConstants.platform == "macosx") { // initialize the sync UI gSyncUI.init(); - - if (AppConstants.E10S_TESTING_ONLY) { - gRemoteTabsUI.init(); - } }; gBrowserInit.nonBrowserWindowShutdown = function() { @@ -3374,8 +3351,6 @@ var PrintPreviewListener = { this._chromeState.notificationsOpen = !notificationBox.notificationsHidden; notificationBox.notificationsHidden = true; - gBrowser.updateWindowResizers(); - this._chromeState.findOpen = gFindBarInitialized && !gFindBar.hidden; if (gFindBarInitialized) gFindBar.close(); @@ -4598,23 +4573,6 @@ var XULBrowserWindow = { setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0); else this.asyncUpdateUI(); - - if (AppConstants.MOZ_CRASHREPORTER && aLocationURI) { - let uri = aLocationURI.clone(); - try { - // If the current URI contains a username/password, remove it. - uri.userPass = ""; - } catch (ex) { /* Ignore failures on about: URIs. */ } - - try { - gCrashReporter.annotateCrashReport("URL", uri.spec); - } catch (ex) { - // Don't make noise when the crash reporter is built but not enabled. - if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED) { - throw ex; - } - } - } }, asyncUpdateUI: function () { @@ -5224,7 +5182,6 @@ function setToolbarVisibility(toolbar, isVisible, persist=true) { PlacesToolbarHelper.init(); BookmarkingUI.onToolbarVisibilityChange(); - gBrowser.updateWindowResizers(); if (isVisible) ToolbarIconColor.inferFromText(); } @@ -7845,16 +7802,6 @@ var TabContextMenu = { for (let menuItem of menuItems) menuItem.disabled = disabled; - if (AppConstants.E10S_TESTING_ONLY) { - menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-remote"); - for (let menuItem of menuItems) { - menuItem.hidden = !gMultiProcessBrowser; - if (menuItem.id == "context_openNonRemoteWindow") { - menuItem.disabled = !!parseInt(this.contextTab.getAttribute("usercontextid")); - } - } - } - disabled = gBrowser.visibleTabs.length == 1; menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple-visible"); for (let menuItem of menuItems) @@ -7920,15 +7867,6 @@ var TabContextMenu = { } }; -Object.defineProperty(this, "HUDService", { - get: function HUDService_getter() { - let devtools = Cu.import("resource://devtools/shared/Loader.jsm", {}).devtools; - return devtools.require("devtools/client/webconsole/hudservice"); - }, - configurable: true, - enumerable: true -}); - // Prompt user to restart the browser in safe mode function safeModeRestart() { if (Services.appinfo.inSafeMode) { @@ -7986,30 +7924,6 @@ function duplicateTabIn(aTab, where, delta) { } } -var Scratchpad = { - openScratchpad: function SP_openScratchpad() { - return this.ScratchpadManager.openScratchpad(); - } -}; - -XPCOMUtils.defineLazyGetter(Scratchpad, "ScratchpadManager", function() { - let tmp = {}; - Cu.import("resource://devtools/client/scratchpad/scratchpad-manager.jsm", tmp); - return tmp.ScratchpadManager; -}); - -var ResponsiveUI = { - toggle: function RUI_toggle() { - this.ResponsiveUIManager.toggle(window, gBrowser.selectedTab); - } -}; - -XPCOMUtils.defineLazyGetter(ResponsiveUI, "ResponsiveUIManager", function() { - let tmp = {}; - Cu.import("resource://devtools/client/responsivedesign/responsivedesign.jsm", tmp); - return tmp.ResponsiveUIManager; -}); - var MousePosTracker = { _listeners: new Set(), _x: 0, @@ -8075,6 +7989,7 @@ var ToolbarIconColor = { 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 @@ -8089,6 +8004,7 @@ var ToolbarIconColor = { window.removeEventListener("activate", this); window.removeEventListener("deactivate", this); Services.obs.removeObserver(this, "lightweight-theme-styling-update"); + gPrefService.removeObserver("ui.colorChanged", this); }, handleEvent: function (event) { @@ -8107,6 +8023,18 @@ var ToolbarIconColor = { // 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); } }, @@ -8130,16 +8058,19 @@ var ToolbarIconColor = { let luminances = new Map; for (let toolbar of document.querySelectorAll(toolbarSelector)) { let [r, g, b] = parseRGB(getComputedStyle(toolbar).color); - let luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b; + let luminance = (2 * r + 5 * g + b) / 8; luminances.set(toolbar, luminance); } for (let [toolbar, luminance] of luminances) { - if (luminance <= 110) + if (luminance <= 128) toolbar.removeAttribute("brighttext"); else toolbar.setAttribute("brighttext", "true"); } + + // Clear pref if set, since we're done applying the color changes. + gPrefService.clearUserPref("ui.colorChanged"); } } diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 2c74aecdf..ae531e167 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -98,12 +98,6 @@ accesskey="&moveToNewWindow.accesskey;" tbattr="tabbrowser-multiple" oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/> -#ifdef E10S_TESTING_ONLY - <menuitem id="context_openNonRemoteWindow" label="Open in new non-e10s window" - tbattr="tabbrowser-remote" - hidden="true" - oncommand="gBrowser.openNonRemoteWindow(TabContextMenu.contextTab);"/> -#endif <menuseparator id="context_sendTabToDevice_separator" hidden="true"/> <menu id="context_sendTabToDevice" label="&sendTabToDevice.label;" accesskey="&sendTabToDevice.accesskey;" hidden="true"> @@ -546,10 +540,8 @@ #ifdef MENUBAR_CAN_AUTOHIDE toolbarname="&menubarCmd.label;" accesskey="&menubarCmd.accesskey;" -#if defined(MOZ_WIDGET_GTK) autohide="true" #endif -#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 diff --git a/browser/base/content/newtab/customize.js b/browser/base/content/newtab/customize.js index 28a52373c..39724fa91 100644 --- a/browser/base/content/newtab/customize.js +++ b/browser/base/content/newtab/customize.js @@ -25,7 +25,6 @@ var gCustomize = { this._nodes.button.addEventListener("click", e => this.showPanel(e)); this._nodes.blank.addEventListener("click", this); this._nodes.classic.addEventListener("click", this); - this._nodes.enhanced.addEventListener("click", this); this._nodes.learn.addEventListener("click", this); this.updateSelected(); @@ -87,11 +86,7 @@ var gCustomize = { sendAsyncMessage("NewTab:Customize", {enabled: false, enhanced: false}); break; case "newtab-customize-classic": - if (this._nodes.enhanced.getAttribute("selected")){ - sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: true}); - } else { - sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: false}); - } + sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: false}); break; case "newtab-customize-enhanced": sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: !gAllPages.enhanced}); @@ -114,9 +109,9 @@ var gCustomize = { }, updateSelected: function() { - let {enabled, enhanced} = gAllPages; - let selected = enabled ? enhanced ? "enhanced" : "classic" : "blank"; - ["enhanced", "classic", "blank"].forEach(id => { + let {enabled} = gAllPages; + let selected = enabled ? "classic" : "blank"; + ["classic", "blank"].forEach(id => { let node = this._nodes[id]; if (id == selected) { node.setAttribute("selected", true); @@ -125,9 +120,5 @@ var gCustomize = { node.removeAttribute("selected"); } }); - if (selected == "enhanced") { - // If enhanced is selected, so is classic (since enhanced is a subitem of classic) - this._nodes.classic.setAttribute("selected", true); - } }, }; diff --git a/browser/base/content/newtab/newTab.xhtml b/browser/base/content/newtab/newTab.xhtml index 07fb0093e..eef51b4b2 100644 --- a/browser/base/content/newtab/newTab.xhtml +++ b/browser/base/content/newtab/newTab.xhtml @@ -33,15 +33,8 @@ <div id="newtab-customize-title" class="newtab-customize-panel-item"> <label>&newtab.customize.cog.title2;</label> </div> - - <div class="newtab-customize-complex-option"> - <div id="newtab-customize-classic" class="newtab-customize-panel-superitem newtab-customize-panel-item selectable"> - <label>&newtab.customize.classic;</label> - </div> - <div id="newtab-customize-enhanced" class="newtab-customize-panel-subitem"> - <label class="checkbox"></label> - <label>&newtab.customize.cog.enhanced;</label> - </div> + <div id="newtab-customize-classic" class="newtab-customize-panel-item selectable"> + <label>&newtab.customize.classic;</label> </div> <div id="newtab-customize-blank" class="newtab-customize-panel-item selectable"> <label>&newtab.customize.blank2;</label> diff --git a/browser/base/content/sync/customize.xul b/browser/base/content/sync/customize.xul index d95536d9a..827edf565 100644 --- a/browser/base/content/sync/customize.xul +++ b/browser/base/content/sync/customize.xul @@ -31,12 +31,7 @@ <label id="sync-customize-title" value="&syncCustomize.title;"/> <description id="sync-customize-subtitle" -#ifdef XP_UNIX - value="&syncCustomizeUnix.description;" -#else - value="&syncCustomize.description;" -#endif - /> + value="&syncCustomize.description;"/> <vbox align="start"> <checkbox label="&engine.tabs.label;" diff --git a/browser/base/content/tab-content.js b/browser/base/content/tab-content.js index 05f8e00ab..7e803796a 100644 --- a/browser/base/content/tab-content.js +++ b/browser/base/content/tab-content.js @@ -147,13 +147,10 @@ var AboutHomeListener = { if (aData.showRestoreLastSession && !PrivateBrowsingUtils.isContentWindowPrivate(content)) doc.getElementById("launcher").setAttribute("session", "true"); - // Inject search engine and snippets URL. + // Inject search engine URL. let docElt = doc.documentElement; - // Set snippetsVersion last, which triggers to show the snippets when it's set. - docElt.setAttribute("snippetsURL", aData.snippetsURL); if (aData.showKnowYourRights) docElt.setAttribute("showKnowYourRights", "true"); - docElt.setAttribute("snippetsVersion", aData.snippetsVersion); }, onPageLoad: function() { diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 3f4c3518e..b27846835 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -214,18 +214,6 @@ ]]></body> </method> - <method name="updateWindowResizers"> - <body><![CDATA[ - if (!window.gShowPageResizers) - return; - - var show = 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[ @@ -1970,10 +1958,6 @@ b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aParams.opener); } - if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) { - b.setAttribute("showresizer", "true"); - } - if (!aParams.isPreloadBrowser && this.hasAttribute("autocompletepopup")) { b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup")); } @@ -3238,20 +3222,6 @@ </body> </method> - <!-- Opens a given tab to a non-remote window. --> - <method name="openNonRemoteWindow"> - <parameter name="aTab"/> - <body> - <![CDATA[ - if (!this.AppConstants.E10S_TESTING_ONLY) { - throw "This method is intended only for e10s testing!"; - } - let url = aTab.linkedBrowser.currentURI.spec; - return window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no,non-remote", url); - ]]> - </body> - </method> - <method name="moveTabTo"> <parameter name="aTab"/> <parameter name="aIndex"/> @@ -4597,8 +4567,7 @@ label = this.mStringBundle.getString(stringID); } } else { - label = tab.getAttribute("label") + - (this.AppConstants.E10S_TESTING_ONLY && tab.linkedBrowser && tab.linkedBrowser.isRemoteBrowser ? " - e10s" : ""); + label = tab.getAttribute("label"); } event.target.setAttribute("label", label); ]]></body> @@ -4835,7 +4804,6 @@ 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, false); @@ -5854,8 +5822,6 @@ this._handleTabSelect(); this.mTabstripWidth = width; } - - this.tabbrowser.updateWindowResizers(); break; case "mouseout": // If the "related target" (the node to which the pointer went) is not diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index 833369f4d..0b703b6f8 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -35,7 +35,7 @@ var gBidiUI = false; * Determines whether the given url is considered a special URL for new tabs. */ function isBlankPageURL(aURL) { - return aURL == "about:blank" || aURL == BROWSER_NEW_TAB_URL; + return aURL == "about:blank" || aURL == "about:newtab" || aURL == "about:logopage"; } function getBrowserURL() diff --git a/browser/base/content/win6BrowserOverlay.xul b/browser/base/content/win6BrowserOverlay.xul deleted file mode 100644 index a69e3f6bd..000000000 --- a/browser/base/content/win6BrowserOverlay.xul +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> - -<!-- -*- Mode: HTML -*- --> -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - -<overlay id="win6-browser-overlay" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <toolbar id="toolbar-menubar" - autohide="true"/> -</overlay> diff --git a/browser/base/jar.mn b/browser/base/jar.mn index c9dbbbb9f..9cbfe7c15 100644 --- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -8,9 +8,6 @@ browser.jar: % overlay chrome://mozapps/content/update/updates.xul chrome://browser/content/softwareUpdateOverlay.xul % overlay chrome://global/content/console.xul chrome://browser/content/jsConsoleOverlay.xul #endif -#ifdef XP_WIN -% overlay chrome://browser/content/browser.xul chrome://browser/content/win6BrowserOverlay.xul os=WINNT osversion>=6 -#endif % overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul % overlay chrome://global/content/viewPartialSource.xul chrome://browser/content/viewSourceOverlay.xul @@ -70,7 +67,7 @@ browser.jar: content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js) content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml) * content/browser/browser.css (content/browser.css) - content/browser/browser.js (content/browser.js) +* content/browser/browser.js (content/browser.js) * content/browser/browser.xul (content/browser.xul) content/browser/browser-addons.js (content/browser-addons.js) content/browser/browser-captivePortal.js (content/browser-captivePortal.js) @@ -83,7 +80,7 @@ browser.jar: content/browser/browser-fullZoom.js (content/browser-fullZoom.js) content/browser/browser-fxaccounts.js (content/browser-fxaccounts.js) content/browser/browser-gestureSupport.js (content/browser-gestureSupport.js) - content/browser/browser-media.js (content/browser-media.js) +* content/browser/browser-media.js (content/browser-media.js) content/browser/browser-places.js (content/browser-places.js) content/browser/browser-plugins.js (content/browser-plugins.js) content/browser/browser-refreshblocker.js (content/browser-refreshblocker.js) @@ -152,7 +149,7 @@ browser.jar: content/browser/sync/genericChange.js (content/sync/genericChange.js) content/browser/sync/key.xhtml (content/sync/key.xhtml) content/browser/sync/utils.js (content/sync/utils.js) -* content/browser/sync/customize.xul (content/sync/customize.xul) + content/browser/sync/customize.xul (content/sync/customize.xul) content/browser/sync/customize.js (content/sync/customize.js) content/browser/sync/customize.css (content/sync/customize.css) content/browser/safeMode.css (content/safeMode.css) @@ -186,9 +183,6 @@ browser.jar: * content/browser/webrtcIndicator.xul (content/webrtcIndicator.xul) content/browser/webrtcIndicator.js (content/webrtcIndicator.js) #endif -#ifdef XP_WIN - content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul) -#endif # the following files are browser-specific overrides * content/browser/license.html (/toolkit/content/license.html) % override chrome://global/content/license.html chrome://browser/content/license.html diff --git a/browser/branding/official/bgintro.bmp b/browser/branding/official/bgintro.bmp Binary files differdeleted file mode 100644 index 9c2fc80cf..000000000 --- a/browser/branding/official/bgintro.bmp +++ /dev/null diff --git a/browser/branding/official/branding.nsi b/browser/branding/official/branding.nsi index 24b0f4bba..58d7554df 100644 --- a/browser/branding/official/branding.nsi +++ b/browser/branding/official/branding.nsi @@ -20,7 +20,7 @@ !define OFFICIAL !define URLStubDownload "" !define URLManualDownload "" -!define URLSystemRequirements "" +!define URLSystemRequirements "http://www.basilisk-browser.org/requirements.shtml" !define Channel "release" # The installer's certificate name and issuer expected by the stub installer diff --git a/browser/branding/official/clock.bmp b/browser/branding/official/clock.bmp Binary files differdeleted file mode 100644 index 7da034d3b..000000000 --- a/browser/branding/official/clock.bmp +++ /dev/null diff --git a/browser/branding/official/moz.build b/browser/branding/official/moz.build index f1a839c9d..e3b7fd1ab 100644 --- a/browser/branding/official/moz.build +++ b/browser/branding/official/moz.build @@ -9,53 +9,5 @@ DIRS += ['content', 'locales'] DIST_SUBDIR = 'browser' export('DIST_SUBDIR') -JS_PREFERENCE_FILES += [ - 'pref/firefox-branding.js', -] - -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': - FINAL_TARGET_FILES['..'] += [ - 'basilisk.VisualElementsManifest.xml', - ] - FINAL_TARGET_FILES.VisualElements += [ - 'VisualElements_150.png', - 'VisualElements_70.png', - ] - BRANDING_FILES += [ - 'appname.bmp', - 'bgintro.bmp', - 'branding.nsi', - 'clock.bmp', - 'document.ico', - 'firefox.ico', - 'newtab.ico', - 'newwindow.ico', - 'particles.bmp', - 'pbmode.ico', - 'pencil-rtl.bmp', - 'pencil.bmp', - 'wizHeader.bmp', - 'wizHeaderRTL.bmp', - 'wizWatermark.bmp', - ] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - BRANDING_FILES += [ - 'background.png', - 'disk.icns', - 'document.icns', - 'dsstore', - 'firefox.icns', - ] -elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: - BRANDING_FILES += [ - 'default16.png', - 'default32.png', - 'default48.png', - 'mozicon128.png', - ] - FINAL_TARGET_FILES.icons += ['mozicon128.png'] - FINAL_TARGET_FILES.chrome.icons.default += [ - 'default16.png', - 'default32.png', - 'default48.png', - ] +include('../shared/branding.mozbuild') +ApplicationBranding()
\ No newline at end of file diff --git a/browser/branding/official/particles.bmp b/browser/branding/official/particles.bmp Binary files differdeleted file mode 100644 index d523606c2..000000000 --- a/browser/branding/official/particles.bmp +++ /dev/null diff --git a/browser/branding/official/pencil-rtl.bmp b/browser/branding/official/pencil-rtl.bmp Binary files differdeleted file mode 100644 index 67d2fe5d2..000000000 --- a/browser/branding/official/pencil-rtl.bmp +++ /dev/null diff --git a/browser/branding/official/pencil.bmp b/browser/branding/official/pencil.bmp Binary files differdeleted file mode 100644 index 7dd55741f..000000000 --- a/browser/branding/official/pencil.bmp +++ /dev/null diff --git a/browser/branding/official/pref/firefox-branding.js b/browser/branding/official/pref/firefox-branding.js index a3d6927bb..190b84e78 100644 --- a/browser/branding/official/pref/firefox-branding.js +++ b/browser/branding/official/pref/firefox-branding.js @@ -2,55 +2,47 @@ * 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/. */ -pref("startup.homepage_override_url", "https://www.basilisk-browser.org/releasenotes.shtml"); -pref("startup.homepage_welcome_url", "http://www.basilisk-browser.org/firstrun/"); +#filter substitution +#filter emptyLines + +// Set defines to construct URLs +#define BRANDING_BASEURL basilisk-browser.org +#define BRANDING_SITEURL www.@BRANDING_BASEURL@ +#define BRANDING_RELNOTESPATH releasenotes.shtml +#define BRANDING_FIRSTRUNPATH firstrun/ +#define BRANDING_APPUPDATEURL aus.@BRANDING_BASEURL@ +#define BRANDING_APPUPDATEPATH ?application=%PRODUCT%&version=%VERSION%&arch=%BUILD_TARGET%&buildid=%BUILD_ID%&channel=%CHANNEL% + +// Shared Branding Preferences +// XXX: These should REALLY go back to application preferences +#include ../../shared/preferences.inc + +// Branding Specific Preferences +pref("startup.homepage_override_url", "https://@BRANDING_SITEURL@/@BRANDING_RELNOTESPATH@"); +pref("startup.homepage_welcome_url", "http://@BRANDING_SITEURL@/@BRANDING_FIRSTRUNPATH@"); pref("startup.homepage_welcome_url.additional", ""); -pref("app.update.url", "https://aus.basilisk-browser.org/?application=%PRODUCT%&version=%VERSION%&arch=%BUILD_TARGET%&buildid=%BUILD_ID%&channel=%CHANNEL%"); -// Interval: Time between checks for a new version (in seconds) -pref("app.update.interval", 86400); // 1 day -// The time interval between the downloading of mar file chunks in the -// background (in seconds) -// 0 means "download everything at once" -pref("app.update.download.backgroundInterval", 0); -// Give the user x seconds to react before showing the big UI. default=192 hours -pref("app.update.promptWaitTime", 691200); +// Version release notes +pref("app.releaseNotesURL", "http://@BRANDING_SITEURL@/@BRANDING_RELNOTESPATH@"); + +// Vendor home page +pref("app.vendorURL", "http://@BRANDING_SITEURL@/"); + +pref("app.update.url", "https://@BRANDING_APPUPDATEURL@/@BRANDING_APPUPDATEPATH@"); + // URL user can browse to manually if for some reason all update installation // attempts fail. -pref("app.update.url.manual", "https://www.basilisk-browser.org/"); +pref("app.update.url.manual", "https://@BRANDING_SITEURL@/"); // A default value for the "More information about this update" link // supplied in the "An update is available" page of the update wizard. -pref("app.update.url.details", "https://www.basilisk-browser.org/releasenotes.shtml"); +pref("app.update.url.details", "https://@BRANDING_SITEURL@/@BRANDING_RELNOTESPATH@"); + +// Provide UA Gecko and Firefox slices for web compatibility +pref("general.useragent.compatMode.firefox",true); +pref("general.useragent.compatMode.gecko",true); // Switch Application Updates off for now pref("app.update.enabled", false); -// Version release notes -pref("app.releaseNotesURL", "http://www.basilisk-browser.org/releasenotes.shtml"); -// Vendor home page -pref("app.vendorURL", "http://www.basilisk-browser.org/"); - -// The number of days a binary is permitted to be old -// without checking for an update. This assumes that -// app.update.checkInstallTime is true. -pref("app.update.checkInstallTime.days", 14); - -// Give the user x seconds to reboot before showing a badge on the hamburger -// button. default=immediately -pref("app.update.badgeWaitTime", 0); - -// Number of usages of the web console or scratchpad. -// If this is less than 5, then pasting code into the web console or scratchpad is disabled -pref("devtools.selfxss.count", 100); - -// Disable Google Safebrowsing by default. Without an API key, this won't work. -pref("browser.safebrowsing.phishing.enabled", false); -pref("browser.safebrowsing.malware.enabled", false); -pref("browser.safebrowsing.downloads.enabled", false); -pref("browser.safebrowsing.downloads.remote.enabled", false); -// Disable the UI controls for it as well for Basilisk-official. -pref("browser.safebrowsing.UI.enabled", false); - -// FxA override -pref("general.useragent.override.accounts.firefox.com", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Goanna/4.0 Basilisk/55.0.0"); - +// Shared User Agent Overrides +#include ../../shared/uaoverrides.inc diff --git a/browser/branding/branding-common.mozbuild b/browser/branding/shared/branding.mozbuild index f74724f4a..e6fee3f4e 100644 --- a/browser/branding/branding-common.mozbuild +++ b/browser/branding/shared/branding.mozbuild @@ -5,42 +5,37 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. @template -def FirefoxBranding(): - JS_PREFERENCE_FILES += [ +def ApplicationBranding(): + JS_PREFERENCE_PP_FILES += [ 'pref/firefox-branding.js', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': FINAL_TARGET_FILES['..'] += [ - 'firefox.VisualElementsManifest.xml', + 'basilisk.VisualElementsManifest.xml', ] FINAL_TARGET_FILES.VisualElements += [ 'VisualElements_150.png', 'VisualElements_70.png', ] BRANDING_FILES += [ + '../shared/newtab.ico', + '../shared/newwindow.ico', + '../shared/pbmode.ico', 'appname.bmp', - 'bgintro.bmp', 'branding.nsi', - 'clock.bmp', 'document.ico', 'firefox.ico', - 'newtab.ico', - 'newwindow.ico', - 'particles.bmp', - 'pbmode.ico', - 'pencil-rtl.bmp', - 'pencil.bmp', 'wizHeader.bmp', 'wizHeaderRTL.bmp', 'wizWatermark.bmp', ] elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': BRANDING_FILES += [ + '../shared/dsstore', 'background.png', 'disk.icns', 'document.icns', - 'dsstore', 'firefox.icns', ] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: @@ -56,3 +51,6 @@ def FirefoxBranding(): 'default32.png', 'default48.png', ] + DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] + DEFINES['MOZ_BRANDING_DIRECTORY'] = CONFIG['MOZ_BRANDING_DIRECTORY'] + DEFINES['MOZILLA_UAVERSION_U'] = CONFIG['MOZILLA_UAVERSION_U'] diff --git a/browser/branding/official/dsstore b/browser/branding/shared/dsstore Binary files differindex 8ea703674..8ea703674 100644 --- a/browser/branding/official/dsstore +++ b/browser/branding/shared/dsstore diff --git a/browser/branding/official/newtab.ico b/browser/branding/shared/newtab.ico Binary files differindex a9b37c08c..a9b37c08c 100644 --- a/browser/branding/official/newtab.ico +++ b/browser/branding/shared/newtab.ico diff --git a/browser/branding/official/newwindow.ico b/browser/branding/shared/newwindow.ico Binary files differindex 553720771..553720771 100644 --- a/browser/branding/official/newwindow.ico +++ b/browser/branding/shared/newwindow.ico diff --git a/browser/branding/official/pbmode.ico b/browser/branding/shared/pbmode.ico Binary files differindex 47677c13f..47677c13f 100644 --- a/browser/branding/official/pbmode.ico +++ b/browser/branding/shared/pbmode.ico diff --git a/browser/branding/shared/preferences.inc b/browser/branding/shared/preferences.inc new file mode 100644 index 000000000..90fd3da06 --- /dev/null +++ b/browser/branding/shared/preferences.inc @@ -0,0 +1,35 @@ +// Interval: Time between checks for a new version (in seconds) +pref("app.update.interval", 86400); // 1 day + +// The time interval between the downloading of mar file chunks in the +// background (in seconds) +// 0 means "download everything at once" +pref("app.update.download.backgroundInterval", 0); + +// Give the user x seconds to react before showing the big UI. default=192 hours +pref("app.update.promptWaitTime", 691200); + +// The number of days a binary is permitted to be old +// without checking for an update. This assumes that +// app.update.checkInstallTime is true. +pref("app.update.checkInstallTime.days", 14); + +// Give the user x seconds to reboot before showing a badge on the hamburger +// button. default=immediately +pref("app.update.badgeWaitTime", 0); + +// Number of usages of the web console or scratchpad. +// If this is less than 5, then pasting code into the web console or scratchpad is disabled +pref("devtools.selfxss.count", 100); + +// Disable Google Safebrowsing by default. Without an API key, this won't work. +pref("browser.safebrowsing.phishing.enabled", false); +pref("browser.safebrowsing.malware.enabled", false); +pref("browser.safebrowsing.downloads.enabled", false); +pref("browser.safebrowsing.downloads.remote.enabled", false); + +// Disable the UI controls for it as well for Basilisk-official. +pref("browser.safebrowsing.UI.enabled", false); + +// +pref("general.useragent.appVersionIsBuildID", true); diff --git a/browser/branding/shared/uaoverrides.inc b/browser/branding/shared/uaoverrides.inc new file mode 100644 index 000000000..13a89ed7f --- /dev/null +++ b/browser/branding/shared/uaoverrides.inc @@ -0,0 +1,38 @@ +#define GUAO_PREF general.useragent.override
+
+#define GRE_VERSION @MOZILLA_UAVERSION_U@
+#define GRE_VERSION_SLICE Goanna/@GRE_VERSION@
+#define GRE_DATE_SLICE Goanna/20170101
+#define APP_SLICE Basilisk/@MOZ_APP_VERSION@
+
+#define GK_VERSION 52.0
+#define GK_SLICE Gecko/20100101
+#define FX_SLICE Firefox/@GK_VERSION@
+
+#ifdef XP_UNIX
+#ifndef XP_MACOSX
+#define OS_SLICE X11; Linux x86_64;
+#else
+#define OS_SLICE Macintosh; Intel Mac OS X 10.11;
+#endif
+#else
+#define OS_SLICE Windows NT 6.1; WOW64;
+#endif
+
+// FxA override
+pref("@GUAO_PREF@.accounts.firefox.com", "Mozilla/5.0 (@OS_SLICE@ rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@");
+
+// Required for domains that have proven unresponsive to requests from users
+
+// The never-ending Facebook debacle...
+
+// UA-Sniffing domains below are pending responses from their operators - temp workaround
+
+// The following requires native mode. Or it blocks.. "too old firefox", breakage, etc.
+
+// UA-Sniffing domains below have indicated no interest in supporting Pale Moon (BOO!)
+
+// UA-sniffing domains that are "app/vendor-specific" and do not like Pale Moon
+
+// The following domains do not like the Goanna slice
+
diff --git a/browser/branding/unofficial/VisualElements_150.png b/browser/branding/unofficial/VisualElements_150.png Binary files differindex 461961e8d..eb74e4adc 100644 --- a/browser/branding/unofficial/VisualElements_150.png +++ b/browser/branding/unofficial/VisualElements_150.png diff --git a/browser/branding/unofficial/VisualElements_70.png b/browser/branding/unofficial/VisualElements_70.png Binary files differindex aad81f40d..571532a9b 100644 --- a/browser/branding/unofficial/VisualElements_70.png +++ b/browser/branding/unofficial/VisualElements_70.png diff --git a/browser/branding/unofficial/bgintro.bmp b/browser/branding/unofficial/bgintro.bmp Binary files differdeleted file mode 100644 index 9f2a0a6e0..000000000 --- a/browser/branding/unofficial/bgintro.bmp +++ /dev/null diff --git a/browser/branding/unofficial/branding.nsi b/browser/branding/unofficial/branding.nsi index 34214453f..77f08a4cb 100644 --- a/browser/branding/unofficial/branding.nsi +++ b/browser/branding/unofficial/branding.nsi @@ -8,19 +8,19 @@ # BrandFullNameInternal is used for some registry and file system values # instead of BrandFullName and typically should not be modified. -!define BrandFullNameInternal "Mozilla Developer Preview" -!define CompanyName "mozilla.org" -!define URLInfoAbout "https://www.mozilla.org" -!define HelpLink "https://support.mozilla.org" +!define BrandFullNameInternal "Serpent" +!define CompanyName "Moonchild Productions" +!define URLInfoAbout "http://www.basilisk-browser.org" +!define HelpLink "https://forum.palemoon.org" -!define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest" -!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=release&installer_lang=${AB_CD}" -!define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/" +!define URLStubDownload "" +!define URLManualDownload "" +!define URLSystemRequirements "" !define Channel "unofficial" # The installer's certificate name and issuer expected by the stub installer -!define CertNameDownload "Mozilla Corporation" -!define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA" +!define CertNameDownload "" +!define CertIssuerDownload "" # Dialog units are used so the UI displays correctly with the system's DPI # settings. diff --git a/browser/branding/unofficial/clock.bmp b/browser/branding/unofficial/clock.bmp Binary files differdeleted file mode 100644 index c74398edb..000000000 --- a/browser/branding/unofficial/clock.bmp +++ /dev/null diff --git a/browser/branding/unofficial/configure.sh b/browser/branding/unofficial/configure.sh index edd3bd3e8..ea4e37e45 100644 --- a/browser/branding/unofficial/configure.sh +++ b/browser/branding/unofficial/configure.sh @@ -2,4 +2,4 @@ # 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/. -MOZ_APP_DISPLAYNAME=Nightly +MOZ_APP_DISPLAYNAME=Serpent diff --git a/browser/branding/unofficial/content/about-background.png b/browser/branding/unofficial/content/about-background.png Binary files differindex 70eb8dafd..e36211b08 100644 --- a/browser/branding/unofficial/content/about-background.png +++ b/browser/branding/unofficial/content/about-background.png diff --git a/browser/branding/unofficial/content/about-logo.png b/browser/branding/unofficial/content/about-logo.png Binary files differindex 4c7214ba3..c5a838178 100644 --- a/browser/branding/unofficial/content/about-logo.png +++ b/browser/branding/unofficial/content/about-logo.png diff --git a/browser/branding/unofficial/content/about-logo@2x.png b/browser/branding/unofficial/content/about-logo@2x.png Binary files differindex 3526eda54..48c31564c 100644 --- a/browser/branding/unofficial/content/about-logo@2x.png +++ b/browser/branding/unofficial/content/about-logo@2x.png diff --git a/browser/branding/unofficial/content/about-wordmark.svg b/browser/branding/unofficial/content/about-wordmark.svg index 60b278d03..ce7a5c07b 100644 --- a/browser/branding/unofficial/content/about-wordmark.svg +++ b/browser/branding/unofficial/content/about-wordmark.svg @@ -1,22 +1,87 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<svg xmlns="http://www.w3.org/2000/svg" width="132px" height="48px" viewBox="0 0 132 48"> - <path fill="#fff" d="M60.6,14.3l-2.4-2.4C57,12.7,56,13,54.7,13c-3,0-3.8-1.4-7.6-1.4c-5.4,0-9.2,3.4-9.2,8.4 - c0,3.3,2.2,6.1,5.6,7.2c-3.4,1-4.5,2.2-4.5,4.3c0,2.2,1.8,3.6,4.7,3.6h3.8c2.5,0,3.9,0.2,4.9,0.9c0.9,0.6,1.4,1.6,1.4,3 - c0,3.1-2.2,4.4-6,4.4c-2,0-3.8-0.5-5.1-1.2c-0.9-0.6-1.5-1.6-1.5-2.9c0-0.8,0.3-1.7,0.7-2.2l-4.1,0.4c-0.3,1-0.5,1.7-0.5,2.6 - c0,3.5,3,6.4,10.8,6.4c6.1,0,9.9-2.5,9.9-7.9c0-2.1-0.8-3.9-2.7-5.3c-1.5-1.1-3.1-1.4-6-1.4h-4c-1.3,0-2-0.5-2-1.2 - c0-0.8,1.1-1.7,4.5-2.9c1.8,0,3.4-0.3,4.7-1.1c2.3-1.4,3.7-4.1,3.7-6.8c0-1.6-0.5-3-1.5-4.3c0.4,0.2,1.1,0.3,1.7,0.3 - C57.9,15.8,59,15.4,60.6,14.3z M47.1,24.8c-3.1,0-4.8-1.7-4.8-4.8c0-3.5,1.6-5.1,4.7-5.1c3.3,0,4.6,1.5,4.6,4.9 - C51.6,23.1,50.1,24.8,47.1,24.8z M30.7,1.3c-1.7,0-3,1.4-3,3.1s1.4,3,3,3c1.7,0,3.1-1.3,3.1-3C33.7,2.7,32.4,1.3,30.7,1.3z - M107.7,34.5c-1.1,0-1.4-0.6-1.4-2.5V6.5c0-3.8-0.6-5.9-0.6-5.9l-3.9,0.8c0,0,0.6,1.9,0.6,5.1v26.4c0,1.8,0.4,2.8,1.2,3.5 - c0.7,0.7,1.7,1,2.9,1c1,0,1.5-0.1,2.5-0.5l-0.8-2.5C108.2,34.4,107.8,34.5,107.7,34.5z M74.7,11.6c-3.2,0-6.1,1.8-8.3,3.9 - c0,0,0.2-1.8,0.2-3.4V6.3c0-3.8-0.7-5.9-0.7-5.9l-3.9,0.7c0,0,0.7,1.9,0.7,5.1V37h3.9V19.3c2.1-2.7,4.9-4.2,7.2-4.2 - c1.3,0,2.3,0.4,2.9,1c0.7,0.7,0.9,1.8,0.9,3.7V37h3.8V19.1c0-1.8-0.1-2.6-0.4-3.6C80.4,13.2,77.7,11.6,74.7,11.6z M127.4,12.1 - l-4.9,16.4c-0.6,2-1.6,5.2-1.6,5.2s-0.7-3.9-1.5-6.2l-5.1-16.2l-3.9,1.3l5.4,15.6c0.8,2.5,2.2,7.4,2.5,9l1.6-0.3 - c-1.3,5.1-2.5,6.7-5.7,7.6l1.2,2.7c4.4-1,6.4-4.3,8-9.3l8.6-25.8H127.4z M96.9,15l1.2-2.9h-6.2c0-3.3,0.5-7.2,0.5-7.2l-4.1,0.9 - c0,0-0.4,3.9-0.4,6.3h-3.2V15h3.2v17.1c0,2.5,0.7,4.1,2.4,5c0.9,0.4,1.9,0.7,3.3,0.7c1.8,0,3.1-0.4,4.4-1l-0.6-2.5 - c-0.7,0.3-1.3,0.5-2.4,0.5c-2.4,0-3.2-0.9-3.2-3.7V15H96.9z M28.6,37h4.1V11.5l-4.1,0.6V37z M18.9,21.3c0,5,0.4,10.5,0.4,10.5 - s-1.4-3.8-3.2-7.2L4.8,2.7H0V37h4.2L4,17.1c0-4.5-0.4-9.3-0.4-9.3s1.7,4.1,3.9,8.2l11,21h4.3V2.7h-4L18.9,21.3z"/> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="132px" + height="48px" + viewBox="0 0 132 48" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="about-wordmark.svg"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1215" + inkscape:window-height="778" + id="namedview6" + showgrid="false" + inkscape:zoom="2.4090909" + inkscape:cx="91.154186" + inkscape:cy="24" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="0" + inkscape:current-layer="svg2" /> + <g + transform="scale(0.83939803,1.1913299)" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:42.56122971px;line-height:125%;font-family:'Levenim MT';-inkscape-font-specification:'Levenim MT';letter-spacing:0px;word-spacing:0px;fill:#a8e6db;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="text4138"> + <path + d="m 18.521413,24.115665 q 0,3.470569 -2.618513,5.881264 -2.535386,2.348349 -6.0475185,2.348349 -5.6942271,0 -9.22714164,-6.463156 L 3.2259712,24.323483 q 2.7432042,5.04999 6.3384644,5.04999 3.4082234,0 4.9460804,-2.639295 0.706583,-1.205347 0.706583,-2.556167 0,-1.537857 -1.039093,-3.013369 Q 12.827186,19.23193 9.1487985,16.488726 5.3872836,13.703958 4.1819363,12.082974 2.560952,9.9008792 2.560952,7.4070572 q 0,-4.2394975 3.6576056,-6.2345551 1.7248936,-0.93518331 3.761515,-0.93518331 4.3641884,0 8.0217944,5.00842591 L 15.508045,7.1368931 Q 14.115661,5.3080903 13.138914,4.5391618 11.684184,3.3961601 9.917727,3.3961601 q -1.7664573,0 -2.9510228,1.0598743 -1.246911,1.0806563 -1.246911,2.8263317 0,2.0574032 1.9327121,3.9693339 0.56111,0.540328 3.9485517,3.054932 3.117277,2.306785 4.655134,4.15637 2.265222,2.763986 2.265222,5.652663 z" + style="" + id="path4143" /> + <path + d="m 46.743165,20.499623 -20.324649,0 q 0.08313,3.803079 2.369131,6.338464 2.410694,2.660077 6.151427,2.660077 3.616042,0 6.130646,-2.202876 1.143002,-0.997529 2.47304,-3.221187 l 2.452259,1.288475 q -2.286004,4.468098 -6.338465,6.026737 -1.974275,0.768928 -4.468097,0.768928 -5.091554,0 -8.437432,-3.36666 -3.325096,-3.366659 -3.325096,-8.458213 0,-4.301843 2.639295,-7.668503 3.345878,-4.2810608 8.956978,-4.2810608 5.777354,0 9.227141,4.3849708 2.452259,3.117277 2.493822,7.730848 z M 43.54276,17.985019 q -1.080656,-4.301843 -4.634352,-5.964391 -1.828803,-0.852056 -3.844643,-0.852056 -3.325096,0 -5.715008,2.140531 -1.745676,1.558639 -2.639295,4.675916 l 16.833298,0 z" + style="" + id="path4145" /> + <path + d="m 62.516592,9.1527326 -1.517075,2.4522584 q -0.914401,-0.394855 -1.537857,-0.394855 -3.491351,0 -4.862953,4.904517 -0.540328,1.932712 -0.540328,7.813975 l 0,7.647721 -2.971805,0 0,-22.610653 2.971805,0 0,3.304314 q 2.639295,-3.8862058 5.881264,-3.8862058 1.205347,0 2.576949,0.7689284 z" + style="" + id="path4147" /> + <path + d="m 88.577029,20.208677 q 0,4.94608 -3.325096,8.416649 -3.366659,3.532915 -8.271176,3.532915 -5.382499,0 -9.060887,-4.468098 l 0,12.157383 -2.888677,0 0,-30.88183 2.888677,0 0,4.15637 q 3.449787,-4.7382618 8.977759,-4.7382618 4.883735,0 8.271177,3.4705688 3.408223,3.470569 3.408223,8.354304 z m -2.930241,0.103909 q 0,-2.410694 -1.205347,-4.572007 -1.205347,-2.161312 -3.283532,-3.345878 -2.057403,-1.205347 -4.48888,-1.205347 -3.865424,0 -6.421592,2.660077 -2.535385,2.660077 -2.535385,6.546283 0,5.403281 4.468097,7.897103 2.140531,1.205347 4.530444,1.205347 2.410694,0 4.488879,-1.246911 2.01584,-1.226129 3.221187,-3.387441 1.226129,-2.161313 1.226129,-4.551226 z" + style="" + id="path4149" /> + <path + d="m 116.23767,20.499623 -20.324647,0 q 0.08313,3.803079 2.36913,6.338464 2.410697,2.660077 6.151427,2.660077 3.61604,0 6.13065,-2.202876 1.143,-0.997529 2.47304,-3.221187 l 2.45226,1.288475 q -2.28601,4.468098 -6.33847,6.026737 -1.97427,0.768928 -4.4681,0.768928 -5.09155,0 -8.437428,-3.36666 -3.325096,-3.366659 -3.325096,-8.458213 0,-4.301843 2.639295,-7.668503 3.345878,-4.2810608 8.956979,-4.2810608 5.77735,0 9.22714,4.3849708 2.45226,3.117277 2.49382,7.730848 z m -3.2004,-2.514604 q -1.08066,-4.301843 -4.63436,-5.964391 -1.8288,-0.852056 -3.84464,-0.852056 -3.32509,0 -5.715007,2.140531 -1.745675,1.558639 -2.639295,4.675916 l 16.833302,0 z" + style="" + id="path4151" /> + <path + d="m 141.4045,31.576349 -2.88868,0 0,-10.78578 q 0,-3.823861 -0.33251,-5.216245 -1.08066,-4.509661 -5.69423,-4.509661 -2.63929,0 -4.73826,1.745675 -2.07819,1.724894 -2.7432,4.322625 -0.41564,1.641766 -0.41564,6.151428 l 0,8.291958 -2.90946,0 0,-22.610653 2.90946,0 0,4.052461 q 3.47057,-4.6343528 8.47899,-4.6343528 2.47304,0 4.44732,1.2676928 1.99506,1.246911 2.93024,3.470569 0.95597,2.202876 0.95597,6.816447 l 0,11.637836 z" + style="" + id="path4153" /> + <path + d="m 157.69747,11.459518 -4.61357,0 0,20.116831 -2.93024,0 0,-20.116831 -3.96934,0 0,-2.493822 3.96934,0 0,-8.3958676 2.93024,0 0,8.3958676 4.61357,0 0,2.493822 z" + style="" + id="path4155" /> + </g> </svg> diff --git a/browser/branding/unofficial/content/about.png b/browser/branding/unofficial/content/about.png Binary files differindex 231449344..e323c8df5 100644 --- a/browser/branding/unofficial/content/about.png +++ b/browser/branding/unofficial/content/about.png diff --git a/browser/branding/unofficial/content/icon48.png b/browser/branding/unofficial/content/icon48.png Binary files differindex 5fc7861e5..16e022a64 100644 --- a/browser/branding/unofficial/content/icon48.png +++ b/browser/branding/unofficial/content/icon48.png diff --git a/browser/branding/unofficial/content/icon64.png b/browser/branding/unofficial/content/icon64.png Binary files differindex 83f7016bc..9860917e3 100644 --- a/browser/branding/unofficial/content/icon64.png +++ b/browser/branding/unofficial/content/icon64.png diff --git a/browser/branding/unofficial/default16.png b/browser/branding/unofficial/default16.png Binary files differindex d285a90b4..67ef39df8 100644 --- a/browser/branding/unofficial/default16.png +++ b/browser/branding/unofficial/default16.png diff --git a/browser/branding/unofficial/default32.png b/browser/branding/unofficial/default32.png Binary files differindex 95adf2497..2f709e6b2 100644 --- a/browser/branding/unofficial/default32.png +++ b/browser/branding/unofficial/default32.png diff --git a/browser/branding/unofficial/default48.png b/browser/branding/unofficial/default48.png Binary files differindex d38185f54..02a1e14c1 100644 --- a/browser/branding/unofficial/default48.png +++ b/browser/branding/unofficial/default48.png diff --git a/browser/branding/unofficial/firefox.icns b/browser/branding/unofficial/firefox.icns Binary files differindex 0c6941acf..2c613634b 100644 --- a/browser/branding/unofficial/firefox.icns +++ b/browser/branding/unofficial/firefox.icns diff --git a/browser/branding/unofficial/firefox.ico b/browser/branding/unofficial/firefox.ico Binary files differindex 5217a6c0b..0c7acb61b 100644 --- a/browser/branding/unofficial/firefox.ico +++ b/browser/branding/unofficial/firefox.ico diff --git a/browser/branding/unofficial/locales/en-US/brand.dtd b/browser/branding/unofficial/locales/en-US/brand.dtd index cf4596ae0..17c243606 100644 --- a/browser/branding/unofficial/locales/en-US/brand.dtd +++ b/browser/branding/unofficial/locales/en-US/brand.dtd @@ -2,8 +2,9 @@ - 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/. --> -<!ENTITY brandShorterName "Nightly"> -<!ENTITY brandShortName "Nightly"> -<!ENTITY brandFullName "Nightly"> -<!ENTITY vendorShortName "Mozilla"> +<!ENTITY brandShorterName "Serpent"> +<!ENTITY brandShortName "Serpent"> +<!ENTITY brandFullName "Serpent"> +<!ENTITY vendorShortName "Moonchild"> +<!ENTITY vendorFullName "Moonchild Productions"> <!ENTITY trademarkInfo.part1 " "> diff --git a/browser/branding/unofficial/locales/en-US/brand.properties b/browser/branding/unofficial/locales/en-US/brand.properties index 8cd2c2ec9..80349f0e3 100644 --- a/browser/branding/unofficial/locales/en-US/brand.properties +++ b/browser/branding/unofficial/locales/en-US/brand.properties @@ -2,9 +2,10 @@ # 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/. -brandShorterName=Nightly -brandShortName=Nightly -brandFullName=Nightly -vendorShortName=Mozilla +brandShorterName=Serpent +brandShortName=Serpent +brandFullName=Serpent +vendorShortName=Moonchild +vendorFullName=Moonchild Productions syncBrandShortName=Sync diff --git a/browser/branding/unofficial/moz.build b/browser/branding/unofficial/moz.build index 9045cee11..0d829fa5e 100644 --- a/browser/branding/unofficial/moz.build +++ b/browser/branding/unofficial/moz.build @@ -9,5 +9,5 @@ DIRS += ['content', 'locales'] DIST_SUBDIR = 'browser' export('DIST_SUBDIR') -include('../branding-common.mozbuild') -FirefoxBranding() +include('../shared/branding.mozbuild') +ApplicationBranding() diff --git a/browser/branding/unofficial/mozicon128.png b/browser/branding/unofficial/mozicon128.png Binary files differindex 471cf4645..739b61084 100644 --- a/browser/branding/unofficial/mozicon128.png +++ b/browser/branding/unofficial/mozicon128.png diff --git a/browser/branding/unofficial/newtab.ico b/browser/branding/unofficial/newtab.ico Binary files differdeleted file mode 100644 index a9b37c08c..000000000 --- a/browser/branding/unofficial/newtab.ico +++ /dev/null diff --git a/browser/branding/unofficial/newwindow.ico b/browser/branding/unofficial/newwindow.ico Binary files differdeleted file mode 100644 index 553720771..000000000 --- a/browser/branding/unofficial/newwindow.ico +++ /dev/null diff --git a/browser/branding/unofficial/particles.bmp b/browser/branding/unofficial/particles.bmp Binary files differdeleted file mode 100644 index ab74ce047..000000000 --- a/browser/branding/unofficial/particles.bmp +++ /dev/null diff --git a/browser/branding/unofficial/pbmode.ico b/browser/branding/unofficial/pbmode.ico Binary files differdeleted file mode 100644 index 47677c13f..000000000 --- a/browser/branding/unofficial/pbmode.ico +++ /dev/null diff --git a/browser/branding/unofficial/pencil-rtl.bmp b/browser/branding/unofficial/pencil-rtl.bmp Binary files differdeleted file mode 100644 index e50d92db7..000000000 --- a/browser/branding/unofficial/pencil-rtl.bmp +++ /dev/null diff --git a/browser/branding/unofficial/pencil.bmp b/browser/branding/unofficial/pencil.bmp Binary files differdeleted file mode 100644 index 252c10f41..000000000 --- a/browser/branding/unofficial/pencil.bmp +++ /dev/null diff --git a/browser/branding/unofficial/pref/firefox-branding.js b/browser/branding/unofficial/pref/firefox-branding.js index b20a3a309..a5b617a53 100644 --- a/browser/branding/unofficial/pref/firefox-branding.js +++ b/browser/branding/unofficial/pref/firefox-branding.js @@ -2,32 +2,39 @@ * 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 +#filter emptyLines + +// Set defines to construct URLs +#define BRANDING_BASEURL basilisk-browser.org +#define BRANDING_SITEURL www.@BRANDING_BASEURL@ + +// Shared Branding Preferences +// XXX: These should REALLY go back to application preferences +#include ../../shared/preferences.inc + +// Branding Specific Preferences pref("startup.homepage_override_url", ""); pref("startup.homepage_welcome_url", ""); pref("startup.homepage_welcome_url.additional", ""); -// The time interval between checks for a new version (in seconds) -pref("app.update.interval", 86400); // 24 hours -// The time interval between the downloading of mar file chunks in the -// background (in seconds) -pref("app.update.download.backgroundInterval", 60); -// Give the user x seconds to react before showing the big UI. default=24 hours -pref("app.update.promptWaitTime", 86400); + +// Version release notes +pref("app.releaseNotesURL", "about:blank"); + +// Vendor home page +pref("app.vendorURL", "about:"); + +pref("app.update.url", ""); + // URL user can browse to manually if for some reason all update installation // attempts fail. -pref("app.update.url.manual", "https://nightly.mozilla.org"); +pref("app.update.url.manual", "about:"); // A default value for the "More information about this update" link // supplied in the "An update is available" page of the update wizard. -pref("app.update.url.details", "https://nightly.mozilla.org"); - -// The number of days a binary is permitted to be old -// without checking for an update. This assumes that -// app.update.checkInstallTime is true. -pref("app.update.checkInstallTime.days", 2); +pref("app.update.url.details", "about:"); -// Give the user x seconds to reboot before showing a badge on the hamburger -// button. default=immediately -pref("app.update.badgeWaitTime", 0); +// Switch Application Updates off for unofficial branding +pref("app.update.enabled", false); -// Number of usages of the web console or scratchpad. -// If this is less than 5, then pasting code into the web console or scratchpad is disabled -pref("devtools.selfxss.count", 0); +// Shared User Agent Overrides +#include ../../shared/uaoverrides.inc diff --git a/browser/branding/unofficial/firefox.VisualElementsManifest.xml b/browser/branding/unofficial/serpent.VisualElementsManifest.xml index 7654e0ab7..5046ee7da 100644 --- a/browser/branding/unofficial/firefox.VisualElementsManifest.xml +++ b/browser/branding/unofficial/serpent.VisualElementsManifest.xml @@ -4,5 +4,5 @@ Square150x150Logo='browser\VisualElements\VisualElements_150.png' Square70x70Logo='browser\VisualElements\VisualElements_70.png' ForegroundText='light' - BackgroundColor='#14171a'/> + BackgroundColor='#304D7E'/> </Application> diff --git a/browser/components/BrowserComponents.manifest b/browser/components/BrowserComponents.manifest index dbfc3d2ec..0c80006be 100644 --- a/browser/components/BrowserComponents.manifest +++ b/browser/components/BrowserComponents.manifest @@ -39,6 +39,4 @@ component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc} category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314} component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js -#ifndef MOZ_MULET contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} -#endif diff --git a/browser/components/about/AboutRedirector.cpp b/browser/components/about/AboutRedirector.cpp index a09932d95..717ae9c48 100644 --- a/browser/components/about/AboutRedirector.cpp +++ b/browser/components/about/AboutRedirector.cpp @@ -35,75 +35,117 @@ struct RedirEntry { URI_SAFE_FOR_UNTRUSTED_CONTENT. */ static RedirEntry kRedirMap[] = { - { "blocked", "chrome://browser/content/blockedSite.xhtml", + { + "basilisk", "chrome://global/content/memoriam.xhtml", + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "blocked", "chrome://browser/content/blockedSite.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, - { "certerror", "chrome://browser/content/aboutNetError.xhtml", + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "certerror", "chrome://browser/content/aboutNetError.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, - { "socialerror", "chrome://browser/content/aboutSocialError.xhtml", + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "socialerror", "chrome://browser/content/aboutSocialError.xhtml", nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, - { "providerdirectory", "chrome://browser/content/aboutProviderDirectory.xhtml", + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "providerdirectory", "chrome://browser/content/aboutProviderDirectory.xhtml", nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, - { "tabcrashed", "chrome://browser/content/aboutTabCrashed.xhtml", + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "tabcrashed", "chrome://browser/content/aboutTabCrashed.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, - { "feeds", "chrome://browser/content/feeds/subscribe.xhtml", + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "feeds", "chrome://browser/content/feeds/subscribe.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, - { "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml", + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml", nsIAboutModule::URI_MUST_LOAD_IN_CHILD | - nsIAboutModule::ALLOW_SCRIPT }, - { "rights", - "chrome://global/content/aboutRights.xhtml", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "rights", "chrome://global/content/aboutRights.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::MAKE_LINKABLE | - nsIAboutModule::ALLOW_SCRIPT }, - { "robots", "chrome://browser/content/aboutRobots.xhtml", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "robots", "chrome://browser/content/aboutRobots.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::ALLOW_SCRIPT }, - { "searchreset", "chrome://browser/content/search/searchReset.xhtml", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "searchreset", "chrome://browser/content/search/searchReset.xhtml", nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, - { "sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml", - nsIAboutModule::ALLOW_SCRIPT }, - { "welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml", - nsIAboutModule::ALLOW_SCRIPT }, - { "sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul", - nsIAboutModule::ALLOW_SCRIPT }, - // Linkable because of indexeddb use (bug 1228118) + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, + { + "sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul", + nsIAboutModule::ALLOW_SCRIPT + }, { "home", "chrome://browser/content/abouthome/aboutHome.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | + // Linkable because of indexeddb use (bug 1228118) nsIAboutModule::MAKE_LINKABLE | nsIAboutModule::ENABLE_INDEXED_DB }, - // the newtab's actual URL will be determined when the channel is created - { "newtab", "about:blank", - nsIAboutModule::ALLOW_SCRIPT }, - { "preferences", "chrome://browser/content/preferences/in-content/preferences.xul", - nsIAboutModule::ALLOW_SCRIPT }, - { "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul", - nsIAboutModule::ALLOW_SCRIPT }, + { + // the newtab's actual URL will be determined when the channel is created + "newtab", "about:blank", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "preferences", "chrome://browser/content/preferences/in-content/preferences.xul", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul", + nsIAboutModule::ALLOW_SCRIPT + }, #ifdef MOZ_SERVICES_HEALTHREPORT - { "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml", - nsIAboutModule::ALLOW_SCRIPT }, + { + "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml", + nsIAboutModule::ALLOW_SCRIPT + }, #endif - { "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml", - nsIAboutModule::ALLOW_SCRIPT }, - { "reader", "chrome://global/content/reader/aboutReader.html", + { + "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml", + nsIAboutModule::ALLOW_SCRIPT + }, + { + "reader", "chrome://global/content/reader/aboutReader.html", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD | - nsIAboutModule::HIDE_FROM_ABOUTABOUT }, + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, }; static const int kRedirTotal = ArrayLength(kRedirMap); diff --git a/browser/components/build/nsModule.cpp b/browser/components/build/nsModule.cpp index f85d8812c..1fad0ce68 100644 --- a/browser/components/build/nsModule.cpp +++ b/browser/components/build/nsModule.cpp @@ -85,6 +85,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = { { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID }, #endif { NS_FEEDSNIFFER_CONTRACTID, &kNS_FEEDSNIFFER_CID }, + { NS_ABOUT_MODULE_CONTRACTID_PREFIX "basilisk", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "blocked", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "certerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "socialerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, diff --git a/browser/components/customizableui/CustomizableUI.jsm b/browser/components/customizableui/CustomizableUI.jsm index 86ff2708b..cb0f519b2 100644 --- a/browser/components/customizableui/CustomizableUI.jsm +++ b/browser/components/customizableui/CustomizableUI.jsm @@ -207,15 +207,6 @@ var CustomizableUIInternal = { panelPlacements.splice(-1, 0, "developer-button"); } - if (AppConstants.E10S_TESTING_ONLY) { - if (gPalette.has("e10s-button")) { - let newWindowIndex = panelPlacements.indexOf("new-window-button"); - if (newWindowIndex > -1) { - panelPlacements.splice(newWindowIndex + 1, 0, "e10s-button"); - } - } - } - let showCharacterEncoding = Services.prefs.getComplexValue( "browser.menu.showCharacterEncoding", Ci.nsIPrefLocalizedString @@ -262,24 +253,14 @@ var CustomizableUIInternal = { defaultCollapsed: false, }, true); - if (AppConstants.platform != "macosx") { + if (AppConstants.MENUBAR_CAN_AUTOHIDE) { this.registerArea(CustomizableUI.AREA_MENUBAR, { legacy: true, type: CustomizableUI.TYPE_TOOLBAR, defaultPlacements: [ "menubar-items", ], - get defaultCollapsed() { - if (AppConstants.MENUBAR_CAN_AUTOHIDE) { - if (AppConstants.platform == "linux") { - return true; - } - // This is duplicated logic from /browser/base/jar.mn - // for win6BrowserOverlay.xul. - return AppConstants.isPlatformAndVersionAtLeast("win", 6); - } - return false; - } + defaultCollapsed: true, }, true); } diff --git a/browser/components/customizableui/CustomizableWidgets.jsm b/browser/components/customizableui/CustomizableWidgets.jsm index 907e2e0f7..3e83b081c 100644 --- a/browser/components/customizableui/CustomizableWidgets.jsm +++ b/browser/components/customizableui/CustomizableWidgets.jsm @@ -1187,10 +1187,7 @@ let preferencesButton = { win.openPreferences(); } }; -if (AppConstants.platform == "win") { - preferencesButton.label = "preferences-button.labelWin"; - preferencesButton.tooltiptext = "preferences-button.tooltipWin2"; -} else if (AppConstants.platform == "macosx") { +if (AppConstants.platform == "macosx") { preferencesButton.tooltiptext = "preferences-button.tooltiptext.withshortcut"; preferencesButton.shortcutId = "key_preferencesCmdMac"; } else { @@ -1261,21 +1258,3 @@ if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) { }, }); } - -if (AppConstants.E10S_TESTING_ONLY) { - if (Services.appinfo.browserTabsRemoteAutostart) { - CustomizableWidgets.push({ - id: "e10s-button", - defaultArea: CustomizableUI.AREA_PANEL, - onBuild: function(aDocument) { - let node = aDocument.createElementNS(kNSXUL, "toolbarbutton"); - node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label")); - node.setAttribute("tooltiptext", CustomizableUI.getLocalizedProperty(this, "tooltiptext")); - }, - onCommand: function(aEvent) { - let win = aEvent.view; - win.OpenBrowserWindow({remote: false}); - }, - }); - } -} diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index e8fe0fe93..74144fc1b 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -454,16 +454,16 @@ nsBrowserContentHandler.prototype = { get helpInfo() { let info = - " --browser Open a browser window.\n" + - " --new-window <url> Open <url> in a new window.\n" + - " --new-tab <url> Open <url> in a new tab.\n" + - " --private-window <url> Open <url> in a new private window.\n"; + " --browser Open a browser window.\n" + + " --new-window <url> Open <url> in a new window.\n" + + " --new-tab <url> Open <url> in a new tab.\n" + + " --private-window <url> Open <url> in a new private window.\n"; if (AppConstants.platform == "win") { - info += " --preferences Open Options dialog.\n"; + info += " --preferences Open Options dialog.\n"; } else { - info += " --preferences Open Preferences dialog.\n"; + info += " --preferences Open Preferences dialog.\n"; } - info += " --search <term> Search <term> with your default search engine.\n"; + info += " --search <term> Search <term> with your default search engine.\n"; return info; }, @@ -558,7 +558,7 @@ nsBrowserContentHandler.prototype = { if (overridePage && startPage && !willRestoreSession && !skipStartPage) return overridePage + "|" + startPage; - return overridePage || startPage || "about:blank"; + return overridePage || startPage || "about:blank" || "about:logopage"; }, get startPage() { diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index d69a11f6b..448bb910d 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -64,20 +64,12 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s ["Task", "resource://gre/modules/Task.jsm"], ["UITour", "resource:///modules/UITour.jsm"], ["URLBarZoom", "resource:///modules/URLBarZoom.jsm"], + ["UserAgentOverrides", "resource://gre/modules/UserAgentOverrides.jsm"], ["WebChannel", "resource://gre/modules/WebChannel.jsm"], ["WindowsRegistry", "resource://gre/modules/WindowsRegistry.jsm"], ["webrtcUI", "resource:///modules/webrtcUI.jsm"], ].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource)); -if (AppConstants.MOZ_CRASHREPORTER) { - XPCOMUtils.defineLazyModuleGetter(this, "PluginCrashReporter", - "resource:///modules/ContentCrashHandlers.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "UnsubmittedCrashHandler", - "resource:///modules/ContentCrashHandlers.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "CrashSubmit", - "resource://gre/modules/CrashSubmit.jsm"); -} - XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() { return Services.strings.createBundle('chrome://branding/locale/brand.properties'); }); @@ -662,6 +654,8 @@ BrowserGlue.prototype = { } } catch (ex) { /* missing any of the prefs is not critical */ } + UserAgentOverrides.init(); + PageThumbs.init(); webrtcUI.init(); AboutHome.init(); @@ -707,10 +701,6 @@ BrowserGlue.prototype = { } TabCrashHandler.init(); - if (AppConstants.MOZ_CRASHREPORTER) { - PluginCrashReporter.init(); - UnsubmittedCrashHandler.init(); - } Services.obs.notifyObservers(null, "browser-ui-startup-complete", ""); }, @@ -1042,6 +1032,7 @@ BrowserGlue.prototype = { BrowserUsageTelemetry.uninit(); SelfSupportBackend.uninit(); + UserAgentOverrides.uninit(); PageThumbs.uninit(); NewTabMessages.uninit(); AboutNewTab.uninit(); diff --git a/browser/components/places/PlacesUIUtils.jsm b/browser/components/places/PlacesUIUtils.jsm index b25835a71..17fa276aa 100644 --- a/browser/components/places/PlacesUIUtils.jsm +++ b/browser/components/places/PlacesUIUtils.jsm @@ -46,43 +46,6 @@ let gFaviconLoadDataMap = new Map(); // copied from utilityOverlay.js const TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab"; -// This function isn't public both because it's synchronous and because it is -// going to be removed in bug 1072833. -function IsLivemark(aItemId) { - // Since this check may be done on each dragover event, it's worth maintaining - // a cache. - let self = IsLivemark; - if (!("ids" in self)) { - const LIVEMARK_ANNO = PlacesUtils.LMANNO_FEEDURI; - - let idsVec = PlacesUtils.annotations.getItemsWithAnnotation(LIVEMARK_ANNO); - self.ids = new Set(idsVec); - - let obs = Object.freeze({ - QueryInterface: XPCOMUtils.generateQI(Ci.nsIAnnotationObserver), - - onItemAnnotationSet(itemId, annoName) { - if (annoName == LIVEMARK_ANNO) - self.ids.add(itemId); - }, - - onItemAnnotationRemoved(itemId, annoName) { - // If annoName is set to an empty string, the item is gone. - if (annoName == LIVEMARK_ANNO || annoName == "") - self.ids.delete(itemId); - }, - - onPageAnnotationSet() { }, - onPageAnnotationRemoved() { }, - }); - PlacesUtils.annotations.addObserver(obs); - PlacesUtils.registerShutdownFunction(() => { - PlacesUtils.annotations.removeObserver(obs); - }); - } - return self.ids.has(aItemId); -} - let InternalFaviconLoader = { /** * This gets called for every inner window that is destroyed. @@ -509,6 +472,52 @@ this.PlacesUIUtils = { }, /** + * Test if a bookmark item = a live bookmark item. + * + * @param aItemId + * item identifier + * @return true if a live bookmark item, false otherwise. + * + * @note Maybe this should be removed later, see bug 1072833. + */ + _isLivemark: + function PUIU__isLivemark(aItemId) + { + // Since this check may be done on each dragover event, it's worth maintaining + // a cache. + let self = PUIU__isLivemark; + if (!("ids" in self)) { + const LIVEMARK_ANNO = PlacesUtils.LMANNO_FEEDURI; + + let idsVec = PlacesUtils.annotations.getItemsWithAnnotation(LIVEMARK_ANNO); + self.ids = new Set(idsVec); + + let obs = Object.freeze({ + QueryInterface: XPCOMUtils.generateQI(Ci.nsIAnnotationObserver), + + onItemAnnotationSet(itemId, annoName) { + if (annoName == LIVEMARK_ANNO) + self.ids.add(itemId); + }, + + onItemAnnotationRemoved(itemId, annoName) { + // If annoName is set to an empty string, the item is gone. + if (annoName == LIVEMARK_ANNO || annoName == "") + self.ids.delete(itemId); + }, + + onPageAnnotationSet() { }, + onPageAnnotationRemoved() { }, + }); + PlacesUtils.annotations.addObserver(obs); + PlacesUtils.registerShutdownFunction(() => { + PlacesUtils.annotations.removeObserver(obs); + }); + } + return self.ids.has(aItemId); + }, + + /** * Constructs a Transaction for the drop or paste of a blob of data into * a container. * @param data @@ -857,7 +866,7 @@ this.PlacesUIUtils = { throw new Error("invalid value for aNodeOrItemId"); } - if (itemId == PlacesUtils.placesRootId || IsLivemark(itemId)) + if (itemId == PlacesUtils.placesRootId || this._isLivemark(itemId)) return true; // leftPaneFolderId, and as a result, allBookmarksFolderId, is a lazy getter diff --git a/browser/components/places/content/treeView.js b/browser/components/places/content/treeView.js index 5baf3a21f..181bb5404 100644 --- a/browser/components/places/content/treeView.js +++ b/browser/components/places/content/treeView.js @@ -170,7 +170,9 @@ PlacesTreeView.prototype = { let row = -1; let useNodeIndex = typeof(aNodeIndex) == "number"; if (parent == this._rootNode) { - row = useNodeIndex ? aNodeIndex : this._rootNode.getChildIndex(aNode); + if (aNode instanceof Ci.nsINavHistoryResultNode) { + row = useNodeIndex ? aNodeIndex : this._rootNode.getChildIndex(aNode); + } } else if (useNodeIndex && typeof(aParentRow) == "number") { // If we have both the row of the parent node, and the node's index, we diff --git a/browser/components/preferences/in-content/advanced.js b/browser/components/preferences/in-content/advanced.js index 448a21dae..5f9458eee 100644 --- a/browser/components/preferences/in-content/advanced.js +++ b/browser/components/preferences/in-content/advanced.js @@ -40,9 +40,6 @@ var gAdvancedPane = { this.updateReadPrefs(); } this.updateOfflineApps(); - if (AppConstants.MOZ_CRASHREPORTER) { - this.initSubmitCrashes(); - } this.initTelemetry(); if (AppConstants.MOZ_TELEMETRY_REPORTING) { this.initSubmitHealthReport(); diff --git a/browser/components/preferences/in-content/advanced.xul b/browser/components/preferences/in-content/advanced.xul index facaaeaa9..4973f8e09 100644 --- a/browser/components/preferences/in-content/advanced.xul +++ b/browser/components/preferences/in-content/advanced.xul @@ -54,13 +54,6 @@ type="bool"/> #endif - <!-- Data Choices tab --> -#ifdef MOZ_CRASHREPORTER - <preference id="browser.crashReports.unsubmittedCheck.autoSubmit2" - name="browser.crashReports.unsubmittedCheck.autoSubmit2" - type="bool"/> -#endif - <!-- Network tab --> <preference id="browser.cache.disk.capacity" name="browser.cache.disk.capacity" @@ -233,22 +226,6 @@ </vbox> </groupbox> #endif -#ifdef MOZ_CRASHREPORTER - <groupbox> - <caption> - <checkbox id="automaticallySubmitCrashesBox" - preference="browser.crashReports.unsubmittedCheck.autoSubmit2" - label="&alwaysSubmitCrashReports.label;" - accesskey="&alwaysSubmitCrashReports.accesskey;"/> - </caption> - <hbox class="indent"> - <label flex="1">&crashReporterDesc2.label;</label> - <spacer flex="10"/> - <label id="crashReporterLearnMore" - class="text-link">&crashReporterLearnMore.label;</label> - </hbox> - </groupbox> -#endif </tabpanel> #endif diff --git a/browser/components/preferences/in-content/content.js b/browser/components/preferences/in-content/content.js index 5ba334b02..a957b1dd5 100644 --- a/browser/components/preferences/in-content/content.js +++ b/browser/components/preferences/in-content/content.js @@ -78,6 +78,7 @@ var gContentPane = { document.getElementById("notificationsPolicyLearnMore").setAttribute("href", notificationInfoURL); +#ifdef MOZ_EME let drmInfoURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content"; document.getElementById("playDRMContentLink").setAttribute("href", drmInfoURL); @@ -91,6 +92,7 @@ var gContentPane = { // of the pane hiding/showing code potentially interfering: document.getElementById("drmGroup").setAttribute("style", "display: none !important"); } +#endif }, // UTILITY FUNCTIONS diff --git a/browser/components/preferences/in-content/content.xul b/browser/components/preferences/in-content/content.xul index c646c16a2..9434cba62 100644 --- a/browser/components/preferences/in-content/content.xul +++ b/browser/components/preferences/in-content/content.xul @@ -6,10 +6,12 @@ <preferences id="contentPreferences" hidden="true" data-category="paneContent"> +#ifdef MOZ_EME <!-- DRM content --> <preference id="media.eme.enabled" name="media.eme.enabled" type="bool"/> +#endif <!-- Popups --> <preference id="dom.disable_open_during_load" @@ -40,6 +42,7 @@ <html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a> </hbox> +#ifdef MOZ_EME <groupbox id="drmGroup" data-category="paneContent" hidden="true"> <caption><label>&drmContent.label;</label></caption> <grid id="contentGrid2"> @@ -60,6 +63,7 @@ </rows> </grid> </groupbox> +#endif <groupbox id="notificationsGroup" data-category="paneContent" hidden="true"> <caption><label>¬ificationsPolicy.label;</label></caption> diff --git a/browser/components/preferences/in-content/jar.mn b/browser/components/preferences/in-content/jar.mn index 52f536e96..3497ff555 100644 --- a/browser/components/preferences/in-content/jar.mn +++ b/browser/components/preferences/in-content/jar.mn @@ -12,7 +12,7 @@ browser.jar: content/browser/preferences/in-content/containers.js content/browser/preferences/in-content/advanced.js content/browser/preferences/in-content/applications.js - content/browser/preferences/in-content/content.js +* content/browser/preferences/in-content/content.js content/browser/preferences/in-content/sync.js content/browser/preferences/in-content/security.js content/browser/preferences/in-content/search.js diff --git a/browser/components/preferences/in-content/main.js b/browser/components/preferences/in-content/main.js index 4f20ba8c3..bac771bec 100644 --- a/browser/components/preferences/in-content/main.js +++ b/browser/components/preferences/in-content/main.js @@ -11,11 +11,6 @@ Components.utils.import("resource:///modules/TransientPrefs.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); -if (AppConstants.E10S_TESTING_ONLY) { - XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); -} - var gMainPane = { /** * Initialization of this. @@ -83,26 +78,6 @@ var gMainPane = { setEventListener("chooseFolder", "command", gMainPane.chooseFolder); - if (AppConstants.E10S_TESTING_ONLY) { - setEventListener("e10sAutoStart", "command", - gMainPane.enableE10SChange); - let e10sCheckbox = document.getElementById("e10sAutoStart"); - - let e10sPref = document.getElementById("browser.tabs.remote.autostart"); - let e10sTempPref = document.getElementById("e10sTempPref"); - let e10sForceEnable = document.getElementById("e10sForceEnable"); - - let preffedOn = e10sPref.value || e10sTempPref.value || e10sForceEnable.value; - - if (preffedOn) { - // The checkbox is checked if e10s is preffed on and enabled. - e10sCheckbox.checked = Services.appinfo.browserTabsRemoteAutostart; - - // but if it's force disabled, then the checkbox is disabled. - e10sCheckbox.disabled = !Services.appinfo.browserTabsRemoteAutostart; - } - } - if (AppConstants.MOZ_DEV_EDITION) { let uAppData = OS.Constants.Path.userApplicationDataDir; let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile"); @@ -123,36 +98,7 @@ var gMainPane = { enableE10SChange: function () { - if (AppConstants.E10S_TESTING_ONLY) { - let e10sCheckbox = document.getElementById("e10sAutoStart"); - let e10sPref = document.getElementById("browser.tabs.remote.autostart"); - let e10sTempPref = document.getElementById("e10sTempPref"); - - let prefsToChange; - if (e10sCheckbox.checked) { - // Enabling e10s autostart - prefsToChange = [e10sPref]; - } else { - // Disabling e10s autostart - prefsToChange = [e10sPref]; - if (e10sTempPref.value) { - prefsToChange.push(e10sTempPref); - } - } - - let buttonIndex = confirmRestartPrompt(e10sCheckbox.checked, 0, - true, false); - if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { - for (let prefToChange of prefsToChange) { - prefToChange.value = e10sCheckbox.checked; - } - - Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); - } - - // Revert the checkbox in case we didn't quit - e10sCheckbox.checked = e10sPref.value || e10sTempPref.value; - } + // **STUB** }, separateProfileModeChange: function () diff --git a/browser/components/preferences/in-content/main.xul b/browser/components/preferences/in-content/main.xul index 526bbc714..8eca11877 100644 --- a/browser/components/preferences/in-content/main.xul +++ b/browser/components/preferences/in-content/main.xul @@ -9,18 +9,6 @@ <preferences id="mainPreferences" hidden="true" data-category="paneGeneral"> -#ifdef E10S_TESTING_ONLY - <preference id="browser.tabs.remote.autostart" - name="browser.tabs.remote.autostart" - type="bool"/> - <preference id="e10sTempPref" - name="browser.tabs.remote.autostart.2" - type="bool"/> - <preference id="e10sForceEnable" - name="browser.tabs.remote.force-enable" - type="bool"/> -#endif - <!-- Startup --> <preference id="browser.startup.page" name="browser.startup.page" @@ -135,11 +123,6 @@ </vbox> #endif -#ifdef E10S_TESTING_ONLY - <checkbox id="e10sAutoStart" - label="&e10sEnabled.label;"/> -#endif - #ifdef HAVE_SHELL_SERVICE <vbox id="defaultBrowserBox"> <hbox align="center"> diff --git a/browser/components/preferences/in-content/preferences.xul b/browser/components/preferences/in-content/preferences.xul index e9664eaf4..7ec7ef119 100644 --- a/browser/components/preferences/in-content/preferences.xul +++ b/browser/components/preferences/in-content/preferences.xul @@ -55,18 +55,10 @@ %advancedDTD; ]> -#ifdef XP_WIN -#define USE_WIN_TITLE_STYLE -#endif - <page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" disablefastfind="true" -#ifdef USE_WIN_TITLE_STYLE - title="&prefWindow.titleWin;"> -#else title="&prefWindow.title;"> -#endif <html:link rel="shortcut icon" href="chrome://browser/skin/preferences/in-content/favicon.ico"/> diff --git a/browser/components/preferences/in-content/security.xul b/browser/components/preferences/in-content/security.xul index a10576c25..b7bdb9361 100644 --- a/browser/components/preferences/in-content/security.xul +++ b/browser/components/preferences/in-content/security.xul @@ -45,6 +45,7 @@ <!-- Passwords --> <preference id="signon.rememberSignons" name="signon.rememberSignons" type="bool"/> + <preference id="signon.autofillForms" name="signon.autofillForms" type="bool"/> </preferences> @@ -103,6 +104,9 @@ accesskey="&passwordExceptions.accesskey;" preference="pref.privacy.disable_button.view_passwords_exceptions"/> </hbox> + <checkbox id="autofillPasswords" flex="1" + label="&autofillPasswords.label;" accesskey="&autofillPasswords.accesskey;" + preference="signon.autofillForms"/> <grid id="passwordGrid"> <columns> <column flex="1"/> diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 2f44b2af3..93e21357f 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -186,6 +186,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "ViewSourceBrowser", XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown", "resource://gre/modules/AsyncShutdown.jsm"); +Object.defineProperty(this, "HUDService", { + get: function HUDService_getter() { + let devtools = Cu.import("resource://devtools/shared/Loader.jsm", {}).devtools; + return devtools.require("devtools/client/webconsole/hudservice").HUDService; + }, + configurable: true, + enumerable: true +}); + /** * |true| if we are in debug mode, |false| otherwise. * Debug mode is controlled by preference browser.sessionstore.debug @@ -2570,10 +2579,16 @@ var SessionStoreInternal = { this._capClosedWindows(); } + // Scratchpad if (lastSessionState.scratchpads) { ScratchpadManager.restoreSession(lastSessionState.scratchpads); } + // The Browser Console + if (lastSessionState.browserConsole) { + HUDService.restoreBrowserConsoleSession(); + } + // Set data that persists between sessions this._recentCrashes = lastSessionState.session && lastSessionState.session.recentCrashes || 0; @@ -2931,6 +2946,7 @@ var SessionStoreInternal = { global: this._globalState.getState() }; + // Scratchpad if (Cu.isModuleLoaded("resource://devtools/client/scratchpad/scratchpad-manager.jsm")) { // get open Scratchpad window states too let scratchpads = ScratchpadManager.getSessionState(); @@ -2939,6 +2955,9 @@ var SessionStoreInternal = { } } + // The Browser Console + state.browserConsole = HUDService.getBrowserConsoleSessionState(); + // Persist the last session if we deferred restoring it if (LastSession.canRestore) { state.lastSessionState = LastSession.getState(); @@ -3290,9 +3309,15 @@ var SessionStoreInternal = { this.restoreWindow(aWindow, root.windows[0], aOptions); + // Scratchpad if (aState.scratchpads) { ScratchpadManager.restoreSession(aState.scratchpads); } + + // The Browser Console + if (aState.browserConsole) { + HUDService.restoreBrowserConsoleSession(); + } }, /** diff --git a/browser/components/shell/ShellService.jsm b/browser/components/shell/ShellService.jsm index 2a3400b60..cc225eae0 100644 --- a/browser/components/shell/ShellService.jsm +++ b/browser/components/shell/ShellService.jsm @@ -62,10 +62,10 @@ let ShellServiceInternal = { if (AppConstants.platform == "win") { let optOutValue = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "Software\\Mozilla\\Firefox", + "Software\\Mozilla\\Basilisk", "DefaultBrowserOptOut"); WindowsRegistry.removeRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "Software\\Mozilla\\Firefox", + "Software\\Mozilla\\Basilisk", "DefaultBrowserOptOut"); if (optOutValue == "True") { Services.prefs.setBoolPref("browser.shell.checkDefaultBrowser", false); diff --git a/browser/components/shell/nsGNOMEShellService.cpp b/browser/components/shell/nsGNOMEShellService.cpp index 1001a52ae..613b5bffc 100644 --- a/browser/components/shell/nsGNOMEShellService.cpp +++ b/browser/components/shell/nsGNOMEShellService.cpp @@ -451,7 +451,7 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement, // Set the image to an empty string first to force a refresh // (since we could be writing a new image on top of an existing - // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes) + // Basilisk_wallpaper.png and nautilus doesn't monitor the file for changes) gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), EmptyCString()); diff --git a/browser/components/shell/nsSetDefaultBrowser.js b/browser/components/shell/nsSetDefaultBrowser.js index bb09ab213..c7a78c538 100644 --- a/browser/components/shell/nsSetDefaultBrowser.js +++ b/browser/components/shell/nsSetDefaultBrowser.js @@ -21,7 +21,7 @@ nsSetDefaultBrowser.prototype = { } }, - helpInfo: " --setDefaultBrowser Set this app as the default browser.\n", + helpInfo: " --setDefaultBrowser Set this app as the default browser.\n", classID: Components.ID("{F57899D0-4E2C-4ac6-9E29-50C736103B0C}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]), diff --git a/browser/components/shell/nsWindowsShellService.cpp b/browser/components/shell/nsWindowsShellService.cpp index 6c43d95db..879b0c7f0 100644 --- a/browser/components/shell/nsWindowsShellService.cpp +++ b/browser/components/shell/nsWindowsShellService.cpp @@ -135,7 +135,7 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey) // The following keys are set to make Basilisk appear in the Start Menu as the // browser: // -// HKCU\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\ +// HKCU\SOFTWARE\Clients\StartMenuInternet\BASILISK.EXE\ // (default) REG_SZ <appname> // DefaultIcon (default) REG_SZ <apppath>,0 // InstallInfo HideIconsCommand REG_SZ <uninstpath> /HideShortcuts @@ -648,11 +648,6 @@ nsWindowsShellService::LaunchControlPanelDefaultsSelectionUI() nsresult nsWindowsShellService::LaunchControlPanelDefaultPrograms() { - // This Default Programs feature is Win7+ only. - if (!IsWin7OrLater()) { - return NS_ERROR_FAILURE; - } - // Build the path control.exe path safely WCHAR controlEXEPath[MAX_PATH + 1] = { '\0' }; if (!GetSystemDirectoryW(controlEXEPath, MAX_PATH)) { diff --git a/browser/components/webextensions/extension-win-panel.css b/browser/components/webextensions/extension-win-panel.css index ddafe3ea5..9da6da14c 100644 --- a/browser/components/webextensions/extension-win-panel.css +++ b/browser/components/webextensions/extension-win-panel.css @@ -1,6 +1,4 @@ -@media (-moz-os-version: windows-xp), - (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { +@media (-moz-os-version: windows-win7) { body { border-radius: 4px; } diff --git a/browser/config/mozconfigs/win32/common-opt b/browser/config/mozconfigs/win32/common-opt index d43a9878b..816c8926a 100644 --- a/browser/config/mozconfigs/win32/common-opt +++ b/browser/config/mozconfigs/win32/common-opt @@ -4,7 +4,6 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-jemalloc -ac_add_options --enable-require-all-d3dc-versions if [ -f /c/builds/gapi.data ]; then _gapi_keyfile=c:/builds/gapi.data diff --git a/browser/config/mozconfigs/win32/debug b/browser/config/mozconfigs/win32/debug index 6beee93c2..815276d0f 100644 --- a/browser/config/mozconfigs/win32/debug +++ b/browser/config/mozconfigs/win32/debug @@ -6,7 +6,6 @@ ac_add_options --enable-debug ac_add_options --enable-dmd ac_add_options --enable-profiling # needed for --enable-dmd to work on Windows ac_add_options --enable-verify-mar -ac_add_options --enable-require-all-d3dc-versions # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 diff --git a/browser/config/version.txt b/browser/config/version.txt index b406fbef6..d90a8c220 100644 --- a/browser/config/version.txt +++ b/browser/config/version.txt @@ -1 +1 @@ -55.0.0 +52.9.0 diff --git a/browser/config/version_display.txt b/browser/config/version_display.txt index b406fbef6..d90a8c220 100644 --- a/browser/config/version_display.txt +++ b/browser/config/version_display.txt @@ -1 +1 @@ -55.0.0 +52.9.0 diff --git a/browser/confvars.sh b/browser/confvars.sh index d4c2c008d..03b4cea97 100755 --- a/browser/confvars.sh +++ b/browser/confvars.sh @@ -18,7 +18,7 @@ if test "$OS_ARCH" = "WINNT"; then MOZ_MAINTENANCE_SERVICE= fi -# For Basilisk we want to use 55.0.YYYY.MM.DD as MOZ_APP_VERSION in release +# For Basilisk we want to use 52.9.YYYY.MM.DD as MOZ_APP_VERSION in release # builds so add-on developers have something to target while maintaining # Firefox compatiblity. # To enable add "export BASILISK_VERSION=1" to the .mozconfig file. @@ -26,7 +26,7 @@ fi # don't export the variable if you are in development or don't care. # When not exported we fall back the value in the version*.txt file. if test -n "$BASILISK_VERSION" ; then - MOZ_APP_VERSION=55.0.`date --utc '+%Y.%m.%d'` + MOZ_APP_VERSION=52.9.`date --utc '+%Y.%m.%d'` MOZ_APP_VERSION_DISPLAY=`date --utc '+%Y.%m.%d'` else MOZ_APP_VERSION=`cat ${_topsrcdir}/$MOZ_BUILD_APP/config/version.txt` @@ -53,13 +53,13 @@ MOZ_PROFILE_MIGRATOR=1 MOZ_APP_STATIC_INI=1 MOZ_WEBGL_CONFORMANT=1 MOZ_JSDOWNLOADS=1 -MOZ_RUST_MP4PARSE=1 -MOZ_RUST_URLPARSE=1 +MOZ_WEBRTC=1 MOZ_WEBEXTENSIONS=1 +MOZ_DEVTOOLS=1 +MOZ_SERVICES_COMMON=1 +MOZ_SERVICES_SYNC=1 +MOZ_SERVICES_HEALTHREPORT=1 # Disable checking that add-ons are signed by the trusted root MOZ_ADDON_SIGNING=0 MOZ_REQUIRE_SIGNING=0 - -# Include the DevTools client, not just the server (which is the default) -MOZ_DEVTOOLS=all diff --git a/browser/experiments/.eslintrc.js b/browser/experiments/.eslintrc.js deleted file mode 100644 index 1f6b11d67..000000000 --- a/browser/experiments/.eslintrc.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; - -module.exports = { - "rules": { - "no-unused-vars": ["error", { - "vars": "all", - "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$", - "args": "none" - }] - } -}; diff --git a/browser/experiments/Experiments.jsm b/browser/experiments/Experiments.jsm deleted file mode 100644 index e9a63f19f..000000000 --- a/browser/experiments/Experiments.jsm +++ /dev/null @@ -1,2354 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = [ - "Experiments", -]; - -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); -Cu.import("resource://gre/modules/Log.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/AsyncShutdown.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", - "resource://gre/modules/AddonManager.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate", - "resource://gre/modules/AddonManager.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEnvironment", - "resource://gre/modules/TelemetryEnvironment.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "TelemetryLog", - "resource://gre/modules/TelemetryLog.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "TelemetryUtils", - "resource://gre/modules/TelemetryUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", - "resource://services-common/utils.js"); - -XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter", - "@mozilla.org/xre/app-info;1", - "nsICrashReporter"); - -const FILE_CACHE = "experiments.json"; -const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed"; -const MANIFEST_VERSION = 1; -const CACHE_VERSION = 1; - -const KEEP_HISTORY_N_DAYS = 180; - -const PREF_BRANCH = "experiments."; -const PREF_ENABLED = "enabled"; // experiments.enabled -const PREF_ACTIVE_EXPERIMENT = "activeExperiment"; // whether we have an active experiment -const PREF_LOGGING = "logging"; -const PREF_LOGGING_LEVEL = PREF_LOGGING + ".level"; // experiments.logging.level -const PREF_LOGGING_DUMP = PREF_LOGGING + ".dump"; // experiments.logging.dump -const PREF_MANIFEST_URI = "manifest.uri"; // experiments.logging.manifest.uri -const PREF_FORCE_SAMPLE = "force-sample-value"; // experiments.force-sample-value - -const PREF_BRANCH_TELEMETRY = "toolkit.telemetry."; -const PREF_TELEMETRY_ENABLED = "enabled"; - -const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties"; -const STRING_TYPE_NAME = "type.%ID%.name"; - -const CACHE_WRITE_RETRY_DELAY_SEC = 60 * 3; -const MANIFEST_FETCH_TIMEOUT_MSEC = 60 * 3 * 1000; // 3 minutes - -const TELEMETRY_LOG = { - // log(key, [kind, experimentId, details]) - ACTIVATION_KEY: "EXPERIMENT_ACTIVATION", - ACTIVATION: { - // Successfully activated. - ACTIVATED: "ACTIVATED", - // Failed to install the add-on. - INSTALL_FAILURE: "INSTALL_FAILURE", - // Experiment does not meet activation requirements. Details will - // be provided. - REJECTED: "REJECTED", - }, - - // log(key, [kind, experimentId, optionalDetails...]) - TERMINATION_KEY: "EXPERIMENT_TERMINATION", - TERMINATION: { - // The Experiments service was disabled. - SERVICE_DISABLED: "SERVICE_DISABLED", - // Add-on uninstalled. - ADDON_UNINSTALLED: "ADDON_UNINSTALLED", - // The experiment disabled itself. - FROM_API: "FROM_API", - // The experiment expired (e.g. by exceeding the end date). - EXPIRED: "EXPIRED", - // Disabled after re-evaluating conditions. If this is specified, - // details will be provided. - RECHECK: "RECHECK", - }, -}; -XPCOMUtils.defineConstant(this, "TELEMETRY_LOG", TELEMETRY_LOG); - -const gPrefs = new Preferences(PREF_BRANCH); -const gPrefsTelemetry = new Preferences(PREF_BRANCH_TELEMETRY); -var gExperimentsEnabled = false; -var gAddonProvider = null; -var gExperiments = null; -var gLogAppenderDump = null; -var gPolicyCounter = 0; -var gExperimentsCounter = 0; -var gExperimentEntryCounter = 0; -var gPreviousProviderCounter = 0; - -// Tracks active AddonInstall we know about so we can deny external -// installs. -var gActiveInstallURLs = new Set(); - -// Tracks add-on IDs that are being uninstalled by us. This allows us -// to differentiate between expected uninstalled and user-driven uninstalls. -var gActiveUninstallAddonIDs = new Set(); - -var gLogger; -var gLogDumping = false; - -function configureLogging() { - if (!gLogger) { - gLogger = Log.repository.getLogger("Browser.Experiments"); - gLogger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter())); - } - gLogger.level = gPrefs.get(PREF_LOGGING_LEVEL, Log.Level.Warn); - - let logDumping = gPrefs.get(PREF_LOGGING_DUMP, false); - if (logDumping != gLogDumping) { - if (logDumping) { - gLogAppenderDump = new Log.DumpAppender(new Log.BasicFormatter()); - gLogger.addAppender(gLogAppenderDump); - } else { - gLogger.removeAppender(gLogAppenderDump); - gLogAppenderDump = null; - } - gLogDumping = logDumping; - } -} - -// Loads a JSON file using OS.file. file is a string representing the path -// of the file to be read, options contains additional options to pass to -// OS.File.read. -// Returns a Promise resolved with the json payload or rejected with -// OS.File.Error or JSON.parse() errors. -function loadJSONAsync(file, options) { - return Task.spawn(function*() { - let rawData = yield OS.File.read(file, options); - // Read json file into a string - let data; - try { - // Obtain a converter to read from a UTF-8 encoded input stream. - let converter = new TextDecoder(); - data = JSON.parse(converter.decode(rawData)); - } catch (ex) { - gLogger.error("Experiments: Could not parse JSON: " + file + " " + ex); - throw ex; - } - return data; - }); -} - -// Returns a promise that is resolved with the AddonInstall for that URL. -function addonInstallForURL(url, hash) { - let deferred = Promise.defer(); - AddonManager.getInstallForURL(url, install => deferred.resolve(install), - "application/x-xpinstall", hash); - return deferred.promise; -} - -// Returns a promise that is resolved with an Array<Addon> of the installed -// experiment addons. -function installedExperimentAddons() { - let deferred = Promise.defer(); - AddonManager.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons.filter(a => !a.appDisabled)); - }); - return deferred.promise; -} - -// Takes an Array<Addon> and returns a promise that is resolved when the -// addons are uninstalled. -function uninstallAddons(addons) { - let ids = new Set(addons.map(addon => addon.id)); - let deferred = Promise.defer(); - - let listener = {}; - listener.onUninstalled = addon => { - if (!ids.has(addon.id)) { - return; - } - - ids.delete(addon.id); - if (ids.size == 0) { - AddonManager.removeAddonListener(listener); - deferred.resolve(); - } - }; - - AddonManager.addAddonListener(listener); - - for (let addon of addons) { - // Disabling the add-on before uninstalling is necessary to cause tests to - // pass. This might be indicative of a bug in XPIProvider. - // TODO follow up in bug 992396. - addon.userDisabled = true; - addon.uninstall(); - } - - return deferred.promise; -} - -/** - * The experiments module. - */ - -var Experiments = { - /** - * Provides access to the global `Experiments.Experiments` instance. - */ - instance: function () { - if (!gExperiments) { - gExperiments = new Experiments.Experiments(); - } - - return gExperiments; - }, -}; - -/* - * The policy object allows us to inject fake enviroment data from the - * outside by monkey-patching. - */ - -Experiments.Policy = function () { - this._log = Log.repository.getLoggerWithMessagePrefix( - "Browser.Experiments.Policy", - "Policy #" + gPolicyCounter++ + "::"); - - // Set to true to ignore hash verification on downloaded XPIs. This should - // not be used outside of testing. - this.ignoreHashes = false; -}; - -Experiments.Policy.prototype = { - now: function () { - return new Date(); - }, - - random: function () { - let pref = gPrefs.get(PREF_FORCE_SAMPLE); - if (pref !== undefined) { - let val = Number.parseFloat(pref); - this._log.debug("random sample forced: " + val); - if (isNaN(val) || val < 0) { - return 0; - } - if (val > 1) { - return 1; - } - return val; - } - return Math.random(); - }, - - futureDate: function (offset) { - return new Date(this.now().getTime() + offset); - }, - - oneshotTimer: function (callback, timeout, thisObj, name) { - return CommonUtils.namedTimer(callback, timeout, thisObj, name); - }, - - updatechannel: function () { - return UpdateUtils.UpdateChannel; - }, - - locale: function () { - let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry); - return chrome.getSelectedLocale("global"); - }, - - /** - * For testing a race condition, one of the tests delays the callback of - * writing the cache by replacing this policy function. - */ - delayCacheWrite: function(promise) { - return promise; - }, -}; - -function AlreadyShutdownError(message="already shut down") { - Error.call(this, message); - let error = new Error(); - this.name = "AlreadyShutdownError"; - this.message = message; - this.stack = error.stack; -} -AlreadyShutdownError.prototype = Object.create(Error.prototype); -AlreadyShutdownError.prototype.constructor = AlreadyShutdownError; - -function CacheWriteError(message="Error writing cache file") { - Error.call(this, message); - let error = new Error(); - this.name = "CacheWriteError"; - this.message = message; - this.stack = error.stack; -} -CacheWriteError.prototype = Object.create(Error.prototype); -CacheWriteError.prototype.constructor = CacheWriteError; - -/** - * Manages the experiments and provides an interface to control them. - */ - -Experiments.Experiments = function (policy=new Experiments.Policy()) { - let log = Log.repository.getLoggerWithMessagePrefix( - "Browser.Experiments.Experiments", - "Experiments #" + gExperimentsCounter++ + "::"); - - // At the time of this writing, Experiments.jsm has severe - // crashes. For forensics purposes, keep the last few log - // messages in memory and upload them in case of crash. - this._forensicsLogs = []; - this._forensicsLogs.length = 30; - this._log = Object.create(log); - this._log.log = (level, string, params) => { - this._addToForensicsLog("Experiments", string); - log.log(level, string, params); - }; - - this._log.trace("constructor"); - - // Capture the latest error, for forensics purposes. - this._latestError = null; - - - this._policy = policy; - - // This is a Map of (string -> ExperimentEntry), keyed with the experiment id. - // It holds both the current experiments and history. - // Map() preserves insertion order, which means we preserve the manifest order. - // This is null until we've successfully completed loading the cache from - // disk the first time. - this._experiments = null; - this._refresh = false; - this._terminateReason = null; // or TELEMETRY_LOG.TERMINATION.... - this._dirty = false; - - // Loading the cache happens once asynchronously on startup - this._loadTask = null; - - // The _main task handles all other actions: - // * refreshing the manifest off the network (if _refresh) - // * disabling/enabling experiments - // * saving the cache (if _dirty) - this._mainTask = null; - - // Timer for re-evaluating experiment status. - this._timer = null; - - this._shutdown = false; - this._networkRequest = null; - - // We need to tell when we first evaluated the experiments to fire an - // experiments-changed notification when we only loaded completed experiments. - this._firstEvaluate = true; - - this.init(); -}; - -Experiments.Experiments.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsIObserver]), - - /** - * `true` if the experiments manager is currently setup (has been fully initialized - * and not uninitialized yet). - */ - get isReady() { - return !this._shutdown; - }, - - init: function () { - this._shutdown = false; - configureLogging(); - - gExperimentsEnabled = gPrefs.get(PREF_ENABLED, false) && TelemetryUtils.isTelemetryEnabled; - this._log.trace("enabled=" + gExperimentsEnabled + ", " + this.enabled); - - gPrefs.observe(PREF_LOGGING, configureLogging); - gPrefs.observe(PREF_MANIFEST_URI, this.updateManifest, this); - gPrefs.observe(PREF_ENABLED, this._toggleExperimentsEnabled, this); - - gPrefsTelemetry.observe(PREF_TELEMETRY_ENABLED, this._telemetryStatusChanged, this); - - AddonManager.shutdown.addBlocker("Experiments.jsm shutdown", - this.uninit.bind(this), - this._getState.bind(this) - ); - - this._registerWithAddonManager(); - - this._loadTask = this._loadFromCache(); - - return this._loadTask.then( - () => { - this._log.trace("_loadTask finished ok"); - this._loadTask = null; - return this._run(); - }, - (e) => { - this._log.error("_loadFromCache caught error: " + e); - this._latestError = e; - throw e; - } - ); - }, - - /** - * Uninitialize this instance. - * - * This function is susceptible to race conditions. If it is called multiple - * times before the previous uninit() has completed or if it is called while - * an init() operation is being performed, the object may get in bad state - * and/or deadlock could occur. - * - * @return Promise<> - * The promise is fulfilled when all pending tasks are finished. - */ - uninit: Task.async(function* () { - this._log.trace("uninit: started"); - yield this._loadTask; - this._log.trace("uninit: finished with _loadTask"); - - if (!this._shutdown) { - this._log.trace("uninit: no previous shutdown"); - this._unregisterWithAddonManager(); - - gPrefs.ignore(PREF_LOGGING, configureLogging); - gPrefs.ignore(PREF_MANIFEST_URI, this.updateManifest, this); - gPrefs.ignore(PREF_ENABLED, this._toggleExperimentsEnabled, this); - - gPrefsTelemetry.ignore(PREF_TELEMETRY_ENABLED, this._telemetryStatusChanged, this); - - if (this._timer) { - this._timer.clear(); - } - } - - this._shutdown = true; - if (this._mainTask) { - if (this._networkRequest) { - try { - this._log.trace("Aborting pending network request: " + this._networkRequest); - this._networkRequest.abort(); - } catch (e) { - // pass - } - } - try { - this._log.trace("uninit: waiting on _mainTask"); - yield this._mainTask; - } catch (e) { - // We error out of tasks after shutdown via this exception. - this._log.trace(`uninit: caught error - ${e}`); - if (!(e instanceof AlreadyShutdownError)) { - this._latestError = e; - throw e; - } - } - } - - this._log.info("Completed uninitialization."); - }), - - // Return state information, for debugging purposes. - _getState: function() { - let activeExperiment = this._getActiveExperiment(); - let state = { - isShutdown: this._shutdown, - isEnabled: gExperimentsEnabled, - isRefresh: this._refresh, - isDirty: this._dirty, - isFirstEvaluate: this._firstEvaluate, - hasLoadTask: !!this._loadTask, - hasMainTask: !!this._mainTask, - hasTimer: !!this._hasTimer, - hasAddonProvider: !!gAddonProvider, - latestLogs: this._forensicsLogs, - experiments: this._experiments ? [...this._experiments.keys()] : null, - terminateReason: this._terminateReason, - activeExperiment: activeExperiment ? activeExperiment.id : null, - }; - if (this._latestError) { - if (typeof this._latestError == "object") { - state.latestError = { - message: this._latestError.message, - stack: this._latestError.stack - }; - } else { - state.latestError = "" + this._latestError; - } - } - return state; - }, - - _addToForensicsLog: function (what, string) { - this._forensicsLogs.shift(); - let timeInSec = Math.floor(Services.telemetry.msSinceProcessStart() / 1000); - this._forensicsLogs.push(`${timeInSec}: ${what} - ${string}`); - }, - - _registerWithAddonManager: function (previousExperimentsProvider) { - this._log.trace("Registering instance with Addon Manager."); - - AddonManager.addAddonListener(this); - AddonManager.addInstallListener(this); - - if (!gAddonProvider) { - // The properties of this AddonType should be kept in sync with the - // experiment AddonType registered in XPIProvider. - this._log.trace("Registering previous experiment add-on provider."); - gAddonProvider = previousExperimentsProvider || new Experiments.PreviousExperimentProvider(this); - AddonManagerPrivate.registerProvider(gAddonProvider, [ - new AddonManagerPrivate.AddonType("experiment", - URI_EXTENSION_STRINGS, - STRING_TYPE_NAME, - AddonManager.VIEW_TYPE_LIST, - 11000, - AddonManager.TYPE_UI_HIDE_EMPTY), - ]); - } - - }, - - _unregisterWithAddonManager: function () { - this._log.trace("Unregistering instance with Addon Manager."); - - this._log.trace("Removing install listener from add-on manager."); - AddonManager.removeInstallListener(this); - this._log.trace("Removing addon listener from add-on manager."); - AddonManager.removeAddonListener(this); - this._log.trace("Finished unregistering with addon manager."); - - if (gAddonProvider) { - this._log.trace("Unregistering previous experiment add-on provider."); - AddonManagerPrivate.unregisterProvider(gAddonProvider); - gAddonProvider = null; - } - }, - - /* - * Change the PreviousExperimentsProvider that this instance uses. - * For testing only. - */ - _setPreviousExperimentsProvider: function (provider) { - this._unregisterWithAddonManager(); - this._registerWithAddonManager(provider); - }, - - /** - * Throws an exception if we've already shut down. - */ - _checkForShutdown: function() { - if (this._shutdown) { - throw new AlreadyShutdownError("uninit() already called"); - } - }, - - /** - * Whether the experiments feature is enabled. - */ - get enabled() { - return gExperimentsEnabled; - }, - - /** - * Toggle whether the experiments feature is enabled or not. - */ - set enabled(enabled) { - this._log.trace("set enabled(" + enabled + ")"); - gPrefs.set(PREF_ENABLED, enabled); - }, - - _toggleExperimentsEnabled: Task.async(function* (enabled) { - this._log.trace("_toggleExperimentsEnabled(" + enabled + ")"); - let wasEnabled = gExperimentsEnabled; - gExperimentsEnabled = enabled && TelemetryUtils.isTelemetryEnabled; - - if (wasEnabled == gExperimentsEnabled) { - return; - } - - if (gExperimentsEnabled) { - yield this.updateManifest(); - } else { - yield this.disableExperiment(TELEMETRY_LOG.TERMINATION.SERVICE_DISABLED); - if (this._timer) { - this._timer.clear(); - } - } - }), - - _telemetryStatusChanged: function () { - this._toggleExperimentsEnabled(gExperimentsEnabled); - }, - - /** - * Returns a promise that is resolved with an array of `ExperimentInfo` objects, - * which provide info on the currently and recently active experiments. - * The array is in chronological order. - * - * The experiment info is of the form: - * { - * id: <string>, - * name: <string>, - * description: <string>, - * active: <boolean>, - * endDate: <integer>, // epoch ms - * detailURL: <string>, - * ... // possibly extended later - * } - * - * @return Promise<Array<ExperimentInfo>> Array of experiment info objects. - */ - getExperiments: function () { - return Task.spawn(function*() { - yield this._loadTask; - let list = []; - - for (let [id, experiment] of this._experiments) { - if (!experiment.startDate) { - // We only collect experiments that are or were active. - continue; - } - - list.push({ - id: id, - name: experiment._name, - description: experiment._description, - active: experiment.enabled, - endDate: experiment.endDate.getTime(), - detailURL: experiment._homepageURL, - branch: experiment.branch, - }); - } - - // Sort chronologically, descending. - list.sort((a, b) => b.endDate - a.endDate); - return list; - }.bind(this)); - }, - - /** - * Returns the ExperimentInfo for the active experiment, or null - * if there is none. - */ - getActiveExperiment: function () { - let experiment = this._getActiveExperiment(); - if (!experiment) { - return null; - } - - let info = { - id: experiment.id, - name: experiment._name, - description: experiment._description, - active: experiment.enabled, - endDate: experiment.endDate.getTime(), - detailURL: experiment._homepageURL, - }; - - return info; - }, - - /** - * Experiment "branch" support. If an experiment has multiple branches, it - * can record the branch with the experiment system and it will - * automatically be included in data reporting (FHR/telemetry payloads). - */ - - /** - * Set the experiment branch for the specified experiment ID. - * @returns Promise<> - */ - setExperimentBranch: Task.async(function*(id, branchstr) { - yield this._loadTask; - let e = this._experiments.get(id); - if (!e) { - throw new Error("Experiment not found"); - } - e.branch = String(branchstr); - this._log.trace("setExperimentBranch(" + id + ", " + e.branch + ") _dirty=" + this._dirty); - this._dirty = true; - Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null); - yield this._run(); - }), - /** - * Get the branch of the specified experiment. If the experiment is unknown, - * throws an error. - * - * @param id The ID of the experiment. Pass null for the currently running - * experiment. - * @returns Promise<string|null> - * @throws Error if the specified experiment ID is unknown, or if there is no - * current experiment. - */ - getExperimentBranch: Task.async(function*(id=null) { - yield this._loadTask; - let e; - if (id) { - e = this._experiments.get(id); - if (!e) { - throw new Error("Experiment not found"); - } - } else { - e = this._getActiveExperiment(); - if (e === null) { - throw new Error("No active experiment"); - } - } - return e.branch; - }), - - /** - * Determine whether another date has the same UTC day as now(). - */ - _dateIsTodayUTC: function (d) { - let now = this._policy.now(); - - return stripDateToMidnight(now).getTime() == stripDateToMidnight(d).getTime(); - }, - - /** - * Obtain the entry of the most recent active experiment that was active - * today. - * - * If no experiment was active today, this resolves to nothing. - * - * Assumption: Only a single experiment can be active at a time. - * - * @return Promise<object> - */ - lastActiveToday: function () { - return Task.spawn(function* getMostRecentActiveExperimentTask() { - let experiments = yield this.getExperiments(); - - // Assumption: Ordered chronologically, descending, with active always - // first. - for (let experiment of experiments) { - if (experiment.active) { - return experiment; - } - - if (experiment.endDate && this._dateIsTodayUTC(experiment.endDate)) { - return experiment; - } - } - return null; - }.bind(this)); - }, - - _run: function() { - this._log.trace("_run"); - this._checkForShutdown(); - if (!this._mainTask) { - this._mainTask = Task.spawn(function*() { - try { - yield this._main(); - } catch (e) { - // In the CacheWriteError case we want to reschedule - if (!(e instanceof CacheWriteError)) { - this._log.error("_main caught error: " + e); - return; - } - } finally { - this._mainTask = null; - } - this._log.trace("_main finished, scheduling next run"); - try { - yield this._scheduleNextRun(); - } catch (ex) { - // We error out of tasks after shutdown via this exception. - if (!(ex instanceof AlreadyShutdownError)) { - throw ex; - } - } - }.bind(this)); - } - return this._mainTask; - }, - - _main: function*() { - do { - this._log.trace("_main iteration"); - yield this._loadTask; - if (!gExperimentsEnabled) { - this._refresh = false; - } - - if (this._refresh) { - yield this._loadManifest(); - } - yield this._evaluateExperiments(); - if (this._dirty) { - yield this._saveToCache(); - } - // If somebody called .updateManifest() or disableExperiment() - // while we were running, go again right now. - } - while (this._refresh || this._terminateReason || this._dirty); - }, - - _loadManifest: function*() { - this._log.trace("_loadManifest"); - let uri = Services.urlFormatter.formatURLPref(PREF_BRANCH + PREF_MANIFEST_URI); - - this._checkForShutdown(); - - this._refresh = false; - try { - let responseText = yield this._httpGetRequest(uri); - this._log.trace("_loadManifest() - responseText=\"" + responseText + "\""); - - if (this._shutdown) { - return; - } - - let data = JSON.parse(responseText); - this._updateExperiments(data); - } catch (e) { - this._log.error("_loadManifest - failure to fetch/parse manifest (continuing anyway): " + e); - } - }, - - /** - * Fetch an updated list of experiments and trigger experiment updates. - * Do only use when experiments are enabled. - * - * @return Promise<> - * The promise is resolved when the manifest and experiment list is updated. - */ - updateManifest: function () { - this._log.trace("updateManifest()"); - - if (!gExperimentsEnabled) { - return Promise.reject(new Error("experiments are disabled")); - } - - if (this._shutdown) { - return Promise.reject(Error("uninit() alrady called")); - } - - this._refresh = true; - return this._run(); - }, - - notify: function (timer) { - this._log.trace("notify()"); - this._checkForShutdown(); - return this._run(); - }, - - // START OF ADD-ON LISTENERS - - onUninstalled: function (addon) { - this._log.trace("onUninstalled() - addon id: " + addon.id); - if (gActiveUninstallAddonIDs.has(addon.id)) { - this._log.trace("matches pending uninstall"); - return; - } - let activeExperiment = this._getActiveExperiment(); - if (!activeExperiment || activeExperiment._addonId != addon.id) { - return; - } - - this.disableExperiment(TELEMETRY_LOG.TERMINATION.ADDON_UNINSTALLED); - }, - - /** - * @returns {Boolean} returns false when we cancel the install. - */ - onInstallStarted: function (install) { - if (install.addon.type != "experiment") { - return true; - } - - this._log.trace("onInstallStarted() - " + install.addon.id); - if (install.addon.appDisabled) { - // This is a PreviousExperiment - return true; - } - - // We want to be in control of all experiment add-ons: reject installs - // for add-ons that we don't know about. - - // We have a race condition of sorts to worry about here. We have 2 - // onInstallStarted listeners. This one (the global one) and the one - // created as part of ExperimentEntry._installAddon. Because of the order - // they are registered in, this one likely executes first. Unfortunately, - // this means that the add-on ID is not yet set on the ExperimentEntry. - // So, we can't just look at this._trackedAddonIds because the new experiment - // will have its add-on ID set to null. We work around this by storing a - // identifying field - the source URL of the install - in a module-level - // variable (so multiple Experiments instances doesn't cancel each other - // out). - - if (this._trackedAddonIds.has(install.addon.id)) { - this._log.info("onInstallStarted allowing install because add-on ID " + - "tracked by us."); - return true; - } - - if (gActiveInstallURLs.has(install.sourceURI.spec)) { - this._log.info("onInstallStarted allowing install because install " + - "tracked by us."); - return true; - } - - this._log.warn("onInstallStarted cancelling install of unknown " + - "experiment add-on: " + install.addon.id); - return false; - }, - - // END OF ADD-ON LISTENERS. - - _getExperimentByAddonId: function (addonId) { - for (let [, entry] of this._experiments) { - if (entry._addonId === addonId) { - return entry; - } - } - - return null; - }, - - /* - * Helper function to make HTTP GET requests. Returns a promise that is resolved with - * the responseText when the request is complete. - */ - _httpGetRequest: function (url) { - this._log.trace("httpGetRequest(" + url + ")"); - let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest); - - this._networkRequest = xhr; - let deferred = Promise.defer(); - - let log = this._log; - let errorhandler = (evt) => { - log.error("httpGetRequest::onError() - Error making request to " + url + ": " + evt.type); - deferred.reject(new Error("Experiments - XHR error for " + url + " - " + evt.type)); - this._networkRequest = null; - }; - xhr.onerror = errorhandler; - xhr.ontimeout = errorhandler; - xhr.onabort = errorhandler; - - xhr.onload = (event) => { - if (xhr.status !== 200 && xhr.state !== 0) { - log.error("httpGetRequest::onLoad() - Request to " + url + " returned status " + xhr.status); - deferred.reject(new Error("Experiments - XHR status for " + url + " is " + xhr.status)); - this._networkRequest = null; - return; - } - - deferred.resolve(xhr.responseText); - this._networkRequest = null; - }; - - try { - xhr.open("GET", url); - - if (xhr.channel instanceof Ci.nsISupportsPriority) { - xhr.channel.priority = Ci.nsISupportsPriority.PRIORITY_LOWEST; - } - - xhr.timeout = MANIFEST_FETCH_TIMEOUT_MSEC; - xhr.send(null); - } catch (e) { - this._log.error("httpGetRequest() - Error opening request to " + url + ": " + e); - return Promise.reject(new Error("Experiments - Error opening XHR for " + url)); - } - return deferred.promise; - }, - - /* - * Path of the cache file we use in the profile. - */ - get _cacheFilePath() { - return OS.Path.join(OS.Constants.Path.profileDir, FILE_CACHE); - }, - - /* - * Part of the main task to save the cache to disk, called from _main. - */ - _saveToCache: function* () { - this._log.trace("_saveToCache"); - let path = this._cacheFilePath; - this._dirty = false; - try { - let textData = JSON.stringify({ - version: CACHE_VERSION, - data: [...this._experiments.values()].map(e => e.toJSON()), - }); - - let encoder = new TextEncoder(); - let data = encoder.encode(textData); - let options = { tmpPath: path + ".tmp", compression: "lz4" }; - yield this._policy.delayCacheWrite(OS.File.writeAtomic(path, data, options)); - } catch (e) { - // We failed to write the cache, it's still dirty. - this._dirty = true; - this._log.error("_saveToCache failed and caught error: " + e); - throw new CacheWriteError(); - } - - this._log.debug("_saveToCache saved to " + path); - }, - - /* - * Task function, load the cached experiments manifest file from disk. - */ - _loadFromCache: Task.async(function* () { - this._log.trace("_loadFromCache"); - let path = this._cacheFilePath; - try { - let result = yield loadJSONAsync(path, { compression: "lz4" }); - this._populateFromCache(result); - } catch (e) { - if (e instanceof OS.File.Error && e.becauseNoSuchFile) { - // No cached manifest yet. - this._experiments = new Map(); - } else { - throw e; - } - } - }), - - _populateFromCache: function (data) { - this._log.trace("populateFromCache() - data: " + JSON.stringify(data)); - - // If the user has a newer cache version than we can understand, we fail - // hard; no experiments should be active in this older client. - if (CACHE_VERSION !== data.version) { - throw new Error("Experiments::_populateFromCache() - invalid cache version"); - } - - let experiments = new Map(); - for (let item of data.data) { - let entry = new Experiments.ExperimentEntry(this._policy); - if (!entry.initFromCacheData(item)) { - continue; - } - - // Discard old experiments if they ended more than 180 days ago. - if (entry.shouldDiscard()) { - // We discarded an experiment, the cache needs to be updated. - this._dirty = true; - continue; - } - - experiments.set(entry.id, entry); - } - - this._experiments = experiments; - }, - - /* - * Update the experiment entries from the experiments - * array in the manifest - */ - _updateExperiments: function (manifestObject) { - this._log.trace("_updateExperiments() - experiments: " + JSON.stringify(manifestObject)); - - if (manifestObject.version !== MANIFEST_VERSION) { - this._log.warning("updateExperiments() - unsupported version " + manifestObject.version); - } - - let experiments = new Map(); // The new experiments map - - // Collect new and updated experiments. - for (let data of manifestObject.experiments) { - let entry = this._experiments.get(data.id); - - if (entry) { - if (!entry.updateFromManifestData(data)) { - this._log.error("updateExperiments() - Invalid manifest data for " + data.id); - continue; - } - } else { - entry = new Experiments.ExperimentEntry(this._policy); - if (!entry.initFromManifestData(data)) { - continue; - } - } - - if (entry.shouldDiscard()) { - continue; - } - - experiments.set(entry.id, entry); - } - - // Make sure we keep experiments that are or were running. - // We remove them after KEEP_HISTORY_N_DAYS. - for (let [id, entry] of this._experiments) { - if (experiments.has(id)) { - continue; - } - - if (!entry.startDate || entry.shouldDiscard()) { - this._log.trace("updateExperiments() - discarding entry for " + id); - continue; - } - - experiments.set(id, entry); - } - - this._experiments = experiments; - this._dirty = true; - }, - - getActiveExperimentID: function() { - if (!this._experiments) { - return null; - } - let e = this._getActiveExperiment(); - if (!e) { - return null; - } - return e.id; - }, - - getActiveExperimentBranch: function() { - if (!this._experiments) { - return null; - } - let e = this._getActiveExperiment(); - if (!e) { - return null; - } - return e.branch; - }, - - _getActiveExperiment: function () { - let enabled = [...this._experiments.values()].filter(experiment => experiment._enabled); - - if (enabled.length == 1) { - return enabled[0]; - } - - if (enabled.length > 1) { - this._log.error("getActiveExperimentId() - should not have more than 1 active experiment"); - throw new Error("have more than 1 active experiment"); - } - - return null; - }, - - /** - * Disables all active experiments. - * - * @return Promise<> Promise that will get resolved once the task is done or failed. - */ - disableExperiment: function (reason) { - if (!reason) { - throw new Error("Must specify a termination reason."); - } - - this._log.trace("disableExperiment()"); - this._terminateReason = reason; - return this._run(); - }, - - /** - * The Set of add-on IDs that we know about from manifests. - */ - get _trackedAddonIds() { - if (!this._experiments) { - return new Set(); - } - - return new Set([...this._experiments.values()].map(e => e._addonId)); - }, - - /* - * Task function to check applicability of experiments, disable the active - * experiment if needed and activate the first applicable candidate. - */ - _evaluateExperiments: function*() { - this._log.trace("_evaluateExperiments"); - - this._checkForShutdown(); - - // The first thing we do is reconcile our state against what's in the - // Addon Manager. It's possible that the Addon Manager knows of experiment - // add-ons that we don't. This could happen if an experiment gets installed - // when we're not listening or if there is a bug in our synchronization - // code. - // - // We have a few options of what to do with unknown experiment add-ons - // coming from the Addon Manager. Ideally, we'd convert these to - // ExperimentEntry instances and stuff them inside this._experiments. - // However, since ExperimentEntry contain lots of metadata from the - // manifest and trying to make up data could be error prone, it's safer - // to not try. Furthermore, if an experiment really did come from us, we - // should have some record of it. In the end, we decide to discard all - // knowledge for these unknown experiment add-ons. - let installedExperiments = yield installedExperimentAddons(); - let expectedAddonIds = this._trackedAddonIds; - let unknownAddons = installedExperiments.filter(a => !expectedAddonIds.has(a.id)); - if (unknownAddons.length) { - this._log.warn("_evaluateExperiments() - unknown add-ons in AddonManager: " + - unknownAddons.map(a => a.id).join(", ")); - - yield uninstallAddons(unknownAddons); - } - - let activeExperiment = this._getActiveExperiment(); - let activeChanged = false; - - if (!activeExperiment) { - // Avoid this pref staying out of sync if there were e.g. crashes. - gPrefs.set(PREF_ACTIVE_EXPERIMENT, false); - } - - // Ensure the active experiment is in the proper state. This may install, - // uninstall, upgrade, or enable the experiment add-on. What exactly is - // abstracted away from us by design. - if (activeExperiment) { - let changes; - let shouldStopResult = yield activeExperiment.shouldStop(); - if (shouldStopResult.shouldStop) { - let expireReasons = ["endTime", "maxActiveSeconds"]; - let kind, reason; - - if (expireReasons.indexOf(shouldStopResult.reason[0]) != -1) { - kind = TELEMETRY_LOG.TERMINATION.EXPIRED; - reason = null; - } else { - kind = TELEMETRY_LOG.TERMINATION.RECHECK; - reason = shouldStopResult.reason; - } - changes = yield activeExperiment.stop(kind, reason); - } - else if (this._terminateReason) { - changes = yield activeExperiment.stop(this._terminateReason); - } - else { - changes = yield activeExperiment.reconcileAddonState(); - } - - if (changes) { - this._dirty = true; - activeChanged = true; - } - - if (!activeExperiment._enabled) { - activeExperiment = null; - activeChanged = true; - } - } - - this._terminateReason = null; - - if (!activeExperiment && gExperimentsEnabled) { - for (let [id, experiment] of this._experiments) { - let applicable; - let reason = null; - try { - applicable = yield experiment.isApplicable(); - } - catch (e) { - applicable = false; - reason = e; - } - - if (!applicable && reason && reason[0] != "was-active") { - // Report this from here to avoid over-reporting. - let data = [TELEMETRY_LOG.ACTIVATION.REJECTED, id]; - data = data.concat(reason); - const key = TELEMETRY_LOG.ACTIVATION_KEY; - TelemetryLog.log(key, data); - this._log.trace("evaluateExperiments() - added " + key + " to TelemetryLog: " + JSON.stringify(data)); - } - - if (!applicable) { - continue; - } - - this._log.debug("evaluateExperiments() - activating experiment " + id); - try { - yield experiment.start(); - activeChanged = true; - activeExperiment = experiment; - this._dirty = true; - break; - } catch (e) { - // On failure, clean up the best we can and try the next experiment. - this._log.error("evaluateExperiments() - Unable to start experiment: " + e.message); - experiment._enabled = false; - yield experiment.reconcileAddonState(); - } - } - } - - gPrefs.set(PREF_ACTIVE_EXPERIMENT, activeExperiment != null); - - if (activeChanged || this._firstEvaluate) { - Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null); - this._firstEvaluate = false; - } - - if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) { - try { - gCrashReporter.annotateCrashReport("ActiveExperiment", activeExperiment.id); - gCrashReporter.annotateCrashReport("ActiveExperimentBranch", activeExperiment.branch); - } catch (e) { - // It's ok if crash reporting is disabled. - } - } - }, - - /* - * Schedule the soonest re-check of experiment applicability that is needed. - */ - _scheduleNextRun: function () { - this._checkForShutdown(); - - if (this._timer) { - this._timer.clear(); - } - - if (!gExperimentsEnabled || this._experiments.length == 0) { - return; - } - - let time = null; - let now = this._policy.now().getTime(); - if (this._dirty) { - // If we failed to write the cache, we should try again periodically - time = now + 1000 * CACHE_WRITE_RETRY_DELAY_SEC; - } - - for (let [, experiment] of this._experiments) { - let scheduleTime = experiment.getScheduleTime(); - if (scheduleTime > now) { - if (time !== null) { - time = Math.min(time, scheduleTime); - } else { - time = scheduleTime; - } - } - } - - if (time === null) { - // No schedule time found. - return; - } - - this._log.trace("scheduleExperimentEvaluation() - scheduling for "+time+", now: "+now); - this._policy.oneshotTimer(this.notify, time - now, this, "_timer"); - }, -}; - - -/* - * Represents a single experiment. - */ - -Experiments.ExperimentEntry = function (policy) { - this._policy = policy || new Experiments.Policy(); - let log = Log.repository.getLoggerWithMessagePrefix( - "Browser.Experiments.Experiments", - "ExperimentEntry #" + gExperimentEntryCounter++ + "::"); - this._log = Object.create(log); - this._log.log = (level, string, params) => { - if (gExperiments) { - gExperiments._addToForensicsLog("ExperimentEntry", string); - } - log.log(level, string, params); - }; - - // Is the experiment supposed to be running. - this._enabled = false; - // When this experiment was started, if ever. - this._startDate = null; - // When this experiment was ended, if ever. - this._endDate = null; - // The condition data from the manifest. - this._manifestData = null; - // For an active experiment, signifies whether we need to update the xpi. - this._needsUpdate = false; - // A random sample value for comparison against the manifest conditions. - this._randomValue = null; - // When this entry was last changed for respecting history retention duration. - this._lastChangedDate = null; - // Has this experiment failed to activate before? - this._failedStart = false; - // The experiment branch - this._branch = null; - - // We grab these from the addon after download. - this._name = null; - this._description = null; - this._homepageURL = null; - this._addonId = null; -}; - -Experiments.ExperimentEntry.prototype = { - MANIFEST_REQUIRED_FIELDS: new Set([ - "id", - "xpiURL", - "xpiHash", - "startTime", - "endTime", - "maxActiveSeconds", - "appName", - "channel", - ]), - - MANIFEST_OPTIONAL_FIELDS: new Set([ - "maxStartTime", - "minVersion", - "maxVersion", - "version", - "minBuildID", - "maxBuildID", - "buildIDs", - "os", - "locale", - "sample", - "disabled", - "frozen", - "jsfilter", - ]), - - SERIALIZE_KEYS: new Set([ - "_enabled", - "_manifestData", - "_needsUpdate", - "_randomValue", - "_failedStart", - "_name", - "_description", - "_homepageURL", - "_addonId", - "_startDate", - "_endDate", - "_branch", - ]), - - DATE_KEYS: new Set([ - "_startDate", - "_endDate", - ]), - - UPGRADE_KEYS: new Map([ - ["_branch", null], - ]), - - ADDON_CHANGE_NONE: 0, - ADDON_CHANGE_INSTALL: 1, - ADDON_CHANGE_UNINSTALL: 2, - ADDON_CHANGE_ENABLE: 4, - - /* - * Initialize entry from the manifest. - * @param data The experiment data from the manifest. - * @return boolean Whether initialization succeeded. - */ - initFromManifestData: function (data) { - if (!this._isManifestDataValid(data)) { - return false; - } - - this._manifestData = data; - - this._randomValue = this._policy.random(); - this._lastChangedDate = this._policy.now(); - - return true; - }, - - get enabled() { - return this._enabled; - }, - - get id() { - return this._manifestData.id; - }, - - get branch() { - return this._branch; - }, - - set branch(v) { - this._branch = v; - }, - - get startDate() { - return this._startDate; - }, - - get endDate() { - if (!this._startDate) { - return null; - } - - let endTime = 0; - - if (!this._enabled) { - return this._endDate; - } - - let maxActiveMs = 1000 * this._manifestData.maxActiveSeconds; - endTime = Math.min(1000 * this._manifestData.endTime, - this._startDate.getTime() + maxActiveMs); - - return new Date(endTime); - }, - - get needsUpdate() { - return this._needsUpdate; - }, - - /* - * Initialize entry from the cache. - * @param data The entry data from the cache. - * @return boolean Whether initialization succeeded. - */ - initFromCacheData: function (data) { - for (let [key, dval] of this.UPGRADE_KEYS) { - if (!(key in data)) { - data[key] = dval; - } - } - - for (let key of this.SERIALIZE_KEYS) { - if (!(key in data) && !this.DATE_KEYS.has(key)) { - this._log.error("initFromCacheData() - missing required key " + key); - return false; - } - } - - if (!this._isManifestDataValid(data._manifestData)) { - return false; - } - - // Dates are restored separately from epoch ms, everything else is just - // copied in. - - this.SERIALIZE_KEYS.forEach(key => { - if (!this.DATE_KEYS.has(key)) { - this[key] = data[key]; - } - }); - - this.DATE_KEYS.forEach(key => { - if (key in data) { - let date = new Date(); - date.setTime(data[key]); - this[key] = date; - } - }); - - // In order for the experiment's data expiration mechanism to work, use the experiment's - // |_endData| as the |_lastChangedDate| (if available). - this._lastChangedDate = this._endDate ? this._endDate : this._policy.now(); - - return true; - }, - - /* - * Returns a JSON representation of this object. - */ - toJSON: function () { - let obj = {}; - - // Dates are serialized separately as epoch ms. - - this.SERIALIZE_KEYS.forEach(key => { - if (!this.DATE_KEYS.has(key)) { - obj[key] = this[key]; - } - }); - - this.DATE_KEYS.forEach(key => { - if (this[key]) { - obj[key] = this[key].getTime(); - } - }); - - return obj; - }, - - /* - * Update from the experiment data from the manifest. - * @param data The experiment data from the manifest. - * @return boolean Whether updating succeeded. - */ - updateFromManifestData: function (data) { - let old = this._manifestData; - - if (!this._isManifestDataValid(data)) { - return false; - } - - if (this._enabled) { - if (old.xpiHash !== data.xpiHash) { - // A changed hash means we need to update active experiments. - this._needsUpdate = true; - } - } else if (this._failedStart && - (old.xpiHash !== data.xpiHash) || - (old.xpiURL !== data.xpiURL)) { - // Retry installation of previously invalid experiments - // if hash or url changed. - this._failedStart = false; - } - - this._manifestData = data; - this._lastChangedDate = this._policy.now(); - - return true; - }, - - /* - * Is this experiment applicable? - * @return Promise<> Resolved if the experiment is applicable. - * If it is not applicable it is rejected with - * a Promise<string> which contains the reason. - */ - isApplicable: function () { - let versionCmp = Cc["@mozilla.org/xpcom/version-comparator;1"] - .getService(Ci.nsIVersionComparator); - let app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); - let runtime = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); - - let locale = this._policy.locale(); - let channel = this._policy.updatechannel(); - let data = this._manifestData; - - let now = this._policy.now() / 1000; // The manifest times are in seconds. - let maxActive = data.maxActiveSeconds || 0; - let startSec = (this.startDate || 0) / 1000; - - this._log.trace("isApplicable() - now=" + now - + ", randomValue=" + this._randomValue); - - // Not applicable if it already ran. - - if (!this.enabled && this._endDate) { - return Promise.reject(["was-active"]); - } - - // Define and run the condition checks. - - let simpleChecks = [ - { name: "failedStart", - condition: () => !this._failedStart }, - { name: "disabled", - condition: () => !data.disabled }, - { name: "frozen", - condition: () => !data.frozen || this._enabled }, - { name: "startTime", - condition: () => now >= data.startTime }, - { name: "endTime", - condition: () => now < data.endTime }, - { name: "maxStartTime", - condition: () => this._startDate || !data.maxStartTime || now <= data.maxStartTime }, - { name: "maxActiveSeconds", - condition: () => !this._startDate || now <= (startSec + maxActive) }, - { name: "appName", - condition: () => !data.appName || data.appName.indexOf(app.name) != -1 }, - { name: "minBuildID", - condition: () => !data.minBuildID || app.platformBuildID >= data.minBuildID }, - { name: "maxBuildID", - condition: () => !data.maxBuildID || app.platformBuildID <= data.maxBuildID }, - { name: "buildIDs", - condition: () => !data.buildIDs || data.buildIDs.indexOf(app.platformBuildID) != -1 }, - { name: "os", - condition: () => !data.os || data.os.indexOf(runtime.OS) != -1 }, - { name: "channel", - condition: () => !data.channel || data.channel.indexOf(channel) != -1 }, - { name: "locale", - condition: () => !data.locale || data.locale.indexOf(locale) != -1 }, - { name: "sample", - condition: () => data.sample === undefined || this._randomValue <= data.sample }, - { name: "version", - condition: () => !data.version || data.version.indexOf(app.version) != -1 }, - { name: "minVersion", - condition: () => !data.minVersion || versionCmp.compare(app.version, data.minVersion) >= 0 }, - { name: "maxVersion", - condition: () => !data.maxVersion || versionCmp.compare(app.version, data.maxVersion) <= 0 }, - ]; - - for (let check of simpleChecks) { - let result = check.condition(); - if (!result) { - this._log.debug("isApplicable() - id=" - + data.id + " - test '" + check.name + "' failed"); - return Promise.reject([check.name]); - } - } - - if (data.jsfilter) { - return this._runFilterFunction(data.jsfilter); - } - - return Promise.resolve(true); - }, - - /* - * Run the jsfilter function from the manifest in a sandbox and return the - * result (forced to boolean). - */ - _runFilterFunction: Task.async(function* (jsfilter) { - this._log.trace("runFilterFunction() - filter: " + jsfilter); - - let ssm = Services.scriptSecurityManager; - const nullPrincipal = ssm.createNullPrincipal({}); - let options = { - sandboxName: "telemetry experiments jsfilter sandbox", - wantComponents: false, - }; - - let sandbox = Cu.Sandbox(nullPrincipal, options); - try { - Cu.evalInSandbox(jsfilter, sandbox); - } catch (e) { - this._log.error("runFilterFunction() - failed to eval jsfilter: " + e.message); - throw ["jsfilter-evalfailed"]; - } - - let currentEnvironment = yield TelemetryEnvironment.onInitialized(); - - Object.defineProperty(sandbox, "_e", - { get: () => Cu.cloneInto(currentEnvironment, sandbox) }); - - let result = false; - try { - result = !!Cu.evalInSandbox("filter({get telemetryEnvironment() { return _e; } })", sandbox); - } - catch (e) { - this._log.debug("runFilterFunction() - filter function failed: " - + e.message + ", " + e.stack); - throw ["jsfilter-threw", e.message]; - } - finally { - Cu.nukeSandbox(sandbox); - } - - if (!result) { - throw ["jsfilter-false"]; - } - - return true; - }), - - /* - * Start running the experiment. - * - * @return Promise<> Resolved when the operation is complete. - */ - start: Task.async(function* () { - this._log.trace("start() for " + this.id); - - this._enabled = true; - return yield this.reconcileAddonState(); - }), - - // Async install of the addon for this experiment, part of the start task above. - _installAddon: Task.async(function* () { - let deferred = Promise.defer(); - - let hash = this._policy.ignoreHashes ? null : this._manifestData.xpiHash; - - let install = yield addonInstallForURL(this._manifestData.xpiURL, hash); - gActiveInstallURLs.add(install.sourceURI.spec); - - let failureHandler = (install, handler) => { - let message = "AddonInstall " + handler + " for " + this.id + ", state=" + - (install.state || "?") + ", error=" + install.error; - this._log.error("_installAddon() - " + message); - this._failedStart = true; - gActiveInstallURLs.delete(install.sourceURI.spec); - - TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY, - [TELEMETRY_LOG.ACTIVATION.INSTALL_FAILURE, this.id]); - - deferred.reject(new Error(message)); - }; - - let listener = { - _expectedID: null, - - onDownloadEnded: install => { - this._log.trace("_installAddon() - onDownloadEnded for " + this.id); - - if (install.existingAddon) { - this._log.warn("_installAddon() - onDownloadEnded, addon already installed"); - } - - if (install.addon.type !== "experiment") { - this._log.error("_installAddon() - onDownloadEnded, wrong addon type"); - install.cancel(); - } - }, - - onInstallStarted: install => { - this._log.trace("_installAddon() - onInstallStarted for " + this.id); - - if (install.existingAddon) { - this._log.warn("_installAddon() - onInstallStarted, addon already installed"); - } - - if (install.addon.type !== "experiment") { - this._log.error("_installAddon() - onInstallStarted, wrong addon type"); - return false; - } - return undefined; - }, - - onInstallEnded: install => { - this._log.trace("_installAddon() - install ended for " + this.id); - gActiveInstallURLs.delete(install.sourceURI.spec); - - this._lastChangedDate = this._policy.now(); - this._startDate = this._policy.now(); - this._enabled = true; - - TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY, - [TELEMETRY_LOG.ACTIVATION.ACTIVATED, this.id]); - - let addon = install.addon; - this._name = addon.name; - this._addonId = addon.id; - this._description = addon.description || ""; - this._homepageURL = addon.homepageURL || ""; - - // Experiment add-ons default to userDisabled=true. Enable if needed. - if (addon.userDisabled) { - this._log.trace("Add-on is disabled. Enabling."); - listener._expectedID = addon.id; - AddonManager.addAddonListener(listener); - addon.userDisabled = false; - } else { - this._log.trace("Add-on is enabled. start() completed."); - deferred.resolve(); - } - }, - - onEnabled: addon => { - this._log.info("onEnabled() for " + addon.id); - - if (addon.id != listener._expectedID) { - return; - } - - AddonManager.removeAddonListener(listener); - deferred.resolve(); - }, - }; - - ["onDownloadCancelled", "onDownloadFailed", "onInstallCancelled", "onInstallFailed"] - .forEach(what => { - listener[what] = install => failureHandler(install, what) - }); - - install.addListener(listener); - install.install(); - - return yield deferred.promise; - }), - - /** - * Stop running the experiment if it is active. - * - * @param terminationKind (optional) - * The termination kind, e.g. ADDON_UNINSTALLED or EXPIRED. - * @param terminationReason (optional) - * The termination reason details for termination kind RECHECK. - * @return Promise<> Resolved when the operation is complete. - */ - stop: Task.async(function* (terminationKind, terminationReason) { - this._log.trace("stop() - id=" + this.id + ", terminationKind=" + terminationKind); - if (!this._enabled) { - throw new Error("Must not call stop() on an inactive experiment."); - } - - this._enabled = false; - let now = this._policy.now(); - this._lastChangedDate = now; - this._endDate = now; - - let changes = yield this.reconcileAddonState(); - this._logTermination(terminationKind, terminationReason); - - if (terminationKind == TELEMETRY_LOG.TERMINATION.ADDON_UNINSTALLED) { - changes |= this.ADDON_CHANGE_UNINSTALL; - } - - return changes; - }), - - /** - * Reconcile the state of the add-on against what it's supposed to be. - * - * If we are active, ensure the add-on is enabled and up to date. - * - * If we are inactive, ensure the add-on is not installed. - */ - reconcileAddonState: Task.async(function* () { - this._log.trace("reconcileAddonState()"); - - if (!this._enabled) { - if (!this._addonId) { - this._log.trace("reconcileAddonState() - Experiment is not enabled and " + - "has no add-on. Doing nothing."); - return this.ADDON_CHANGE_NONE; - } - - let addon = yield this._getAddon(); - if (!addon) { - this._log.trace("reconcileAddonState() - Inactive experiment has no " + - "add-on. Doing nothing."); - return this.ADDON_CHANGE_NONE; - } - - this._log.info("reconcileAddonState() - Uninstalling add-on for inactive " + - "experiment: " + addon.id); - gActiveUninstallAddonIDs.add(addon.id); - yield uninstallAddons([addon]); - gActiveUninstallAddonIDs.delete(addon.id); - return this.ADDON_CHANGE_UNINSTALL; - } - - // If we get here, we're supposed to be active. - - let changes = 0; - - // That requires an add-on. - let currentAddon = yield this._getAddon(); - - // If we have an add-on but it isn't up to date, uninstall it - // (to prepare for reinstall). - if (currentAddon && this._needsUpdate) { - this._log.info("reconcileAddonState() - Uninstalling add-on because update " + - "needed: " + currentAddon.id); - gActiveUninstallAddonIDs.add(currentAddon.id); - yield uninstallAddons([currentAddon]); - gActiveUninstallAddonIDs.delete(currentAddon.id); - changes |= this.ADDON_CHANGE_UNINSTALL; - } - - if (!currentAddon || this._needsUpdate) { - this._log.info("reconcileAddonState() - Installing add-on."); - yield this._installAddon(); - changes |= this.ADDON_CHANGE_INSTALL; - } - - let addon = yield this._getAddon(); - if (!addon) { - throw new Error("Could not obtain add-on for experiment that should be " + - "enabled."); - } - - // If we have the add-on and it is enabled, we are done. - if (!addon.userDisabled) { - return changes; - } - - // Check permissions to see if we can enable the addon. - if (!(addon.permissions & AddonManager.PERM_CAN_ENABLE)) { - throw new Error("Don't have permission to enable addon " + addon.id + ", perm=" + addon.permission); - } - - // Experiment addons should not require a restart. - if (addon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_ENABLE) { - throw new Error("Experiment addon requires a restart: " + addon.id); - } - - let deferred = Promise.defer(); - - // Else we need to enable it. - let listener = { - onEnabled: enabledAddon => { - if (enabledAddon.id != addon.id) { - return; - } - - AddonManager.removeAddonListener(listener); - deferred.resolve(); - }, - }; - - for (let handler of ["onDisabled", "onOperationCancelled", "onUninstalled"]) { - listener[handler] = (evtAddon) => { - if (evtAddon.id != addon.id) { - return; - } - - AddonManager.removeAddonListener(listener); - deferred.reject("Failed to enable addon " + addon.id + " due to: " + handler); - }; - } - - this._log.info("reconcileAddonState() - Activating add-on: " + addon.id); - AddonManager.addAddonListener(listener); - addon.userDisabled = false; - yield deferred.promise; - changes |= this.ADDON_CHANGE_ENABLE; - - this._log.info("reconcileAddonState() - Add-on has been enabled: " + addon.id); - return changes; - }), - - /** - * Obtain the underlying Addon from the Addon Manager. - * - * @return Promise<Addon|null> - */ - _getAddon: function () { - if (!this._addonId) { - return Promise.resolve(null); - } - - let deferred = Promise.defer(); - - AddonManager.getAddonByID(this._addonId, (addon) => { - if (addon && addon.appDisabled) { - // Don't return PreviousExperiments. - addon = null; - } - - deferred.resolve(addon); - }); - - return deferred.promise; - }, - - _logTermination: function (terminationKind, terminationReason) { - if (terminationKind === undefined) { - return; - } - - if (!(terminationKind in TELEMETRY_LOG.TERMINATION)) { - this._log.warn("stop() - unknown terminationKind " + terminationKind); - return; - } - - let data = [terminationKind, this.id]; - if (terminationReason) { - data = data.concat(terminationReason); - } - - TelemetryLog.log(TELEMETRY_LOG.TERMINATION_KEY, data); - }, - - /** - * Determine whether an active experiment should be stopped. - */ - shouldStop: function () { - if (!this._enabled) { - throw new Error("shouldStop must not be called on disabled experiments."); - } - - let deferred = Promise.defer(); - this.isApplicable().then( - () => deferred.resolve({shouldStop: false}), - reason => deferred.resolve({shouldStop: true, reason: reason}) - ); - - return deferred.promise; - }, - - /* - * Should this be discarded from the cache due to age? - */ - shouldDiscard: function () { - let limit = this._policy.now(); - limit.setDate(limit.getDate() - KEEP_HISTORY_N_DAYS); - return (this._lastChangedDate < limit); - }, - - /* - * Get next date (in epoch-ms) to schedule a re-evaluation for this. - * Returns 0 if it doesn't need one. - */ - getScheduleTime: function () { - if (this._enabled) { - let startTime = this._startDate.getTime(); - let maxActiveTime = startTime + 1000 * this._manifestData.maxActiveSeconds; - return Math.min(1000 * this._manifestData.endTime, maxActiveTime); - } - - if (this._endDate) { - return this._endDate.getTime(); - } - - return 1000 * this._manifestData.startTime; - }, - - /* - * Perform sanity checks on the experiment data. - */ - _isManifestDataValid: function (data) { - this._log.trace("isManifestDataValid() - data: " + JSON.stringify(data)); - - for (let key of this.MANIFEST_REQUIRED_FIELDS) { - if (!(key in data)) { - this._log.error("isManifestDataValid() - missing required key: " + key); - return false; - } - } - - for (let key in data) { - if (!this.MANIFEST_OPTIONAL_FIELDS.has(key) && - !this.MANIFEST_REQUIRED_FIELDS.has(key)) { - this._log.error("isManifestDataValid() - unknown key: " + key); - return false; - } - } - - return true; - }, -}; - -/** - * Strip a Date down to its UTC midnight. - * - * This will return a cloned Date object. The original is unchanged. - */ -var stripDateToMidnight = function (d) { - let m = new Date(d); - m.setUTCHours(0, 0, 0, 0); - - return m; -}; - -/** - * An Add-ons Manager provider that knows about old experiments. - * - * This provider exposes read-only add-ons corresponding to previously-active - * experiments. The existence of this provider (and the add-ons it knows about) - * facilitates the display of old experiments in the Add-ons Manager UI with - * very little custom code in that component. - */ -this.Experiments.PreviousExperimentProvider = function (experiments) { - this._experiments = experiments; - this._experimentList = []; - this._log = Log.repository.getLoggerWithMessagePrefix( - "Browser.Experiments.Experiments", - "PreviousExperimentProvider #" + gPreviousProviderCounter++ + "::"); -} - -this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({ - name: "PreviousExperimentProvider", - - startup: function () { - this._log.trace("startup()"); - Services.obs.addObserver(this, EXPERIMENTS_CHANGED_TOPIC, false); - }, - - shutdown: function () { - this._log.trace("shutdown()"); - try { - Services.obs.removeObserver(this, EXPERIMENTS_CHANGED_TOPIC); - } catch (e) { - // Prevent crash in mochitest-browser3 on Mulet - } - }, - - observe: function (subject, topic, data) { - switch (topic) { - case EXPERIMENTS_CHANGED_TOPIC: - this._updateExperimentList(); - break; - } - }, - - getAddonByID: function (id, cb) { - for (let experiment of this._experimentList) { - if (experiment.id == id) { - cb(new PreviousExperimentAddon(experiment)); - return; - } - } - - cb(null); - }, - - getAddonsByTypes: function (types, cb) { - if (types && types.length > 0 && types.indexOf("experiment") == -1) { - cb([]); - return; - } - - cb(this._experimentList.map(e => new PreviousExperimentAddon(e))); - }, - - _updateExperimentList: function () { - return this._experiments.getExperiments().then((experiments) => { - let list = experiments.filter(e => !e.active); - - let newMap = new Map(list.map(e => [e.id, e])); - let oldMap = new Map(this._experimentList.map(e => [e.id, e])); - - let added = [...newMap.keys()].filter(id => !oldMap.has(id)); - let removed = [...oldMap.keys()].filter(id => !newMap.has(id)); - - for (let id of added) { - this._log.trace("updateExperimentList() - adding " + id); - let wrapper = new PreviousExperimentAddon(newMap.get(id)); - AddonManagerPrivate.callInstallListeners("onExternalInstall", null, wrapper, null, false); - AddonManagerPrivate.callAddonListeners("onInstalling", wrapper, false); - } - - for (let id of removed) { - this._log.trace("updateExperimentList() - removing " + id); - let wrapper = new PreviousExperimentAddon(oldMap.get(id)); - AddonManagerPrivate.callAddonListeners("onUninstalling", wrapper, false); - } - - this._experimentList = list; - - for (let id of added) { - let wrapper = new PreviousExperimentAddon(newMap.get(id)); - AddonManagerPrivate.callAddonListeners("onInstalled", wrapper); - } - - for (let id of removed) { - let wrapper = new PreviousExperimentAddon(oldMap.get(id)); - AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper); - } - - return this._experimentList; - }); - }, -}); - -/** - * An add-on that represents a previously-installed experiment. - */ -function PreviousExperimentAddon(experiment) { - this._id = experiment.id; - this._name = experiment.name; - this._endDate = experiment.endDate; - this._description = experiment.description; -} - -PreviousExperimentAddon.prototype = Object.freeze({ - // BEGIN REQUIRED ADDON PROPERTIES - - get appDisabled() { - return true; - }, - - get blocklistState() { - Ci.nsIBlocklistService.STATE_NOT_BLOCKED - }, - - get creator() { - return new AddonManagerPrivate.AddonAuthor(""); - }, - - get foreignInstall() { - return false; - }, - - get id() { - return this._id; - }, - - get isActive() { - return false; - }, - - get isCompatible() { - return true; - }, - - get isPlatformCompatible() { - return true; - }, - - get name() { - return this._name; - }, - - get pendingOperations() { - return AddonManager.PENDING_NONE; - }, - - get permissions() { - return 0; - }, - - get providesUpdatesSecurely() { - return true; - }, - - get scope() { - return AddonManager.SCOPE_PROFILE; - }, - - get type() { - return "experiment"; - }, - - get userDisabled() { - return true; - }, - - get version() { - return null; - }, - - // END REQUIRED PROPERTIES - - // BEGIN OPTIONAL PROPERTIES - - get description() { - return this._description; - }, - - get updateDate() { - return new Date(this._endDate); - }, - - // END OPTIONAL PROPERTIES - - // BEGIN REQUIRED METHODS - - isCompatibleWith: function (appVersion, platformVersion) { - return true; - }, - - findUpdates: function (listener, reason, appVersion, platformVersion) { - AddonManagerPrivate.callNoUpdateListeners(this, listener, reason, - appVersion, platformVersion); - }, - - // END REQUIRED METHODS - - /** - * The end-date of the experiment, required for the Addon Manager UI. - */ - - get endDate() { - return this._endDate; - }, - -}); diff --git a/browser/experiments/Experiments.manifest b/browser/experiments/Experiments.manifest deleted file mode 100644 index 4a6a05a60..000000000 --- a/browser/experiments/Experiments.manifest +++ /dev/null @@ -1,6 +0,0 @@ -component {f7800463-3b97-47f9-9341-b7617e6d8d49} ExperimentsService.js -contract @mozilla.org/browser/experiments-service;1 {f7800463-3b97-47f9-9341-b7617e6d8d49} -category update-timer ExperimentsService @mozilla.org/browser/experiments-service;1,getService,experiments-update-timer,experiments.manifest.fetchIntervalSeconds,86400 -category profile-after-change ExperimentsService @mozilla.org/browser/experiments-service;1 - - diff --git a/browser/experiments/ExperimentsService.js b/browser/experiments/ExperimentsService.js deleted file mode 100644 index 53e811251..000000000 --- a/browser/experiments/ExperimentsService.js +++ /dev/null @@ -1,118 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const {interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "Experiments", - "resource:///modules/experiments/Experiments.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", - "resource://services-common/utils.js"); - -const PREF_EXPERIMENTS_ENABLED = "experiments.enabled"; -const PREF_ACTIVE_EXPERIMENT = "experiments.activeExperiment"; // whether we have an active experiment -const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled"; -const PREF_TELEMETRY_UNIFIED = "toolkit.telemetry.unified"; -const DELAY_INIT_MS = 30 * 1000; - -// Whether the FHR/Telemetry unification features are enabled. -// Changing this pref requires a restart. -const IS_UNIFIED_TELEMETRY = Preferences.get(PREF_TELEMETRY_UNIFIED, false); - -XPCOMUtils.defineLazyGetter( - this, "gPrefs", () => { - return new Preferences(); - }); - -XPCOMUtils.defineLazyGetter( - this, "gExperimentsEnabled", () => { - // We can enable experiments if either unified Telemetry or FHR is on, and the user - // has opted into Telemetry. - return gPrefs.get(PREF_EXPERIMENTS_ENABLED, false) && - IS_UNIFIED_TELEMETRY && gPrefs.get(PREF_TELEMETRY_ENABLED, false); - }); - -XPCOMUtils.defineLazyGetter( - this, "gActiveExperiment", () => { - return gPrefs.get(PREF_ACTIVE_EXPERIMENT); - }); - -function ExperimentsService() { - this._initialized = false; - this._delayedInitTimer = null; -} - -ExperimentsService.prototype = { - classID: Components.ID("{f7800463-3b97-47f9-9341-b7617e6d8d49}"), - QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsIObserver]), - - notify: function (timer) { - if (!gExperimentsEnabled) { - return; - } - if (OS.Constants.Path.profileDir === undefined) { - throw Error("Update timer fired before profile was initialized?"); - } - let instance = Experiments.instance(); - if (instance.isReady) { - instance.updateManifest(); - } - }, - - _delayedInit: function () { - if (!this._initialized) { - this._initialized = true; - Experiments.instance(); // for side effects - } - }, - - observe: function (subject, topic, data) { - switch (topic) { - case "profile-after-change": - if (gExperimentsEnabled) { - Services.obs.addObserver(this, "quit-application", false); - Services.obs.addObserver(this, "sessionstore-state-finalized", false); - Services.obs.addObserver(this, "EM-loaded", false); - - if (gActiveExperiment) { - this._initialized = true; - Experiments.instance(); // for side effects - } - } - break; - case "sessionstore-state-finalized": - if (!this._initialized) { - CommonUtils.namedTimer(this._delayedInit, DELAY_INIT_MS, this, "_delayedInitTimer"); - } - break; - case "EM-loaded": - if (!this._initialized) { - Experiments.instance(); // for side effects - this._initialized = true; - - if (this._delayedInitTimer) { - this._delayedInitTimer.clear(); - } - } - break; - case "quit-application": - Services.obs.removeObserver(this, "quit-application"); - Services.obs.removeObserver(this, "sessionstore-state-finalized"); - Services.obs.removeObserver(this, "EM-loaded"); - if (this._delayedInitTimer) { - this._delayedInitTimer.clear(); - } - break; - } - }, -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ExperimentsService]); diff --git a/browser/experiments/Makefile.in b/browser/experiments/Makefile.in deleted file mode 100644 index 5558582a6..000000000 --- a/browser/experiments/Makefile.in +++ /dev/null @@ -1,16 +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/. - -include $(topsrcdir)/config/rules.mk - -# This is so hacky. Waiting on bug 988938. -addondir = $(srcdir)/test/addons -testdir = $(topobjdir)/_tests/xpcshell/browser/experiments/test/xpcshell - -misc:: $(call mkdir_deps,$(testdir)) - $(EXIT_ON_ERROR) \ - for dir in $(addondir)/*; do \ - base=`basename $$dir`; \ - (cd $$dir && zip -qr $(testdir)/$$base.xpi *); \ - done diff --git a/browser/experiments/docs/index.rst b/browser/experiments/docs/index.rst deleted file mode 100644 index 11e5d4faa..000000000 --- a/browser/experiments/docs/index.rst +++ /dev/null @@ -1,13 +0,0 @@ -===================== -Telemetry Experiments -===================== - -Telemetry Experiments is a feature of Firefox that allows the installation -of add-ons called experiments to a subset of the Firefox population for -the purposes of experimenting with changes and collecting data on specific -aspects of application usage. - -.. toctree:: - :maxdepth: 1 - - manifest diff --git a/browser/experiments/docs/manifest.rst b/browser/experiments/docs/manifest.rst deleted file mode 100644 index d4fad5243..000000000 --- a/browser/experiments/docs/manifest.rst +++ /dev/null @@ -1,429 +0,0 @@ -.. _experiments_manifests: - -===================== -Experiments Manifests -===================== - -*Experiments Manifests* are documents that describe the set of active -experiments a client may run. - -*Experiments Manifests* are fetched periodically by clients. When -fetched, clients look at the experiments within the manifest and -determine which experiments are applicable. If an experiment is -applicable, the client may download and start the experiment. - -Manifest Format -=============== - -Manifests are JSON documents where the main element is an object. - -The *schema* of the object is versioned and defined by the presence -of a top-level ``version`` property, whose integer value is the -schema version used by that manifest. Each version is documented -in the sections below. - -Version 1 ---------- - -Version 1 is the original manifest format. - -The following properties may exist in the root object: - -experiments - An array of objects describing candidate experiments. The format of - these objects is documented below. - - An array is used to create an explicit priority of experiments. - Experiments listed at the beginning of the array take priority over - experiments that follow. - -Experiments Objects -^^^^^^^^^^^^^^^^^^^ - -Each object in the ``experiments`` array may contain the following -properties: - -id - (required) String identifier of this experiment. The identifier should - be treated as opaque by clients. It is used to uniquely identify an - experiment for all of time. - -xpiURL - (required) String URL of the XPI that implements this experiment. - - If the experiment is activated, the client will download and install this - XPI. - -xpiHash - (required) String hash of the XPI that implements this experiment. - - The value is composed of a hash identifier followed by a colon - followed by the hash value. e.g. - `sha1:f677428b9172e22e9911039aef03f3736e7f78a7`. `sha1` and `sha256` - are the two supported hashing mechanisms. The hash value is the hex - encoding of the binary hash. - - When the client downloads the XPI for the experiment, it should compare - the hash of that XPI against this value. If the hashes don't match, - the client should not install the XPI. - - Clients may also use this hash as a means of determining when an - experiment's XPI has changed and should be refreshed. - -startTime - Integer seconds since UNIX epoch that this experiment should - start. Clients should not start an experiment if *now()* is less than - this value. - -maxStartTime - (optional) Integer seconds since UNIX epoch after which this experiment - should no longer start. - - Some experiments may wish to impose hard deadlines after which no new - clients should activate the experiment. This property may be used to - facilitate that. - -endTime - Integer seconds since UNIX epoch after which this experiment - should no longer run. Clients should cease an experiment when the current - time is beyond this value. - -maxActiveSeconds - Integer seconds defining the max wall time this experiment should be - active for. - - The client should deactivate the experiment this many seconds after - initial activation. - - This value only involves wall time, not browser activity or session time. - -appName - Array of application names this experiment should run on. - - An application name comes from ``nsIXULAppInfo.name``. It is a value - like ``Firefox``, ``Fennec``, or `B2G`. - - The client should compare its application name against the members of - this array. If a match is found, the experiment is applicable. - -minVersion - (optional) String version number of the minimum application version this - experiment should run on. - - A version number is something like ``27.0.0`` or ``28``. - - The client should compare its version number to this value. If the client's - version is greater or equal to this version (using a version-aware comparison - function), the experiment is applicable. - - If this is not specified, there is no lower bound to versions this - experiment should run on. - -maxVersion - (optional) String version number of the maximum application version this - experiment should run on. - - This is similar to ``minVersion`` except it sets the upper bound for - application versions. - - If the client's version is less than or equal to this version, the - experiment is applicable. - - If this is not specified, there is no upper bound to versions this - experiment should run on. - -version - (optional) Array of application versions this experiment should run on. - - This is similar to ``minVersion`` and ``maxVersion`` except only a - whitelisted set of specific versions are allowed. - - The client should compare its version to members of this array. If a match - is found, the experiment is applicable. - -minBuildID - (optional) String minimum Build ID this experiment should run on. - - Build IDs are values like ``201402261424``. - - The client should perform a string comparison of its Build ID against this - value. If its value is greater than or equal to this value, the experiment - is applicable. - -maxBuildID - (optional) String maximum Build ID this experiment should run on. - - This is similar to ``minBuildID`` except it sets the upper bound - for Build IDs. - - The client should perform a string comparison of its Build ID against - this value. If its value is less than or equal to this value, the - experiment is applicable. - -buildIDs - (optional) Array of Build IDs this experiment should run on. - - This is similar to ``minBuildID`` and ``maxBuildID`` except only a - whitelisted set of Build IDs are considered. - - The client should compare its Build ID to members of this array. If a - match is found, the experiment is applicable. - -os - (optional) Array of operating system identifiers this experiment should - run on. - - Values for this array come from ``nsIXULRuntime.OS``. - - The client will compare its operating system identifier to members - of this array. If a match is found, the experiment is applicable to the - client. - -channel - (optional) Array of release channel identifiers this experiment should run - on. - - The client will compare its channel to members of this array. If a match - is found, the experiment is applicable. - - If this property is not defined, the client should assume the experiment - is to run on all channels. - -locale - (optional) Array of locale identifiers this experiment should run on. - - A locale identifier is a string like ``en-US`` or ``zh-CN`` and is - obtained by looking at - ``nsIXULChromeRegistry.getSelectedLocale("global")``. - - The client should compare its locale identifier to members of this array. - If a match is found, the experiment is applicable. - - If this property is not defined, the client should assume the experiment - is to run on all locales. - -sample - (optional) Decimal number indicating the sampling rate for this experiment. - - This will contain a value between ``0.0`` and ``1.0``. The client should - generate a random decimal between ``0.0`` and ``1.0``. If the randomly - generated number is less than or equal to the value of this field, the - experiment is applicable. - -disabled - (optional) Boolean value indicating whether an experiment is disabled. - - Normally, experiments are deactivated after a certain time has passed or - after the experiment itself determines it no longer needs to run (perhaps - it collected sufficient data already). - - This property serves as a backup mechanism to remotely disable an - experiment before it was scheduled to be disabled. It can be used to - kill experiments that are found to be doing wrong or bad things or that - aren't useful. - - If this property is not defined or is false, the client should assume - the experiment is active and a candidate for activation. - -frozen - (optional) Boolean value indicating this experiment is frozen and no - longer accepting new enrollments. - - If a client sees a true value in this field, it should not attempt to - activate an experiment. - -jsfilter - (optional) JavaScript code that will be evaluated to determine experiment - applicability. - - This property contains the string representation of JavaScript code that - will be evaluated in a sandboxed environment using JavaScript's - ``eval()``. - - The string is expected to contain the definition of a JavaScript function - ``filter(context)``. This function receives as its argument an object - holding application state. See the section below for the definition of - this object. - - The purpose of this property is to allow experiments to define complex - rules and logic for evaluating experiment applicability in a manner - that is privacy conscious and doesn't require the transmission of - excessive data. - - The return value of this filter indicates whether the experiment is - applicable. Functions should return true if the experiment is - applicable. - - If an experiment is not applicable, they should throw an Error whose - message contains the reason the experiment is not applicable. This - message may be logged and sent to remote servers, so it should not - contain private or otherwise sensitive data that wouldn't normally - be submitted. - - If a falsey (or undefined) value is returned, the client should - assume the experiment is not applicable. - - If this property is not defined, the client does not consider a custom - JavaScript filter function when determining whether an experiment is - applicable. - -JavaScript Filter Context Objects -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The object passed to a ``jsfilter`` ``filter()`` function contains the -following properties: - -healthReportSubmissionEnabled - This property contains a boolean indicating whether Firefox Health - Report has its data submission flag enabled (whether Firefox Health - Report is sending data to remote servers). - -healthReportPayload - This property contains the current Firefox Health Report payload. - - The payload format is documented at :ref:`healthreport_dataformat`. - -telemetryPayload - This property contains the current Telemetry payload. - -The evaluation sandbox for the JavaScript filters may be destroyed -immediately after ``filter()`` returns. This function should not assume -async code will finish. - -Experiment Applicability and Client Behavior -============================================ - -The point of an experiment manifest is to define which experiments are -available and where and how to run them. This section explains those -rules in more detail. - -Many of the properties in *Experiment Objects* are related to determining -whether an experiment should run on a given client. This evaluation is -performed client side. - -1. Multiple conditions in an experiment ---------------------------------------- - -If multiple conditions are defined for an experiment, the client should -combine each condition with a logical *AND*: all conditions must be -satisfied for an experiment to run. If one condition fails, the experiment -is not applicable. - -2. Active experiment disappears from manifest ---------------------------------------------- - -If a specific experiment disappears from the manifest, the client should -continue conducting an already-active experiment. Furthermore, the -client should remember what the expiration events were for an experiment -and honor them. - -The rationale here is that we want to prevent an accidental deletion -or temporary failure on the server to inadvertantly deactivate -supposed-to-be-active experiments. We also don't want premature deletion -of an experiment from the manifest to result in indefinite activation -periods. - -3. Inactive experiment disappears from manifest ------------------------------------------------ - -If an inactive but scheduled-to-be-active experiment disappears from the -manifest, the client should not activate the experiment. - -If that experiment reappears in the manifest, the client should not -treat that experiment any differently than any other new experiment. Put -another way, the fact an inactive experiment disappears and then -reappears should not be significant. - -The rationale here is that server operators should have complete -control of an inactive experiment up to it's go-live date. - -4. Re-evaluating applicability on manifest refresh --------------------------------------------------- - -When an experiment manifest is refreshed or updated, the client should -re-evaluate the applicability of each experiment therein. - -The rationale here is that the server may change the parameters of an -experiment and want clients to pick those up. - -5. Activating a previously non-applicable experiment ----------------------------------------------------- - -If the conditions of an experiment change or the state of the client -changes to allow an experiment to transition from previously -non-applicable to applicable, the experiment should be activated. - -For example, if a client is running version 28 and the experiment -initially requires version 29 or above, the client will not mark the -experiment as applicable. But if the client upgrades to version 29 or if -the manifest is updated to require 28 or above, the experiment will -become applicable. - -6. Deactivating a previously active experiment ----------------------------------------------- - -If the conditions of an experiment change or the state of the client -changes and an active experiment is no longer applicable, that -experiment should be deactivated. - -7. Calculation of sampling-based applicability ----------------------------------------------- - -For calculating sampling-based applicability, the client will associate -a random value between ``0.0`` and ``1.0`` for each observed experiment -ID. This random value will be generated the first time sampling -applicability is evaluated. This random value will be persisted and used -in future applicability evaluations for this experiment. - -By saving and re-using the value, the client is able to reliably and -consistently evaluate applicability, even if the sampling threshold -in the manifest changes. - -Clients should retain the randomly-generated sampling value for -experiments that no longer appear in a manifest for a period of at least -30 days. The rationale is that if an experiment disappears and reappears -from a manifest, the client will not have multiple opportunities to -generate a random value that satisfies the sampling criteria. - -8. Incompatible version numbers -------------------------------- - -If a client receives a manifest with a version number that it doesn't -recognize, it should ignore the manifest. - -9. Usage of old manifests -------------------------- - -If a client experiences an error fetching a manifest (server not -available) or if the manifest is corrupt, not readable, or compatible, -the client may use a previously-fetched (cached) manifest. - -10. Updating XPIs ------------------ - -If the URL or hash of an active experiment's XPI changes, the client -should fetch the new XPI, uninstall the old XPI, and install the new -XPI. - -Examples -======== - -Here is an example manifest:: - - { - "version": 1, - "experiments": [ - { - "id": "da9d7f4f-f3f9-4f81-bacd-6f0626ffa360", - "xpiURL": "https://experiments.mozilla.org/foo.xpi", - "xpiHash": "sha1:cb1eb32b89d86d78b7326f416cf404548c5e0099", - "startTime": 1393000000, - "endTime": 1394000000, - "appName": ["Firefox", "Fennec"], - "minVersion": "28", - "maxVersion": "30", - "os": ["windows", "linux", "osx"], - "jsfilter": "function filter(context) { return context.healthReportEnabled; }" - } - ] - } diff --git a/browser/experiments/moz.build b/browser/experiments/moz.build deleted file mode 100644 index a11e4b725..000000000 --- a/browser/experiments/moz.build +++ /dev/null @@ -1,18 +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/. - -HAS_MISC_RULE = True - -EXTRA_COMPONENTS += [ - 'Experiments.manifest', - 'ExperimentsService.js', -] - -EXTRA_JS_MODULES.experiments += [ - 'Experiments.jsm', -] - -XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini'] - -SPHINX_TREES['experiments'] = 'docs' diff --git a/browser/experiments/test/addons/experiment-1/install.rdf b/browser/experiments/test/addons/experiment-1/install.rdf deleted file mode 100644 index f9d70054a..000000000 --- a/browser/experiments/test/addons/experiment-1/install.rdf +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test-experiment-1@tests.mozilla.org</em:id> - <em:version>1</em:version> - <em:type>128</em:type> - - <!-- Front End MetaData --> - <em:name>Test experiment 1</em:name> - <em:description>Yet another experiment that experiments experimentally.</em:description> - - </Description> -</RDF> diff --git a/browser/experiments/test/addons/experiment-1a/install.rdf b/browser/experiments/test/addons/experiment-1a/install.rdf deleted file mode 100644 index 7806b11b1..000000000 --- a/browser/experiments/test/addons/experiment-1a/install.rdf +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test-experiment-1@tests.mozilla.org</em:id> - <em:version>1.1</em:version> - <em:type>128</em:type> - - <!-- Front End MetaData --> - <em:name>Test experiment 1.1</em:name> - <em:description>And yet another experiment that experiments experimentally.</em:description> - - </Description> -</RDF> diff --git a/browser/experiments/test/addons/experiment-2/install.rdf b/browser/experiments/test/addons/experiment-2/install.rdf deleted file mode 100644 index 69122c0ef..000000000 --- a/browser/experiments/test/addons/experiment-2/install.rdf +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - - <Description about="urn:mozilla:install-manifest"> - <em:id>test-experiment-2@tests.mozilla.org</em:id> - <em:version>1</em:version> - <em:type>128</em:type> - - <!-- Front End MetaData --> - <em:name>Test experiment 2</em:name> - <em:description>And yet another experiment that experiments experimentally.</em:description> - - </Description> -</RDF> diff --git a/browser/experiments/test/addons/experiment-racybranch/bootstrap.js b/browser/experiments/test/addons/experiment-racybranch/bootstrap.js deleted file mode 100644 index e8278f50f..000000000 --- a/browser/experiments/test/addons/experiment-racybranch/bootstrap.js +++ /dev/null @@ -1,35 +0,0 @@ -/* exported startup, shutdown, install, uninstall */ - -var {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource:///modules/experiments/Experiments.jsm"); - -var gStarted = false; - -function startup(data, reasonCode) { - if (gStarted) { - return; - } - gStarted = true; - - // delay realstartup to trigger the race condition - Cc['@mozilla.org/thread-manager;1'].getService(Ci.nsIThreadManager) - .mainThread.dispatch(realstartup, 0); -} - -function realstartup() { - let experiments = Experiments.instance(); - let experiment = experiments._getActiveExperiment(); - if (experiment.branch) { - Cu.reportError("Found pre-existing branch: " + experiment.branch); - return; - } - - let branch = "racy-set"; - experiments.setExperimentBranch(experiment.id, branch) - .then(null, Cu.reportError); -} - -function shutdown() { } -function install() { } -function uninstall() { } diff --git a/browser/experiments/test/addons/experiment-racybranch/install.rdf b/browser/experiments/test/addons/experiment-racybranch/install.rdf deleted file mode 100644 index cebaede56..000000000 --- a/browser/experiments/test/addons/experiment-racybranch/install.rdf +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
- <Description about="urn:mozilla:install-manifest">
- <em:id>test-experiment-racybranch@tests.mozilla.org</em:id>
- <em:version>1</em:version>
- <em:type>128</em:type>
-
- <!-- Front End MetaData -->
- <em:name>Test experiment racybranch</em:name>
- <em:description>An experiment that sets the experiment branch in a potentially racy way.</em:description>
-
- </Description>
-</RDF>
diff --git a/browser/experiments/test/xpcshell/.eslintrc.js b/browser/experiments/test/xpcshell/.eslintrc.js deleted file mode 100644 index 1f540a05b..000000000 --- a/browser/experiments/test/xpcshell/.eslintrc.js +++ /dev/null @@ -1,15 +0,0 @@ -"use strict"; - -module.exports = { - "extends": [ - "../../../../testing/xpcshell/xpcshell.eslintrc.js" - ], - - "rules": { - "no-unused-vars": ["error", { - "vars": "all", - "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$", - "args": "none" - }] - } -}; diff --git a/browser/experiments/test/xpcshell/experiments_1.manifest b/browser/experiments/test/xpcshell/experiments_1.manifest deleted file mode 100644 index 0401ea328..000000000 --- a/browser/experiments/test/xpcshell/experiments_1.manifest +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": 1, - "experiments": [ - { - "id": "test-experiment-1@tests.mozilla.org", - "xpiURL": "https://experiments.mozilla.org/foo.xpi", - "xpiHash": "sha1:cb1eb32b89d86d78b7326f416cf404548c5e0099", - "startTime": 1393000000, - "endTime": 1394000000, - "appName": ["Firefox", "Fennec"], - "minVersion": "28", - "maxVersion": "30", - "maxActiveSeconds": 60, - "os": ["windows", "linux", "osx"], - "channel": ["daily", "weekly", "nightly"], - "jsfilter": "function filter(context) { return true; }" - } - ] -} diff --git a/browser/experiments/test/xpcshell/head.js b/browser/experiments/test/xpcshell/head.js deleted file mode 100644 index ae356ea2d..000000000 --- a/browser/experiments/test/xpcshell/head.js +++ /dev/null @@ -1,199 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/* exported PREF_EXPERIMENTS_ENABLED, PREF_LOGGING_LEVEL, PREF_LOGGING_DUMP - PREF_MANIFEST_URI, PREF_FETCHINTERVAL, EXPERIMENT1_ID, - EXPERIMENT1_NAME, EXPERIMENT1_XPI_SHA1, EXPERIMENT1A_NAME, - EXPERIMENT1A_XPI_SHA1, EXPERIMENT2_ID, EXPERIMENT2_XPI_SHA1, - EXPERIMENT3_ID, EXPERIMENT4_ID, FAKE_EXPERIMENTS_1, - FAKE_EXPERIMENTS_2, gAppInfo, removeCacheFile, defineNow, - futureDate, dateToSeconds, loadAddonManager, promiseRestartManager, - startAddonManagerOnly, getExperimentAddons, replaceExperiments */ - -var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); -Cu.import("resource://testing-common/AddonManagerTesting.jsm"); -Cu.import("resource://testing-common/AddonTestUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", - "resource://gre/modules/AddonManager.jsm"); - -const PREF_EXPERIMENTS_ENABLED = "experiments.enabled"; -const PREF_LOGGING_LEVEL = "experiments.logging.level"; -const PREF_LOGGING_DUMP = "experiments.logging.dump"; -const PREF_MANIFEST_URI = "experiments.manifest.uri"; -const PREF_FETCHINTERVAL = "experiments.manifest.fetchIntervalSeconds"; -const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled"; - -function getExperimentPath(base) { - let p = do_get_cwd(); - p.append(base); - return p.path; -} - -function sha1File(path) { - let f = Cc["@mozilla.org/file/local;1"] - .createInstance(Ci.nsILocalFile); - f.initWithPath(path); - let hasher = Cc["@mozilla.org/security/hash;1"] - .createInstance(Ci.nsICryptoHash); - hasher.init(hasher.SHA1); - - let is = Cc["@mozilla.org/network/file-input-stream;1"] - .createInstance(Ci.nsIFileInputStream); - is.init(f, -1, 0, 0); - hasher.updateFromStream(is, Math.pow(2, 32) - 1); - is.close(); - let bytes = hasher.finish(false); - - let rv = ""; - for (let i = 0; i < bytes.length; i++) { - rv += ("0" + bytes.charCodeAt(i).toString(16)).substr(-2); - } - return rv; -} - -const EXPERIMENT1_ID = "test-experiment-1@tests.mozilla.org"; -const EXPERIMENT1_XPI_NAME = "experiment-1.xpi"; -const EXPERIMENT1_NAME = "Test experiment 1"; -const EXPERIMENT1_PATH = getExperimentPath(EXPERIMENT1_XPI_NAME); -const EXPERIMENT1_XPI_SHA1 = "sha1:" + sha1File(EXPERIMENT1_PATH); - - -const EXPERIMENT1A_XPI_NAME = "experiment-1a.xpi"; -const EXPERIMENT1A_NAME = "Test experiment 1.1"; -const EXPERIMENT1A_PATH = getExperimentPath(EXPERIMENT1A_XPI_NAME); -const EXPERIMENT1A_XPI_SHA1 = "sha1:" + sha1File(EXPERIMENT1A_PATH); - -const EXPERIMENT2_ID = "test-experiment-2@tests.mozilla.org" -const EXPERIMENT2_XPI_NAME = "experiment-2.xpi"; -const EXPERIMENT2_PATH = getExperimentPath(EXPERIMENT2_XPI_NAME); -const EXPERIMENT2_XPI_SHA1 = "sha1:" + sha1File(EXPERIMENT2_PATH); - -const EXPERIMENT3_ID = "test-experiment-3@tests.mozilla.org"; -const EXPERIMENT4_ID = "test-experiment-4@tests.mozilla.org"; - -const FAKE_EXPERIMENTS_1 = [ - { - id: "id1", - name: "experiment1", - description: "experiment 1", - active: true, - detailUrl: "https://dummy/experiment1", - branch: "foo", - }, -]; - -const FAKE_EXPERIMENTS_2 = [ - { - id: "id2", - name: "experiment2", - description: "experiment 2", - active: false, - endDate: new Date(2014, 2, 11, 2, 4, 35, 42).getTime(), - detailUrl: "https://dummy/experiment2", - branch: null, - }, - { - id: "id1", - name: "experiment1", - description: "experiment 1", - active: false, - endDate: new Date(2014, 2, 10, 0, 0, 0, 0).getTime(), - detailURL: "https://dummy/experiment1", - branch: null, - }, -]; - -var gAppInfo = null; - -function removeCacheFile() { - let path = OS.Path.join(OS.Constants.Path.profileDir, "experiments.json"); - return OS.File.remove(path); -} - -function patchPolicy(policy, data) { - for (let key of Object.keys(data)) { - Object.defineProperty(policy, key, { - value: data[key], - writable: true, - }); - } -} - -function defineNow(policy, time) { - patchPolicy(policy, { now: () => new Date(time) }); -} - -function futureDate(date, offset) { - return new Date(date.getTime() + offset); -} - -function dateToSeconds(date) { - return date.getTime() / 1000; -} - -var gGlobalScope = this; -function loadAddonManager() { - AddonTestUtils.init(gGlobalScope); - AddonTestUtils.overrideCertDB(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - return AddonTestUtils.promiseStartupManager(); -} - -const { - promiseRestartManager, -} = AddonTestUtils; - -// Starts the addon manager without creating app info. We can't directly use -// |loadAddonManager| defined above in test_conditions.js as it would make the test fail. -function startAddonManagerOnly() { - let addonManager = Cc["@mozilla.org/addons/integration;1"] - .getService(Ci.nsIObserver) - .QueryInterface(Ci.nsITimerCallback); - addonManager.observe(null, "addons-startup", null); -} - -function getExperimentAddons(previous=false) { - let deferred = Promise.defer(); - - AddonManager.getAddonsByTypes(["experiment"], (addons) => { - if (previous) { - deferred.resolve(addons); - } else { - deferred.resolve(addons.filter(a => !a.appDisabled)); - } - }); - - return deferred.promise; -} - -function createAppInfo(ID="xpcshell@tests.mozilla.org", name="XPCShell", - version="1.0", platformVersion="1.0") { - AddonTestUtils.createAppInfo(ID, name, version, platformVersion); - gAppInfo = AddonTestUtils.appInfo; -} - -/** - * Replace the experiments on an Experiments with a new list. - * - * This monkeypatches getExperiments(). It doesn't monkeypatch the internal - * experiments list. So its utility is not as great as it could be. - */ -function replaceExperiments(experiment, list) { - Object.defineProperty(experiment, "getExperiments", { - writable: true, - value: () => { - return Promise.resolve(list); - }, - }); -} - -// Experiments require Telemetry to be enabled, and that's not true for debug -// builds. Let's just enable it here instead of going through each test. -Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, true); diff --git a/browser/experiments/test/xpcshell/test_activate.js b/browser/experiments/test/xpcshell/test_activate.js deleted file mode 100644 index 60deafbfb..000000000 --- a/browser/experiments/test/xpcshell/test_activate.js +++ /dev/null @@ -1,151 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource:///modules/experiments/Experiments.jsm"); - -const SEC_IN_ONE_DAY = 24 * 60 * 60; -const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; - -var gHttpServer = null; -var gHttpRoot = null; -var gPolicy = null; - -function ManifestEntry(data) { - this.id = data.id || EXPERIMENT1_ID; - this.xpiURL = data.xpiURL || gHttpRoot + EXPERIMENT1_XPI_NAME; - this.xpiHash = data.xpiHash || EXPERIMENT1_XPI_SHA1; - this.appName = data.appName || ["XPCShell"]; - this.channel = data.appName || ["nightly"]; - this.startTime = data.startTime || new Date(2010, 0, 1, 12).getTime() / 1000; - this.endTime = data.endTime || new Date(9001, 0, 1, 12).getTime() / 1000; - this.maxActiveSeconds = data.maxActiveSeconds || 5 * SEC_IN_ONE_DAY; -} - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - loadAddonManager(); - gPolicy = new Experiments.Policy(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let port = gHttpServer.identity.primaryPort; - gHttpRoot = "http://localhost:" + port + "/"; - gHttpServer.registerDirectory("/", do_get_cwd()); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - }); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); -}); - -function isApplicable(experiment) { - let deferred = Promise.defer(); - experiment.isApplicable().then( - result => deferred.resolve({ applicable: true, reason: null }), - reason => deferred.resolve({ applicable: false, reason: reason }) - ); - - return deferred.promise; -} - -add_task(function* test_startStop() { - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 30 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 60 * MS_IN_ONE_DAY); - let manifestData = new ManifestEntry({ - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - }); - let experiment = new Experiments.ExperimentEntry(gPolicy); - experiment.initFromManifestData(manifestData); - - // We need to associate it with the singleton so the onInstallStarted - // Addon Manager listener will know about it. - Experiments.instance()._experiments = new Map(); - Experiments.instance()._experiments.set(experiment.id, experiment); - - let result; - - defineNow(gPolicy, baseDate); - result = yield isApplicable(experiment); - Assert.equal(result.applicable, false, "Experiment should not be applicable."); - Assert.equal(experiment.enabled, false, "Experiment should not be enabled."); - - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "No experiment add-ons are installed."); - - defineNow(gPolicy, futureDate(startDate, 5 * MS_IN_ONE_DAY)); - result = yield isApplicable(experiment); - Assert.equal(result.applicable, true, "Experiment should now be applicable."); - Assert.equal(experiment.enabled, false, "Experiment should not be enabled."); - - let changes = yield experiment.start(); - Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL, "Add-on was installed."); - addons = yield getExperimentAddons(); - Assert.equal(experiment.enabled, true, "Experiment should now be enabled."); - Assert.equal(addons.length, 1, "1 experiment add-on is installed."); - Assert.equal(addons[0].id, experiment._addonId, "The add-on is the one we expect."); - Assert.equal(addons[0].userDisabled, false, "The add-on is not userDisabled."); - Assert.ok(addons[0].isActive, "The add-on is active."); - - changes = yield experiment.stop(); - Assert.equal(changes, experiment.ADDON_CHANGE_UNINSTALL, "Add-on was uninstalled."); - addons = yield getExperimentAddons(); - Assert.equal(experiment.enabled, false, "Experiment should not be enabled."); - Assert.equal(addons.length, 0, "Experiment should be uninstalled from the Addon Manager."); - - changes = yield experiment.start(); - Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL, "Add-on was installed."); - addons = yield getExperimentAddons(); - Assert.equal(experiment.enabled, true, "Experiment should now be enabled."); - Assert.equal(addons.length, 1, "1 experiment add-on is installed."); - Assert.equal(addons[0].id, experiment._addonId, "The add-on is the one we expect."); - Assert.equal(addons[0].userDisabled, false, "The add-on is not userDisabled."); - Assert.ok(addons[0].isActive, "The add-on is active."); - - result = yield experiment.shouldStop(); - Assert.equal(result.shouldStop, false, "shouldStop should be false."); - Assert.equal(experiment.enabled, true, "Experiment should be enabled."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "Experiment still in add-ons manager."); - Assert.ok(addons[0].isActive, "The add-on is still active."); - - defineNow(gPolicy, futureDate(endDate, MS_IN_ONE_DAY)); - result = yield experiment.shouldStop(); - Assert.equal(result.shouldStop, true, "shouldStop should now be true."); - changes = yield experiment.stop(); - Assert.equal(changes, experiment.ADDON_CHANGE_UNINSTALL, "Add-on should be uninstalled."); - Assert.equal(experiment.enabled, false, "Experiment should be disabled."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Experiment add-on is uninstalled."); - - // Ensure hash validation works. - // We set an incorrect hash and expect the install to fail. - experiment._manifestData.xpiHash = "sha1:41014dcc66b4dcedcd973491a1530a32f0517d8a"; - let errored = false; - try { - yield experiment.start(); - } catch (ex) { - errored = true; - } - Assert.ok(experiment._failedStart, "Experiment failed to start."); - Assert.ok(errored, "start() threw an exception."); - - // Make sure "ignore hashes" mode works. - gPolicy.ignoreHashes = true; - changes = yield experiment.start(); - Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL); - yield experiment.stop(); - gPolicy.ignoreHashes = false; -}); diff --git a/browser/experiments/test/xpcshell/test_api.js b/browser/experiments/test/xpcshell/test_api.js deleted file mode 100644 index 9f0112570..000000000 --- a/browser/experiments/test/xpcshell/test_api.js +++ /dev/null @@ -1,1647 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/AddonManagerTesting.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "Experiments", - "resource:///modules/experiments/Experiments.jsm"); - -const MANIFEST_HANDLER = "manifests/handler"; - -const SEC_IN_ONE_DAY = 24 * 60 * 60; -const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; - -var gHttpServer = null; -var gHttpRoot = null; -var gDataRoot = null; -var gPolicy = null; -var gManifestObject = null; -var gManifestHandlerURI = null; -var gTimerScheduleOffset = -1; - -function uninstallExperimentAddons() { - return Task.spawn(function* () { - let addons = yield getExperimentAddons(); - for (let a of addons) { - yield AddonManagerTesting.uninstallAddonByID(a.id); - } - }); -} - -function testCleanup(experimentsInstance) { - return Task.spawn(function* () { - yield promiseRestartManager(); - yield uninstallExperimentAddons(); - yield removeCacheFile(); - }); -} - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - loadAddonManager(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let port = gHttpServer.identity.primaryPort; - gHttpRoot = "http://localhost:" + port + "/"; - gDataRoot = gHttpRoot + "data/"; - gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER; - gHttpServer.registerDirectory("/data/", do_get_cwd()); - gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => { - response.setStatusLine(null, 200, "OK"); - response.write(JSON.stringify(gManifestObject)); - response.processAsync(); - response.finish(); - }); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); - Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI); - Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0); - - gPolicy = new Experiments.Policy(); - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - oneshotTimer: (callback, timeout, thisObj, name) => gTimerScheduleOffset = timeout, - }); -}); - -add_task(function* test_contract() { - Cc["@mozilla.org/browser/experiments-service;1"].getService(); -}); - -// Test basic starting and stopping of experiments. - -add_task(function* test_getExperiments() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY); - let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let startDate2 = futureDate(baseDate, 150 * MS_IN_ONE_DAY); - let endDate2 = futureDate(baseDate, 200 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - startTime: dateToSeconds(startDate2), - endTime: dateToSeconds(endDate2), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate1), - endTime: dateToSeconds(endDate1), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - // Data to compare the result of Experiments.getExperiments() against. - - let experimentListData = [ - { - id: EXPERIMENT2_ID, - name: "Test experiment 2", - description: "And yet another experiment that experiments experimentally.", - }, - { - id: EXPERIMENT1_ID, - name: EXPERIMENT1_NAME, - description: "Yet another experiment that experiments experimentally.", - }, - ]; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - // Use updateManifest() to provide for coverage of that path. - - let now = baseDate; - gTimerScheduleOffset = -1; - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - Assert.equal(experiments.getActiveExperimentID(), null, - "getActiveExperimentID should return null"); - - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are installed."); - - try { - yield experiments.getExperimentBranch(); - Assert.ok(false, "getExperimentBranch should fail with no experiment"); - } - catch (e) { - Assert.ok(true, "getExperimentBranch correctly threw"); - } - - // Trigger update, clock set for experiment 1 to start. - - now = futureDate(startDate1, 5 * MS_IN_ONE_DAY); - gTimerScheduleOffset = -1; - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - Assert.equal(experiments.getActiveExperimentID(), EXPERIMENT1_ID, - "getActiveExperimentID should return the active experiment1"); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "An experiment add-on was installed."); - - experimentListData[1].active = true; - experimentListData[1].endDate = now.getTime() + 10 * MS_IN_ONE_DAY; - for (let k of Object.keys(experimentListData[1])) { - Assert.equal(experimentListData[1][k], list[0][k], - "Property " + k + " should match reference data."); - } - - let b = yield experiments.getExperimentBranch(); - Assert.strictEqual(b, null, "getExperimentBranch should return null by default"); - - b = yield experiments.getExperimentBranch(EXPERIMENT1_ID); - Assert.strictEqual(b, null, "getExperimentsBranch should return null (with id)"); - - yield experiments.setExperimentBranch(EXPERIMENT1_ID, "foo"); - b = yield experiments.getExperimentBranch(); - Assert.strictEqual(b, "foo", "getExperimentsBranch should return the set value"); - - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - Assert.equal(gTimerScheduleOffset, 10 * MS_IN_ONE_DAY, - "Experiment re-evaluation should have been scheduled correctly."); - - // Trigger update, clock set for experiment 1 to stop. - - now = futureDate(endDate1, 1000); - gTimerScheduleOffset = -1; - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - Assert.equal(experiments.getActiveExperimentID(), null, - "getActiveExperimentID should return null again"); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "The experiment add-on should be uninstalled."); - - experimentListData[1].active = false; - experimentListData[1].endDate = now.getTime(); - for (let k of Object.keys(experimentListData[1])) { - Assert.equal(experimentListData[1][k], list[0][k], - "Property " + k + " should match reference data."); - } - - Assert.equal(gTimerScheduleOffset, startDate2 - now, - "Experiment re-evaluation should have been scheduled correctly."); - - // Trigger update, clock set for experiment 2 to start. - // Use notify() to provide for coverage of that path. - - now = startDate2; - gTimerScheduleOffset = -1; - defineNow(gPolicy, now); - - yield experiments.notify(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - Assert.equal(experiments.getActiveExperimentID(), EXPERIMENT2_ID, - "getActiveExperimentID should return the active experiment2"); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries now."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "An experiment add-on is installed."); - - experimentListData[0].active = true; - experimentListData[0].endDate = now.getTime() + 10 * MS_IN_ONE_DAY; - for (let i=0; i<experimentListData.length; ++i) { - let entry = experimentListData[i]; - for (let k of Object.keys(entry)) { - Assert.equal(entry[k], list[i][k], - "Entry " + i + " - Property '" + k + "' should match reference data."); - } - } - - Assert.equal(gTimerScheduleOffset, 10 * MS_IN_ONE_DAY, - "Experiment re-evaluation should have been scheduled correctly."); - - // Trigger update, clock set for experiment 2 to stop. - - now = futureDate(startDate2, 10 * MS_IN_ONE_DAY + 1000); - gTimerScheduleOffset = -1; - defineNow(gPolicy, now); - yield experiments.notify(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - Assert.equal(experiments.getActiveExperimentID(), null, - "getActiveExperimentID should return null again2"); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries now."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "No experiments add-ons are installed."); - - experimentListData[0].active = false; - experimentListData[0].endDate = now.getTime(); - for (let i=0; i<experimentListData.length; ++i) { - let entry = experimentListData[i]; - for (let k of Object.keys(entry)) { - Assert.equal(entry[k], list[i][k], - "Entry " + i + " - Property '" + k + "' should match reference data."); - } - } - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -add_task(function* test_getActiveExperimentID() { - // Check that getActiveExperimentID returns the correct result even - // after .uninit() - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY); - let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate1), - endTime: dateToSeconds(endDate1), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let now = futureDate(startDate1, 5 * MS_IN_ONE_DAY); - gTimerScheduleOffset = -1; - defineNow(gPolicy, now); - - let experiments = new Experiments.Experiments(gPolicy); - yield experiments.updateManifest(); - - Assert.equal(experiments.getActiveExperimentID(), EXPERIMENT1_ID, - "getActiveExperimentID should return the active experiment1"); - - yield promiseRestartManager(); - Assert.equal(experiments.getActiveExperimentID(), EXPERIMENT1_ID, - "getActiveExperimentID should return the active experiment1 after uninit()"); - - yield testCleanup(experiments); -}); - -// Test that we handle the experiments addon already being -// installed properly. -// We should just pave over them. - -add_task(function* test_addonAlreadyInstalled() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for the experiment to start. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "1 add-on is installed."); - - // Install conflicting addon. - - yield AddonManagerTesting.installXPIFromURL(gDataRoot + EXPERIMENT1_XPI_NAME, EXPERIMENT1_XPI_SHA1); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "1 add-on is installed."); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should still have 1 entry."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -add_task(function* test_lastActiveToday() { - let experiments = new Experiments.Experiments(gPolicy); - - replaceExperiments(experiments, FAKE_EXPERIMENTS_1); - - let e = yield experiments.getExperiments(); - Assert.equal(e.length, 1, "Monkeypatch successful."); - Assert.equal(e[0].id, "id1", "ID looks sane"); - Assert.ok(e[0].active, "Experiment is active."); - - let lastActive = yield experiments.lastActiveToday(); - Assert.equal(e[0], lastActive, "Last active object is expected."); - - replaceExperiments(experiments, FAKE_EXPERIMENTS_2); - e = yield experiments.getExperiments(); - Assert.equal(e.length, 2, "Monkeypatch successful."); - - defineNow(gPolicy, e[0].endDate); - - lastActive = yield experiments.lastActiveToday(); - Assert.ok(lastActive, "Have a last active experiment"); - Assert.equal(lastActive, e[0], "Last active object is expected."); - - yield testCleanup(experiments); -}); - -// Test explicitly disabling experiments. - -add_task(function* test_disableExperiment() { - // Dates this test is based on. - - let startDate = new Date(2004, 10, 9, 12); - let endDate = futureDate(startDate, 100 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - // Data to compare the result of Experiments.getExperiments() against. - - let experimentInfo = { - id: EXPERIMENT1_ID, - name: EXPERIMENT1_NAME, - description: "Yet another experiment that experiments experimentally.", - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set for the experiment to start. - - let now = futureDate(startDate, 5 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - - experimentInfo.active = true; - experimentInfo.endDate = now.getTime() + 10 * MS_IN_ONE_DAY; - for (let k of Object.keys(experimentInfo)) { - Assert.equal(experimentInfo[k], list[0][k], - "Property " + k + " should match reference data."); - } - - // Test disabling the experiment. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.disableExperiment("foo"); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - - experimentInfo.active = false; - experimentInfo.endDate = now.getTime(); - for (let k of Object.keys(experimentInfo)) { - Assert.equal(experimentInfo[k], list[0][k], - "Property " + k + " should match reference data."); - } - - // Test that updating the list doesn't re-enable it. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - - for (let k of Object.keys(experimentInfo)) { - Assert.equal(experimentInfo[k], list[0][k], - "Property " + k + " should match reference data."); - } - - yield testCleanup(experiments); -}); - -add_task(function* test_disableExperimentsFeature() { - // Dates this test is based on. - - let startDate = new Date(2004, 10, 9, 12); - let endDate = futureDate(startDate, 100 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - // Data to compare the result of Experiments.getExperiments() against. - - let experimentInfo = { - id: EXPERIMENT1_ID, - name: EXPERIMENT1_NAME, - description: "Yet another experiment that experiments experimentally.", - }; - - let experiments = new Experiments.Experiments(gPolicy); - Assert.equal(experiments.enabled, true, "Experiments feature should be enabled."); - - // Trigger update, clock set for the experiment to start. - - let now = futureDate(startDate, 5 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - - experimentInfo.active = true; - experimentInfo.endDate = now.getTime() + 10 * MS_IN_ONE_DAY; - for (let k of Object.keys(experimentInfo)) { - Assert.equal(experimentInfo[k], list[0][k], - "Property " + k + " should match reference data."); - } - - // Test disabling experiments. - - experiments._toggleExperimentsEnabled(false); - yield experiments.notify(); - Assert.equal(experiments.enabled, false, "Experiments feature should be disabled now."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - - experimentInfo.active = false; - experimentInfo.endDate = now.getTime(); - for (let k of Object.keys(experimentInfo)) { - Assert.equal(experimentInfo[k], list[0][k], - "Property " + k + " should match reference data."); - } - - // Test that updating the list doesn't re-enable it. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - try { - yield experiments.updateManifest(); - } catch (e) { - // Exception expected, the feature is disabled. - } - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - - for (let k of Object.keys(experimentInfo)) { - Assert.equal(experimentInfo[k], list[0][k], - "Property " + k + " should match reference data."); - } - - yield testCleanup(experiments); -}); - -// Test that after a failed experiment install: -// * the next applicable experiment gets installed -// * changing the experiments data later triggers re-evaluation - -add_task(function* test_installFailure() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - // Data to compare the result of Experiments.getExperiments() against. - - let experimentListData = [ - { - id: EXPERIMENT1_ID, - name: EXPERIMENT1_NAME, - description: "Yet another experiment that experiments experimentally.", - }, - { - id: EXPERIMENT2_ID, - name: "Test experiment 2", - description: "And yet another experiment that experiments experimentally.", - }, - ]; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for experiment 1 & 2 to start, - // invalid hash for experiment 1. - // Order in the manifest matters, so we should start experiment 1, - // fail to install it & start experiment 2 instead. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].xpiHash = "sha1:0000000000000000000000000000000000000000"; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT2_ID, "Experiment 2 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 2 should be active."); - - // Trigger update, clock set for experiment 2 to stop. - - now = futureDate(now, 20 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - experimentListData[0].active = false; - experimentListData[0].endDate = now; - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT2_ID, "Experiment 2 should be the sole entry."); - Assert.equal(list[0].active, false, "Experiment should not be active."); - - // Trigger update with a fixed entry for experiment 1, - // which should get re-evaluated & started now. - - now = futureDate(now, 20 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].xpiHash = EXPERIMENT1_XPI_SHA1; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - experimentListData[0].active = true; - experimentListData[0].endDate = now.getTime() + 10 * MS_IN_ONE_DAY; - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries now."); - - for (let i=0; i<experimentListData.length; ++i) { - let entry = experimentListData[i]; - for (let k of Object.keys(entry)) { - Assert.equal(entry[k], list[i][k], - "Entry " + i + " - Property '" + k + "' should match reference data."); - } - } - - yield testCleanup(experiments); -}); - -// Test that after an experiment was disabled by user action, -// the experiment is not activated again if manifest data changes. - -add_task(function* test_userDisabledAndUpdated() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for experiment 1 to start. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - let todayActive = yield experiments.lastActiveToday(); - Assert.ok(todayActive, "Last active for today reports a value."); - Assert.equal(todayActive.id, list[0].id, "The entry is what we expect."); - - // Explicitly disable an experiment. - - now = futureDate(now, 20 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.disableExperiment("foo"); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, false, "Experiment should not be active anymore."); - todayActive = yield experiments.lastActiveToday(); - Assert.ok(todayActive, "Last active for today still returns a value."); - Assert.equal(todayActive.id, list[0].id, "The ID is still the same."); - - // Trigger an update with a faked change for experiment 1. - - now = futureDate(now, 20 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - experiments._experiments.get(EXPERIMENT1_ID)._manifestData.xpiHash = - "sha1:0000000000000000000000000000000000000000"; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, expectedObserverFireCount, - "Experiments observer should not have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, false, "Experiment should still be inactive."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// Test that changing the hash for an active experiments triggers an -// update for it. - -add_task(function* test_updateActiveExperiment() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - let todayActive = yield experiments.lastActiveToday(); - Assert.equal(todayActive, null, "No experiment active today."); - - // Trigger update, clock set for the experiment to start. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - Assert.equal(list[0].name, EXPERIMENT1_NAME, "Experiments name should match."); - todayActive = yield experiments.lastActiveToday(); - Assert.ok(todayActive, "todayActive() returns a value."); - Assert.equal(todayActive.id, list[0].id, "It returns the active experiment."); - - // Trigger an update for the active experiment by changing it's hash (and xpi) - // in the manifest. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].xpiHash = EXPERIMENT1A_XPI_SHA1; - gManifestObject.experiments[0].xpiURL = gDataRoot + EXPERIMENT1A_XPI_NAME; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should still be active."); - Assert.equal(list[0].name, EXPERIMENT1A_NAME, "Experiments name should have been updated."); - todayActive = yield experiments.lastActiveToday(); - Assert.equal(todayActive.id, list[0].id, "last active today is still sane."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// Tests that setting the disable flag for an active experiment -// stops it. - -add_task(function* test_disableActiveExperiment() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for the experiment to start. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - - // Trigger an update with the experiment being disabled. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].disabled = true; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, false, "Experiment 1 should be disabled."); - - // Check that the experiment stays disabled. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - delete gManifestObject.experiments[0].disabled; - yield experiments.updateManifest(); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, false, "Experiment 1 should still be disabled."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// Test that: -// * setting the frozen flag for a not-yet-started experiment keeps -// it from starting -// * after a removing the frozen flag, the experiment can still start - -add_task(function* test_freezePendingExperiment() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for the experiment to start but frozen. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].frozen = true; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, expectedObserverFireCount, - "Experiments observer should have not been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should have no entries yet."); - - // Trigger an update with the experiment not being frozen anymore. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - delete gManifestObject.experiments[0].frozen; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active now."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// Test that setting the frozen flag for an active experiment doesn't -// stop it. - -add_task(function* test_freezeActiveExperiment() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for the experiment to start. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - Assert.equal(list[0].name, EXPERIMENT1_NAME, "Experiments name should match."); - - // Trigger an update with the experiment being disabled. - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].frozen = true; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should still be active."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// Test that removing an active experiment from the manifest doesn't -// stop it. - -add_task(function* test_removeActiveExperiment() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - let startDate2 = futureDate(baseDate, 20000 * MS_IN_ONE_DAY); - let endDate2 = futureDate(baseDate, 30000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - startTime: dateToSeconds(startDate2), - endTime: dateToSeconds(endDate2), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for the experiment to start. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - Assert.equal(list[0].name, EXPERIMENT1_NAME, "Experiments name should match."); - - // Trigger an update with experiment 1 missing from the manifest - - now = futureDate(now, 1 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].frozen = true; - yield experiments.updateManifest(); - Assert.equal(observerFireCount, expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should still be active."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// Test that we correctly handle experiment start & install failures. - -add_task(function* test_invalidUrl() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME + ".invalid", - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: 0, - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set for the experiment to start. - - let now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gTimerScheduleOffset = null; - - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - Assert.equal(gTimerScheduleOffset, null, "No new timer should have been scheduled."); - - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// Test that we handle it properly when active experiment addons are being -// uninstalled. - -add_task(function* test_unexpectedUninstall() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(baseDate, 10000 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Trigger update, clock set for the experiment to start. - - now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, true, "Experiment 1 should be active."); - - // Uninstall the addon through the addon manager instead of stopping it through - // the experiments API. - - yield AddonManagerTesting.uninstallAddonByID(EXPERIMENT1_ID); - yield experiments._mainTask; - - yield experiments.notify(); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.equal(list[0].active, false, "Experiment 1 should not be active anymore."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield testCleanup(experiments); -}); - -// If the Addon Manager knows of an experiment that we don't, it should get -// uninstalled. -add_task(function* testUnknownExperimentsUninstalled() { - let experiments = new Experiments.Experiments(gPolicy); - - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are present."); - - // Simulate us not listening. - experiments._unregisterWithAddonManager(); - yield AddonManagerTesting.installXPIFromURL(gDataRoot + EXPERIMENT1_XPI_NAME, EXPERIMENT1_XPI_SHA1); - experiments._registerWithAddonManager(); - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "Experiment 1 installed via AddonManager"); - - // Simulate no known experiments. - gManifestObject = { - "version": 1, - experiments: [], - }; - - yield experiments.updateManifest(); - let fromManifest = yield experiments.getExperiments(); - Assert.equal(fromManifest.length, 0, "No experiments known in manifest."); - - // And the unknown add-on should be gone. - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Experiment 1 was uninstalled."); - - yield testCleanup(experiments); -}); - -// If someone else installs an experiment add-on, we detect and stop that. -add_task(function* testForeignExperimentInstall() { - let experiments = new Experiments.Experiments(gPolicy); - - gManifestObject = { - "version": 1, - experiments: [], - }; - - yield experiments.init(); - - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Precondition: No experiment add-ons present."); - - let failed = false; - try { - yield AddonManagerTesting.installXPIFromURL(gDataRoot + EXPERIMENT1_XPI_NAME, EXPERIMENT1_XPI_SHA1); - } catch (ex) { - failed = true; - } - Assert.ok(failed, "Add-on install should not have completed successfully"); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Add-on install should have been cancelled."); - - yield testCleanup(experiments); -}); - -// Experiment add-ons will be disabled after Addon Manager restarts. Ensure -// we enable them automatically. -add_task(function* testEnabledAfterRestart() { - let experiments = new Experiments.Experiments(gPolicy); - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: gPolicy.now().getTime() / 1000 - 60, - endTime: gPolicy.now().getTime() / 1000 + 60, - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Precondition: No experiment add-ons installed."); - - yield experiments.updateManifest(); - let fromManifest = yield experiments.getExperiments(); - Assert.equal(fromManifest.length, 1, "A single experiment is known."); - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "A single experiment add-on is installed."); - Assert.ok(addons[0].isActive, "That experiment is active."); - - dump("Restarting Addon Manager\n"); - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "The experiment is still there after restart."); - Assert.ok(addons[0].userDisabled, "But it is disabled."); - Assert.equal(addons[0].isActive, false, "And not active."); - - yield experiments.updateManifest(); - Assert.ok(addons[0].isActive, "It activates when the manifest is evaluated."); - - yield testCleanup(experiments); -}); - -// If experiment add-ons were ever started, maxStartTime shouldn't be evaluated -// anymore. Ensure that if maxStartTime is passed but experiment has started -// already, maxStartTime does not cause deactivation. - -add_task(function* testMaxStartTimeEvaluation() { - - // Dates the following tests are based on. - - let startDate = new Date(2014, 5, 1, 12); - let now = futureDate(startDate, 10 * MS_IN_ONE_DAY); - let maxStartDate = futureDate(startDate, 100 * MS_IN_ONE_DAY); - let endDate = futureDate(startDate, 1000 * MS_IN_ONE_DAY); - - defineNow(gPolicy, now); - - // The manifest data we test with. - // We set a value for maxStartTime. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate), - endTime: dateToSeconds(endDate), - maxActiveSeconds: 1000 * SEC_IN_ONE_DAY, - maxStartTime: dateToSeconds(maxStartDate), - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Precondition: No experiment add-ons installed."); - - yield experiments.updateManifest(); - let fromManifest = yield experiments.getExperiments(); - Assert.equal(fromManifest.length, 1, "A single experiment is known."); - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "A single experiment add-on is installed."); - Assert.ok(addons[0].isActive, "That experiment is active."); - - dump("Setting current time to maxStartTime + 100 days and reloading manifest\n"); - now = futureDate(maxStartDate, 100 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - yield experiments.updateManifest(); - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "The experiment is still there."); - Assert.ok(addons[0].isActive, "It is still active."); - - yield testCleanup(experiments); -}); - -// Test coverage for an add-on uninstall disabling the experiment and that it stays -// disabled over restarts. -add_task(function* test_foreignUninstallAndRestart() { - let experiments = new Experiments.Experiments(gPolicy); - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: gPolicy.now().getTime() / 1000 - 60, - endTime: gPolicy.now().getTime() / 1000 + 60, - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Precondition: No experiment add-ons installed."); - - yield experiments.updateManifest(); - let experimentList = yield experiments.getExperiments(); - Assert.equal(experimentList.length, 1, "A single experiment is known."); - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "A single experiment add-on is installed."); - Assert.ok(addons[0].isActive, "That experiment is active."); - - yield AddonManagerTesting.uninstallAddonByID(EXPERIMENT1_ID); - yield experiments._mainTask; - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Experiment add-on should have been removed."); - - experimentList = yield experiments.getExperiments(); - Assert.equal(experimentList.length, 1, "A single experiment is known."); - Assert.equal(experimentList[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.ok(!experimentList[0].active, "Experiment 1 should not be active anymore."); - - // Fake restart behaviour. - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - yield experiments.updateManifest(); - - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "No experiment add-ons installed."); - - experimentList = yield experiments.getExperiments(); - Assert.equal(experimentList.length, 1, "A single experiment is known."); - Assert.equal(experimentList[0].id, EXPERIMENT1_ID, "Experiment 1 should be the sole entry."); - Assert.ok(!experimentList[0].active, "Experiment 1 should not be active."); - - yield testCleanup(experiments); -}); diff --git a/browser/experiments/test/xpcshell/test_cache.js b/browser/experiments/test/xpcshell/test_cache.js deleted file mode 100644 index 4f2bce881..000000000 --- a/browser/experiments/test/xpcshell/test_cache.js +++ /dev/null @@ -1,399 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -XPCOMUtils.defineLazyModuleGetter(this, "Experiments", - "resource:///modules/experiments/Experiments.jsm"); - -const MANIFEST_HANDLER = "manifests/handler"; - -const SEC_IN_ONE_DAY = 24 * 60 * 60; -const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; - -var gHttpServer = null; -var gHttpRoot = null; -var gDataRoot = null; -var gPolicy = null; -var gManifestObject = null; -var gManifestHandlerURI = null; - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - loadAddonManager(); - yield removeCacheFile(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let port = gHttpServer.identity.primaryPort; - gHttpRoot = "http://localhost:" + port + "/"; - gDataRoot = gHttpRoot + "data/"; - gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER; - gHttpServer.registerDirectory("/data/", do_get_cwd()); - gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => { - response.setStatusLine(null, 200, "OK"); - response.write(JSON.stringify(gManifestObject)); - response.processAsync(); - response.finish(); - }); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); - Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI); - Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0); - - gPolicy = new Experiments.Policy(); - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - oneshotTimer: (callback, timeout, thisObj, name) => {}, - }); -}); - -function checkExperimentListsEqual(list, list2) { - Assert.equal(list.length, list2.length, "Lists should have the same length.") - - for (let i=0; i<list.length; ++i) { - for (let k of Object.keys(list[i])) { - Assert.equal(list[i][k], list2[i][k], - "Field '" + k + "' should match for list entry " + i + "."); - } - } -} - -function checkExperimentSerializations(experimentEntryIterator) { - for (let experiment of experimentEntryIterator) { - let experiment2 = new Experiments.ExperimentEntry(gPolicy); - let jsonStr = JSON.stringify(experiment.toJSON()); - Assert.ok(experiment2.initFromCacheData(JSON.parse(jsonStr)), - "Should have initialized successfully from JSON serialization."); - Assert.equal(JSON.stringify(experiment), JSON.stringify(experiment2), - "Object stringifications should match."); - } -} - -function validateCache(cachedExperiments, experimentIds) { - let cachedExperimentIds = new Set(cachedExperiments); - Assert.equal(cachedExperimentIds.size, experimentIds.length, - "The number of cached experiments does not match with the provided list"); - for (let id of experimentIds) { - Assert.ok(cachedExperimentIds.has(id), "The cache must contain the experiment with id " + id); - } -} - -// Set up an experiments instance and check if it is properly restored from cache. - -add_task(function* test_cache() { - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT3_ID, - xpiURL: "https://inval.id/foo.xpi", - xpiHash: "sha1:0000000000000000000000000000000000000000", - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - // Setup dates for the experiments. - - let baseDate = new Date(2014, 5, 1, 12); - let startDates = []; - let endDates = []; - - for (let i=0; i<gManifestObject.experiments.length; ++i) { - let experiment = gManifestObject.experiments[i]; - startDates.push(futureDate(baseDate, (50 + (150 * i)) * MS_IN_ONE_DAY)); - endDates .push(futureDate(startDates[i], 50 * MS_IN_ONE_DAY)); - experiment.startTime = dateToSeconds(startDates[i]); - experiment.endTime = dateToSeconds(endDates[i]); - } - - // Data to compare the result of Experiments.getExperiments() against. - - let experimentListData = [ - { - id: EXPERIMENT2_ID, - name: "Test experiment 2", - description: "And yet another experiment that experiments experimentally.", - }, - { - id: EXPERIMENT1_ID, - name: EXPERIMENT1_NAME, - description: "Yet another experiment that experiments experimentally.", - }, - ]; - - // Trigger update & re-init, clock set to before any activation. - - let now = baseDate; - defineNow(gPolicy, now); - - let experiments = new Experiments.Experiments(gPolicy); - yield experiments.updateManifest(); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - checkExperimentSerializations(experiments._experiments.values()); - - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - - yield experiments._run(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - checkExperimentSerializations(experiments._experiments.values()); - - // Re-init, clock set for experiment 1 to start. - - now = futureDate(startDates[0], 5 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - yield experiments._run(); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - - experimentListData[1].active = true; - experimentListData[1].endDate = now.getTime() + 10 * MS_IN_ONE_DAY; - checkExperimentListsEqual(experimentListData.slice(1), list); - checkExperimentSerializations(experiments._experiments.values()); - - let branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); - Assert.strictEqual(branch, null); - - yield experiments.setExperimentBranch(EXPERIMENT1_ID, "testbranch"); - branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); - Assert.strictEqual(branch, "testbranch"); - - // Re-init, clock set for experiment 1 to stop. - - now = futureDate(now, 20 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - yield experiments._run(); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - - experimentListData[1].active = false; - experimentListData[1].endDate = now.getTime(); - checkExperimentListsEqual(experimentListData.slice(1), list); - checkExperimentSerializations(experiments._experiments.values()); - - branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); - Assert.strictEqual(branch, "testbranch"); - - // Re-init, clock set for experiment 2 to start. - - now = futureDate(startDates[1], 20 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - yield experiments._run(); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries."); - - experimentListData[0].active = true; - experimentListData[0].endDate = now.getTime() + 10 * MS_IN_ONE_DAY; - checkExperimentListsEqual(experimentListData, list); - checkExperimentSerializations(experiments._experiments.values()); - - // Re-init, clock set for experiment 2 to stop. - - now = futureDate(now, 20 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - yield experiments._run(); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries."); - - experimentListData[0].active = false; - experimentListData[0].endDate = now.getTime(); - checkExperimentListsEqual(experimentListData, list); - checkExperimentSerializations(experiments._experiments.values()); - - // Cleanup. - - yield experiments._toggleExperimentsEnabled(false); - yield promiseRestartManager(); - yield removeCacheFile(); -}); - -add_task(function* test_expiration() { - // The manifest data we test with. - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - maxActiveSeconds: 50 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - // The 3rd experiment will never run, so it's ok to use experiment's 2 data. - { - id: EXPERIMENT3_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - } - ], - }; - - // Data to compare the result of Experiments.getExperiments() against. - let experimentListData = [ - { - id: EXPERIMENT2_ID, - name: "Test experiment 2", - description: "And yet another experiment that experiments experimentally.", - }, - { - id: EXPERIMENT1_ID, - name: EXPERIMENT1_NAME, - description: "Yet another experiment that experiments experimentally.", - }, - ]; - - // Setup dates for the experiments. - let baseDate = new Date(2014, 5, 1, 12); - let startDates = []; - let endDates = []; - - for (let i=0; i<gManifestObject.experiments.length; ++i) { - let experiment = gManifestObject.experiments[i]; - // Spread out experiments in time so that one experiment can end and expire while - // the next is still running. - startDates.push(futureDate(baseDate, (50 + (200 * i)) * MS_IN_ONE_DAY)); - endDates .push(futureDate(startDates[i], 50 * MS_IN_ONE_DAY)); - experiment.startTime = dateToSeconds(startDates[i]); - experiment.endTime = dateToSeconds(endDates[i]); - } - - let now = null; - let experiments = null; - - let setDateAndRestartExperiments = new Task.async(function* (newDate) { - now = newDate; - defineNow(gPolicy, now); - - yield promiseRestartManager(); - experiments = new Experiments.Experiments(gPolicy); - yield experiments._run(); - }); - - // Trigger update & re-init, clock set to before any activation. - now = baseDate; - defineNow(gPolicy, now); - - experiments = new Experiments.Experiments(gPolicy); - yield experiments.updateManifest(); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - // Re-init, clock set for experiment 1 to start... - yield setDateAndRestartExperiments(startDates[0]); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "The first experiment should have started."); - - // ... init again, and set the clock so that the first experiment ends. - yield setDateAndRestartExperiments(endDates[0]); - - // The experiment just ended, it should still be in the cache, but marked - // as finished. - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - - experimentListData[1].active = false; - experimentListData[1].endDate = now.getTime(); - checkExperimentListsEqual(experimentListData.slice(1), list); - validateCache([...experiments._experiments.keys()], [EXPERIMENT1_ID, EXPERIMENT2_ID, EXPERIMENT3_ID]); - - // Start the second experiment. - yield setDateAndRestartExperiments(startDates[1]); - - // The experiments cache should contain the finished experiment and the - // one that's still running. - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries."); - - experimentListData[0].active = true; - experimentListData[0].endDate = now.getTime() + 50 * MS_IN_ONE_DAY; - checkExperimentListsEqual(experimentListData, list); - - // Move the clock in the future, just 31 days after the start date of the second experiment, - // so that the cache for the first experiment expires and the second experiment is still running. - yield setDateAndRestartExperiments(futureDate(startDates[1], 31 * MS_IN_ONE_DAY)); - validateCache([...experiments._experiments.keys()], [EXPERIMENT2_ID, EXPERIMENT3_ID]); - - // Make sure that the expired experiment is not reported anymore. - let history = yield experiments.getExperiments(); - Assert.equal(history.length, 1, "Experiments older than 180 days must be removed from the cache."); - - // Test that we don't write expired experiments in the cache. - yield setDateAndRestartExperiments(now); - validateCache([...experiments._experiments.keys()], [EXPERIMENT2_ID, EXPERIMENT3_ID]); - - // The first experiment should be expired and not in the cache, it ended more than - // 180 days ago. We should see the one still running in the cache. - history = yield experiments.getExperiments(); - Assert.equal(history.length, 1, "Expired experiments must not be saved to cache."); - checkExperimentListsEqual(experimentListData.slice(0, 1), history); - - // Test that experiments that are cached locally but never ran are removed from cache - // when they are removed from the manifest (this is cached data, not really history). - gManifestObject["experiments"] = gManifestObject["experiments"].slice(1, 1); - yield experiments.updateManifest(); - validateCache([...experiments._experiments.keys()], [EXPERIMENT2_ID]); - - // Cleanup. - yield experiments._toggleExperimentsEnabled(false); - yield promiseRestartManager(); - yield removeCacheFile(); -}); diff --git a/browser/experiments/test/xpcshell/test_cacherace.js b/browser/experiments/test/xpcshell/test_cacherace.js deleted file mode 100644 index ff77cfdc4..000000000 --- a/browser/experiments/test/xpcshell/test_cacherace.js +++ /dev/null @@ -1,102 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Timer.jsm"); - -const MANIFEST_HANDLER = "manifests/handler"; - -const SEC_IN_ONE_DAY = 24 * 60 * 60; -const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; - -var gHttpServer = null; -var gHttpRoot = null; -var gDataRoot = null; -var gPolicy = null; -var gManifestObject = null; -var gManifestHandlerURI = null; - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - loadAddonManager(); - yield removeCacheFile(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let port = gHttpServer.identity.primaryPort; - gHttpRoot = "http://localhost:" + port + "/"; - gDataRoot = gHttpRoot + "data/"; - gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER; - gHttpServer.registerDirectory("/data/", do_get_cwd()); - gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => { - response.setStatusLine(null, 200, "OK"); - response.write(JSON.stringify(gManifestObject)); - response.processAsync(); - response.finish(); - }); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); - Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI); - Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0); - - let ExperimentsScope = Cu.import("resource:///modules/experiments/Experiments.jsm"); - let Experiments = ExperimentsScope.Experiments; - - gPolicy = new Experiments.Policy(); - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - delayCacheWrite: (promise) => { - return new Promise((resolve, reject) => { - promise.then( - (result) => { setTimeout(() => resolve(result), 500); }, - (err) => { reject(err); } - ); - }); - }, - }); - - let now = new Date(2014, 5, 1, 12); - defineNow(gPolicy, now); - - let experimentName = "experiment-racybranch.xpi"; - let experimentPath = getExperimentPath(experimentName); - let experimentHash = "sha1:" + sha1File(experimentPath); - - gManifestObject = { - version: 1, - experiments: [ - { - id: "test-experiment-racybranch@tests.mozilla.org", - xpiURL: gDataRoot + "experiment-racybranch.xpi", - xpiHash: experimentHash, - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - startTime: dateToSeconds(futureDate(now, -MS_IN_ONE_DAY)), - endTime: dateToSeconds(futureDate(now, MS_IN_ONE_DAY)), - }, - ], - }; - - do_print("gManifestObject: " + JSON.stringify(gManifestObject)); - - // In order for the addon manager to work properly, we hack - // Experiments.instance which is used by the XPIProvider - let experiments = new Experiments.Experiments(gPolicy); - Assert.strictEqual(ExperimentsScope.gExperiments, null); - ExperimentsScope.gExperiments = experiments; - - yield experiments.updateManifest(); - let active = experiments._getActiveExperiment(); - Assert.ok(active); - Assert.equal(active.branch, "racy-set"); - Assert.ok(!experiments._dirty); -}); diff --git a/browser/experiments/test/xpcshell/test_conditions.js b/browser/experiments/test/xpcshell/test_conditions.js deleted file mode 100644 index 23c147fdb..000000000 --- a/browser/experiments/test/xpcshell/test_conditions.js +++ /dev/null @@ -1,325 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - - -Cu.import("resource:///modules/experiments/Experiments.jsm"); -Cu.import("resource://gre/modules/TelemetryController.jsm", this); - -const SEC_IN_ONE_DAY = 24 * 60 * 60; - -var gPolicy = null; - -function ManifestEntry(data) { - this.id = EXPERIMENT1_ID; - this.xpiURL = "http://localhost:1/dummy.xpi"; - this.xpiHash = EXPERIMENT1_XPI_SHA1; - this.startTime = new Date(2010, 0, 1, 12).getTime() / 1000; - this.endTime = new Date(9001, 0, 1, 12).getTime() / 1000; - this.maxActiveSeconds = SEC_IN_ONE_DAY; - this.appName = ["XPCShell"]; - this.channel = ["nightly"]; - - data = data || {}; - for (let k of Object.keys(data)) { - this[k] = data[k]; - } - - if (!this.endTime) { - this.endTime = this.startTime + 5 * SEC_IN_ONE_DAY; - } -} - -function applicableFromManifestData(data, policy) { - let manifestData = new ManifestEntry(data); - let entry = new Experiments.ExperimentEntry(policy); - entry.initFromManifestData(manifestData); - return entry.isApplicable(); -} - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - createAppInfo(); - do_get_profile(); - startAddonManagerOnly(); - yield TelemetryController.testSetup(); - gPolicy = new Experiments.Policy(); - - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - locale: () => "en-US", - random: () => 0.5, - }); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); -}); - -function arraysEqual(a, b) { - if (a.length !== b.length) { - return false; - } - - for (let i=0; i<a.length; ++i) { - if (a[i] !== b[i]) { - return false; - } - } - - return true; -} - -// This function exists solely to be .toSource()d -const sanityFilter = function filter(c) { - if (c.telemetryEnvironment === undefined) { - throw Error("No .telemetryEnvironment"); - } - if (c.telemetryEnvironment.build == undefined) { - throw Error("No .telemetryEnvironment.build"); - } - return true; -} - -// Utility function to generate build ID for previous/next date. -function addDate(buildId, diff) { - let m = /^([0-9]{4})([0-9]{2})([0-9]{2})(.*)$/.exec(buildId); - if (!m) { - throw Error("Unsupported build ID: " + buildId); - } - let year = Number.parseInt(m[1], 10); - let month = Number.parseInt(m[2], 10); - let date = Number.parseInt(m[3], 10); - let remainingParts = m[4]; - - let d = new Date(); - d.setUTCFullYear(year, month - 1, date); - d.setTime(d.getTime() + diff * 24 * 60 * 60 * 1000); - - let yearStr = String(d.getUTCFullYear()); - let monthStr = ("0" + String(d.getUTCMonth() + 1)).slice(-2); - let dateStr = ("0" + String(d.getUTCDate())).slice(-2); - return yearStr + monthStr + dateStr + remainingParts; -} -function prevDate(buildId) { - return addDate(buildId, -1); -} -function nextDate(buildId) { - return addDate(buildId, 1); -} - -add_task(function* test_simpleFields() { - let testData = [ - // "expected applicable?", failure reason or null, manifest data - - // misc. environment - - [false, ["appName"], {appName: []}], - [false, ["appName"], {appName: ["foo", gAppInfo.name + "-invalid"]}], - [true, null, {appName: ["not-an-app-name", gAppInfo.name]}], - - [false, ["os"], {os: []}], - [false, ["os"], {os: ["42", "abcdef"]}], - [true, null, {os: [gAppInfo.OS, "plan9"]}], - - [false, ["channel"], {channel: []}], - [false, ["channel"], {channel: ["foo", gPolicy.updatechannel() + "-invalid"]}], - [true, null, {channel: ["not-a-channel", gPolicy.updatechannel()]}], - - [false, ["locale"], {locale: []}], - [false, ["locale"], {locale: ["foo", gPolicy.locale + "-invalid"]}], - [true, null, {locale: ["not-a-locale", gPolicy.locale()]}], - - // version - - [false, ["version"], {version: []}], - [false, ["version"], {version: ["-1", gAppInfo.version + "-invalid", "asdf", "0,4", "99.99", "0.1.1.1"]}], - [true, null, {version: ["99999999.999", "-1", gAppInfo.version]}], - - [false, ["minVersion"], {minVersion: "1.0.1"}], - [true, null, {minVersion: "1.0b1"}], - [true, null, {minVersion: "1.0"}], - [true, null, {minVersion: "0.9"}], - - [false, ["maxVersion"], {maxVersion: "0.1"}], - [false, ["maxVersion"], {maxVersion: "0.9.9"}], - [false, ["maxVersion"], {maxVersion: "1.0b1"}], - [true, ["maxVersion"], {maxVersion: "1.0"}], - [true, ["maxVersion"], {maxVersion: "1.7pre"}], - - // build id - - [false, ["buildIDs"], {buildIDs: []}], - [false, ["buildIDs"], {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID + "-invalid"]}], - [true, null, {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID]}], - - [true, null, {minBuildID: prevDate(gAppInfo.platformBuildID)}], - [true, null, {minBuildID: gAppInfo.platformBuildID}], - [false, ["minBuildID"], {minBuildID: nextDate(gAppInfo.platformBuildID)}], - - [false, ["maxBuildID"], {maxBuildID: prevDate(gAppInfo.platformBuildID)}], - [true, null, {maxBuildID: gAppInfo.platformBuildID}], - [true, null, {maxBuildID: nextDate(gAppInfo.platformBuildID)}], - - // sample - - [false, ["sample"], {sample: -1 }], - [false, ["sample"], {sample: 0.0}], - [false, ["sample"], {sample: 0.1}], - [true, null, {sample: 0.5}], - [true, null, {sample: 0.6}], - [true, null, {sample: 1.0}], - [true, null, {sample: 0.5}], - - // experiment control - - [false, ["disabled"], {disabled: true}], - [true, null, {disabled: false}], - - [false, ["frozen"], {frozen: true}], - [true, null, {frozen: false}], - - [false, null, {frozen: true, disabled: true}], - [false, null, {frozen: true, disabled: false}], - [false, null, {frozen: false, disabled: true}], - [true, null, {frozen: false, disabled: false}], - - // jsfilter - - [true, null, {jsfilter: "function filter(c) { return true; }"}], - [false, ["jsfilter-false"], {jsfilter: "function filter(c) { return false; }"}], - [true, null, {jsfilter: "function filter(c) { return 123; }"}], // truthy - [false, ["jsfilter-false"], {jsfilter: "function filter(c) { return ''; }"}], // falsy - [false, ["jsfilter-false"], {jsfilter: "function filter(c) { var a = []; }"}], // undefined - [false, ["jsfilter-threw", "some error"], {jsfilter: "function filter(c) { throw new Error('some error'); }"}], - [false, ["jsfilter-evalfailed"], {jsfilter: "123, this won't work"}], - [true, null, {jsfilter: "var filter = " + sanityFilter.toSource()}], - ]; - - for (let i=0; i<testData.length; ++i) { - let entry = testData[i]; - let applicable; - let reason = null; - - yield applicableFromManifestData(entry[2], gPolicy).then( - value => applicable = value, - value => { - applicable = false; - reason = value; - } - ); - - Assert.equal(applicable, entry[0], - "Experiment entry applicability should match for test " - + i + ": " + JSON.stringify(entry[2])); - - let expectedReason = entry[1]; - if (!applicable && expectedReason) { - Assert.ok(arraysEqual(reason, expectedReason), - "Experiment rejection reasons should match for test " + i + ". " - + "Got " + JSON.stringify(reason) + ", expected " - + JSON.stringify(expectedReason)); - } - } -}); - -add_task(function* test_times() { - let now = new Date(2014, 5, 6, 12); - let nowSec = now.getTime() / 1000; - let testData = [ - // "expected applicable?", rejection reason or null, fake now date, manifest data - - // start time - - [true, null, now, - {startTime: nowSec - 5 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [true, null, now, - {startTime: nowSec, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [false, "startTime", now, - {startTime: nowSec + 5 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - - // end time - - [false, "endTime", now, - {startTime: nowSec - 5 * SEC_IN_ONE_DAY, - endTime: nowSec - 10 * SEC_IN_ONE_DAY}], - [false, "endTime", now, - {startTime: nowSec - 5 * SEC_IN_ONE_DAY, - endTime: nowSec - 5 * SEC_IN_ONE_DAY}], - - // max start time - - [false, "maxStartTime", now, - {maxStartTime: nowSec - 15 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [false, "maxStartTime", now, - {maxStartTime: nowSec - 1 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [false, "maxStartTime", now, - {maxStartTime: nowSec - 10 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [true, null, now, - {maxStartTime: nowSec, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [true, null, now, - {maxStartTime: nowSec + 1 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - - // max active seconds - - [true, null, now, - {maxActiveSeconds: 5 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [true, null, now, - {maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [true, null, now, - {maxActiveSeconds: 15 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - [true, null, now, - {maxActiveSeconds: 20 * SEC_IN_ONE_DAY, - startTime: nowSec - 10 * SEC_IN_ONE_DAY, - endTime: nowSec + 10 * SEC_IN_ONE_DAY}], - ]; - - for (let i=0; i<testData.length; ++i) { - let entry = testData[i]; - let applicable; - let reason = null; - defineNow(gPolicy, entry[2]); - - yield applicableFromManifestData(entry[3], gPolicy).then( - value => applicable = value, - value => { - applicable = false; - reason = value; - } - ); - - Assert.equal(applicable, entry[0], - "Experiment entry applicability should match for test " - + i + ": " + JSON.stringify([entry[2], entry[3]])); - if (!applicable && entry[1]) { - Assert.equal(reason, entry[1], "Experiment rejection reason should match for test " + i); - } - } -}); - -add_task(function* test_shutdown() { - yield TelemetryController.testShutdown(); -}); diff --git a/browser/experiments/test/xpcshell/test_disableExperiments.js b/browser/experiments/test/xpcshell/test_disableExperiments.js deleted file mode 100644 index 8441b922d..000000000 --- a/browser/experiments/test/xpcshell/test_disableExperiments.js +++ /dev/null @@ -1,180 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://testing-common/AddonManagerTesting.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "Experiments", - "resource:///modules/experiments/Experiments.jsm"); - -const MANIFEST_HANDLER = "manifests/handler"; - -const SEC_IN_ONE_DAY = 24 * 60 * 60; -const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; - -var gHttpServer = null; -var gHttpRoot = null; -var gDataRoot = null; -var gPolicy = null; -var gManifestObject = null; -var gManifestHandlerURI = null; - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - loadAddonManager(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let port = gHttpServer.identity.primaryPort; - gHttpRoot = "http://localhost:" + port + "/"; - gDataRoot = gHttpRoot + "data/"; - gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER; - gHttpServer.registerDirectory("/data/", do_get_cwd()); - gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => { - response.setStatusLine(null, 200, "OK"); - response.write(JSON.stringify(gManifestObject)); - response.processAsync(); - response.finish(); - }); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); - Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI); - Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0); - - gPolicy = new Experiments.Policy(); - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - oneshotTimer: (callback, timeout, thisObj, name) => {}, - }); -}); - -// Test disabling the feature stops current and future experiments. - -add_task(function* test_disableExperiments() { - const OBSERVER_TOPIC = "experiments-changed"; - let observerFireCount = 0; - let expectedObserverFireCount = 0; - let observer = () => ++observerFireCount; - Services.obs.addObserver(observer, OBSERVER_TOPIC, false); - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY); - let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let startDate2 = futureDate(baseDate, 150 * MS_IN_ONE_DAY); - let endDate2 = futureDate(baseDate, 200 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - startTime: dateToSeconds(startDate2), - endTime: dateToSeconds(endDate2), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate1), - endTime: dateToSeconds(endDate1), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - // Use updateManifest() to provide for coverage of that path. - - let now = baseDate; - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - let addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are installed."); - - // Trigger update, clock set for experiment 1 to start. - - now = futureDate(startDate1, 5 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - Assert.equal(list[0].active, true, "Experiment should be active."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 1, "An experiment add-on was installed."); - - // Disable the experiments feature. Check that we stop the running experiment. - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, false); - yield experiments._mainTask; - - Assert.equal(observerFireCount, ++expectedObserverFireCount, - "Experiments observer should have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - Assert.equal(list[0].active, false, "Experiment entry should not be active."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "The experiment add-on should be uninstalled."); - - // Trigger update, clock set for experiment 2 to start. Verify we don't start it. - - now = startDate2; - defineNow(gPolicy, now); - - try { - yield experiments.updateManifest(); - } catch (e) { - // This exception is expected, we rethrow everything else - if (e.message != "experiments are disabled") { - throw e; - } - } - - experiments.notify(); - yield experiments._mainTask; - - Assert.equal(observerFireCount, expectedObserverFireCount, - "Experiments observer should not have been called."); - - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should still have 1 entry."); - Assert.equal(list[0].active, false, "Experiment entry should not be active."); - addons = yield getExperimentAddons(); - Assert.equal(addons.length, 0, "There should still be no experiment add-on installed."); - - // Cleanup. - - Services.obs.removeObserver(observer, OBSERVER_TOPIC); - yield promiseRestartManager(); - yield removeCacheFile(); -}); diff --git a/browser/experiments/test/xpcshell/test_fetch.js b/browser/experiments/test/xpcshell/test_fetch.js deleted file mode 100644 index e8d76fa35..000000000 --- a/browser/experiments/test/xpcshell/test_fetch.js +++ /dev/null @@ -1,68 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); -Cu.import("resource:///modules/experiments/Experiments.jsm"); - -var gHttpServer = null; -var gHttpRoot = null; -var gPolicy = new Experiments.Policy(); - -function run_test() { - loadAddonManager(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let port = gHttpServer.identity.primaryPort; - gHttpRoot = "http://localhost:" + port + "/"; - gHttpServer.registerDirectory("/", do_get_cwd()); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); - - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - }); - - run_next_test(); -} - -add_task(function* test_fetchAndCache() { - Services.prefs.setCharPref(PREF_MANIFEST_URI, gHttpRoot + "experiments_1.manifest"); - let ex = new Experiments.Experiments(gPolicy); - - Assert.equal(ex._experiments, null, "There should be no cached experiments yet."); - yield ex.updateManifest(); - Assert.notEqual(ex._experiments.size, 0, "There should be cached experiments now."); - - yield promiseRestartManager(); -}); - -add_task(function* test_checkCache() { - let ex = new Experiments.Experiments(gPolicy); - yield ex.notify(); - Assert.notEqual(ex._experiments.size, 0, "There should be cached experiments now."); - - yield promiseRestartManager(); -}); - -add_task(function* test_fetchInvalid() { - yield removeCacheFile(); - - Services.prefs.setCharPref(PREF_MANIFEST_URI, gHttpRoot + "experiments_1.manifest"); - let ex = new Experiments.Experiments(gPolicy); - yield ex.updateManifest(); - Assert.notEqual(ex._experiments.size, 0, "There should be experiments"); - - Services.prefs.setCharPref(PREF_MANIFEST_URI, gHttpRoot + "invalid.manifest"); - yield ex.updateManifest() - Assert.notEqual(ex._experiments.size, 0, "There should still be experiments: fetch failure shouldn't remove them."); - - yield promiseRestartManager(); -}); diff --git a/browser/experiments/test/xpcshell/test_nethang_bug1012924.js b/browser/experiments/test/xpcshell/test_nethang_bug1012924.js deleted file mode 100644 index 7ef604901..000000000 --- a/browser/experiments/test/xpcshell/test_nethang_bug1012924.js +++ /dev/null @@ -1,47 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource:///modules/experiments/Experiments.jsm"); - -const MANIFEST_HANDLER = "manifests/handler"; - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - loadAddonManager(); - do_get_profile(); - - let httpServer = new HttpServer(); - httpServer.start(-1); - let port = httpServer.identity.primaryPort; - let httpRoot = "http://localhost:" + port + "/"; - let handlerURI = httpRoot + MANIFEST_HANDLER; - httpServer.registerPathHandler("/" + MANIFEST_HANDLER, - (request, response) => { - response.processAsync(); - response.setStatus(null, 200, "OK"); - response.write("["); // never finish! - }); - - do_register_cleanup(() => httpServer.stop(() => {})); - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); - Services.prefs.setCharPref(PREF_MANIFEST_URI, handlerURI); - Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0); - - let experiments = Experiments.instance(); - experiments.updateManifest().then( - () => { - Assert.ok(true, "updateManifest finished successfully"); - }, - (e) => { - do_throw("updateManifest should not have failed: got error " + e); - }); - yield experiments.uninit(); -}); diff --git a/browser/experiments/test/xpcshell/test_previous_provider.js b/browser/experiments/test/xpcshell/test_previous_provider.js deleted file mode 100644 index f7186e159..000000000 --- a/browser/experiments/test/xpcshell/test_previous_provider.js +++ /dev/null @@ -1,179 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource:///modules/experiments/Experiments.jsm"); -Cu.import("resource://testing-common/httpd.js"); - -var gDataRoot; -var gHttpServer; -var gManifestObject; - -function run_test() { - run_next_test(); -} - -add_task(function test_setup() { - loadAddonManager(); - do_get_profile(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let httpRoot = "http://localhost:" + gHttpServer.identity.primaryPort + "/"; - gDataRoot = httpRoot + "data/"; - gHttpServer.registerDirectory("/data/", do_get_cwd()); - gHttpServer.registerPathHandler("/manifests/handler", (req, res) => { - res.setStatusLine(null, 200, "OK"); - res.write(JSON.stringify(gManifestObject)); - res.processAsync(); - res.finish(); - }); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - Services.prefs.setBoolPref("experiments.enabled", true); - Services.prefs.setCharPref("experiments.manifest.uri", - httpRoot + "manifests/handler"); - Services.prefs.setBoolPref("experiments.logging.dump", true); - Services.prefs.setCharPref("experiments.logging.level", "Trace"); -}); - -add_task(function* test_provider_basic() { - let e = Experiments.instance(); - - let provider = new Experiments.PreviousExperimentProvider(e); - e._setPreviousExperimentsProvider(provider); - - let deferred = Promise.defer(); - provider.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - let experimentAddons = yield deferred.promise; - Assert.ok(Array.isArray(experimentAddons), "getAddonsByTypes returns an Array."); - Assert.equal(experimentAddons.length, 0, "No previous add-ons returned."); - - gManifestObject = { - version: 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: Date.now() / 1000 - 60, - endTime: Date.now() / 1000 + 60, - maxActiveSeconds: 60, - appName: ["XPCShell"], - channel: [e._policy.updatechannel()], - }, - ], - }; - - yield e.updateManifest(); - - deferred = Promise.defer(); - provider.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - experimentAddons = yield deferred.promise; - Assert.equal(experimentAddons.length, 0, "Still no previous experiment."); - - let experiments = yield e.getExperiments(); - Assert.equal(experiments.length, 1, "1 experiment present."); - Assert.ok(experiments[0].active, "It is active."); - - // Deactivate it. - defineNow(e._policy, new Date(gManifestObject.experiments[0].endTime * 1000 + 1000)); - yield e.updateManifest(); - - experiments = yield e.getExperiments(); - Assert.equal(experiments.length, 1, "1 experiment present."); - Assert.equal(experiments[0].active, false, "It isn't active."); - - deferred = Promise.defer(); - provider.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - experimentAddons = yield deferred.promise; - Assert.equal(experimentAddons.length, 1, "1 previous add-on known."); - Assert.equal(experimentAddons[0].id, EXPERIMENT1_ID, "ID matches expected."); - - deferred = Promise.defer(); - provider.getAddonByID(EXPERIMENT1_ID, (addon) => { - deferred.resolve(addon); - }); - let addon = yield deferred.promise; - Assert.ok(addon, "We got an add-on from its ID."); - Assert.equal(addon.id, EXPERIMENT1_ID, "ID matches expected."); - Assert.ok(addon.appDisabled, "Add-on is a previous experiment."); - Assert.ok(addon.userDisabled, "Add-on is disabled."); - Assert.equal(addon.type, "experiment", "Add-on is an experiment."); - Assert.equal(addon.isActive, false, "Add-on is not active."); - Assert.equal(addon.permissions, 0, "Add-on has no permissions."); - - deferred = Promise.defer(); - AddonManager.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - experimentAddons = yield deferred.promise; - Assert.equal(experimentAddons.length, 1, "Got 1 experiment from add-on manager."); - Assert.equal(experimentAddons[0].id, EXPERIMENT1_ID, "ID matches expected."); - Assert.ok(experimentAddons[0].appDisabled, "It is a previous experiment add-on."); -}); - -add_task(function* test_active_and_previous() { - // Building on the previous test, activate experiment 2. - let e = Experiments.instance(); - let provider = new Experiments.PreviousExperimentProvider(e); - e._setPreviousExperimentsProvider(provider); - - gManifestObject = { - version: 1, - experiments: [ - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - startTime: Date.now() / 1000 - 60, - endTime: Date.now() / 1000 + 60, - maxActiveSeconds: 60, - appName: ["XPCShell"], - channel: [e._policy.updatechannel()], - }, - ], - }; - - defineNow(e._policy, new Date()); - yield e.updateManifest(); - - let experiments = yield e.getExperiments(); - Assert.equal(experiments.length, 2, "2 experiments known."); - - let deferred = Promise.defer(); - provider.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - let experimentAddons = yield deferred.promise; - Assert.equal(experimentAddons.length, 1, "1 previous experiment."); - - deferred = Promise.defer(); - AddonManager.getAddonsByTypes(["experiment"], (addons) => { - deferred.resolve(addons); - }); - experimentAddons = yield deferred.promise; - Assert.equal(experimentAddons.length, 2, "2 experiment add-ons known."); - - for (let addon of experimentAddons) { - if (addon.id == EXPERIMENT1_ID) { - Assert.equal(addon.isActive, false, "Add-on is not active."); - Assert.ok(addon.appDisabled, "Should be a previous experiment."); - } - else if (addon.id == EXPERIMENT2_ID) { - Assert.ok(addon.isActive, "Add-on is active."); - Assert.ok(!addon.appDisabled, "Should not be a previous experiment."); - } - else { - throw new Error("Unexpected add-on ID: " + addon.id); - } - } -}); diff --git a/browser/experiments/test/xpcshell/test_telemetry.js b/browser/experiments/test/xpcshell/test_telemetry.js deleted file mode 100644 index 02bd15d2b..000000000 --- a/browser/experiments/test/xpcshell/test_telemetry.js +++ /dev/null @@ -1,294 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://testing-common/httpd.js"); -Cu.import("resource://gre/modules/TelemetryLog.jsm"); -var bsp = Cu.import("resource:///modules/experiments/Experiments.jsm"); - - -const MANIFEST_HANDLER = "manifests/handler"; - -const SEC_IN_ONE_DAY = 24 * 60 * 60; -const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; - - -var gHttpServer = null; -var gHttpRoot = null; -var gDataRoot = null; -var gPolicy = null; -var gManifestObject = null; -var gManifestHandlerURI = null; - -const TLOG = bsp.TELEMETRY_LOG; - -function checkEvent(event, id, data) -{ - do_print("Checking message " + id); - Assert.equal(event[0], id, "id should match"); - Assert.ok(event[1] > 0, "timestamp should be greater than 0"); - - if (data === undefined) { - Assert.equal(event.length, 2, "event array should have 2 entries"); - } else { - Assert.equal(event.length, data.length + 2, "event entry count should match expected count"); - for (var i = 0; i < data.length; ++i) { - Assert.equal(typeof(event[i + 2]), "string", "event entry should be a string"); - Assert.equal(event[i + 2], data[i], "event entry should match expected entry"); - } - } -} - -function run_test() { - run_next_test(); -} - -add_task(function* test_setup() { - loadAddonManager(); - - gHttpServer = new HttpServer(); - gHttpServer.start(-1); - let port = gHttpServer.identity.primaryPort; - gHttpRoot = "http://localhost:" + port + "/"; - gDataRoot = gHttpRoot + "data/"; - gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER; - gHttpServer.registerDirectory("/data/", do_get_cwd()); - gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => { - response.setStatusLine(null, 200, "OK"); - response.write(JSON.stringify(gManifestObject)); - response.processAsync(); - response.finish(); - }); - do_register_cleanup(() => gHttpServer.stop(() => {})); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); - Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); - Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI); - Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0); - - gPolicy = new Experiments.Policy(); - let dummyTimer = { cancel: () => {}, clear: () => {} }; - patchPolicy(gPolicy, { - updatechannel: () => "nightly", - oneshotTimer: (callback, timeout, thisObj, name) => dummyTimer, - }); - - yield removeCacheFile(); -}); - -// Test basic starting and stopping of experiments. - -add_task(function* test_telemetryBasics() { - // Check TelemetryLog instead of TelemetrySession.getPayload().log because - // TelemetrySession gets Experiments.instance() and side-effects log entries. - - let expectedLogLength = 0; - - // Dates the following tests are based on. - - let baseDate = new Date(2014, 5, 1, 12); - let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY); - let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY); - let startDate2 = futureDate(baseDate, 150 * MS_IN_ONE_DAY); - let endDate2 = futureDate(baseDate, 200 * MS_IN_ONE_DAY); - - // The manifest data we test with. - - gManifestObject = { - "version": 1, - experiments: [ - { - id: EXPERIMENT1_ID, - xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, - xpiHash: EXPERIMENT1_XPI_SHA1, - startTime: dateToSeconds(startDate1), - endTime: dateToSeconds(endDate1), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - { - id: EXPERIMENT2_ID, - xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, - xpiHash: EXPERIMENT2_XPI_SHA1, - startTime: dateToSeconds(startDate2), - endTime: dateToSeconds(endDate2), - maxActiveSeconds: 10 * SEC_IN_ONE_DAY, - appName: ["XPCShell"], - channel: ["nightly"], - }, - ], - }; - - let experiments = new Experiments.Experiments(gPolicy); - - // Trigger update, clock set to before any activation. - // Use updateManifest() to provide for coverage of that path. - - let now = baseDate; - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - let list = yield experiments.getExperiments(); - Assert.equal(list.length, 0, "Experiment list should be empty."); - - expectedLogLength += 2; - let log = TelemetryLog.entries(); - do_print("Telemetry log: " + JSON.stringify(log)); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-2], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.REJECTED, EXPERIMENT1_ID, "startTime"]); - checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.REJECTED, EXPERIMENT2_ID, "startTime"]); - - // Trigger update, clock set for experiment 1 to start. - - now = futureDate(startDate1, 5 * MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries. Got " + log.toSource()); - checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT1_ID]); - - // Trigger update, clock set for experiment 1 to stop. - - now = futureDate(endDate1, 1000); - defineNow(gPolicy, now); - - yield experiments.updateManifest(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entry."); - - expectedLogLength += 2; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-2], TLOG.TERMINATION_KEY, - [TLOG.TERMINATION.EXPIRED, EXPERIMENT1_ID]); - checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.REJECTED, EXPERIMENT2_ID, "startTime"]); - - // Trigger update, clock set for experiment 2 to start with invalid hash. - - now = startDate2; - defineNow(gPolicy, now); - gManifestObject.experiments[1].xpiHash = "sha1:0000000000000000000000000000000000000000"; - - yield experiments.updateManifest(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 1, "Experiment list should have 1 entries."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.INSTALL_FAILURE, EXPERIMENT2_ID]); - - // Trigger update, clock set for experiment 2 to properly start now. - - now = futureDate(now, MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[1].xpiHash = EXPERIMENT2_XPI_SHA1; - - yield experiments.updateManifest(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT2_ID]); - - // Fake user uninstall of experiment via add-on manager. - - now = futureDate(now, MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield experiments.disableExperiment(TLOG.TERMINATION.ADDON_UNINSTALLED); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 2, "Experiment list should have 2 entries."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-1], TLOG.TERMINATION_KEY, - [TLOG.TERMINATION.ADDON_UNINSTALLED, EXPERIMENT2_ID]); - - // Trigger update with experiment 1a ready to start. - - now = futureDate(now, MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].id = EXPERIMENT3_ID; - gManifestObject.experiments[0].endTime = dateToSeconds(futureDate(now, 50 * MS_IN_ONE_DAY)); - - yield experiments.updateManifest(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 3, "Experiment list should have 3 entries."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT3_ID]); - - // Trigger disable of an experiment via the API. - - now = futureDate(now, MS_IN_ONE_DAY); - defineNow(gPolicy, now); - - yield experiments.disableExperiment(TLOG.TERMINATION.FROM_API); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 3, "Experiment list should have 3 entries."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-1], TLOG.TERMINATION_KEY, - [TLOG.TERMINATION.FROM_API, EXPERIMENT3_ID]); - - // Trigger update with experiment 1a ready to start. - - now = futureDate(now, MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].id = EXPERIMENT4_ID; - gManifestObject.experiments[0].endTime = dateToSeconds(futureDate(now, 50 * MS_IN_ONE_DAY)); - - yield experiments.updateManifest(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 4, "Experiment list should have 4 entries."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY, - [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT4_ID]); - - // Trigger experiment termination by something other than expiry via the manifest. - - now = futureDate(now, MS_IN_ONE_DAY); - defineNow(gPolicy, now); - gManifestObject.experiments[0].os = "Plan9"; - - yield experiments.updateManifest(); - list = yield experiments.getExperiments(); - Assert.equal(list.length, 4, "Experiment list should have 4 entries."); - - expectedLogLength += 1; - log = TelemetryLog.entries(); - Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries."); - checkEvent(log[log.length-1], TLOG.TERMINATION_KEY, - [TLOG.TERMINATION.RECHECK, EXPERIMENT4_ID, "os"]); - - // Cleanup. - - yield promiseRestartManager(); - yield removeCacheFile(); -}); diff --git a/browser/experiments/test/xpcshell/test_telemetry_disabled.js b/browser/experiments/test/xpcshell/test_telemetry_disabled.js deleted file mode 100644 index 74f85ccfc..000000000 --- a/browser/experiments/test/xpcshell/test_telemetry_disabled.js +++ /dev/null @@ -1,21 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource:///modules/experiments/Experiments.jsm"); - -add_test(function test_experiments_activation() { - do_get_profile(); - loadAddonManager(); - - Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); - Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, false); - - let experiments = Experiments.instance(); - Assert.ok(!experiments.enabled, "Experiments must be disabled if Telemetry is disabled."); - - // TODO: Test that Experiments are turned back on when bug 1232648 lands. - - run_next_test(); -}); diff --git a/browser/experiments/test/xpcshell/test_upgrade.js b/browser/experiments/test/xpcshell/test_upgrade.js deleted file mode 100644 index f094a406d..000000000 --- a/browser/experiments/test/xpcshell/test_upgrade.js +++ /dev/null @@ -1,52 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; -Cu.import("resource:///modules/experiments/Experiments.jsm"); - -var cacheData = { - _enabled: true, - _manifestData: { - id: "foobartestid", - xpiURL: "http://example.com/foo.xpi", - xpiHash: "sha256:abcde", - startTime: 0, - endTime: 2000000000, - maxActiveSeconds: 40000000, - appName: "TestApp", - channel: "test-foo", - }, - _needsUpdate: false, - _randomValue: 0.5, - _failedStart: false, - _name: "Foo", - _description: "Foobar", - _homepageURL: "", - _addonId: "foo@test", - _startDate: 0, - _endDate: 2000000000, - _branch: null -}; - -add_task(function* test_valid() { - let e = new Experiments.ExperimentEntry(); - Assert.ok(e.initFromCacheData(cacheData)); - Assert.ok(e.enabled); -}); - -add_task(function* test_upgrade() { - let e = new Experiments.ExperimentEntry(); - delete cacheData._branch; - Assert.ok(e.initFromCacheData(cacheData)); - Assert.ok(e.enabled); -}); - -add_task(function* test_missing() { - let e = new Experiments.ExperimentEntry(); - delete cacheData._name; - Assert.ok(!e.initFromCacheData(cacheData)); -}); - -function run_test() { - run_next_test(); -} diff --git a/browser/experiments/test/xpcshell/xpcshell.ini b/browser/experiments/test/xpcshell/xpcshell.ini deleted file mode 100644 index 5921c9c47..000000000 --- a/browser/experiments/test/xpcshell/xpcshell.ini +++ /dev/null @@ -1,31 +0,0 @@ -[DEFAULT] -head = head.js -tail = -tags = addons -firefox-appdir = browser -skip-if = toolkit == 'android' -support-files = - experiments_1.manifest - experiment-1.xpi - experiment-1a.xpi - experiment-2.xpi - experiment-racybranch.xpi - !/toolkit/mozapps/webextensions/test/xpcshell/head_addons.js -generated-files = - experiment-1.xpi - experiment-1a.xpi - experiment-2.xpi - experiment-racybranch.xpi - -[test_activate.js] -[test_api.js] -[test_cache.js] -[test_cacherace.js] -[test_conditions.js] -[test_disableExperiments.js] -[test_fetch.js] -[test_telemetry.js] -[test_telemetry_disabled.js] -[test_previous_provider.js] -[test_upgrade.js] -[test_nethang_bug1012924.js] diff --git a/browser/fonts/EmojiOneMozilla.ttf b/browser/fonts/EmojiOneMozilla.ttf Binary files differdeleted file mode 100644 index 50356509d..000000000 --- a/browser/fonts/EmojiOneMozilla.ttf +++ /dev/null diff --git a/browser/fonts/README.txt b/browser/fonts/README.txt index 188ea3fff..ac1f6d9de 100644 --- a/browser/fonts/README.txt +++ b/browser/fonts/README.txt @@ -1,9 +1,9 @@ -EmojiOne Mozilla +Twemoji Mozilla ================ -The upstream repository of EmojiOne Mozilla can be found at +The upstream repository of Twemoji Mozilla can be found at - https://github.com/mozilla/emojione-colr + https://github.com/mozilla/twemoji-colr Please refer commit history for the current version of the font. This file purposely omit the version, so there is no need to update it here. diff --git a/browser/fonts/TwemojiMozilla.ttf b/browser/fonts/TwemojiMozilla.ttf Binary files differnew file mode 100644 index 000000000..1933891d9 --- /dev/null +++ b/browser/fonts/TwemojiMozilla.ttf diff --git a/browser/fonts/moz.build b/browser/fonts/moz.build index b1a43e528..5cb98333b 100644 --- a/browser/fonts/moz.build +++ b/browser/fonts/moz.build @@ -7,5 +7,5 @@ if CONFIG['OS_ARCH'] in ('WINNT', 'Linux'): DIST_SUBDIR = '' FINAL_TARGET_FILES.fonts += [ - 'EmojiOneMozilla.ttf' + 'TwemojiMozilla.ttf' ] diff --git a/browser/installer/Makefile.in b/browser/installer/Makefile.in index 55df797ef..4a934fe45 100644 --- a/browser/installer/Makefile.in +++ b/browser/installer/Makefile.in @@ -13,11 +13,7 @@ MOZ_PKG_MANIFEST = $(srcdir)/package-manifest.in MOZ_PKG_DUPEFLAGS = -f $(srcdir)/allowed-dupes.mn # Some files have been already bundled with xulrunner -ifndef MOZ_MULET MOZ_PKG_FATAL_WARNINGS = 1 -else -DEFINES += -DMOZ_MULET -endif # When packaging an artifact build not all xpt files expected by the # packager will be present. @@ -61,9 +57,6 @@ DEFINES += -DMOZ_ANGLE_RENDERER=$(MOZ_ANGLE_RENDERER) ifdef MOZ_D3DCOMPILER_VISTA_DLL DEFINES += -DMOZ_D3DCOMPILER_VISTA_DLL=$(MOZ_D3DCOMPILER_VISTA_DLL) endif -ifdef MOZ_D3DCOMPILER_XP_DLL -DEFINES += -DMOZ_D3DCOMPILER_XP_DLL=$(MOZ_D3DCOMPILER_XP_DLL) -endif endif DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME) diff --git a/browser/installer/allowed-dupes.mn b/browser/installer/allowed-dupes.mn index 366842598..7baa6ebed 100644 --- a/browser/installer/allowed-dupes.mn +++ b/browser/installer/allowed-dupes.mn @@ -171,7 +171,7 @@ chrome/toolkit/skin/classic/global/dialog.css chrome/toolkit/skin/classic/global/dropmarker.css chrome/toolkit/skin/classic/global/global.css chrome/toolkit/skin/classic/global/groupbox.css -chrome/toolkit/skin/classic/global/icons/close-XPVista7.png +chrome/toolkit/skin/classic/global/icons/close-win7.png chrome/toolkit/skin/classic/global/icons/tabprompts-bgtexture.png chrome/toolkit/skin/classic/global/listbox.css chrome/toolkit/skin/classic/global/media/clicktoplay-bgtexture.png @@ -196,7 +196,6 @@ chrome/toolkit/skin/classic/global/toolbarbutton.css chrome/toolkit/skin/classic/global/tree.css chrome/toolkit/skin/classic/global/wizard.css chrome/toolkit/skin/classic/mozapps/downloads/buttons.png -chrome/toolkit/skin/classic/mozapps/downloads/downloadButtons-XP.png chrome/toolkit/skin/classic/mozapps/downloads/downloadButtons.png chrome/toolkit/skin/classic/mozapps/extensions/category-dictionaries.png chrome/toolkit/skin/classic/mozapps/extensions/category-experiments.png @@ -209,7 +208,6 @@ chrome/toolkit/skin/classic/mozapps/extensions/localeGeneric.png chrome/toolkit/skin/classic/mozapps/extensions/category-extensions.png chrome/toolkit/skin/classic/mozapps/extensions/extensionGeneric.png chrome/toolkit/skin/classic/mozapps/update/buttons.png -chrome/toolkit/skin/classic/mozapps/update/downloadButtons-XP.png chrome/toolkit/skin/classic/mozapps/update/downloadButtons.png chrome/toolkit/skin/classic/mozapps/xpinstall/xpinstallItemGeneric.png diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index bddca2f29..5540feed9 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -374,8 +374,6 @@ @RESPATH@/browser/components/devtools-startup.js @RESPATH@/browser/components/webideCli.js @RESPATH@/browser/components/webideComponents.manifest -@RESPATH@/browser/components/Experiments.manifest -@RESPATH@/browser/components/ExperimentsService.js @RESPATH@/browser/components/browser-newtab.xpt @RESPATH@/browser/components/aboutNewTabService.js @RESPATH@/browser/components/NewTabComponents.manifest @@ -607,10 +605,6 @@ #ifdef MOZ_D3DCOMPILER_VISTA_DLL @BINPATH@/@MOZ_D3DCOMPILER_VISTA_DLL@ #endif - -#ifdef MOZ_D3DCOMPILER_XP_DLL -@BINPATH@/@MOZ_D3DCOMPILER_XP_DLL@ -#endif #endif # MOZ_ANGLE_RENDERER ; [Browser Chrome Files] @@ -785,28 +779,6 @@ bin/libfreebl_32int64_3.so @BINPATH@/maintenanceservice_installer.exe #endif -; [Crash Reporter] -; -#ifdef MOZ_CRASHREPORTER -@RESPATH@/components/CrashService.manifest -@RESPATH@/components/CrashService.js -@RESPATH@/components/toolkit_crashservice.xpt -#ifdef XP_MACOSX -@BINPATH@/crashreporter.app/ -#else -@BINPATH@/crashreporter@BIN_SUFFIX@ -@BINPATH@/minidump-analyzer@BIN_SUFFIX@ -@RESPATH@/crashreporter.ini -#ifdef XP_UNIX -@RESPATH@/Throbber-small.gif -#endif -#endif -@RESPATH@/browser/crashreporter-override.ini -#ifdef MOZ_CRASHREPORTER_INJECTOR -@BINPATH@/breakpadinjector.dll -#endif -#endif - @RESPATH@/components/dom_audiochannel.xpt ; Shutdown Terminator @@ -825,15 +797,13 @@ bin/libfreebl_32int64_3.so ; media +#ifdef MOZ_EME @RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@ @RESPATH@/gmp-clearkey/0.1/clearkey.info +#endif ; gfx #ifdef XP_WIN @RESPATH@/components/GfxSanityTest.manifest @RESPATH@/components/SanityTest.js #endif - -#ifdef MOZ_MULET -#include ../../b2g/installer/package-manifest.in -#endif diff --git a/browser/installer/windows/Makefile.in b/browser/installer/windows/Makefile.in index fa6fd5ba9..600bdfeb6 100644 --- a/browser/installer/windows/Makefile.in +++ b/browser/installer/windows/Makefile.in @@ -5,15 +5,13 @@ include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk CONFIG_DIR = instgen -SFX_MODULE = $(topsrcdir)/other-licenses/7zstub/firefox/7zSD.sfx +SFX_MODULE = $(topsrcdir)/other-licenses/7zstub/uxp/7zSD.sfx INSTALLER_FILES = \ app.tag \ nsis/installer.nsi \ nsis/uninstaller.nsi \ - nsis/stub.nsi \ nsis/shared.nsh \ - stub.tag \ $(NULL) ifdef MOZ_MAINTENANCE_SERVICE @@ -25,11 +23,6 @@ endif BRANDING_FILES = \ branding.nsi \ appname.bmp \ - bgintro.bmp \ - clock.bmp \ - particles.bmp \ - pencil.bmp \ - pencil-rtl.bmp \ wizHeader.bmp \ wizHeaderRTL.bmp \ wizWatermark.bmp \ @@ -90,9 +83,6 @@ $(CONFIG_DIR)/setup.exe:: --preprocess-single-file $(topsrcdir) \ $(PPL_LOCALE_ARGS) $(CONFIG_DIR) \ nsisstrings.properties nsisstrings.nlf - $(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \ - --convert-utf8-utf16le \ - $(srcdir)/nsis/oneoff_en-US.nsh $(CONFIG_DIR)/oneoff_en-US.nsh GARBARGE_DIRS += instgen diff --git a/browser/installer/windows/app.tag b/browser/installer/windows/app.tag index 479d9f714..7be6d2e42 100644 --- a/browser/installer/windows/app.tag +++ b/browser/installer/windows/app.tag @@ -1,4 +1,4 @@ ;!@Install@!UTF-8! -Title="Mozilla Firefox" +Title="Basilisk" RunProgram="setup.exe" ;!@InstallEnd@!
\ No newline at end of file diff --git a/browser/installer/windows/nsis/defines.nsi.in b/browser/installer/windows/nsis/defines.nsi.in index ffb23ff1c..5ad9b7966 100644 --- a/browser/installer/windows/nsis/defines.nsi.in +++ b/browser/installer/windows/nsis/defines.nsi.in @@ -21,15 +21,15 @@ !endif # These defines should match application.ini settings -!define AppName "Firefox" +!define AppName "Basilisk" !define AppVersion "@APP_VERSION@" !define GREVersion @MOZILLA_VERSION@ !define AB_CD "@AB_CD@" !define FileMainEXE "@MOZ_APP_NAME@.exe" -!define WindowClass "FirefoxMessageWindow" -!define DDEApplication "Firefox" -!define AppRegName "Firefox" +!define WindowClass "BasiliskMessageWindow" +!define DDEApplication "Basilisk" +!define AppRegName "Basilisk" !ifndef DEV_EDITION !define BrandShortName "@MOZ_APP_DISPLAYNAME@" @@ -55,14 +55,6 @@ !define UpdateChannel "@MOZ_UPDATE_CHANNEL@" !endif -# Due to official and beta using the same branding this is needed to -# differentiante between the url used by the stub for downloading. -!if "@MOZ_UPDATE_CHANNEL@" == "beta" -!define BETA_UPDATE_CHANNEL -!endif - -!define BaseURLStubPing "http://download-stats.mozilla.org/stub" - # ARCH is used when it is necessary to differentiate the x64 registry keys from # the x86 registry keys (e.g. the uninstall registry key). #ifdef HAVE_64BIT_BUILD @@ -71,7 +63,7 @@ !define MinSupportedVer "Microsoft Windows 7 x64" #else !define ARCH "x86" -!define MinSupportedVer "Microsoft Windows XP SP2" +!define MinSupportedVer "Microsoft Windows 7" #endif !define MinSupportedCPU "SSE2" @@ -85,7 +77,7 @@ VIProductVersion "1.0.0.0" VIAddVersionKey "ProductName" "${BrandShortName}" VIAddVersionKey "CompanyName" "${CompanyName}" #ifdef MOZ_OFFICIAL_BRANDING -VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of The Mozilla Foundation." +VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of Moonchild Productions." #endif VIAddVersionKey "LegalCopyright" "${CompanyName}" VIAddVersionKey "FileVersion" "${AppVersion}" @@ -93,12 +85,6 @@ VIAddVersionKey "ProductVersion" "${AppVersion}" # Comments is not used but left below commented out for future reference # VIAddVersionKey "Comments" "Comments" -# It isn't possible to get the size of the installation prior to downloading -# so the stub installer uses an estimate. The size is derived from the size of -# the complete installer, the size of the extracted complete installer, and at -# least 15 MB additional for working room. -!define APPROXIMATE_REQUIRED_SPACE_MB "145" - # Control positions in Dialog Units so they are placed correctly with # non-default DPI settings !define OPTIONS_ITEM_EDGE_DU 90u diff --git a/browser/installer/windows/nsis/installer.nsi b/browser/installer/windows/nsis/installer.nsi index aed5808cd..994c09279 100755 --- a/browser/installer/windows/nsis/installer.nsi +++ b/browser/installer/windows/nsis/installer.nsi @@ -1139,13 +1139,11 @@ Function .onInit ; Don't install on systems that don't support SSE2. The parameter value of ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the - ; SSE2 instruction set is available. + ; SSE2 instruction set is available. Result returned in $R7. System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7" -!ifdef HAVE_64BIT_BUILD - ; Restrict x64 builds from being installed on x86 and pre Win7 - ${Unless} ${RunningX64} - ${OrUnless} ${AtLeastWin7} + ; Windows NT 6.0 and lower are not supported on any architecture. + ${Unless} ${AtLeastWin7} ${If} "$R7" == "0" strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" ${Else} @@ -1156,59 +1154,28 @@ Function .onInit Quit ${EndUnless} - SetRegView 64 -!else - StrCpy $R8 "0" - ${If} ${AtMostWin2000} - StrCpy $R8 "1" - ${EndIf} - - ${If} ${IsWinXP} - ${AndIf} ${AtMostServicePack} 1 - StrCpy $R8 "1" - ${EndIf} - - ${If} $R8 == "1" - ; XXX-rstrong - some systems failed the AtLeastWin2000 test that we - ; used to use for an unknown reason and likely fail the AtMostWin2000 - ; and possibly the IsWinXP test as well. To work around this also - ; check if the Windows NT registry Key exists and if it does if the - ; first char in CurrentVersion is equal to 3 (Windows NT 3.5 and - ; 3.5.1), 4 (Windows NT 4), or 5 (Windows 2000 and Windows XP). - StrCpy $R8 "" - ClearErrors - ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion" - StrCpy $R8 "$R8" 1 - ${If} ${Errors} - ${OrIf} "$R8" == "3" - ${OrIf} "$R8" == "4" - ${OrIf} "$R8" == "5" - ${If} "$R7" == "0" - strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" - ${Else} - strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_MSG)" - ${EndIf} - MessageBox MB_OKCANCEL|MB_ICONSTOP "$R7" IDCANCEL +2 - ExecShell "open" "${URLSystemRequirements}" - Quit - ${EndIf} - ${EndUnless} -!endif - + ; SSE2 support ${If} "$R7" == "0" MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_CPU_MSG)" IDCANCEL +2 ExecShell "open" "${URLSystemRequirements}" Quit ${EndIf} +!ifdef HAVE_64BIT_BUILD + ${Unless} ${RunningX64} + MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_OSVER_MSG)" IDCANCEL +2 + ExecShell "open" "${URLSystemRequirements}" + Quit + ${EndUnless} + SetRegView 64 +!endif + ${InstallOnInitCommon} "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" ; The commands inside this ifndef are needed prior to NSIS 3.0a2 and can be ; removed after we require NSIS 3.0a2 or greater. !ifndef NSIS_PACKEDVERSION - ${If} ${AtLeastWinVista} - System::Call 'user32::SetProcessDPIAware()' - ${EndIf} + System::Call 'user32::SetProcessDPIAware()' !endif !insertmacro InitInstallOptionsFile "options.ini" diff --git a/browser/installer/windows/nsis/maintenanceservice_installer.nsi b/browser/installer/windows/nsis/maintenanceservice_installer.nsi index 4bc9d2bed..1f73bac6a 100644 --- a/browser/installer/windows/nsis/maintenanceservice_installer.nsi +++ b/browser/installer/windows/nsis/maintenanceservice_installer.nsi @@ -120,10 +120,7 @@ Function .onInit SetSilent silent - ; On Windows 2000 we do not install the maintenance service. - ; We won't run this installer from the parent installer, but just in case - ; someone tries to execute it on Windows 2000... - ${Unless} ${AtLeastWinXP} + ${Unless} ${AtLeastWin7} Abort ${EndUnless} FunctionEnd diff --git a/browser/installer/windows/nsis/oneoff_en-US.nsh b/browser/installer/windows/nsis/oneoff_en-US.nsh deleted file mode 100644 index 62d95ade9..000000000 --- a/browser/installer/windows/nsis/oneoff_en-US.nsh +++ /dev/null @@ -1,12 +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/. - -; Custom strings for en-US. This is not in the locale directory so these strings -; aren't translated. -!define INDENT " " -!define INTRO_BLURB "Thanks for choosing $BrandFullName. We’re not just designed to be different, we’re different by design." -!define INSTALL_BLURB1 "You're about to enjoy the very latest in speed, flexibility and security so you're always in control." -!define INSTALL_BLURB2 "And you're joining a global community of users, contributors and developers working to make the best browser in the world." -!define INSTALL_BLURB3 "You even get a haiku:$\n${INDENT}Proudly non-profit$\n${INDENT}Free to innovate for you$\n${INDENT}And a better Web" -!undef INDENT diff --git a/browser/installer/windows/nsis/shared.nsh b/browser/installer/windows/nsis/shared.nsh index 8d7eea618..fb2239d24 100755 --- a/browser/installer/windows/nsis/shared.nsh +++ b/browser/installer/windows/nsis/shared.nsh @@ -10,12 +10,12 @@ System::Call "kernel32::ProcessIdToSessionId(i $0, *i ${NSIS_MAX_STRLEN} r9)" ; Determine if we're the protected UserChoice default or not. If so fix the - ; start menu tile. In case there are 2 Firefox installations, we only do + ; start menu tile. In case there are 2 Basilisk installations, we only do ; this if the application being updated is the default. ReadRegStr $0 HKCU "Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice" "ProgId" - ${If} $0 == "FirefoxURL" + ${If} $0 == "BasiliskURL" ${AndIf} $9 != 0 ; We're not running in session 0 - ReadRegStr $0 HKCU "Software\Classes\FirefoxURL\shell\open\command" "" + ReadRegStr $0 HKCU "Software\Classes\BasiliskURL\shell\open\command" "" ${GetPathFromString} "$0" $0 ${GetParent} "$0" $0 ${If} ${FileExists} "$0" @@ -327,13 +327,13 @@ ClearErrors EnumRegKey $7 HKCR "${FILE_TYPE}" 0 ${If} ${Errors} - WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}" "" "FirefoxHTML" + WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}" "" "BasiliskHTML" ${EndIf} - WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}\OpenWithProgids" "FirefoxHTML" "" + WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}\OpenWithProgids" "BasiliskHTML" "" !macroend !define AddAssociationIfNoneExist "!insertmacro AddAssociationIfNoneExist" -; Adds the protocol and file handler registry entries for making Firefox the +; Adds the protocol and file handler registry entries for making Basilisk the ; default handler (uses SHCTX). !macro SetHandlers ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8 @@ -341,30 +341,30 @@ StrCpy $0 "SOFTWARE\Classes" StrCpy $2 "$\"$8$\" -osint -url $\"%1$\"" - ; Associate the file handlers with FirefoxHTML + ; Associate the file handlers with BasiliskHTML ReadRegStr $6 SHCTX "$0\.htm" "" - ${If} "$6" != "FirefoxHTML" - WriteRegStr SHCTX "$0\.htm" "" "FirefoxHTML" + ${If} "$6" != "BasiliskHTML" + WriteRegStr SHCTX "$0\.htm" "" "BasiliskHTML" ${EndIf} ReadRegStr $6 SHCTX "$0\.html" "" - ${If} "$6" != "FirefoxHTML" - WriteRegStr SHCTX "$0\.html" "" "FirefoxHTML" + ${If} "$6" != "BasiliskHTML" + WriteRegStr SHCTX "$0\.html" "" "BasiliskHTML" ${EndIf} ReadRegStr $6 SHCTX "$0\.shtml" "" - ${If} "$6" != "FirefoxHTML" - WriteRegStr SHCTX "$0\.shtml" "" "FirefoxHTML" + ${If} "$6" != "BasiliskHTML" + WriteRegStr SHCTX "$0\.shtml" "" "BasiliskHTML" ${EndIf} ReadRegStr $6 SHCTX "$0\.xht" "" - ${If} "$6" != "FirefoxHTML" - WriteRegStr SHCTX "$0\.xht" "" "FirefoxHTML" + ${If} "$6" != "BasiliskHTML" + WriteRegStr SHCTX "$0\.xht" "" "BasiliskHTML" ${EndIf} ReadRegStr $6 SHCTX "$0\.xhtml" "" - ${If} "$6" != "FirefoxHTML" - WriteRegStr SHCTX "$0\.xhtml" "" "FirefoxHTML" + ${If} "$6" != "BasiliskHTML" + WriteRegStr SHCTX "$0\.xhtml" "" "BasiliskHTML" ${EndIf} ${AddAssociationIfNoneExist} ".pdf" @@ -374,12 +374,12 @@ ${AddAssociationIfNoneExist} ".pdf" ${AddAssociationIfNoneExist} ".webm" - ; An empty string is used for the 5th param because FirefoxHTML is not a + ; An empty string is used for the 5th param because BasiliskHTML is not a ; protocol handler - ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \ + ${AddDisabledDDEHandlerValues} "BasiliskHTML" "$2" "$8,1" \ "${AppRegName} HTML Document" "" - ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \ + ${AddDisabledDDEHandlerValues} "BasiliskURL" "$2" "$8,1" "${AppRegName} URL" \ "true" ; An empty string is used for the 4th & 5th params because the following ; protocol handlers already have a display name and the additional keys @@ -449,35 +449,35 @@ WriteRegStr ${RegKey} "$0\Capabilities" "ApplicationIcon" "$8,0" WriteRegStr ${RegKey} "$0\Capabilities" "ApplicationName" "${BrandShortName}" - WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".htm" "FirefoxHTML" - WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".html" "FirefoxHTML" - WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".shtml" "FirefoxHTML" - WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".xht" "FirefoxHTML" - WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".xhtml" "FirefoxHTML" + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".htm" "BasiliskHTML" + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".html" "BasiliskHTML" + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".shtml" "BasiliskHTML" + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".xht" "BasiliskHTML" + WriteRegStr ${RegKey} "$0\Capabilities\FileAssociations" ".xhtml" "BasiliskHTML" WriteRegStr ${RegKey} "$0\Capabilities\StartMenu" "StartMenuInternet" "$R9" - WriteRegStr ${RegKey} "$0\Capabilities\URLAssociations" "ftp" "FirefoxURL" - WriteRegStr ${RegKey} "$0\Capabilities\URLAssociations" "http" "FirefoxURL" - WriteRegStr ${RegKey} "$0\Capabilities\URLAssociations" "https" "FirefoxURL" + WriteRegStr ${RegKey} "$0\Capabilities\URLAssociations" "ftp" "BasiliskURL" + WriteRegStr ${RegKey} "$0\Capabilities\URLAssociations" "http" "BasiliskURL" + WriteRegStr ${RegKey} "$0\Capabilities\URLAssociations" "https" "BasiliskURL" ; Vista Registered Application WriteRegStr ${RegKey} "Software\RegisteredApplications" "${AppRegName}" "$0\Capabilities" !macroend !define SetStartMenuInternet "!insertmacro SetStartMenuInternet" -; The IconHandler reference for FirefoxHTML can end up in an inconsistent state +; The IconHandler reference for BasiliskHTML can end up in an inconsistent state ; due to changes not being detected by the IconHandler for side by side ; installs (see bug 268512). The symptoms can be either an incorrect icon or no -; icon being displayed for files associated with Firefox (does not use SHCTX). +; icon being displayed for files associated with Basilisk (does not use SHCTX). !macro FixShellIconHandler RegKey ClearErrors - ReadRegStr $1 ${RegKey} "Software\Classes\FirefoxHTML\ShellEx\IconHandler" "" + ReadRegStr $1 ${RegKey} "Software\Classes\BasiliskHTML\ShellEx\IconHandler" "" ${Unless} ${Errors} - ReadRegStr $1 ${RegKey} "Software\Classes\FirefoxHTML\DefaultIcon" "" + ReadRegStr $1 ${RegKey} "Software\Classes\BasiliskHTML\DefaultIcon" "" ${GetLongPath} "$INSTDIR\${FileMainEXE}" $2 ${If} "$1" != "$2,1" - WriteRegStr ${RegKey} "Software\Classes\FirefoxHTML\DefaultIcon" "" "$2,1" + WriteRegStr ${RegKey} "Software\Classes\BasiliskHTML\DefaultIcon" "" "$2,1" ${EndIf} ${EndUnless} !macroend @@ -612,7 +612,7 @@ ; HKCU Software\Classes keys when associating handlers. The fix uses the merged ; view in HKCR to check for existance of an existing association. This macro ; cleans affected installations by removing the HKLM and HKCU value if it is set -; to FirefoxHTML when there is a value for PersistentHandler or by removing the +; to BasiliskHTML when there is a value for PersistentHandler or by removing the ; HKCU value when the HKLM value has a value other than an empty string. !macro FixBadFileAssociation FILE_TYPE ; Only delete the default value in case the key has values for OpenWithList, @@ -621,16 +621,16 @@ ReadRegStr $1 HKLM "Software\Classes\${FILE_TYPE}" "" ReadRegStr $2 HKCR "${FILE_TYPE}\PersistentHandler" "" ${If} "$2" != "" - ; Since there is a persistent handler remove FirefoxHTML as the default - ; value from both HKCU and HKLM if it set to FirefoxHTML. - ${If} "$0" == "FirefoxHTML" + ; Since there is a persistent handler remove BasiliskHTML as the default + ; value from both HKCU and HKLM if it set to BasiliskHTML. + ${If} "$0" == "BasiliskHTML" DeleteRegValue HKCU "Software\Classes\${FILE_TYPE}" "" ${EndIf} - ${If} "$1" == "FirefoxHTML" + ${If} "$1" == "BasiliskHTML" DeleteRegValue HKLM "Software\Classes\${FILE_TYPE}" "" ${EndIf} - ${ElseIf} "$0" == "FirefoxHTML" - ; Since KHCU is set to FirefoxHTML remove FirefoxHTML as the default value + ${ElseIf} "$0" == "BasiliskHTML" + ; Since KHCU is set to BasiliskHTML remove BasiliskHTML as the default value ; from HKCU if HKLM is set to a value other than an empty string. ${If} "$1" != "" DeleteRegValue HKCU "Software\Classes\${FILE_TYPE}" "" @@ -686,17 +686,17 @@ ; Only set the file and protocol handlers if the existing one under HKCR is ; for this install location. - ${IsHandlerForInstallDir} "FirefoxHTML" $R9 + ${IsHandlerForInstallDir} "BasiliskHTML" $R9 ${If} "$R9" == "true" - ; An empty string is used for the 5th param because FirefoxHTML is not a + ; An empty string is used for the 5th param because BasiliskHTML is not a ; protocol handler. - ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \ + ${AddDisabledDDEHandlerValues} "BasiliskHTML" "$2" "$8,1" \ "${AppRegName} HTML Document" "" ${EndIf} - ${IsHandlerForInstallDir} "FirefoxURL" $R9 + ${IsHandlerForInstallDir} "BasiliskURL" $R9 ${If} "$R9" == "true" - ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" \ + ${AddDisabledDDEHandlerValues} "BasiliskURL" "$2" "$8,1" \ "${AppRegName} URL" "true" ${EndIf} @@ -780,8 +780,8 @@ ${RegCleanAppHandler} "chrome" ; Remove protocol handler registry keys added by the MS shim - DeleteRegKey HKLM "Software\Classes\Firefox.URL" - DeleteRegKey HKCU "Software\Classes\Firefox.URL" + DeleteRegKey HKLM "Software\Classes\Basilisk.URL" + DeleteRegKey HKCU "Software\Classes\Basilisk.URL" ; Delete gopher from Capabilities\URLAssociations if it is present. ${StrFilter} "${FileMainEXE}" "+" "" "" $R9 @@ -792,10 +792,10 @@ DeleteRegValue HKLM "$0\Capabilities\URLAssociations" "gopher" ${EndUnless} - ; Delete gopher from the user's UrlAssociations if it points to FirefoxURL. + ; Delete gopher from the user's UrlAssociations if it points to BasiliskURL. StrCpy $0 "Software\Microsoft\Windows\Shell\Associations\UrlAssociations\gopher" ReadRegStr $2 HKCU "$0\UserChoice" "Progid" - ${If} "$2" == "FirefoxURL" + ${If} "$2" == "BasiliskURL" DeleteRegKey HKCU "$0" ${EndIf} !macroend @@ -943,7 +943,7 @@ ${If} $AddTaskbarSC == "" ; No need to check the default on Win8 and later ${If} ${AtMostWin2008R2} - ; Check if the Firefox is the http handler for this user + ; Check if the Basilisk is the http handler for this user SetShellVarContext current ; Set SHCTX to the current user ${IsHandlerForInstallDir} "http" $R9 ${If} $TmpVal == "HKLM" diff --git a/browser/installer/windows/nsis/stub.nsi b/browser/installer/windows/nsis/stub.nsi deleted file mode 100644 index 5c19c10fe..000000000 --- a/browser/installer/windows/nsis/stub.nsi +++ /dev/null @@ -1,2093 +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/. - -# Required Plugins: -# AppAssocReg -# CertCheck -# InetBgDL -# ShellLink -# UAC - -; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs -!verbose 3 - -SetDatablockOptimize on -SetCompress off -CRCCheck on - -RequestExecutionLevel user - -; The commands inside this ifdef require NSIS 3.0a2 or greater so the ifdef can -; be removed after we require NSIS 3.0a2 or greater. -!ifdef NSIS_PACKEDVERSION - Unicode true - ManifestSupportedOS all - ManifestDPIAware true -!endif - -!addplugindir ./ - -Var Dialog -Var Progressbar -Var ProgressbarMarqueeIntervalMS -Var LabelDownloading -Var LabelInstalling -Var LabelFreeSpace -Var CheckboxSetAsDefault -Var CheckboxShortcutOnBar ; Used for Quicklaunch or Taskbar as appropriate -Var CheckboxShortcutInStartMenu -Var CheckboxShortcutOnDesktop -Var CheckboxSendPing -Var CheckboxInstallMaintSvc -Var DirRequest -Var ButtonBrowse -Var LabelBlurb1 -Var LabelBlurb2 -Var LabelBlurb3 -Var BitmapBlurb1 -Var BitmapBlurb2 -Var BitmapBlurb3 -Var HwndBitmapBlurb1 -Var HwndBitmapBlurb2 -Var HWndBitmapBlurb3 - -Var FontNormal -Var FontItalic -Var FontBlurb - -Var WasOptionsButtonClicked -Var CanWriteToInstallDir -Var HasRequiredSpaceAvailable -Var IsDownloadFinished -Var DownloadSizeBytes -Var HalfOfDownload -Var DownloadReset -Var ExistingTopDir -Var SpaceAvailableBytes -Var InitialInstallDir -Var HandleDownload -Var CanSetAsDefault -Var InstallCounterStep -Var InstallStepSize -Var InstallTotalSteps -Var ProgressCompleted -Var ProgressTotal -Var TmpVal - -Var ExitCode -Var BasiliskLaunchCode - -; The first three tick counts are for the start of a phase and equate equate to -; the display of individual installer pages. -Var StartIntroPhaseTickCount -Var StartOptionsPhaseTickCount -Var StartDownloadPhaseTickCount -; Since the Intro and Options pages can be displayed multiple times the total -; seconds spent on each of these pages is reported. -Var IntroPhaseSeconds -Var OptionsPhaseSeconds -; The tick count for the last download. -Var StartLastDownloadTickCount -; The number of seconds from the start of the download phase until the first -; bytes are received. This is only recorded for first request so it is possible -; to determine connection issues for the first request. -Var DownloadFirstTransferSeconds -; The last four tick counts are for the end of a phase in the installation page. -Var EndDownloadPhaseTickCount -Var EndPreInstallPhaseTickCount -Var EndInstallPhaseTickCount -Var EndFinishPhaseTickCount - -Var InitialInstallRequirementsCode -Var ExistingProfile -Var ExistingVersion -Var ExistingBuildID -Var DownloadedBytes -Var DownloadRetryCount -Var OpenedDownloadPage -Var DownloadServerIP -Var PostSigningData - -Var ControlHeightPX -Var ControlRightPX - -; Uncomment the following to prevent pinging the metrics server when testing -; the stub installer -;!define STUB_DEBUG - -!define StubURLVersion "v7" - -; Successful install exit code -!define ERR_SUCCESS 0 - -/** - * The following errors prefixed with ERR_DOWNLOAD apply to the download phase. - */ -; The download was cancelled by the user -!define ERR_DOWNLOAD_CANCEL 10 - -; Too many attempts to download. The maximum attempts is defined in -; DownloadMaxRetries. -!define ERR_DOWNLOAD_TOO_MANY_RETRIES 11 - -/** - * The following errors prefixed with ERR_PREINSTALL apply to the pre-install - * check phase. - */ -; Unable to acquire a file handle to the downloaded file -!define ERR_PREINSTALL_INVALID_HANDLE 20 - -; The downloaded file's certificate is not trusted by the certificate store. -!define ERR_PREINSTALL_CERT_UNTRUSTED 21 - -; The downloaded file's certificate attribute values were incorrect. -!define ERR_PREINSTALL_CERT_ATTRIBUTES 22 - -; The downloaded file's certificate is not trusted by the certificate store and -; certificate attribute values were incorrect. -!define ERR_PREINSTALL_CERT_UNTRUSTED_AND_ATTRIBUTES 23 - -/** - * The following errors prefixed with ERR_INSTALL apply to the install phase. - */ -; The installation timed out. The installation timeout is defined by the number -; of progress steps defined in InstallTotalSteps and the install timer -; interval defined in InstallIntervalMS -!define ERR_INSTALL_TIMEOUT 30 - -; Maximum times to retry the download before displaying an error -!define DownloadMaxRetries 9 - -; Minimum size expected to download in bytes -!define DownloadMinSizeBytes 15728640 ; 15 MB - -; Maximum size expected to download in bytes -!define DownloadMaxSizeBytes 73400320 ; 70 MB - -; Interval before retrying to download. 3 seconds is used along with 10 -; attempted downloads (the first attempt along with 9 retries) to give a -; minimum of 30 seconds or retrying before giving up. -!define DownloadRetryIntervalMS 3000 - -; Interval for the download timer -!define DownloadIntervalMS 200 - -; Interval for the install timer -!define InstallIntervalMS 100 - -; The first step for the install progress bar. By starting with a large step -; immediate feedback is given to the user. -!define InstallProgressFirstStep 20 - -; The finish step size to quickly increment the progress bar after the -; installation has finished. -!define InstallProgressFinishStep 40 - -; Number of steps for the install progress. -; This might not be enough when installing on a slow network drive so it will -; fallback to downloading the full installer if it reaches this number. The size -; of the install progress step is increased when the full installer finishes -; instead of waiting. - -; Approximately 150 seconds with a 100 millisecond timer and a first step of 20 -; as defined by InstallProgressFirstStep. -!define /math InstallCleanTotalSteps ${InstallProgressFirstStep} + 1500 - -; Approximately 165 seconds (minus 0.2 seconds for each file that is removed) -; with a 100 millisecond timer and a first step of 20 as defined by -; InstallProgressFirstStep . -!define /math InstallPaveOverTotalSteps ${InstallProgressFirstStep} + 1800 - -; On Vista and above attempt to elevate Standard Users in addition to users that -; are a member of the Administrators group. -!define NONADMIN_ELEVATE - -!define CONFIG_INI "config.ini" - -!ifndef FILE_SHARE_READ - !define FILE_SHARE_READ 1 -!endif -!ifndef GENERIC_READ - !define GENERIC_READ 0x80000000 -!endif -!ifndef OPEN_EXISTING - !define OPEN_EXISTING 3 -!endif -!ifndef INVALID_HANDLE_VALUE - !define INVALID_HANDLE_VALUE -1 -!endif - -!include "nsDialogs.nsh" -!include "LogicLib.nsh" -!include "FileFunc.nsh" -!include "TextFunc.nsh" -!include "WinVer.nsh" -!include "WordFunc.nsh" - -!insertmacro GetParameters -!insertmacro GetOptions -!insertmacro LineFind -!insertmacro StrFilter - -!include "locales.nsi" -!include "branding.nsi" - -!include "defines.nsi" - -; Must be included after defines.nsi -!include "locale-fonts.nsh" - -; The OFFICIAL define is a workaround to support different urls for Release and -; Beta since they share the same branding when building with other branches that -; set the update channel to beta. -!ifdef OFFICIAL -!ifdef BETA_UPDATE_CHANNEL -!undef URLStubDownload -!define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-beta-latest" -!undef URLManualDownload -!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=beta&installer_lang=${AB_CD}" -!undef Channel -!define Channel "beta" -!endif -!endif - -!include "common.nsh" - -!insertmacro ElevateUAC -!insertmacro GetLongPath -!insertmacro GetPathFromString -!insertmacro GetParent -!insertmacro GetSingleInstallPath -!insertmacro GetTextWidthHeight -!insertmacro IsUserAdmin -!insertmacro RemovePrecompleteEntries -!insertmacro SetBrandNameVars -!insertmacro ITBL3Create -!insertmacro UnloadUAC - -VIAddVersionKey "FileDescription" "${BrandShortName} Stub Installer" -VIAddVersionKey "OriginalFilename" "setup-stub.exe" - -Name "$BrandFullName" -OutFile "setup-stub.exe" -icon "setup.ico" -XPStyle on -BrandingText " " -ChangeUI all "nsisui.exe" -!ifdef HAVE_64BIT_BUILD - InstallDir "$PROGRAMFILES64\${BrandFullName}\" -!else - InstallDir "$PROGRAMFILES32\${BrandFullName}\" -!endif - -!ifdef ${AB_CD}_rtl - LoadLanguageFile "locale-rtl.nlf" -!else - LoadLanguageFile "locale.nlf" -!endif - -!include "nsisstrings.nlf" - -!if "${AB_CD}" == "en-US" - ; Custom strings for en-US. This is done here so they aren't translated. - !include oneoff_en-US.nsh -!else - !define INTRO_BLURB "$(INTRO_BLURB1)" - !define INSTALL_BLURB1 "$(INSTALL_BLURB1)" - !define INSTALL_BLURB2 "$(INSTALL_BLURB2)" - !define INSTALL_BLURB3 "$(INSTALL_BLURB3)" -!endif - -Caption "$(WIN_CAPTION)" - -Page custom createDummy ; Needed to enable the Intro page's back button -Page custom createIntro leaveIntro ; Introduction page -Page custom createOptions leaveOptions ; Options page -Page custom createInstall ; Download / Installation page - -Function .onInit - ; Remove the current exe directory from the search order. - ; This only effects LoadLibrary calls and not implicitly loaded DLLs. - System::Call 'kernel32::SetDllDirectoryW(w "")' - - StrCpy $LANGUAGE 0 - ; This macro is used to set the brand name variables but the ini file method - ; isn't supported for the stub installer. - ${SetBrandNameVars} "$PLUGINSDIR\ignored.ini" - - ; Don't install on systems that don't support SSE2. The parameter value of - ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the - ; SSE2 instruction set is available. - System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7" - -!ifdef HAVE_64BIT_BUILD - ; Restrict x64 builds from being installed on x86 and pre Win7 - ${Unless} ${RunningX64} - ${OrUnless} ${AtLeastWin7} - ${If} "$R7" == "0" - strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" - ${Else} - strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_MSG)" - ${EndIf} - MessageBox MB_OKCANCEL|MB_ICONSTOP "$R7" IDCANCEL +2 - ExecShell "open" "${URLSystemRequirements}" - Quit - ${EndUnless} - - SetRegView 64 -!else - StrCpy $R8 "0" - ${If} ${AtMostWin2000} - StrCpy $R8 "1" - ${EndIf} - - ${If} ${IsWinXP} - ${AndIf} ${AtMostServicePack} 1 - StrCpy $R8 "1" - ${EndIf} - - ${If} $R8 == "1" - ; XXX-rstrong - some systems failed the AtLeastWin2000 test that we - ; used to use for an unknown reason and likely fail the AtMostWin2000 - ; and possibly the IsWinXP test as well. To work around this also - ; check if the Windows NT registry Key exists and if it does if the - ; first char in CurrentVersion is equal to 3 (Windows NT 3.5 and - ; 3.5.1), 4 (Windows NT 4), or 5 (Windows 2000 and Windows XP). - StrCpy $R8 "" - ClearErrors - ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion" - StrCpy $R8 "$R8" 1 - ${If} ${Errors} - ${OrIf} "$R8" == "3" - ${OrIf} "$R8" == "4" - ${OrIf} "$R8" == "5" - ${If} "$R7" == "0" - strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" - ${Else} - strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_MSG)" - ${EndIf} - MessageBox MB_OKCANCEL|MB_ICONSTOP "$R7" IDCANCEL +2 - ExecShell "open" "${URLSystemRequirements}" - Quit - ${EndIf} - ${EndUnless} -!endif - - ${If} "$R7" == "0" - MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_CPU_MSG)" IDCANCEL +2 - ExecShell "open" "${URLSystemRequirements}" - Quit - ${EndIf} - - ; Require elevation if the user can elevate - ${ElevateUAC} - -; The commands inside this ifndef are needed prior to NSIS 3.0a2 and can be -; removed after we require NSIS 3.0a2 or greater. -!ifndef NSIS_PACKEDVERSION - ${If} ${AtLeastWinVista} - System::Call 'user32::SetProcessDPIAware()' - ${EndIf} -!endif - - SetShellVarContext all ; Set SHCTX to HKLM - ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9 - - ${If} "$R9" == "false" - SetShellVarContext current ; Set SHCTX to HKCU - ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9 - - ${If} ${RunningX64} - ; In HKCU there is no WOW64 redirection, which means we may have gotten - ; the path to a 32-bit install even though we're 64-bit, or vice-versa. - ; In that case, just use the default path instead of offering an upgrade. - ; But only do that override if the existing install is in Program Files, - ; because that's the only place we can be sure is specific - ; to either 32 or 64 bit applications. - ; The WordFind syntax below searches for the first occurence of the - ; "delimiter" (the Program Files path) in the install path and returns - ; anything that appears before that. If nothing appears before that, - ; then the install is under Program Files (32 or 64). -!ifdef HAVE_64BIT_BUILD - ${WordFind} $R9 $PROGRAMFILES32 "+1{" $0 -!else - ${WordFind} $R9 $PROGRAMFILES64 "+1{" $0 -!endif - ${If} $0 == "" - StrCpy $R9 "false" - ${EndIf} - ${EndIf} - ${EndIf} - - ${If} "$R9" != "false" - StrCpy $INSTDIR "$R9" - ${EndIf} - - ; Used to determine if the default installation directory was used. - StrCpy $InitialInstallDir "$INSTDIR" - - ClearErrors - WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \ - "Write Test" - - ; Only display set as default when there is write access to HKLM and on Win7 - ; and below. - ${If} ${Errors} - ${OrIf} ${AtLeastWin8} - StrCpy $CanSetAsDefault "false" - StrCpy $CheckboxSetAsDefault "0" - ${Else} - DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" - StrCpy $CanSetAsDefault "true" - ${EndIf} - - ; The interval in MS used for the progress bars set as marquee. - ${If} ${AtLeastWinVista} - StrCpy $ProgressbarMarqueeIntervalMS "10" - ${Else} - StrCpy $ProgressbarMarqueeIntervalMS "50" - ${EndIf} - - ; Initialize the majority of variables except those that need to be reset - ; when a page is displayed. - StrCpy $IntroPhaseSeconds "0" - StrCpy $OptionsPhaseSeconds "0" - StrCpy $EndPreInstallPhaseTickCount "0" - StrCpy $EndInstallPhaseTickCount "0" - StrCpy $InitialInstallRequirementsCode "" - StrCpy $IsDownloadFinished "" - StrCpy $BasiliskLaunchCode "0" - StrCpy $CheckboxShortcutOnBar "1" - StrCpy $CheckboxShortcutInStartMenu "1" - StrCpy $CheckboxShortcutOnDesktop "1" - StrCpy $CheckboxSendPing "1" -!ifdef MOZ_MAINTENANCE_SERVICE - StrCpy $CheckboxInstallMaintSvc "1" -!else - StrCpy $CheckboxInstallMaintSvc "0" -!endif - StrCpy $WasOptionsButtonClicked "0" - - StrCpy $0 "" -!ifdef FONT_FILE1 - ${If} ${FileExists} "$FONTS\${FONT_FILE1}" - StrCpy $0 "${FONT_NAME1}" - ${EndIf} -!endif - -!ifdef FONT_FILE2 - ${If} $0 == "" - ${AndIf} ${FileExists} "$FONTS\${FONT_FILE2}" - StrCpy $0 "${FONT_NAME2}" - ${EndIf} -!endif - - ${If} $0 == "" - StrCpy $0 "$(^Font)" - ${EndIf} - - CreateFont $FontBlurb "$0" "12" "500" - CreateFont $FontNormal "$0" "11" "500" - CreateFont $FontItalic "$0" "11" "500" /ITALIC - - InitPluginsDir - File /oname=$PLUGINSDIR\bgintro.bmp "bgintro.bmp" - File /oname=$PLUGINSDIR\appname.bmp "appname.bmp" - File /oname=$PLUGINSDIR\clock.bmp "clock.bmp" - File /oname=$PLUGINSDIR\particles.bmp "particles.bmp" -!ifdef ${AB_CD}_rtl - ; The horizontally flipped pencil looks better in RTL - File /oname=$PLUGINSDIR\pencil.bmp "pencil-rtl.bmp" -!else - File /oname=$PLUGINSDIR\pencil.bmp "pencil.bmp" -!endif -FunctionEnd - -; .onGUIInit isn't needed except for RTL locales -!ifdef ${AB_CD}_rtl -Function .onGUIInit - ; Since NSIS RTL support doesn't mirror progress bars use Windows mirroring. - ${NSD_AddExStyle} $HWNDPARENT ${WS_EX_LAYOUTRTL} - ${RemoveExStyle} $HWNDPARENT ${WS_EX_RTLREADING} - ${RemoveExStyle} $HWNDPARENT ${WS_EX_RIGHT} - ${NSD_AddExStyle} $HWNDPARENT ${WS_EX_LEFT}|${WS_EX_LTRREADING} -FunctionEnd -!endif - -Function .onGUIEnd - Delete "$PLUGINSDIR\_temp" - Delete "$PLUGINSDIR\download.exe" - Delete "$PLUGINSDIR\${CONFIG_INI}" - - ${UnloadUAC} -FunctionEnd - -Function .onUserAbort - ${NSD_KillTimer} StartDownload - ${NSD_KillTimer} OnDownload - ${NSD_KillTimer} CheckInstall - ${NSD_KillTimer} FinishInstall - ${NSD_KillTimer} FinishProgressBar - ${NSD_KillTimer} DisplayDownloadError - - ${If} "$IsDownloadFinished" != "" - Call DisplayDownloadError - ; Aborting the abort will allow SendPing which is called by - ; DisplayDownloadError to hide the installer window and close the installer - ; after it sends the metrics ping. - Abort - ${EndIf} -FunctionEnd - -Function SendPing - HideWindow - ; Try to send a ping if a download was attempted - ${If} $CheckboxSendPing == 1 - ${AndIf} $IsDownloadFinished != "" - ; Get the tick count for the completion of all phases. - System::Call "kernel32::GetTickCount()l .s" - Pop $EndFinishPhaseTickCount - - ; When the value of $IsDownloadFinished is false the download was started - ; but didn't finish. In this case the tick count stored in - ; $EndFinishPhaseTickCount is used to determine how long the download was - ; in progress. - ${If} "$IsDownloadFinished" == "false" - ${OrIf} "$EndDownloadPhaseTickCount" == "" - StrCpy $EndDownloadPhaseTickCount "$EndFinishPhaseTickCount" - ; Cancel the download in progress - InetBgDL::Get /RESET /END - ${EndIf} - - - ; When $DownloadFirstTransferSeconds equals an empty string the download - ; never successfully started so set the value to 0. It will be possible to - ; determine that the download didn't successfully start from the seconds for - ; the last download. - ${If} "$DownloadFirstTransferSeconds" == "" - StrCpy $DownloadFirstTransferSeconds "0" - ${EndIf} - - ; When $StartLastDownloadTickCount equals an empty string the download never - ; successfully started so set the value to $EndDownloadPhaseTickCount to - ; compute the correct value. - ${If} $StartLastDownloadTickCount == "" - ; This could happen if the download never successfully starts - StrCpy $StartLastDownloadTickCount "$EndDownloadPhaseTickCount" - ${EndIf} - - ; When $EndPreInstallPhaseTickCount equals 0 the installation phase was - ; never completed so set its value to $EndFinishPhaseTickCount to compute - ; the correct value. - ${If} "$EndPreInstallPhaseTickCount" == "0" - StrCpy $EndPreInstallPhaseTickCount "$EndFinishPhaseTickCount" - ${EndIf} - - ; When $EndInstallPhaseTickCount equals 0 the installation phase was never - ; completed so set its value to $EndFinishPhaseTickCount to compute the - ; correct value. - ${If} "$EndInstallPhaseTickCount" == "0" - StrCpy $EndInstallPhaseTickCount "$EndFinishPhaseTickCount" - ${EndIf} - - ; Get the seconds elapsed from the start of the download phase to the end of - ; the download phase. - ${GetSecondsElapsed} "$StartDownloadPhaseTickCount" "$EndDownloadPhaseTickCount" $0 - - ; Get the seconds elapsed from the start of the last download to the end of - ; the last download. - ${GetSecondsElapsed} "$StartLastDownloadTickCount" "$EndDownloadPhaseTickCount" $1 - - ; Get the seconds elapsed from the end of the download phase to the - ; completion of the pre-installation check phase. - ${GetSecondsElapsed} "$EndDownloadPhaseTickCount" "$EndPreInstallPhaseTickCount" $2 - - ; Get the seconds elapsed from the end of the pre-installation check phase - ; to the completion of the installation phase. - ${GetSecondsElapsed} "$EndPreInstallPhaseTickCount" "$EndInstallPhaseTickCount" $3 - - ; Get the seconds elapsed from the end of the installation phase to the - ; completion of all phases. - ${GetSecondsElapsed} "$EndInstallPhaseTickCount" "$EndFinishPhaseTickCount" $4 - -!ifdef HAVE_64BIT_BUILD - StrCpy $R0 "1" -!else - StrCpy $R0 "0" -!endif - - ${If} ${RunningX64} - StrCpy $R1 "1" - ${Else} - StrCpy $R1 "0" - ${EndIf} - - ; Though these values are sometimes incorrect due to bug 444664 it happens - ; so rarely it isn't worth working around it by reading the registry values. - ${WinVerGetMajor} $5 - ${WinVerGetMinor} $6 - ${WinVerGetBuild} $7 - ${WinVerGetServicePackLevel} $8 - ${If} ${IsServerOS} - StrCpy $9 "1" - ${Else} - StrCpy $9 "0" - ${EndIf} - - ${If} "$ExitCode" == "${ERR_SUCCESS}" - ReadINIStr $R5 "$INSTDIR\application.ini" "App" "Version" - ReadINIStr $R6 "$INSTDIR\application.ini" "App" "BuildID" - ${Else} - StrCpy $R5 "0" - StrCpy $R6 "0" - ${EndIf} - - ; Whether installed into the default installation directory - ${GetLongPath} "$INSTDIR" $R7 - ${GetLongPath} "$InitialInstallDir" $R8 - ${If} "$R7" == "$R8" - StrCpy $R7 "1" - ${Else} - StrCpy $R7 "0" - ${EndIf} - - ClearErrors - WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \ - "Write Test" - ${If} ${Errors} - StrCpy $R8 "0" - ${Else} - DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" - StrCpy $R8 "1" - ${EndIf} - - ${If} "$DownloadServerIP" == "" - StrCpy $DownloadServerIP "Unknown" - ${EndIf} - - StrCpy $R2 "" - SetShellVarContext current ; Set SHCTX to the current user - ReadRegStr $R2 HKCU "Software\Classes\http\shell\open\command" "" - ${If} $R2 != "" - ${GetPathFromString} "$R2" $R2 - ${GetParent} "$R2" $R3 - ${GetLongPath} "$R3" $R3 - ${If} $R3 == $INSTDIR - StrCpy $R2 "1" ; This Basilisk install is set as default. - ${Else} - StrCpy $R2 "$R2" "" -11 # length of firefox.exe - ${If} "$R2" == "${FileMainEXE}" - StrCpy $R2 "2" ; Another Basilisk install is set as default. - ${Else} - StrCpy $R2 "0" - ${EndIf} - ${EndIf} - ${Else} - StrCpy $R2 "0" ; Basilisk is not set as default. - ${EndIf} - - ${If} "$R2" == "0" - ${AndIf} ${AtLeastWinVista} - ; Check to see if this install location is currently set as the default - ; browser by Default Programs which is only available on Vista and above. - ClearErrors - ReadRegStr $R3 HKLM "Software\RegisteredApplications" "${AppRegName}" - ${Unless} ${Errors} - AppAssocReg::QueryAppIsDefaultAll "${AppRegName}" "effective" - Pop $R3 - ${If} $R3 == "1" - StrCpy $R3 "" - ReadRegStr $R2 HKLM "Software\Classes\http\shell\open\command" "" - ${If} $R2 != "" - ${GetPathFromString} "$R2" $R2 - ${GetParent} "$R2" $R3 - ${GetLongPath} "$R3" $R3 - ${If} $R3 == $INSTDIR - StrCpy $R2 "1" ; This Basilisk install is set as default. - ${Else} - StrCpy $R2 "$R2" "" -11 # length of firefox.exe - ${If} "$R2" == "${FileMainEXE}" - StrCpy $R2 "2" ; Another Basilisk install is set as default. - ${Else} - StrCpy $R2 "0" - ${EndIf} - ${EndIf} - ${Else} - StrCpy $R2 "0" ; Basilisk is not set as default. - ${EndIf} - ${EndIf} - ${EndUnless} - ${EndIf} - - ${If} $CanSetAsDefault == "true" - ${If} $CheckboxSetAsDefault == "1" - StrCpy $R3 "2" - ${Else} - StrCpy $R3 "3" - ${EndIf} - ${Else} - ${If} ${AtLeastWin8} - StrCpy $R3 "1" - ${Else} - StrCpy $R3 "0" - ${EndIf} - ${EndIf} - -!ifdef STUB_DEBUG - MessageBox MB_OK "${BaseURLStubPing} \ - $\nStub URL Version = ${StubURLVersion}${StubURLVersionAppend} \ - $\nBuild Channel = ${Channel} \ - $\nUpdate Channel = ${UpdateChannel} \ - $\nLocale = ${AB_CD} \ - $\nBasilisk x64 = $R0 \ - $\nRunning x64 Windows = $R1 \ - $\nMajor = $5 \ - $\nMinor = $6 \ - $\nBuild = $7 \ - $\nServicePack = $8 \ - $\nIsServer = $9 \ - $\nExit Code = $ExitCode \ - $\nBasilisk Launch Code = $BasiliskLaunchCode \ - $\nDownload Retry Count = $DownloadRetryCount \ - $\nDownloaded Bytes = $DownloadedBytes \ - $\nDownload Size Bytes = $DownloadSizeBytes \ - $\nIntroduction Phase Seconds = $IntroPhaseSeconds \ - $\nOptions Phase Seconds = $OptionsPhaseSeconds \ - $\nDownload Phase Seconds = $0 \ - $\nLast Download Seconds = $1 \ - $\nDownload First Transfer Seconds = $DownloadFirstTransferSeconds \ - $\nPreinstall Phase Seconds = $2 \ - $\nInstall Phase Seconds = $3 \ - $\nFinish Phase Seconds = $4 \ - $\nInitial Install Requirements Code = $InitialInstallRequirementsCode \ - $\nOpened Download Page = $OpenedDownloadPage \ - $\nExisting Profile = $ExistingProfile \ - $\nExisting Version = $ExistingVersion \ - $\nExisting Build ID = $ExistingBuildID \ - $\nNew Version = $R5 \ - $\nNew Build ID = $R6 \ - $\nDefault Install Dir = $R7 \ - $\nHas Admin = $R8 \ - $\nDefault Status = $R2 \ - $\nSet As Sefault Status = $R3 \ - $\nDownload Server IP = $DownloadServerIP \ - $\nPost-Signing Data = $PostSigningData" - ; The following will exit the installer - SetAutoClose true - StrCpy $R9 "2" - Call RelativeGotoPage -!else - ${NSD_CreateTimer} OnPing ${DownloadIntervalMS} - InetBgDL::Get "${BaseURLStubPing}/${StubURLVersion}${StubURLVersionAppend}/${Channel}/${UpdateChannel}/${AB_CD}/$R0/$R1/$5/$6/$7/$8/$9/$ExitCode/$BasiliskLaunchCode/$DownloadRetryCount/$DownloadedBytes/$DownloadSizeBytes/$IntroPhaseSeconds/$OptionsPhaseSeconds/$0/$1/$DownloadFirstTransferSeconds/$2/$3/$4/$InitialInstallRequirementsCode/$OpenedDownloadPage/$ExistingProfile/$ExistingVersion/$ExistingBuildID/$R5/$R6/$R7/$R8/$R2/$R3/$DownloadServerIP/$PostSigningData" \ - "$PLUGINSDIR\_temp" /END -!endif - ${Else} - ${If} "$IsDownloadFinished" == "false" - ; Cancel the download in progress - InetBgDL::Get /RESET /END - ${EndIf} - ; The following will exit the installer - SetAutoClose true - StrCpy $R9 "2" - Call RelativeGotoPage - ${EndIf} -FunctionEnd - -Function createDummy -FunctionEnd - -Function createIntro - nsDialogs::Create /NOUNLOAD 1018 - Pop $Dialog - - GetFunctionAddress $0 OnBack - nsDialogs::OnBack /NOUNLOAD $0 - -!ifdef ${AB_CD}_rtl - ; For RTL align the text with the top of the F in the Basilisk bitmap - StrCpy $0 "${INTRO_BLURB_RTL_TOP_DU}" -!else - ; For LTR align the text with the top of the x in the Basilisk bitmap - StrCpy $0 "${INTRO_BLURB_LTR_TOP_DU}" -!endif - ${NSD_CreateLabel} ${INTRO_BLURB_EDGE_DU} $0 ${INTRO_BLURB_WIDTH_DU} 76u "${INTRO_BLURB}" - Pop $0 - SendMessage $0 ${WM_SETFONT} $FontBlurb 0 - SetCtlColors $0 ${INTRO_BLURB_TEXT_COLOR} transparent - - SetCtlColors $HWNDPARENT ${FOOTER_CONTROL_TEXT_COLOR_NORMAL} ${FOOTER_BKGRD_COLOR} - GetDlgItem $0 $HWNDPARENT 10 ; Default browser checkbox - ${If} "$CanSetAsDefault" == "true" - ; The uxtheme must be disabled on checkboxes in order to override the - ; system font color. - System::Call 'uxtheme::SetWindowTheme(i $0 , w " ", w " ")' - SendMessage $0 ${WM_SETFONT} $FontNormal 0 - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(MAKE_DEFAULT)" - SendMessage $0 ${BM_SETCHECK} 1 0 - SetCtlColors $0 ${FOOTER_CONTROL_TEXT_COLOR_NORMAL} ${FOOTER_BKGRD_COLOR} - ${Else} - ShowWindow $0 ${SW_HIDE} - ${EndIf} - GetDlgItem $0 $HWNDPARENT 11 - ShowWindow $0 ${SW_HIDE} - - ${NSD_CreateBitmap} ${APPNAME_BMP_EDGE_DU} ${APPNAME_BMP_TOP_DU} \ - ${APPNAME_BMP_WIDTH_DU} ${APPNAME_BMP_HEIGHT_DU} "" - Pop $2 - ${SetStretchedTransparentImage} $2 $PLUGINSDIR\appname.bmp $0 - - ${NSD_CreateBitmap} 0 0 100% 100% "" - Pop $2 - ${NSD_SetStretchedImage} $2 $PLUGINSDIR\bgintro.bmp $1 - - GetDlgItem $0 $HWNDPARENT 1 ; Install button - ${If} ${FileExists} "$INSTDIR\${FileMainEXE}" - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(UPGRADE_BUTTON)" - ${Else} - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(INSTALL_BUTTON)" - ${EndIf} - ${NSD_SetFocus} $0 - - GetDlgItem $0 $HWNDPARENT 2 ; Cancel button - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(CANCEL_BUTTON)" - - GetDlgItem $0 $HWNDPARENT 3 ; Back button used for Options - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(OPTIONS_BUTTON)" - - System::Call "kernel32::GetTickCount()l .s" - Pop $StartIntroPhaseTickCount - - LockWindow off - nsDialogs::Show - - ${NSD_FreeImage} $0 - ${NSD_FreeImage} $1 -FunctionEnd - -Function leaveIntro - LockWindow on - - System::Call "kernel32::GetTickCount()l .s" - Pop $0 - ${GetSecondsElapsed} "$StartIntroPhaseTickCount" "$0" $IntroPhaseSeconds - ; It is possible for this value to be 0 if the user clicks fast enough so - ; increment the value by 1 if it is 0. - ${If} $IntroPhaseSeconds == 0 - IntOp $IntroPhaseSeconds $IntroPhaseSeconds + 1 - ${EndIf} - - SetShellVarContext all ; Set SHCTX to All Users - ; If the user doesn't have write access to the installation directory set - ; the installation directory to a subdirectory of the All Users application - ; directory and if the user can't write to that location set the installation - ; directory to a subdirectory of the users local application directory - ; (e.g. non-roaming). - Call CanWrite - ${If} "$CanWriteToInstallDir" == "false" - StrCpy $INSTDIR "$APPDATA\${BrandFullName}\" - Call CanWrite - ${If} "$CanWriteToInstallDir" == "false" - ; This should never happen but just in case. - StrCpy $CanWriteToInstallDir "false" - ${Else} - StrCpy $INSTDIR "$LOCALAPPDATA\${BrandFullName}\" - Call CanWrite - ${EndIf} - ${EndIf} - - Call CheckSpace - - ${If} ${FileExists} "$INSTDIR" - ; Always display the long path if the path exists. - ${GetLongPath} "$INSTDIR" $INSTDIR - ${EndIf} - -FunctionEnd - -Function createOptions - ; Check whether the install requirements are satisfied using the default - ; values for metrics. - ${If} "$InitialInstallRequirementsCode" == "" - ${If} "$CanWriteToInstallDir" != "true" - ${AndIf} "$HasRequiredSpaceAvailable" != "true" - StrCpy $InitialInstallRequirementsCode "1" - ${ElseIf} "$CanWriteToInstallDir" != "true" - StrCpy $InitialInstallRequirementsCode "2" - ${ElseIf} "$HasRequiredSpaceAvailable" != "true" - StrCpy $InitialInstallRequirementsCode "3" - ${Else} - StrCpy $InitialInstallRequirementsCode "0" - ${EndIf} - ${EndIf} - - ; Skip the options page unless the Options button was clicked as long as the - ; installation directory can be written to and there is the minimum required - ; space available. - ${If} "$WasOptionsButtonClicked" != "1" - ${If} "$CanWriteToInstallDir" == "true" - ${AndIf} "$HasRequiredSpaceAvailable" == "true" - Abort ; Skip the options page - ${EndIf} - ${EndIf} - - StrCpy $ExistingTopDir "" - - nsDialogs::Create /NOUNLOAD 1018 - Pop $Dialog - ; Since the text color for controls is set in this Dialog the foreground and - ; background colors of the Dialog must also be hardcoded. - SetCtlColors $Dialog ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - - ${NSD_CreateLabel} ${OPTIONS_ITEM_EDGE_DU} 18u ${OPTIONS_ITEM_WIDTH_DU} \ - 12u "$(CREATE_SHORTCUTS)" - Pop $0 - SetCtlColors $0 ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $0 ${WM_SETFONT} $FontNormal 0 - - ${If} ${AtLeastWin7} - StrCpy $0 "$(ADD_SC_TASKBAR)" - ${Else} - StrCpy $0 "$(ADD_SC_QUICKLAUNCHBAR)" - ${EndIf} - ${NSD_CreateCheckbox} ${OPTIONS_SUBITEM_EDGE_DU} 38u \ - ${OPTIONS_SUBITEM_WIDTH_DU} 12u "$0" - Pop $CheckboxShortcutOnBar - ; The uxtheme must be disabled on checkboxes in order to override the system - ; font color. - System::Call 'uxtheme::SetWindowTheme(i $CheckboxShortcutOnBar, w " ", w " ")' - SetCtlColors $CheckboxShortcutOnBar ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $CheckboxShortcutOnBar ${WM_SETFONT} $FontNormal 0 - ${NSD_Check} $CheckboxShortcutOnBar - - ${NSD_CreateCheckbox} ${OPTIONS_SUBITEM_EDGE_DU} 54u ${OPTIONS_SUBITEM_WIDTH_DU} \ - 12u "$(ADD_CheckboxShortcutInStartMenu)" - Pop $CheckboxShortcutInStartMenu - ; The uxtheme must be disabled on checkboxes in order to override the system - ; font color. - System::Call 'uxtheme::SetWindowTheme(i $CheckboxShortcutInStartMenu, w " ", w " ")' - SetCtlColors $CheckboxShortcutInStartMenu ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $CheckboxShortcutInStartMenu ${WM_SETFONT} $FontNormal 0 - ${NSD_Check} $CheckboxShortcutInStartMenu - - ${NSD_CreateCheckbox} ${OPTIONS_SUBITEM_EDGE_DU} 70u ${OPTIONS_SUBITEM_WIDTH_DU} \ - 12u "$(ADD_CheckboxShortcutOnDesktop)" - Pop $CheckboxShortcutOnDesktop - ; The uxtheme must be disabled on checkboxes in order to override the system - ; font color. - System::Call 'uxtheme::SetWindowTheme(i $CheckboxShortcutOnDesktop, w " ", w " ")' - SetCtlColors $CheckboxShortcutOnDesktop ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $CheckboxShortcutOnDesktop ${WM_SETFONT} $FontNormal 0 - ${NSD_Check} $CheckboxShortcutOnDesktop - - ${NSD_CreateLabel} ${OPTIONS_ITEM_EDGE_DU} 100u ${OPTIONS_ITEM_WIDTH_DU} \ - 12u "$(DEST_FOLDER)" - Pop $0 - SetCtlColors $0 ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $0 ${WM_SETFONT} $FontNormal 0 - - ${NSD_CreateDirRequest} ${OPTIONS_SUBITEM_EDGE_DU} 116u 159u 14u "$INSTDIR" - Pop $DirRequest - SetCtlColors $DirRequest ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $DirRequest ${WM_SETFONT} $FontNormal 0 - System::Call shlwapi::SHAutoComplete(i $DirRequest, i ${SHACF_FILESYSTEM}) - ${NSD_OnChange} $DirRequest OnChange_DirRequest - -!ifdef ${AB_CD}_rtl - ; Remove the RTL styling from the directory request text box - ${RemoveStyle} $DirRequest ${SS_RIGHT} - ${RemoveExStyle} $DirRequest ${WS_EX_RIGHT} - ${RemoveExStyle} $DirRequest ${WS_EX_RTLREADING} - ${NSD_AddStyle} $DirRequest ${SS_LEFT} - ${NSD_AddExStyle} $DirRequest ${WS_EX_LTRREADING}|${WS_EX_LEFT} -!endif - - ${NSD_CreateBrowseButton} 280u 116u 50u 14u "$(BROWSE_BUTTON)" - Pop $ButtonBrowse - SetCtlColors $ButtonBrowse "" ${COMMON_BKGRD_COLOR} - ${NSD_OnClick} $ButtonBrowse OnClick_ButtonBrowse - - ; Get the number of pixels from the left of the Dialog to the right side of - ; the "Space Required:" and "Space Available:" labels prior to setting RTL so - ; the correct position of the controls can be set by NSIS for RTL locales. - - ; Get the width and height of both labels and use the tallest for the height - ; and the widest to calculate where to place the labels after these labels. - ${GetTextExtent} "$(SPACE_REQUIRED)" $FontItalic $0 $1 - ${GetTextExtent} "$(SPACE_AVAILABLE)" $FontItalic $2 $3 - ${If} $1 > $3 - StrCpy $ControlHeightPX "$1" - ${Else} - StrCpy $ControlHeightPX "$3" - ${EndIf} - - IntOp $0 $0 + 8 ; Add padding to the control's width - ; Make both controls the same width as the widest control - ${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 134u $0 $ControlHeightPX "$(SPACE_REQUIRED)" - Pop $5 - SetCtlColors $5 ${COMMON_TEXT_COLOR_FADED} ${COMMON_BKGRD_COLOR} - SendMessage $5 ${WM_SETFONT} $FontItalic 0 - - IntOp $2 $2 + 8 ; Add padding to the control's width - ${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 145u $2 $ControlHeightPX "$(SPACE_AVAILABLE)" - Pop $6 - SetCtlColors $6 ${COMMON_TEXT_COLOR_FADED} ${COMMON_BKGRD_COLOR} - SendMessage $6 ${WM_SETFONT} $FontItalic 0 - - ; Use the widest label for aligning the labels next to them - ${If} $0 > $2 - StrCpy $6 "$5" - ${EndIf} - FindWindow $1 "#32770" "" $HWNDPARENT - ${GetDlgItemEndPX} $6 $ControlRightPX - - IntOp $ControlRightPX $ControlRightPX + 6 - - ${NSD_CreateLabel} $ControlRightPX 134u 100% $ControlHeightPX \ - "${APPROXIMATE_REQUIRED_SPACE_MB} $(MEGA)$(BYTE)" - Pop $7 - SetCtlColors $7 ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $7 ${WM_SETFONT} $FontNormal 0 - - ; Create the free space label with an empty string and update it by calling - ; UpdateFreeSpaceLabel - ${NSD_CreateLabel} $ControlRightPX 145u 100% $ControlHeightPX " " - Pop $LabelFreeSpace - SetCtlColors $LabelFreeSpace ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $LabelFreeSpace ${WM_SETFONT} $FontNormal 0 - - Call UpdateFreeSpaceLabel - - ${NSD_CreateCheckbox} ${OPTIONS_ITEM_EDGE_DU} 168u ${OPTIONS_SUBITEM_WIDTH_DU} \ - 12u "$(SEND_PING)" - Pop $CheckboxSendPing - ; The uxtheme must be disabled on checkboxes in order to override the system - ; font color. - System::Call 'uxtheme::SetWindowTheme(i $CheckboxSendPing, w " ", w " ")' - SetCtlColors $CheckboxSendPing ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $CheckboxSendPing ${WM_SETFONT} $FontNormal 0 - ${NSD_Check} $CheckboxSendPing - -!ifdef MOZ_MAINTENANCE_SERVICE - ; We can only install the maintenance service if the user is an admin. - Call IsUserAdmin - Pop $0 - - ; Only show the maintenance service checkbox if we're on XP SP3 or higher; - ; we don't ever want to install it on XP without at least SP3 installed. - ${If} $0 == "true" - ${AndIf} ${IsWinXP} - ${AndIf} ${AtMostServicePack} 2 - StrCpy $0 "false" - ${EndIf} - - ; Only show the maintenance service checkbox if we have write access to HKLM - ClearErrors - WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \ - "Write Test" - ${If} ${Errors} - ${OrIf} $0 != "true" - StrCpy $CheckboxInstallMaintSvc "0" - ${Else} - DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" - ; Read the registry instead of using ServicesHelper::IsInstalled so the - ; plugin isn't included in the stub installer to lessen its size. - ClearErrors - ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\services\MozillaMaintenance" "ImagePath" - ${If} ${Errors} - ${NSD_CreateCheckbox} ${OPTIONS_ITEM_EDGE_DU} 184u ${OPTIONS_ITEM_WIDTH_DU} \ - 12u "$(INSTALL_MAINT_SERVICE)" - Pop $CheckboxInstallMaintSvc - System::Call 'uxtheme::SetWindowTheme(i $CheckboxInstallMaintSvc, w " ", w " ")' - SetCtlColors $CheckboxInstallMaintSvc ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - SendMessage $CheckboxInstallMaintSvc ${WM_SETFONT} $FontNormal 0 - ${NSD_Check} $CheckboxInstallMaintSvc - ${EndIf} - ${EndIf} -!endif - - GetDlgItem $0 $HWNDPARENT 1 ; Install button - ${If} ${FileExists} "$INSTDIR\${FileMainEXE}" - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(UPGRADE_BUTTON)" - ${Else} - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(INSTALL_BUTTON)" - ${EndIf} - ${NSD_SetFocus} $0 - - GetDlgItem $0 $HWNDPARENT 2 ; Cancel button - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(CANCEL_BUTTON)" - - GetDlgItem $0 $HWNDPARENT 3 ; Back button used for Options - EnableWindow $0 0 - ShowWindow $0 ${SW_HIDE} - - ; If the option button was not clicked display the reason for what needs to be - ; resolved to continue the installation. - ${If} "$WasOptionsButtonClicked" != "1" - ${If} "$CanWriteToInstallDir" == "false" - MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_WRITE_ACCESS)" - ${ElseIf} "$HasRequiredSpaceAvailable" == "false" - MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_DISK_SPACE)" - ${EndIf} - ${EndIf} - - System::Call "kernel32::GetTickCount()l .s" - Pop $StartOptionsPhaseTickCount - - LockWindow off - nsDialogs::Show -FunctionEnd - -Function leaveOptions - LockWindow on - - ${GetRoot} "$INSTDIR" $0 - ${GetLongPath} "$INSTDIR" $INSTDIR - ${GetLongPath} "$0" $0 - ${If} "$INSTDIR" == "$0" - LockWindow off - MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_ROOT_INSTALL)" - Abort ; Stay on the page - ${EndIf} - - Call CanWrite - ${If} "$CanWriteToInstallDir" == "false" - LockWindow off - MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_WRITE_ACCESS)" - Abort ; Stay on the page - ${EndIf} - - Call CheckSpace - ${If} "$HasRequiredSpaceAvailable" == "false" - LockWindow off - MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_DISK_SPACE)" - Abort ; Stay on the page - ${EndIf} - - System::Call "kernel32::GetTickCount()l .s" - Pop $0 - ${GetSecondsElapsed} "$StartOptionsPhaseTickCount" "$0" $OptionsPhaseSeconds - ; It is possible for this value to be 0 if the user clicks fast enough so - ; increment the value by 1 if it is 0. - ${If} $OptionsPhaseSeconds == 0 - IntOp $OptionsPhaseSeconds $OptionsPhaseSeconds + 1 - ${EndIf} - - ${NSD_GetState} $CheckboxShortcutOnBar $CheckboxShortcutOnBar - ${NSD_GetState} $CheckboxShortcutInStartMenu $CheckboxShortcutInStartMenu - ${NSD_GetState} $CheckboxShortcutOnDesktop $CheckboxShortcutOnDesktop - ${NSD_GetState} $CheckboxSendPing $CheckboxSendPing -!ifdef MOZ_MAINTENANCE_SERVICE - ${NSD_GetState} $CheckboxInstallMaintSvc $CheckboxInstallMaintSvc -!endif - -FunctionEnd - -Function createInstall - nsDialogs::Create /NOUNLOAD 1018 - Pop $Dialog - ; Since the text color for controls is set in this Dialog the foreground and - ; background colors of the Dialog must also be hardcoded. - SetCtlColors $Dialog ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR} - - ${NSD_CreateLabel} 0 0 49u 64u "" - Pop $0 - ${GetDlgItemWidthHeight} $0 $1 $2 - System::Call 'user32::DestroyWindow(i r0)' - - ${NSD_CreateLabel} 0 0 11u 16u "" - Pop $0 - ${GetDlgItemWidthHeight} $0 $3 $4 - System::Call 'user32::DestroyWindow(i r0)' - - FindWindow $7 "#32770" "" $HWNDPARENT - ${GetDlgItemWidthHeight} $7 $8 $9 - - ; Allow a maximum text width of half of the Dialog's width - IntOp $R0 $8 / 2 - - ${GetTextWidthHeight} "${INSTALL_BLURB1}" $FontBlurb $R0 $5 $6 - IntOp $R1 $1 + $3 - IntOp $R1 $R1 + $5 - IntOp $R1 $8 - $R1 - IntOp $R1 $R1 / 2 - ${NSD_CreateBitmap} $R1 ${INSTALL_BLURB_TOP_DU} 49u 64u "" - Pop $BitmapBlurb1 - ${SetStretchedTransparentImage} $BitmapBlurb1 $PLUGINSDIR\clock.bmp $HwndBitmapBlurb1 - IntOp $R1 $R1 + $1 - IntOp $R1 $R1 + $3 - ${NSD_CreateLabel} $R1 ${INSTALL_BLURB_TOP_DU} $5 $6 "${INSTALL_BLURB1}" - Pop $LabelBlurb1 - SendMessage $LabelBlurb1 ${WM_SETFONT} $FontBlurb 0 - SetCtlColors $LabelBlurb1 ${INSTALL_BLURB_TEXT_COLOR} transparent - - ${GetTextWidthHeight} "${INSTALL_BLURB2}" $FontBlurb $R0 $5 $6 - IntOp $R1 $1 + $3 - IntOp $R1 $R1 + $5 - IntOp $R1 $8 - $R1 - IntOp $R1 $R1 / 2 - ${NSD_CreateBitmap} $R1 ${INSTALL_BLURB_TOP_DU} 49u 64u "" - Pop $BitmapBlurb2 - ${SetStretchedTransparentImage} $BitmapBlurb2 $PLUGINSDIR\particles.bmp $HwndBitmapBlurb2 - IntOp $R1 $R1 + $1 - IntOp $R1 $R1 + $3 - ${NSD_CreateLabel} $R1 ${INSTALL_BLURB_TOP_DU} $5 $6 "${INSTALL_BLURB2}" - Pop $LabelBlurb2 - SendMessage $LabelBlurb2 ${WM_SETFONT} $FontBlurb 0 - SetCtlColors $LabelBlurb2 ${INSTALL_BLURB_TEXT_COLOR} transparent - ShowWindow $BitmapBlurb2 ${SW_HIDE} - ShowWindow $LabelBlurb2 ${SW_HIDE} - - ${GetTextWidthHeight} "${INSTALL_BLURB3}" $FontBlurb $R0 $5 $6 - IntOp $R1 $1 + $3 - IntOp $R1 $R1 + $5 - IntOp $R1 $8 - $R1 - IntOp $R1 $R1 / 2 - ${NSD_CreateBitmap} $R1 ${INSTALL_BLURB_TOP_DU} 49u 64u "" - Pop $BitmapBlurb3 - ${SetStretchedTransparentImage} $BitmapBlurb3 $PLUGINSDIR\pencil.bmp $HWndBitmapBlurb3 - IntOp $R1 $R1 + $1 - IntOp $R1 $R1 + $3 - ${NSD_CreateLabel} $R1 ${INSTALL_BLURB_TOP_DU} $5 $6 "${INSTALL_BLURB3}" - Pop $LabelBlurb3 - SendMessage $LabelBlurb3 ${WM_SETFONT} $FontBlurb 0 - SetCtlColors $LabelBlurb3 ${INSTALL_BLURB_TEXT_COLOR} transparent - ShowWindow $BitmapBlurb3 ${SW_HIDE} - ShowWindow $LabelBlurb3 ${SW_HIDE} - - ${NSD_CreateProgressBar} 103u 166u 241u 9u "" - Pop $Progressbar - ${NSD_AddStyle} $Progressbar ${PBS_MARQUEE} - SendMessage $Progressbar ${PBM_SETMARQUEE} 1 \ - $ProgressbarMarqueeIntervalMS ; start=1|stop=0 interval(ms)=+N - - ${NSD_CreateLabelCenter} 103u 180u 241u 20u "$(DOWNLOADING_LABEL)" - Pop $LabelDownloading - SendMessage $LabelDownloading ${WM_SETFONT} $FontNormal 0 - SetCtlColors $LabelDownloading ${INSTALL_PROGRESS_TEXT_COLOR_NORMAL} transparent - - ${If} ${FileExists} "$INSTDIR\${FileMainEXE}" - ${NSD_CreateLabelCenter} 103u 180u 241u 20u "$(UPGRADING_LABEL)" - ${Else} - ${NSD_CreateLabelCenter} 103u 180u 241u 20u "$(INSTALLING_LABEL)" - ${EndIf} - Pop $LabelInstalling - SendMessage $LabelInstalling ${WM_SETFONT} $FontNormal 0 - SetCtlColors $LabelInstalling ${INSTALL_PROGRESS_TEXT_COLOR_NORMAL} transparent - ShowWindow $LabelInstalling ${SW_HIDE} - - ${NSD_CreateBitmap} ${APPNAME_BMP_EDGE_DU} ${APPNAME_BMP_TOP_DU} \ - ${APPNAME_BMP_WIDTH_DU} ${APPNAME_BMP_HEIGHT_DU} "" - Pop $2 - ${SetStretchedTransparentImage} $2 $PLUGINSDIR\appname.bmp $0 - - GetDlgItem $0 $HWNDPARENT 1 ; Install button - EnableWindow $0 0 - ShowWindow $0 ${SW_HIDE} - - GetDlgItem $0 $HWNDPARENT 3 ; Back button used for Options - EnableWindow $0 0 - ShowWindow $0 ${SW_HIDE} - - GetDlgItem $0 $HWNDPARENT 2 ; Cancel button - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(CANCEL_BUTTON)" - ; Focus the Cancel button otherwise it isn't possible to tab to it since it is - ; the only control that can be tabbed to. - ${NSD_SetFocus} $0 - ; Kill the Cancel button's focus so pressing enter won't cancel the install. - SendMessage $0 ${WM_KILLFOCUS} 0 0 - - ${If} "$CanSetAsDefault" == "true" - GetDlgItem $0 $HWNDPARENT 10 ; Default browser checkbox - SendMessage $0 ${BM_GETCHECK} 0 0 $CheckboxSetAsDefault - EnableWindow $0 0 - ShowWindow $0 ${SW_HIDE} - ${EndIf} - - GetDlgItem $0 $HWNDPARENT 11 - ${If} ${FileExists} "$INSTDIR\${FileMainEXE}" - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(ONE_MOMENT_UPGRADE)" - ${Else} - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(ONE_MOMENT_INSTALL)" - ${EndIf} - SendMessage $0 ${WM_SETFONT} $FontNormal 0 - SetCtlColors $0 ${FOOTER_CONTROL_TEXT_COLOR_FADED} ${FOOTER_BKGRD_COLOR} - ShowWindow $0 ${SW_SHOW} - - ; Set $DownloadReset to true so the first download tick count is measured. - StrCpy $DownloadReset "true" - StrCpy $IsDownloadFinished "false" - StrCpy $DownloadRetryCount "0" - StrCpy $DownloadedBytes "0" - StrCpy $StartLastDownloadTickCount "" - StrCpy $EndDownloadPhaseTickCount "" - StrCpy $DownloadFirstTransferSeconds "" - StrCpy $ExitCode "${ERR_DOWNLOAD_CANCEL}" - StrCpy $OpenedDownloadPage "0" - - ClearErrors - ReadINIStr $ExistingVersion "$INSTDIR\application.ini" "App" "Version" - ${If} ${Errors} - StrCpy $ExistingVersion "0" - ${EndIf} - - ClearErrors - ReadINIStr $ExistingBuildID "$INSTDIR\application.ini" "App" "BuildID" - ${If} ${Errors} - StrCpy $ExistingBuildID "0" - ${EndIf} - - ${If} ${FileExists} "$LOCALAPPDATA\Mozilla\Basilisk" - StrCpy $ExistingProfile "1" - ${Else} - StrCpy $ExistingProfile "0" - ${EndIf} - - StrCpy $DownloadServerIP "" - - System::Call "kernel32::GetTickCount()l .s" - Pop $StartDownloadPhaseTickCount - - ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log" - StrCpy $InstallTotalSteps ${InstallPaveOverTotalSteps} - ${Else} - StrCpy $InstallTotalSteps ${InstallCleanTotalSteps} - ${EndIf} - - ${ITBL3Create} - ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}" - - ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS} - - LockWindow off - nsDialogs::Show - - ${NSD_FreeImage} $0 - ${NSD_FreeImage} $HwndBitmapBlurb1 - ${NSD_FreeImage} $HwndBitmapBlurb2 - ${NSD_FreeImage} $HWndBitmapBlurb3 -FunctionEnd - -Function StartDownload - ${NSD_KillTimer} StartDownload - InetBgDL::Get "${URLStubDownload}${URLStubDownloadAppend}" "$PLUGINSDIR\download.exe" \ - /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END - StrCpy $4 "" - ${NSD_CreateTimer} OnDownload ${DownloadIntervalMS} - ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}" - RmDir /r "$INSTDIR\${TO_BE_DELETED}" - ${EndIf} -FunctionEnd - -Function SetProgressBars - SendMessage $Progressbar ${PBM_SETPOS} $ProgressCompleted 0 - ${ITBL3SetProgressValue} "$ProgressCompleted" "$ProgressTotal" -FunctionEnd - -Function RemoveFileProgressCallback - IntOp $InstallCounterStep $InstallCounterStep + 2 - System::Int64Op $ProgressCompleted + $InstallStepSize - Pop $ProgressCompleted - Call SetProgressBars - System::Int64Op $ProgressCompleted + $InstallStepSize - Pop $ProgressCompleted - Call SetProgressBars -FunctionEnd - -Function OnDownload - InetBgDL::GetStats - # $0 = HTTP status code, 0=Completed - # $1 = Completed files - # $2 = Remaining files - # $3 = Number of downloaded bytes for the current file - # $4 = Size of current file (Empty string if the size is unknown) - # /RESET must be used if status $0 > 299 (e.g. failure) - # When status is $0 =< 299 it is handled by InetBgDL - StrCpy $DownloadServerIP "$5" - ${If} $0 > 299 - ${NSD_KillTimer} OnDownload - IntOp $DownloadRetryCount $DownloadRetryCount + 1 - ${If} "$DownloadReset" != "true" - StrCpy $DownloadedBytes "0" - ${NSD_AddStyle} $Progressbar ${PBS_MARQUEE} - SendMessage $Progressbar ${PBM_SETMARQUEE} 1 \ - $ProgressbarMarqueeIntervalMS ; start=1|stop=0 interval(ms)=+N - ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}" - ${EndIf} - InetBgDL::Get /RESET /END - StrCpy $DownloadSizeBytes "" - StrCpy $DownloadReset "true" - - ${If} $DownloadRetryCount >= ${DownloadMaxRetries} - StrCpy $ExitCode "${ERR_DOWNLOAD_TOO_MANY_RETRIES}" - ; Use a timer so the UI has a chance to update - ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS} - ${Else} - ${NSD_CreateTimer} StartDownload ${DownloadRetryIntervalMS} - ${EndIf} - Return - ${EndIf} - - ${If} "$DownloadReset" == "true" - System::Call "kernel32::GetTickCount()l .s" - Pop $StartLastDownloadTickCount - StrCpy $DownloadReset "false" - ; The seconds elapsed from the start of the download phase until the first - ; bytes are received are only recorded for the first request so it is - ; possible to determine connection issues for the first request. - ${If} "$DownloadFirstTransferSeconds" == "" - ; Get the seconds elapsed from the start of the download phase until the - ; first bytes are received. - ${GetSecondsElapsed} "$StartDownloadPhaseTickCount" "$StartLastDownloadTickCount" $DownloadFirstTransferSeconds - ${EndIf} - ${EndIf} - - ${If} "$DownloadSizeBytes" == "" - ${AndIf} "$4" != "" - ; Handle the case where the size of the file to be downloaded is less than - ; the minimum expected size or greater than the maximum expected size at the - ; beginning of the download. - ${If} $4 < ${DownloadMinSizeBytes} - ${OrIf} $4 > ${DownloadMaxSizeBytes} - ${NSD_KillTimer} OnDownload - InetBgDL::Get /RESET /END - StrCpy $DownloadReset "true" - - ${If} $DownloadRetryCount >= ${DownloadMaxRetries} - ; Use a timer so the UI has a chance to update - ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS} - ${Else} - ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS} - ${EndIf} - Return - ${EndIf} - - StrCpy $DownloadSizeBytes "$4" - System::Int64Op $4 / 2 - Pop $HalfOfDownload - System::Int64Op $HalfOfDownload / $InstallTotalSteps - Pop $InstallStepSize - SendMessage $Progressbar ${PBM_SETMARQUEE} 0 0 ; start=1|stop=0 interval(ms)=+N - ${RemoveStyle} $Progressbar ${PBS_MARQUEE} - System::Int64Op $HalfOfDownload + $DownloadSizeBytes - Pop $ProgressTotal - StrCpy $ProgressCompleted 0 - SendMessage $Progressbar ${PBM_SETRANGE32} $ProgressCompleted $ProgressTotal - ${EndIf} - - ; Don't update the status until after the download starts - ${If} $2 != 0 - ${AndIf} "$4" == "" - Return - ${EndIf} - - ; Handle the case where the downloaded size is greater than the maximum - ; expected size during the download. - ${If} $DownloadedBytes > ${DownloadMaxSizeBytes} - InetBgDL::Get /RESET /END - StrCpy $DownloadReset "true" - - ${If} $DownloadRetryCount >= ${DownloadMaxRetries} - ; Use a timer so the UI has a chance to update - ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS} - ${Else} - ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS} - ${EndIf} - Return - ${EndIf} - - ${If} $IsDownloadFinished != "true" - ${If} $2 == 0 - ${NSD_KillTimer} OnDownload - StrCpy $IsDownloadFinished "true" - ; The first step of the install progress bar is determined by the - ; InstallProgressFirstStep define and provides the user with immediate - ; feedback. - StrCpy $InstallCounterStep "${InstallProgressFirstStep}" - System::Call "kernel32::GetTickCount()l .s" - Pop $EndDownloadPhaseTickCount - - StrCpy $DownloadedBytes "$DownloadSizeBytes" - - ; When a download has finished handle the case where the downloaded size - ; is less than the minimum expected size or greater than the maximum - ; expected size during the download. - ${If} $DownloadedBytes < ${DownloadMinSizeBytes} - ${OrIf} $DownloadedBytes > ${DownloadMaxSizeBytes} - InetBgDL::Get /RESET /END - StrCpy $DownloadReset "true" - - ${If} $DownloadRetryCount >= ${DownloadMaxRetries} - ; Use a timer so the UI has a chance to update - ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS} - ${Else} - ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS} - ${EndIf} - Return - ${EndIf} - - LockWindow on - ; Update the progress bars first in the UI change so they take affect - ; before other UI changes. - StrCpy $ProgressCompleted "$DownloadSizeBytes" - Call SetProgressBars - System::Int64Op $InstallStepSize * ${InstallProgressFirstStep} - Pop $R9 - System::Int64Op $ProgressCompleted + $R9 - Pop $ProgressCompleted - Call SetProgressBars - ShowWindow $LabelDownloading ${SW_HIDE} - ShowWindow $LabelInstalling ${SW_SHOW} - ShowWindow $LabelBlurb2 ${SW_HIDE} - ShowWindow $BitmapBlurb2 ${SW_HIDE} - ShowWindow $LabelBlurb3 ${SW_SHOW} - ShowWindow $BitmapBlurb3 ${SW_SHOW} - ; Disable the Cancel button during the install - GetDlgItem $5 $HWNDPARENT 2 - EnableWindow $5 0 - LockWindow off - - ; Open a handle to prevent modification of the full installer - StrCpy $R9 "${INVALID_HANDLE_VALUE}" - System::Call 'kernel32::CreateFileW(w "$PLUGINSDIR\download.exe", \ - i ${GENERIC_READ}, \ - i ${FILE_SHARE_READ}, i 0, \ - i ${OPEN_EXISTING}, i 0, i 0) i .R9' - StrCpy $HandleDownload "$R9" - - ${If} $HandleDownload == ${INVALID_HANDLE_VALUE} - StrCpy $ExitCode "${ERR_PREINSTALL_INVALID_HANDLE}" - StrCpy $0 "0" - StrCpy $1 "0" - ${Else} - CertCheck::VerifyCertTrust "$PLUGINSDIR\download.exe" - Pop $0 - CertCheck::VerifyCertNameIssuer "$PLUGINSDIR\download.exe" \ - "${CertNameDownload}" "${CertIssuerDownload}" - Pop $1 - ${If} $0 == 0 - ${AndIf} $1 == 0 - StrCpy $ExitCode "${ERR_PREINSTALL_CERT_UNTRUSTED_AND_ATTRIBUTES}" - ${ElseIf} $0 == 0 - StrCpy $ExitCode "${ERR_PREINSTALL_CERT_UNTRUSTED}" - ${ElseIf} $1 == 0 - StrCpy $ExitCode "${ERR_PREINSTALL_CERT_ATTRIBUTES}" - ${EndIf} - ${EndIf} - - System::Call "kernel32::GetTickCount()l .s" - Pop $EndPreInstallPhaseTickCount - - ${If} $0 == 0 - ${OrIf} $1 == 0 - ; Use a timer so the UI has a chance to update - ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS} - Return - ${EndIf} - - ; Instead of extracting the files we use the downloaded installer to - ; install in case it needs to perform operations that the stub doesn't - ; know about. - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "InstallDirectoryPath" "$INSTDIR" - ; Don't create the QuickLaunch or Taskbar shortcut from the launched installer - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "QuickLaunchShortcut" "false" - - ; Either avoid or force adding a taskbar pin based on the checkbox value: - ${If} $CheckboxShortcutOnBar == 0 - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "false" - ${Else} - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "true" - ${EndIf} - - ${If} $CheckboxShortcutOnDesktop == 1 - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "true" - ${Else} - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "false" - ${EndIf} - - ${If} $CheckboxShortcutInStartMenu == 1 - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "StartMenuShortcuts" "true" - ${Else} - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "StartMenuShortcuts" "false" - ${EndIf} - -!ifdef MOZ_MAINTENANCE_SERVICE - ${If} $CheckboxInstallMaintSvc == 1 - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "true" - ${Else} - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "false" - ${EndIf} -!else - WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "false" -!endif - - ; Delete the taskbar shortcut history to ensure we do the right thing based on - ; the config file above. - ${GetShortcutsLogPath} $0 - Delete "$0" - - GetFunctionAddress $0 RemoveFileProgressCallback - ${RemovePrecompleteEntries} $0 - - ; Delete the install.log and let the full installer create it. When the - ; installer closes it we can detect that it has completed. - Delete "$INSTDIR\install.log" - - ; Delete firefox.exe.moz-upgrade and firefox.exe.moz-delete if it exists - ; since it being present will require an OS restart for the full - ; installer. - Delete "$INSTDIR\${FileMainEXE}.moz-upgrade" - Delete "$INSTDIR\${FileMainEXE}.moz-delete" - - System::Call "kernel32::GetTickCount()l .s" - Pop $EndPreInstallPhaseTickCount - - Exec "$\"$PLUGINSDIR\download.exe$\" /INI=$PLUGINSDIR\${CONFIG_INI}" - ${NSD_CreateTimer} CheckInstall ${InstallIntervalMS} - ${Else} - ${If} $HalfOfDownload != "true" - ${AndIf} $3 > $HalfOfDownload - StrCpy $HalfOfDownload "true" - LockWindow on - ShowWindow $LabelBlurb1 ${SW_HIDE} - ShowWindow $BitmapBlurb1 ${SW_HIDE} - ShowWindow $LabelBlurb2 ${SW_SHOW} - ShowWindow $BitmapBlurb2 ${SW_SHOW} - LockWindow off - ${EndIf} - StrCpy $DownloadedBytes "$3" - StrCpy $ProgressCompleted "$DownloadedBytes" - Call SetProgressBars - ${EndIf} - ${EndIf} -FunctionEnd - -Function OnPing - InetBgDL::GetStats - # $0 = HTTP status code, 0=Completed - # $1 = Completed files - # $2 = Remaining files - # $3 = Number of downloaded bytes for the current file - # $4 = Size of current file (Empty string if the size is unknown) - # /RESET must be used if status $0 > 299 (e.g. failure) - # When status is $0 =< 299 it is handled by InetBgDL - ${If} $2 == 0 - ${OrIf} $0 > 299 - ${NSD_KillTimer} OnPing - ${If} $0 > 299 - InetBgDL::Get /RESET /END - ${EndIf} - ; The following will exit the installer - SetAutoClose true - StrCpy $R9 "2" - Call RelativeGotoPage - ${EndIf} -FunctionEnd - -Function CheckInstall - IntOp $InstallCounterStep $InstallCounterStep + 1 - ${If} $InstallCounterStep >= $InstallTotalSteps - ${NSD_KillTimer} CheckInstall - ; Close the handle that prevents modification of the full installer - System::Call 'kernel32::CloseHandle(i $HandleDownload)' - StrCpy $ExitCode "${ERR_INSTALL_TIMEOUT}" - ; Use a timer so the UI has a chance to update - ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS} - Return - ${EndIf} - - System::Int64Op $ProgressCompleted + $InstallStepSize - Pop $ProgressCompleted - Call SetProgressBars - - ${If} ${FileExists} "$INSTDIR\install.log" - Delete "$INSTDIR\install.tmp" - CopyFiles /SILENT "$INSTDIR\install.log" "$INSTDIR\install.tmp" - - ; The unfocus and refocus that happens approximately here is caused by the - ; installer calling SHChangeNotify to refresh the shortcut icons. - - ; When the full installer completes the installation the install.log will no - ; longer be in use. - ClearErrors - Delete "$INSTDIR\install.log" - ${Unless} ${Errors} - ${NSD_KillTimer} CheckInstall - ; Close the handle that prevents modification of the full installer - System::Call 'kernel32::CloseHandle(i $HandleDownload)' - Rename "$INSTDIR\install.tmp" "$INSTDIR\install.log" - Delete "$PLUGINSDIR\download.exe" - Delete "$PLUGINSDIR\${CONFIG_INI}" - System::Call "kernel32::GetTickCount()l .s" - Pop $EndInstallPhaseTickCount - System::Int64Op $InstallStepSize * ${InstallProgressFinishStep} - Pop $InstallStepSize - ${NSD_CreateTimer} FinishInstall ${InstallIntervalMS} - ${EndUnless} - ${EndIf} -FunctionEnd - -Function FinishInstall - ; The full installer has completed but the progress bar still needs to finish - ; so increase the size of the step. - IntOp $InstallCounterStep $InstallCounterStep + ${InstallProgressFinishStep} - ${If} $InstallTotalSteps < $InstallCounterStep - StrCpy $InstallCounterStep "$InstallTotalSteps" - ${EndIf} - - ${If} $InstallTotalSteps != $InstallCounterStep - System::Int64Op $ProgressCompleted + $InstallStepSize - Pop $ProgressCompleted - Call SetProgressBars - Return - ${EndIf} - - ${NSD_KillTimer} FinishInstall - - StrCpy $ProgressCompleted "$ProgressTotal" - Call SetProgressBars - - ${If} "$CheckboxSetAsDefault" == "1" - ; NB: this code is duplicated in installer.nsi. Please keep in sync. - ; For data migration in the app, we want to know what the default browser - ; value was before we changed it. To do so, we read it here and store it - ; in our own registry key. - StrCpy $0 "" - ${If} ${AtLeastWinVista} - AppAssocReg::QueryCurrentDefault "http" "protocol" "effective" - Pop $1 - ; If the method hasn't failed, $1 will contain the progid. Check: - ${If} "$1" != "method failed" - ${AndIf} "$1" != "method not available" - ; Read the actual command from the progid - ReadRegStr $0 HKCR "$1\shell\open\command" "" - ${EndIf} - ${EndIf} - ; If using the App Association Registry didn't happen or failed, fall back - ; to the effective http default: - ${If} "$0" == "" - ReadRegStr $0 HKCR "http\shell\open\command" "" - ${EndIf} - ; If we have something other than empty string now, write the value. - ${If} "$0" != "" - ClearErrors - WriteRegStr HKCU "Software\Mozilla\Basilisk" "OldDefaultBrowserCommand" "$0" - ${EndIf} - - ${GetParameters} $0 - ClearErrors - ${GetOptions} "$0" "/UAC:" $0 - ${If} ${Errors} ; Not elevated - Call ExecSetAsDefaultAppUser - ${Else} ; Elevated - execute the function in the unelevated process - GetFunctionAddress $0 ExecSetAsDefaultAppUser - UAC::ExecCodeSegment $0 - ${EndIf} - ${EndIf} - - ${If} $CheckboxShortcutOnBar == 1 - ${If} ${AtMostWinVista} - ClearErrors - ${GetParameters} $0 - ClearErrors - ${GetOptions} "$0" "/UAC:" $0 - ${If} ${Errors} - Call AddQuickLaunchShortcut - ${Else} - GetFunctionAddress $0 AddQuickLaunchShortcut - UAC::ExecCodeSegment $0 - ${EndIf} - ${EndIf} - ${EndIf} - - ${If} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-upgrade" - Delete "$INSTDIR\${FileMainEXE}" - Rename "$INSTDIR\${FileMainEXE}.moz-upgrade" "$INSTDIR\${FileMainEXE}" - ${EndIf} - - StrCpy $ExitCode "${ERR_SUCCESS}" - - StrCpy $InstallCounterStep 0 - ${NSD_CreateTimer} FinishProgressBar ${InstallIntervalMS} -FunctionEnd - -Function FinishProgressBar - IntOp $InstallCounterStep $InstallCounterStep + 1 - - ${If} $InstallCounterStep < 10 - Return - ${EndIf} - - ${NSD_KillTimer} FinishProgressBar - - Call CopyPostSigningData - Call LaunchApp - Call SendPing -FunctionEnd - -Function OnBack - StrCpy $WasOptionsButtonClicked "1" - StrCpy $R9 "1" ; Goto the next page - Call RelativeGotoPage - ; The call to Abort prevents NSIS from trying to move to the previous or the - ; next page. - Abort -FunctionEnd - -Function RelativeGotoPage - IntCmp $R9 0 0 Move Move - StrCmp $R9 "X" 0 Move - StrCpy $R9 "120" - - Move: - SendMessage $HWNDPARENT "0x408" "$R9" "" -FunctionEnd - -Function UpdateFreeSpaceLabel - ; Only update when $ExistingTopDir isn't set - ${If} "$ExistingTopDir" != "" - StrLen $5 "$ExistingTopDir" - StrLen $6 "$INSTDIR" - ${If} $5 <= $6 - StrCpy $7 "$INSTDIR" $5 - ${If} "$7" == "$ExistingTopDir" - Return - ${EndIf} - ${EndIf} - ${EndIf} - - Call CheckSpace - - StrCpy $0 "$SpaceAvailableBytes" - - StrCpy $1 "$(BYTE)" - - ${If} $0 > 1024 - ${OrIf} $0 < 0 - System::Int64Op $0 / 1024 - Pop $0 - StrCpy $1 "$(KILO)$(BYTE)" - ${If} $0 > 1024 - ${OrIf} $0 < 0 - System::Int64Op $0 / 1024 - Pop $0 - StrCpy $1 "$(MEGA)$(BYTE)" - ${If} $0 > 1024 - ${OrIf} $0 < 0 - System::Int64Op $0 / 1024 - Pop $0 - StrCpy $1 "$(GIGA)$(BYTE)" - ${EndIf} - ${EndIf} - ${EndIf} - - SendMessage $LabelFreeSpace ${WM_SETTEXT} 0 "STR:$0 $1" -FunctionEnd - -Function OnChange_DirRequest - Pop $0 - System::Call 'user32::GetWindowTextW(i $DirRequest, w .r0, i ${NSIS_MAX_STRLEN})' - StrCpy $1 "$0" 1 ; the first character - ${If} "$1" == "$\"" - StrCpy $1 "$0" "" -1 ; the last character - ${If} "$1" == "$\"" - StrCpy $0 "$0" "" 1 ; all but the first character - StrCpy $0 "$0" -1 ; all but the last character - ${EndIf} - ${EndIf} - - StrCpy $INSTDIR "$0" - Call UpdateFreeSpaceLabel - - GetDlgItem $0 $HWNDPARENT 1 ; Install button - ${If} ${FileExists} "$INSTDIR\${FileMainEXE}" - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(UPGRADE_BUTTON)" - ${Else} - SendMessage $0 ${WM_SETTEXT} 0 "STR:$(INSTALL_BUTTON)" - ${EndIf} -FunctionEnd - -Function OnClick_ButtonBrowse - StrCpy $0 "$INSTDIR" - nsDialogs::SelectFolderDialog /NOUNLOAD "$(SELECT_FOLDER_TEXT)" $0 - Pop $0 - ${If} $0 == "error" ; returns 'error' if 'cancel' was pressed? - Return - ${EndIf} - - ${If} $0 != "" - StrCpy $INSTDIR "$0" - System::Call 'user32::SetWindowTextW(i $DirRequest, w "$INSTDIR")' - ${EndIf} -FunctionEnd - -Function CheckSpace - ${If} "$ExistingTopDir" != "" - StrLen $0 "$ExistingTopDir" - StrLen $1 "$INSTDIR" - ${If} $0 <= $1 - StrCpy $2 "$INSTDIR" $3 - ${If} "$2" == "$ExistingTopDir" - Return - ${EndIf} - ${EndIf} - ${EndIf} - - StrCpy $ExistingTopDir "$INSTDIR" - ${DoUntil} ${FileExists} "$ExistingTopDir" - ${GetParent} "$ExistingTopDir" $ExistingTopDir - ${If} "$ExistingTopDir" == "" - StrCpy $SpaceAvailableBytes "0" - StrCpy $HasRequiredSpaceAvailable "false" - Return - ${EndIf} - ${Loop} - - ${GetLongPath} "$ExistingTopDir" $ExistingTopDir - - ; GetDiskFreeSpaceExW requires a backslash. - StrCpy $0 "$ExistingTopDir" "" -1 ; the last character - ${If} "$0" != "\" - StrCpy $0 "\" - ${Else} - StrCpy $0 "" - ${EndIf} - - System::Call 'kernel32::GetDiskFreeSpaceExW(w, *l, *l, *l) i("$ExistingTopDir$0", .r1, .r2, .r3) .' - StrCpy $SpaceAvailableBytes "$1" - - System::Int64Op $SpaceAvailableBytes / 1048576 - Pop $1 - System::Int64Op $1 > ${APPROXIMATE_REQUIRED_SPACE_MB} - Pop $1 - ${If} $1 == 1 - StrCpy $HasRequiredSpaceAvailable "true" - ${Else} - StrCpy $HasRequiredSpaceAvailable "false" - ${EndIf} -FunctionEnd - -Function CanWrite - StrCpy $CanWriteToInstallDir "false" - - StrCpy $0 "$INSTDIR" - ; Use the existing directory when it exists - ${Unless} ${FileExists} "$INSTDIR" - ; Get the topmost directory that exists for new installs - ${DoUntil} ${FileExists} "$0" - ${GetParent} "$0" $0 - ${If} "$0" == "" - Return - ${EndIf} - ${Loop} - ${EndUnless} - - GetTempFileName $2 "$0" - Delete $2 - CreateDirectory "$2" - ${If} ${FileExists} "$2" - ${If} ${FileExists} "$INSTDIR" - GetTempFileName $3 "$INSTDIR" - ${Else} - GetTempFileName $3 "$2" - ${EndIf} - ${If} ${FileExists} "$3" - Delete "$3" - StrCpy $CanWriteToInstallDir "true" - ${EndIf} - RmDir "$2" - ${EndIf} -FunctionEnd - -Function AddQuickLaunchShortcut - CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" - ${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk" - ShellLink::SetShortCutWorkingDirectory "$QUICKLAUNCH\${BrandFullName}.lnk" \ - "$INSTDIR" - ${EndIf} -FunctionEnd - -Function ExecSetAsDefaultAppUser - ; Using the helper.exe lessens the stub installer size. - ; This could ask for elevatation when the user doesn't install as admin. - Exec "$\"$INSTDIR\uninstall\helper.exe$\" /SetAsDefaultAppUser" -FunctionEnd - -Function LaunchApp -!ifndef DEV_EDITION - FindWindow $0 "${WindowClass}" - ${If} $0 <> 0 ; integer comparison - StrCpy $BasiliskLaunchCode "1" - MessageBox MB_OK|MB_ICONQUESTION "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)" - Return - ${EndIf} -!endif - - StrCpy $BasiliskLaunchCode "2" - - ; Set the current working directory to the installation directory - SetOutPath "$INSTDIR" - ClearErrors - ${GetParameters} $0 - ${GetOptions} "$0" "/UAC:" $1 - ${If} ${Errors} - Exec "$\"$INSTDIR\${FileMainEXE}$\"" - ${Else} - GetFunctionAddress $0 LaunchAppFromElevatedProcess - UAC::ExecCodeSegment $0 - ${EndIf} -FunctionEnd - -Function LaunchAppFromElevatedProcess - ; Find the installation directory when launching using GetFunctionAddress - ; from an elevated installer since $INSTDIR will not be set in this installer - ${StrFilter} "${FileMainEXE}" "+" "" "" $R9 - ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" "" - ${GetPathFromString} "$0" $0 - ; Set the current working directory to the installation directory - ${GetParent} "$0" $1 - SetOutPath "$1" - Exec "$\"$0$\"" -FunctionEnd - -Function CopyPostSigningData - ${LineRead} "$EXEDIR\postSigningData" "1" $PostSigningData - ${If} ${Errors} - ClearErrors - StrCpy $PostSigningData "0" - ${Else} - CreateDirectory "$LOCALAPPDATA\Mozilla\Basilisk" - CopyFiles /SILENT "$EXEDIR\postSigningData" "$LOCALAPPDATA\Mozilla\Basilisk" - ${Endif} -FunctionEnd - -Function DisplayDownloadError - ${NSD_KillTimer} DisplayDownloadError - ; To better display the error state on the taskbar set the progress completed - ; value to the total value. - ${ITBL3SetProgressValue} "100" "100" - ${ITBL3SetProgressState} "${TBPF_ERROR}" - MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK +1 - StrCpy $OpenedDownloadPage "1" ; Already initialized to 0 - - ${If} "$OpenedDownloadPage" == "1" - ClearErrors - ${GetParameters} $0 - ${GetOptions} "$0" "/UAC:" $1 - ${If} ${Errors} - Call OpenManualDownloadURL - ${Else} - GetFunctionAddress $0 OpenManualDownloadURL - UAC::ExecCodeSegment $0 - ${EndIf} - ${EndIf} - - Call SendPing -FunctionEnd - -Function OpenManualDownloadURL - ExecShell "open" "${URLManualDownload}${URLManualDownloadAppend}" -FunctionEnd - -Section -SectionEnd diff --git a/browser/installer/windows/nsis/uninstaller.nsi b/browser/installer/windows/nsis/uninstaller.nsi index 687bcd6eb..87f4d838a 100755 --- a/browser/installer/windows/nsis/uninstaller.nsi +++ b/browser/installer/windows/nsis/uninstaller.nsi @@ -351,7 +351,7 @@ Section "Uninstall" StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe" DeleteRegKey HKLM "$0" DeleteRegKey HKCU "$0" - StrCpy $0 "Software\Classes\MIME\Database\Content Type\application/x-xpinstall;app=firefox" + StrCpy $0 "Software\Classes\MIME\Database\Content Type\application/x-xpinstall;app=Basilisk" DeleteRegKey HKLM "$0" DeleteRegKey HKCU "$0" ${Else} @@ -419,8 +419,8 @@ Section "Uninstall" ; Remove the installation directory if it is empty RmDir "$INSTDIR" - ; If firefox.exe was successfully deleted yet we still need to restart to - ; remove other files create a dummy firefox.exe.moz-delete to prevent the + ; If Basilisk.exe was successfully deleted yet we still need to restart to + ; remove other files create a dummy Basilisk.exe.moz-delete to prevent the ; installer from allowing an install without restart when it is required ; to complete an uninstall. ${If} ${RebootFlag} diff --git a/browser/installer/windows/stub.tag b/browser/installer/windows/stub.tag deleted file mode 100644 index f32bef36e..000000000 --- a/browser/installer/windows/stub.tag +++ /dev/null @@ -1,4 +0,0 @@ -;!@Install@!UTF-8! -Title="Mozilla Firefox" -RunProgram="setup-stub.exe" -;!@InstallEnd@!
\ No newline at end of file diff --git a/browser/locales/Makefile.in b/browser/locales/Makefile.in index b3ecfd359..af200147f 100644 --- a/browser/locales/Makefile.in +++ b/browser/locales/Makefile.in @@ -165,11 +165,6 @@ else endif endif -ifdef MOZ_CRASHREPORTER -libs:: crashreporter-override.ini - $(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET) -endif - ident: @printf 'fx_revision ' @$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \ diff --git a/browser/locales/en-US/chrome/browser/aboutHome.dtd b/browser/locales/en-US/chrome/browser/aboutHome.dtd index 7e3b57a79..17b401c6c 100644 --- a/browser/locales/en-US/chrome/browser/aboutHome.dtd +++ b/browser/locales/en-US/chrome/browser/aboutHome.dtd @@ -26,7 +26,7 @@ <!ENTITY abouthome.historyButton.label "History"> <!-- LOCALIZATION NOTE (abouthome.preferencesButtonWin.label): The label for the preferences/options item on about:home on Windows --> -<!ENTITY abouthome.preferencesButtonWin.label "Options"> +<!ENTITY abouthome.preferencesButtonWin.label "Preferences"> <!-- LOCALIZATION NOTE (abouthome.preferencesButtonUnix.label): The label for the preferences/options item on about:home on Linux and OS X --> <!ENTITY abouthome.preferencesButtonUnix.label "Preferences"> diff --git a/browser/locales/en-US/chrome/browser/browser.dtd b/browser/locales/en-US/chrome/browser/browser.dtd index f6fc6e3fd..6de17b64f 100644 --- a/browser/locales/en-US/chrome/browser/browser.dtd +++ b/browser/locales/en-US/chrome/browser/browser.dtd @@ -315,10 +315,8 @@ These should match what Safari and other Apple applications use on OS X Lion. -- <!ENTITY selectAllCmd.label "Select All"> <!ENTITY selectAllCmd.key "A"> <!ENTITY selectAllCmd.accesskey "A"> -<!ENTITY preferencesCmd2.label "Options"> -<!ENTITY preferencesCmd2.accesskey "O"> -<!ENTITY preferencesCmdUnix.label "Preferences"> -<!ENTITY preferencesCmdUnix.accesskey "n"> +<!ENTITY preferencesCmd2.label "Preferences"> +<!ENTITY preferencesCmd2.accesskey "P"> <!ENTITY clearRecentHistory.label "Clear Recent History…"> diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties index 21e794f08..31f61632b 100644 --- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -85,11 +85,14 @@ addonInstallError-2=The add-on could not be installed because it does not match addonInstallError-3=The add-on downloaded from this site could not be installed because it appears to be corrupt. addonInstallError-4=%2$S could not be installed because %1$S cannot modify the needed file. addonInstallError-5=%1$S has prevented this site from installing an unverified add-on. +addonInstallError-9=%2$S could not be installed because %1$S does not support WebExtensions. addonLocalInstallError-1=This add-on could not be installed because of a filesystem error. addonLocalInstallError-2=This add-on could not be installed because it does not match the add-on %1$S expected. addonLocalInstallError-3=This add-on could not be installed because it appears to be corrupt. addonLocalInstallError-4=%2$S could not be installed because %1$S cannot modify the needed file. addonLocalInstallError-5=This add-on could not be installed because it has not been verified. +addonLocalInstallError-9=%2$S could not be installed because %1$S does not support WebExtensions. + # LOCALIZATION NOTE (addonInstallErrorIncompatible): # %1$S is the application name, %2$S is the application version, %3$S is the add-on name @@ -128,10 +131,8 @@ lwthemeNeedsRestart.accesskey=R # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # #1 is brandShortName and #2 is the number of pop-ups blocked. popupWarning.message=#1 prevented this site from opening a pop-up window.;#1 prevented this site from opening #2 pop-up windows. -popupWarningButton=Options -popupWarningButton.accesskey=O -popupWarningButtonUnix=Preferences -popupWarningButtonUnix.accesskey=P +popupWarningButton=Preferences +popupWarningButton.accesskey=P popupAllow=Allow pop-ups for %S popupBlock=Block pop-ups for %S popupWarningDontShowFromMessage=Don’t show this message when pop-ups are blocked @@ -733,11 +734,8 @@ pendingCrashReports.alwaysSend = Always Send decoder.noCodecs.button = Learn how decoder.noCodecs.accesskey = L decoder.noCodecs.message = To play video, you may need to install Microsoft’s Media Feature Pack. -decoder.noCodecsVista.message = To play video, you may need to install Microsoft’s Platform Update Supplement for Windows Vista. -decoder.noCodecsXP.message = To play video, you may need to enable Adobe’s Primetime Content Decryption Module. decoder.noCodecsLinux.message = To play video, you may need to install the required video codecs. decoder.noHWAcceleration.message = To improve video quality, you may need to install Microsoft’s Media Feature Pack. -decoder.noHWAccelerationVista.message = To improve video quality, you may need to install Microsoft’s Platform Update Supplement for Windows Vista. decoder.noPulseAudio.message = To play audio, you may need to install the required PulseAudio software. decoder.unsupportedLibavcodec.message = libavcodec may be vulnerable or is not supported, and should be updated to play video. diff --git a/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties b/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties index a467aef69..a68f59fe3 100644 --- a/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties +++ b/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties @@ -39,10 +39,6 @@ add-ons-button.tooltiptext3 = Manage your add-ons (%S) preferences-button.label = Preferences preferences-button.tooltiptext2 = Open preferences preferences-button.tooltiptext.withshortcut = Open preferences (%S) -# LOCALIZATION NOTE (preferences-button.labelWin): Windows-only label for Options -preferences-button.labelWin = Options -# LOCALIZATION NOTE (preferences-button.tooltipWin): Windows-only tooltip for Options -preferences-button.tooltipWin2 = Open options zoom-controls.label = Zoom Controls zoom-controls.tooltiptext2 = Zoom controls diff --git a/browser/locales/en-US/chrome/browser/migration/migration.dtd b/browser/locales/en-US/chrome/browser/migration/migration.dtd index df6938c51..ad9293a5d 100644 --- a/browser/locales/en-US/chrome/browser/migration/migration.dtd +++ b/browser/locales/en-US/chrome/browser/migration/migration.dtd @@ -5,8 +5,7 @@ <!ENTITY migrationWizard.title "Import Wizard"> -<!ENTITY importFrom.label "Import Options, Bookmarks, History, Passwords and other data from:"> -<!ENTITY importFromUnix.label "Import Preferences, Bookmarks, History, Passwords and other data from:"> +<!ENTITY importFrom.label "Import Preferences, Bookmarks, History, Passwords and other data from:"> <!ENTITY importFromBookmarks.label "Import Bookmarks from:"> <!ENTITY importFromIE.label "Microsoft Internet Explorer"> diff --git a/browser/locales/en-US/chrome/browser/preferences/preferences.dtd b/browser/locales/en-US/chrome/browser/preferences/preferences.dtd index 380da7178..7702c8c51 100644 --- a/browser/locales/en-US/chrome/browser/preferences/preferences.dtd +++ b/browser/locales/en-US/chrome/browser/preferences/preferences.dtd @@ -3,7 +3,6 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<!ENTITY prefWindow.titleWin "Options"> <!ENTITY prefWindow.title "Preferences"> <!-- LOCALIZATION NOTE (prefWindow.titleGNOME): This is not used for in-content preferences --> <!ENTITY prefWindow.titleGNOME "&brandShortName; Preferences"> diff --git a/browser/locales/en-US/chrome/browser/preferences/security.dtd b/browser/locales/en-US/chrome/browser/preferences/security.dtd index ca9420401..7ccc9af50 100644 --- a/browser/locales/en-US/chrome/browser/preferences/security.dtd +++ b/browser/locales/en-US/chrome/browser/preferences/security.dtd @@ -31,6 +31,9 @@ <!ENTITY passwordExceptions.label "Exceptions…"> <!ENTITY passwordExceptions.accesskey "x"> +<!ENTITY autofillPasswords.label "Automatically fill in log-in details"> +<!ENTITY autofillPasswords.accesskey "A"> + <!ENTITY useMasterPassword.label "Use a master password"> <!ENTITY useMasterPassword.accesskey "U"> <!ENTITY changeMasterPassword.label "Change Master Password…"> diff --git a/browser/locales/en-US/chrome/browser/syncCustomize.dtd b/browser/locales/en-US/chrome/browser/syncCustomize.dtd index 3375c48ce..e59d1db25 100644 --- a/browser/locales/en-US/chrome/browser/syncCustomize.dtd +++ b/browser/locales/en-US/chrome/browser/syncCustomize.dtd @@ -6,8 +6,7 @@ <!ENTITY syncCustomize.acceptButton.label "Start"> <!ENTITY syncCustomize.title "What would you like to sync?"> -<!ENTITY syncCustomize.description "You can change this selection in Options."> -<!ENTITY syncCustomizeUnix.description "You can change this selection in Preferences."> +<!ENTITY syncCustomize.description "You can change this selection in Preferences."> <!-- These engine names are the same as in browser/preferences/sync.dtd except diff --git a/browser/locales/en-US/chrome/browser/syncSetup.dtd b/browser/locales/en-US/chrome/browser/syncSetup.dtd index 1fd46942d..950a83553 100644 --- a/browser/locales/en-US/chrome/browser/syncSetup.dtd +++ b/browser/locales/en-US/chrome/browser/syncSetup.dtd @@ -72,7 +72,7 @@ <!-- Existing Account Page 2: Manual Login --> <!ENTITY setup.signInPage.title.label "Sign In"> -<!ENTITY existingRecoveryKey.description "You can get a copy of your Recovery Key by going to &syncBrand.shortName.label; Options on your other device, and selecting "My Recovery Key" under "Manage Account"."> +<!ENTITY existingRecoveryKey.description "You can get a copy of your Recovery Key by going to &syncBrand.shortName.label; Preferences on your other device, and selecting "My Recovery Key" under "Manage Account"."> <!ENTITY verifying.label "Verifying…"> <!ENTITY resetPassword.label "Reset Password"> <!ENTITY resetSyncKey.label "I have lost my other device."> diff --git a/browser/modules/AboutHome.jsm b/browser/modules/AboutHome.jsm index 01cbafba9..8c0fc4c15 100644 --- a/browser/modules/AboutHome.jsm +++ b/browser/modules/AboutHome.jsm @@ -24,17 +24,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); -// Url to fetch snippets, in the urlFormatter service format. -const SNIPPETS_URL_PREF = "browser.aboutHomeSnippets.updateUrl"; - -// Should be bumped up if the snippets content format changes. -const STARTPAGE_VERSION = 4; +// Should be bumped up if any data content format changes. +const STARTPAGE_VERSION = 5; this.AboutHomeUtils = { - get snippetsVersion() { - return STARTPAGE_VERSION; - }, - /* * showKnowYourRights - Determines if the user should be shown the * about:rights notification. The notification should *not* be shown if @@ -77,16 +70,6 @@ this.AboutHomeUtils = { }; /** - * Returns the URL to fetch snippets from, in the urlFormatter service format. - */ -XPCOMUtils.defineLazyGetter(AboutHomeUtils, "snippetsURL", function() { - let updateURL = Services.prefs - .getCharPref(SNIPPETS_URL_PREF) - .replace("%STARTPAGE_VERSION%", STARTPAGE_VERSION); - return Services.urlFormatter.formatURL(updateURL); -}); - -/** * This code provides services to the about:home page. Whenever * about:home needs to do something chrome-privileged, it sends a * message that's handled here. @@ -169,9 +152,7 @@ var AboutHome = { ss.promiseInitialized.then(function() { let data = { showRestoreLastSession: ss.canRestoreLastSession, - snippetsURL: AboutHomeUtils.snippetsURL, - showKnowYourRights: AboutHomeUtils.showKnowYourRights, - snippetsVersion: AboutHomeUtils.snippetsVersion, + showKnowYourRights: AboutHomeUtils.showKnowYourRights }; if (AboutHomeUtils.showKnowYourRights) { diff --git a/browser/modules/ContentCrashHandlers.jsm b/browser/modules/ContentCrashHandlers.jsm index 2f755d142..488cc4f26 100644 --- a/browser/modules/ContentCrashHandlers.jsm +++ b/browser/modules/ContentCrashHandlers.jsm @@ -90,8 +90,6 @@ this.TabCrashHandler = { Services.telemetry .getHistogramById("FX_CONTENT_CRASH_DUMP_UNAVAILABLE") .add(1); - } else if (AppConstants.MOZ_CRASHREPORTER) { - this.childMap.set(childID, dumpID); } if (!this.flushCrashedBrowserQueue(childID)) { @@ -115,15 +113,6 @@ this.TabCrashHandler = { } } - // check for environment affecting crash reporting - let env = Cc["@mozilla.org/process/environment;1"] - .getService(Ci.nsIEnvironment); - let shutdown = env.exists("MOZ_CRASHREPORTER_SHUTDOWN"); - - if (shutdown) { - Services.startup.quit(Ci.nsIAppStartup.eForceQuit); - } - break; } case "oop-frameloader-crashed": { @@ -306,105 +295,10 @@ this.TabCrashHandler = { /** * Submits a crash report from about:tabcrashed, if the crash * reporter is enabled and a crash report can be found. - * - * @param aBrowser - * The <xul:browser> that the report was sent from. - * @param aFormData - * An Object with the following properties: - * - * includeURL (bool): - * Whether to include the URL that the user was on - * in the crashed tab before the crash occurred. - * URL (String) - * The URL that the user was on in the crashed tab - * before the crash occurred. - * emailMe (bool): - * Whether or not to include the user's email address - * in the crash report. - * email (String): - * The email address of the user. - * comments (String): - * Any additional comments from the user. - * - * Note that it is expected that all properties are set, - * even if they are empty. */ maybeSendCrashReport(message) { - if (!AppConstants.MOZ_CRASHREPORTER) { - return; - } - - if (!message.data.hasReport) { - // There was no report, so nothing to do. - return; - } - - let browser = message.target.browser; - - if (message.data.autoSubmit) { - // The user has opted in to autosubmitted backlogged - // crash reports in the future. - UnsubmittedCrashHandler.autoSubmit = true; - } - - let childID = this.browserMap.get(browser.permanentKey); - let dumpID = this.childMap.get(childID); - if (!dumpID) { - return; - } - - if (!message.data.sendReport) { - Services.telemetry.getHistogramById("FX_CONTENT_CRASH_NOT_SUBMITTED").add(1); - this.prefs.setBoolPref("sendReport", false); - return; - } - - let { - includeURL, - comments, - email, - emailMe, - URL, - } = message.data; - - let extraExtraKeyVals = { - "Comments": comments, - "Email": email, - "URL": URL, - }; - - // For the entries in extraExtraKeyVals, we only want to submit the - // extra data values where they are not the empty string. - for (let key in extraExtraKeyVals) { - let val = extraExtraKeyVals[key].trim(); - if (!val) { - delete extraExtraKeyVals[key]; - } - } - - // URL is special, since it's already been written to extra data by - // default. In order to make sure we don't send it, we overwrite it - // with the empty string. - if (!includeURL) { - extraExtraKeyVals["URL"] = ""; - } - - CrashSubmit.submit(dumpID, { - recordSubmission: true, - extraExtraKeyVals, - }).then(null, Cu.reportError); - - this.prefs.setBoolPref("sendReport", true); - this.prefs.setBoolPref("includeURL", includeURL); - this.prefs.setBoolPref("emailMe", emailMe); - if (emailMe) { - this.prefs.setCharPref("email", email); - } else { - this.prefs.setCharPref("email", ""); - } - - this.childMap.set(childID, null); // Avoid resubmission. - this.removeSubmitCheckboxesForSameCrash(childID); + /*** STUB ***/ + return; }, removeSubmitCheckboxesForSameCrash: function(childID) { @@ -518,17 +412,10 @@ this.TabCrashHandler = { /** * For some <xul:browser>, return a crash report dump ID for that browser * if we have been informed of one. Otherwise, return null. - * - * @param browser (<xul:browser) - * The browser to try to get the dump ID for - * @returns dumpID (String) */ getDumpID(browser) { - if (!AppConstants.MOZ_CRASHREPORTER) { - return null; - } - - return this.childMap.get(this.browserMap.get(browser.permanentKey)); + /*** STUB ***/ + return null; }, } diff --git a/browser/modules/ContentWebRTC.jsm b/browser/modules/ContentWebRTC.jsm index bfb98a868..fd50176a0 100644 --- a/browser/modules/ContentWebRTC.jsm +++ b/browser/modules/ContentWebRTC.jsm @@ -208,6 +208,7 @@ function prompt(aContentWindow, aWindowID, aCallID, aConstraints, aDevices, aSec let request = { callID: aCallID, windowID: aWindowID, + origin: aContentWindow.origin, documentURI: aContentWindow.document.documentURI, secure: aSecure, requestTypes: requestTypes, diff --git a/browser/modules/PluginContent.jsm b/browser/modules/PluginContent.jsm index 1bbfa9a50..622d608bc 100644 --- a/browser/modules/PluginContent.jsm +++ b/browser/modules/PluginContent.jsm @@ -660,30 +660,8 @@ PluginContent.prototype = { }, submitReport: function submitReport(plugin) { - if (!AppConstants.MOZ_CRASHREPORTER) { - return; - } - if (!plugin) { - Cu.reportError("Attempted to submit crash report without an associated plugin."); - return; - } - if (!(plugin instanceof Ci.nsIObjectLoadingContent)) { - Cu.reportError("Attempted to submit crash report on plugin that does not" + - "implement nsIObjectLoadingContent."); - return; - } - - let runID = plugin.runID; - let submitURLOptIn = this.getPluginUI(plugin, "submitURLOptIn").checked; - let keyVals = {}; - let userComment = this.getPluginUI(plugin, "submitComment").value.trim(); - if (userComment) - keyVals.PluginUserComment = userComment; - if (submitURLOptIn) - keyVals.PluginContentURL = plugin.ownerDocument.URL; - - this.global.sendAsyncMessage("PluginContent:SubmitReport", - { runID, keyVals, submitURLOptIn }); + /*** STUB ***/ + return; }, reloadPage: function () { diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm index b24135bfc..08de46bb3 100644 --- a/browser/modules/webrtcUI.jsm +++ b/browser/modules/webrtcUI.jsm @@ -290,7 +290,13 @@ function prompt(aBrowser, aRequest) { let {audioDevices: audioDevices, videoDevices: videoDevices, sharingScreen: sharingScreen, sharingAudio: sharingAudio, requestTypes: requestTypes} = aRequest; - let uri = Services.io.newURI(aRequest.documentURI, null, null); + let uri; + try { + // This fails for principals that serialize to "null", e.g. file URIs. + uri = Services.io.newURI(aRequest.origin, null, null); + } catch (e) { + uri = Services.io.newURI(aRequest.documentURI, null, null); + } let host = getHost(uri); let chromeDoc = aBrowser.ownerDocument; let chromeWin = chromeDoc.defaultView; diff --git a/browser/moz.build b/browser/moz.build index a691aeef2..0985148c0 100644 --- a/browser/moz.build +++ b/browser/moz.build @@ -11,7 +11,6 @@ SPHINX_TREES['browser'] = 'docs' DIRS += [ 'base', 'components', - 'experiments', 'fonts', 'locales', 'modules', diff --git a/browser/moz.configure b/browser/moz.configure index fba4603be..d5e7dba11 100644 --- a/browser/moz.configure +++ b/browser/moz.configure @@ -4,9 +4,4 @@ # 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/. -imply_option('MOZ_PLACES', True) -imply_option('MOZ_SERVICES_HEALTHREPORT', True) -imply_option('MOZ_SERVICES_SYNC', True) -imply_option('MOZ_SERVICES_CLOUDSYNC', True) - include('../toolkit/moz.configure') diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index e09029438..0bf023f35 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -129,9 +129,6 @@ browser.jar: skin/classic/browser/syncQuota.css skin/classic/browser/syncProgress-horizontalbar.png skin/classic/browser/syncProgress-horizontalbar@2x.png -#ifdef E10S_TESTING_ONLY - skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png) -#endif [extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar: % override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index fd9b6127d..98ba4e6ea 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -209,9 +209,6 @@ browser.jar: skin/classic/browser/yosemite/tab-stroke-end-inactive@2x.png (tabbrowser/tab-stroke-end-yosemite-inactive@2x.png) skin/classic/browser/yosemite/tab-stroke-start-inactive.png (tabbrowser/tab-stroke-start-yosemite-inactive.png) skin/classic/browser/yosemite/tab-stroke-start-inactive@2x.png (tabbrowser/tab-stroke-start-yosemite-inactive@2x.png) -#ifdef E10S_TESTING_ONLY - skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png) -#endif [extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar: % override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png diff --git a/browser/themes/osx/shared.inc b/browser/themes/osx/shared.inc index b3ea4e199..3076450e2 100644 --- a/browser/themes/osx/shared.inc +++ b/browser/themes/osx/shared.inc @@ -1,4 +1,4 @@ -%include ../../../toolkit/themes/osx/global/shared.inc
+%include ../../../../toolkit/themes/osx/global/shared.inc
%include ../shared/browser.inc
%filter substitution
diff --git a/browser/themes/shared/incontentprefs/preferences.inc.css b/browser/themes/shared/incontentprefs/preferences.inc.css index 577baa6ed..0e62660de 100644 --- a/browser/themes/shared/incontentprefs/preferences.inc.css +++ b/browser/themes/shared/incontentprefs/preferences.inc.css @@ -173,6 +173,11 @@ treecol { margin-inline-start: 0; } +#browserHomePage:-moz-locale-dir(rtl) input { + unicode-bidi: plaintext; + direction: rtl; +} + /* Content pane */ #playDRMContentLink { /* Line up with the buttons in the other grid bits: */ diff --git a/browser/themes/windows/Info-XP.png b/browser/themes/windows/Info-XP.png Binary files differdeleted file mode 100644 index c20f66ce6..000000000 --- a/browser/themes/windows/Info-XP.png +++ /dev/null diff --git a/browser/themes/windows/Privacy-16-XP.png b/browser/themes/windows/Privacy-16-XP.png Binary files differdeleted file mode 100644 index 335febbb3..000000000 --- a/browser/themes/windows/Privacy-16-XP.png +++ /dev/null diff --git a/browser/themes/windows/Toolbar-XP.png b/browser/themes/windows/Toolbar-XP.png Binary files differdeleted file mode 100644 index dff60911f..000000000 --- a/browser/themes/windows/Toolbar-XP.png +++ /dev/null diff --git a/browser/themes/windows/Toolbar-lunaSilver.png b/browser/themes/windows/Toolbar-lunaSilver.png Binary files differdeleted file mode 100644 index 30c425c26..000000000 --- a/browser/themes/windows/Toolbar-lunaSilver.png +++ /dev/null diff --git a/browser/themes/windows/Toolbar-aero.png b/browser/themes/windows/Toolbar-win7.png Binary files differindex b191ce2aa..b191ce2aa 100644 --- a/browser/themes/windows/Toolbar-aero.png +++ b/browser/themes/windows/Toolbar-win7.png diff --git a/browser/themes/windows/Toolbar-aero@2x.png b/browser/themes/windows/Toolbar-win7@2x.png Binary files differindex 033d87dff..033d87dff 100644 --- a/browser/themes/windows/Toolbar-aero@2x.png +++ b/browser/themes/windows/Toolbar-win7@2x.png diff --git a/browser/themes/windows/actionicon-tab-XPVista7.png b/browser/themes/windows/actionicon-tab-win7.png Binary files differindex 8437c7655..8437c7655 100644 --- a/browser/themes/windows/actionicon-tab-XPVista7.png +++ b/browser/themes/windows/actionicon-tab-win7.png diff --git a/browser/themes/windows/browser-aero.css b/browser/themes/windows/browser-aero.css index 5ff9d8250..dbac6bb7a 100644 --- a/browser/themes/windows/browser-aero.css +++ b/browser/themes/windows/browser-aero.css @@ -46,8 +46,7 @@ color: graytext; } - @media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { + @media (-moz-os-version: windows-win7) { .sidebar-header:not(:-moz-lwtheme), #sidebar-header:not(:-moz-lwtheme) { background-color: #EEF3FA; @@ -83,190 +82,353 @@ -moz-appearance: -moz-win-exclude-glass; } - @media not all and (-moz-os-version: windows-vista) { - @media not all and (-moz-os-version: windows-win7) { - @media not all and (-moz-os-version: windows-win8) { - @media (-moz-windows-default-theme) { - #main-window { - background-color: hsl(0, 0%, 78%); - } - - :root[tabsintitlebar] .tab-label:-moz-window-inactive { - /* Calculated to match the opacity change of Windows Explorer - titlebar text change for inactive windows. */ - opacity: .6; - } - } + @media (-moz-os-version: windows-win10) { + /* Draw XUL caption buttons and background on Windows 10 */ + @media (-moz-windows-default-theme) { + #main-window { + background-color: hsl(0, 0%, 78%); + } - @media not all and (-moz-windows-default-theme) { - #main-window { - background-color: transparent; - } - } + :root[tabsintitlebar] .tab-label:-moz-window-inactive { + /* Calculated to match the opacity change of Windows Explorer + titlebar text change for inactive windows. */ + opacity: .6; + } + } - #titlebar-buttonbox, - .titlebar-button { - -moz-appearance: none !important; - } + @media not all and (-moz-windows-accent-color-applies) { + /* Default styling for when no accent color is applied */ + #main-window:not(:-moz-window-inactive):not(:-moz-lwtheme) { + background-color: hsl(235, 33%, 19%); + } + + :root:not(:-moz-window-inactive):not(:-moz-lwtheme) { + --titlebar-text-color: white; + } + + #titlebar-min:not(:-moz-window-inactive):not(:-moz-lwtheme) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-highlight); + } - .titlebar-button { - border: none; - margin: 0 !important; - padding: 10px 17px; - } + #titlebar-max:not(:-moz-window-inactive):not(:-moz-lwtheme) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-highlight); + } - #main-window[sizemode=maximized] .titlebar-button { - padding-top: 8px; - padding-bottom: 8px; - } + #main-window[sizemode="maximized"] #titlebar-max:not(:-moz-window-inactive):not(:-moz-lwtheme) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-highlight); + } + + #titlebar-close:not(:-moz-window-inactive):not(:-moz-lwtheme) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highlight); + } - .titlebar-button > .toolbarbutton-icon { - width: 12px; - height: 12px; - } + .titlebar-button:not(#titlebar-close):not(:-moz-window-inactive):not(:-moz-lwtheme):hover { + background-color: hsla(0, 0%, 100%, .17); + } + + .titlebar-button:not(#titlebar-close):not(:-moz-window-inactive):not(:-moz-lwtheme):hover:active { + background-color: hsla(0, 0%, 100%, .27); + transition: none; + } + + #titlebar-close:not(:-moz-window-inactive):not(:-moz-lwtheme):hover { + background-color: hsla(0, 86%, 49%, 1); + } + + #titlebar-close:not(:-moz-window-inactive):not(:-moz-lwtheme):hover:active { + background-color: hsla(0, 60%, 39%, 1); + transition: none; + } + } + + @media (-moz-windows-accent-color-applies) { + /* Styling for when an accent color is applied to the titlebar */ + #main-window:not(:-moz-window-inactive):not(:-moz-lwtheme) { + background-color: -moz-win-accentcolor; + } + + :root:not(:-moz-window-inactive):not(:-moz-lwtheme) { + --titlebar-text-color: -moz-win-accentcolortext; + } + + #titlebar-min { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize); + } + + #titlebar-max { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize); + } + + #main-window[sizemode="maximized"] #titlebar-max { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore); + } + + #titlebar-close { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close); + } + + .titlebar-button:hover { + background-color: hsla(0, 0%, 0%, .17); + } + .titlebar-button:hover:active { + background-color: hsla(0, 0%, 0%, .27); + transition: none; + } + + @media (-moz-windows-accent-color-is-dark) { + /* dark accent color */ #titlebar-min { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-highlight); } #titlebar-max { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-highlight); } #main-window[sizemode="maximized"] #titlebar-max { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-highlight); } #titlebar-close { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#close); - } - #titlebar-close:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-white); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highlight); } - - #titlebar-min:-moz-lwtheme { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-themes); + + .titlebar-button:not(#titlebar-close):not(:-moz-window-inactive):not(:-moz-lwtheme):hover { + background-color: hsla(0, 0%, 100%, .17); } - #titlebar-max:-moz-lwtheme { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-themes); + .titlebar-button:not(#titlebar-close):not(:-moz-window-inactive):not(:-moz-lwtheme):hover:active { + background-color: hsla(0, 0%, 100%, .27); + transition: none; } - #main-window[sizemode="maximized"] #titlebar-max:-moz-lwtheme { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-themes); + + #titlebar-close:not(:-moz-window-inactive):not(:-moz-lwtheme):hover { + background-color: hsla(0, 86%, 49%, 1); } - #titlebar-close:-moz-lwtheme { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-themes); + + #titlebar-close:not(:-moz-window-inactive):not(:-moz-lwtheme):hover:active { + background-color: hsla(0, 60%, 39%, 1); + transition: none; } + } + } /* Windows 10 accent color applies */ + @media not all and (-moz-windows-default-theme) { + #main-window { + background-color: transparent; + } + } - /* the 12px image renders a 10px icon, and the 10px upscaled gets rounded to 12.5, which - * rounds up to 13px, which makes the icon one pixel too big on 1.25dppx. Fix: */ - @media (min-resolution: 1.20dppx) and (max-resolution: 1.45dppx) { - .titlebar-button > .toolbarbutton-icon { - width: 11.5px; - height: 11.5px; - } - } + #titlebar-buttonbox, + .titlebar-button { + -moz-appearance: none !important; + } - /* 175% dpi should result in the same device pixel sizes as 150% dpi. */ - @media (min-resolution: 1.70dppx) and (max-resolution: 1.95dppx) { - .titlebar-button { - padding-left: 14.1px; - padding-right: 14.1px; - } - - .titlebar-button > .toolbarbutton-icon { - width: 10.8px; - height: 10.8px; - } - } + .titlebar-button { + border: none; + margin: 0 !important; + padding: 9px 17px; + transition: background-color linear 120ms; + } + + #main-window[sizemode="maximized"][tabsontop=true] #tabbrowser-tabs { + min-height: 28px; + } - /* 225% dpi should result in the same device pixel sizes as 200% dpi. */ - @media (min-resolution: 2.20dppx) and (max-resolution: 2.45dppx) { - .titlebar-button { - padding-left: 15.3333px; - padding-right: 15.3333px; - } - - .titlebar-button > .toolbarbutton-icon { - width: 10.8px; - height: 10.8px; - } - } + #main-window[sizemode=maximized] .titlebar-button { + padding-top: 8px; + padding-bottom: 8px; + } - /* 275% dpi should result in the same device pixel sizes as 250% dpi. */ - @media (min-resolution: 2.70dppx) and (max-resolution: 2.95dppx) { - /* NB: todo: this should also change padding on the buttons - * themselves, but without a device to test this on, it's - * impossible to know by how much. */ - .titlebar-button > .toolbarbutton-icon { - width: 10.8px; - height: 10.8px; - } - } + .titlebar-button > .toolbarbutton-icon { + width: 12px; + height: 12px; + } - @media (-moz-windows-default-theme) { - .titlebar-button:hover { - background-color: hsla(0, 0%, 0%, .12); - } + .titlebar-button:not(:hover) > .toolbarbutton-icon:-moz-window-inactive { + opacity: 0.5; + } - .titlebar-button:hover:active { - background-color: hsla(0, 0%, 0%, .22); - } + #main-window[chromemargin^="0,"][sizemode=normal] #navigator-toolbox { + margin-top: -4px; + } - .titlebar-button:not(:hover) > .toolbarbutton-icon:-moz-window-inactive { - opacity: 0.5; - } + #main-window[sizemode="maximized"] #titlebar-close { + padding-right: 19px; + } + + #titlebar-close:hover { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highlight); + background-color: hsla(0, 86%, 49%, 1); + } - #titlebar-close:hover { - background-color: hsl(355, 86%, 49%); - } + #titlebar-close:hover:active { + background-color: hsla(0, 86%, 49%, 0.6); + transition: none; + } + + /* inactive window */ - #titlebar-close:hover:active { - background-color: hsl(355, 82%, 69%); - } - } - @media not all and (-moz-windows-default-theme) { - .titlebar-button { - background-color: -moz-field; - } - .titlebar-button:hover { - background-color: Highlight; - } - - #titlebar-min { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-highcontrast); - } - #titlebar-min:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-highcontrast-hover); - } - - #titlebar-max { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-highcontrast); - } - #titlebar-max:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-highcontrast-hover); - } - - #main-window[sizemode="maximized"] #titlebar-max { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-highcontrast); - } - #main-window[sizemode="maximized"] #titlebar-max:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-highcontrast-hover); - } - - #titlebar-close { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highcontrast); - } - #titlebar-close:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highcontrast-hover); - } - } + #titlebar-min:-moz-window-inactive:not(:-moz-lwtheme) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize); + } + + #titlebar-max:-moz-window-inactive:not(:-moz-lwtheme) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize); + } + + #main-window[sizemode="maximized"] #titlebar-max:-moz-window-inactive:not(:-moz-lwtheme) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore); + } + + #titlebar-close:-moz-window-inactive:not(:-moz-lwtheme):not(:hover) { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close); + } + + .titlebar-button:-moz-window-inactive:not(:-moz-lwtheme):hover { + background-color: hsla(0, 0%, 0%, .17); + } + + .titlebar-button:-moz-window-inactive:not(:-moz-lwtheme):hover:active { + background-color: hsla(0, 0%, 0%, .27); + transition: none; + } + + /* light persona */ + + .titlebar-button:-moz-lwtheme-darktext:hover { + background-color: hsla(0, 0%, 0%, .17); + } + + .titlebar-button:-moz-lwtheme-darktext:hover:active { + background-color: hsla(0, 0%, 0%, .27); + transition: none; + } + + #titlebar-min:-moz-lwtheme-darktext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-outline); + } + + #titlebar-max:-moz-lwtheme-darktext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-outline); + } + + #main-window[sizemode="maximized"]:-moz-lwtheme-darktext #titlebar-max:-moz-lwtheme-darktext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-outline); + } + + #titlebar-close:-moz-lwtheme-darktext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-outline); + } + #titlebar-close:hover:-moz-lwtheme-darktext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-outline); + } + + /* dark persona */ + + .titlebar-button:-moz-lwtheme-brighttext:hover { + background-color: hsla(0, 0%, 100%, .27); + } + + .titlebar-button:-moz-lwtheme-brighttext:hover:active { + background-color: hsla(0, 0%, 100%, .37); + transition: none; + } + + #titlebar-min:-moz-lwtheme-brighttext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-outline-inverted); + } + + #titlebar-max:-moz-lwtheme-brighttext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-outline-inverted); + } + + #main-window[sizemode="maximized"]:-moz-lwtheme-brighttext #titlebar-max:-moz-lwtheme-brighttext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-outline-inverted); + } + + #titlebar-close:-moz-lwtheme-brighttext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-outline-inverted); + } + #titlebar-close:hover:-moz-lwtheme-brighttext { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-outline-inverted); + } + + /* the 12px image renders a 10px icon, and the 10px upscaled gets rounded to 12.5, which + * rounds up to 13px, which makes the icon one pixel too big on 1.25dppx. Fix: */ + @media (min-resolution: 1.20dppx) and (max-resolution: 1.45dppx) { + .titlebar-button > .toolbarbutton-icon { + width: 11.5px; + height: 11.5px; } } - } + + /* 175% dpi should result in the same device pixel sizes as 150% dpi. */ + @media (min-resolution: 1.70dppx) and (max-resolution: 1.95dppx) { + .titlebar-button { + padding-left: 14.1px; + padding-right: 14.1px; + } + .titlebar-button > .toolbarbutton-icon { + width: 10.8px; + height: 10.8px; + } + } + + /* 225% dpi should result in the same device pixel sizes as 200% dpi. */ + @media (min-resolution: 2.20dppx) and (max-resolution: 2.45dppx) { + .titlebar-button { + padding-left: 15.3333px; + padding-right: 15.3333px; + } + .titlebar-button > .toolbarbutton-icon { + width: 10.8px; + height: 10.8px; + } + } + + /* 275% dpi should result in the same device pixel sizes as 250% dpi. */ + @media (min-resolution: 2.70dppx) and (max-resolution: 2.95dppx) { + /* NB: todo: this should also change padding on the buttons + * themselves, but without a device to test this on, it's + * impossible to know by how much. */ + .titlebar-button > .toolbarbutton-icon { + width: 10.8px; + height: 10.8px; + } + } + + + @media not all and (-moz-windows-default-theme) { + .titlebar-button { + background-color: -moz-field; + } + .titlebar-button:hover { + background-color: Highlight; + } - @media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7), + #titlebar-min { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-outine-inverted); + } + + #titlebar-max { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-outine-inverted); + } + + #main-window[sizemode="maximized"] #titlebar-max { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-outine-inverted); + } + + #titlebar-close { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-outine-inverted); + } + #titlebar-close:hover { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-outine-inverted); + } + } + } /* Win 10 styling */ + + @media (-moz-os-version: windows-win7), (-moz-os-version: windows-win8) { #main-window[sizemode="maximized"] #titlebar-buttonbox { margin-inline-end: 3px; @@ -283,7 +445,7 @@ } /* The borders on the glass frame are ours, and inside #browser, and on - * vista and win7 we want to make sure they are "glassy", so we can't use + * win7 we want to make sure they are "glassy", so we can't use * #browser as the exclude-glass container. We use #appcontent instead. */ #browser { -moz-appearance: none; @@ -296,18 +458,13 @@ @media (-moz-os-version: windows-win8) { /* Artificially draw window borders that are covered by lwtheme, see bug 591930. - * Borders for vista/win7 are below, win10 doesn't need them. */ + * Borders for win7 are below, win10 doesn't need them. */ #main-window[sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme { border-top: 1px solid @toolbarShadowColor@; } } @media (-moz-windows-default-theme) { - #toolbar-menubar:not(:-moz-lwtheme), - #TabsToolbar:not(:-moz-lwtheme) { - color: black; - } - #main-menubar > menu:not(:-moz-lwtheme) { color: inherit; } @@ -316,11 +473,9 @@ * On aero, the menubar fog disappears for inactive windows, and renders gray * illegible. */ - @media not all and (-moz-os-version: windows-vista) { - @media not all and (-moz-os-version: windows-win7) { - #toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive { - color: ThreeDShadow; - } + @media not all and (-moz-os-version: windows-win7) { + #toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive { + color: ThreeDShadow; } } } @@ -330,9 +485,8 @@ color: white; } - /* Show borders on vista through win8, but not on win10 and later: */ - @media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7), + /* Show borders on win7 and win8, but not on win10 and later: */ + @media (-moz-os-version: windows-win7), (-moz-os-version: windows-win8) { /* Vertical toolbar border */ #main-window:not([customizing])[sizemode=normal] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(:-moz-lwtheme), diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index 2de5a6545..a0cdabfb2 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -16,6 +16,8 @@ %define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper :root { + --titlebar-text-color: currentColor; + --space-above-tabbar: 15px; --backbutton-urlbar-overlap: 6px; @@ -129,8 +131,7 @@ toolbar:-moz-lwtheme { } @media (-moz-windows-default-theme) { - @media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { + @media (-moz-os-version: windows-win7) { #navigator-toolbox::after { border-bottom-color: #aabccf; } @@ -158,9 +159,7 @@ toolbar:-moz-lwtheme { background-image: linear-gradient(@toolbarHighlight@, @toolbarHighlight@); } -@media (-moz-os-version: windows-xp), - (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { +@media (-moz-os-version: windows-win7) { #nav-bar { background-image: linear-gradient(@toolbarHighlight@, transparent) !important; } @@ -187,19 +186,22 @@ toolbar:-moz-lwtheme { transition: min-height 170ms ease-out, max-height 170ms ease-out, visibility 170ms linear; } +#toolbar-menubar, +#TabsToolbar { + color: var(--titlebar-text-color); +} + @media not all and (-moz-windows-compositor), not all and (-moz-windows-default-theme) { /* Please keep the menu text colors in this media block in sync with * devedition.css, minus the :not(:-moz-lwtheme) condition - see Bug 1165718. */ - #main-window[tabsintitlebar]:not([inFullscreen]) #toolbar-menubar:not(:-moz-lwtheme), - #main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar:not(:-moz-lwtheme) { - color: CaptionText; + :root[tabsintitlebar]:not([inFullscreen]):not(:-moz-lwtheme) { + --titlebar-text-color: CaptionText; } - #main-window[tabsintitlebar]:not([inFullscreen]) #toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive, - #main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar:not(:-moz-lwtheme):-moz-window-inactive { - color: InactiveCaptionText; + :root[tabsintitlebar]:not([inFullscreen]):not(:-moz-lwtheme):-moz-window-inactive { + --titlebar-text-color: InactiveCaptionText; } } @@ -313,64 +315,6 @@ toolbar:-moz-lwtheme { } } -/* Render a window top border for lwthemes on WinXP modern themes: */ -@media (-moz-windows-theme: luna-blue) { - #main-window[tabsintitlebar][sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme { - background-image: linear-gradient(to bottom, - rgb(8, 49, 216) 0, rgb(8, 49, 216) 1px, - rgb(15, 77, 227) 1px, rgb(15, 77, 227) 2px, - rgb(22, 106, 238) 2px, rgb(22, 106, 238) 3px, - rgb(8, 85, 221) 3px, rgb(8, 85, 221) 4px, - transparent 4px); - } - - #main-window[tabsintitlebar][sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme:-moz-window-inactive { - background-image: linear-gradient(to bottom, - rgb(91, 104, 205) 0, rgb(91, 104, 205) 1px, - rgb(116, 128, 220) 1px, rgb(116, 128, 220) 2px, - rgb(117, 140, 221) 2px, rgb(117, 140, 221) 4px, - transparent 4px); - } -} - -@media (-moz-windows-theme: luna-silver) { - #main-window[tabsintitlebar][sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme { - background-image: linear-gradient(to bottom, - rgb(102,102,126) 0, rgb(102,102,126) 1px, - rgb(168,167,191) 1px, rgb(168,167,191) 2px, - white 2px, white 3px, - rgb(188,188,207) 3px, rgb(188,188,207) 4px, - transparent 4px); - } - - #main-window[tabsintitlebar][sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme:-moz-window-inactive { - background-image: linear-gradient(to bottom, - rgb(186,186,197) 0, rgb(186,186,197) 1px, - rgb(236,238,245) 1px, rgb(236,238,245) 2px, - white 2px, white 3px, - rgb(215,215,227) 3px, rgb(215,215,227) 4px, - transparent 4px); - } -} - -@media (-moz-windows-theme: luna-olive) { - #main-window[tabsintitlebar][sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme { - background-image: linear-gradient(to bottom, - rgb(139,161,105) 0, rgb(139,161,105) 1px, - rgb(171, 189, 133) 1px, rgb(171, 189, 133) 2px, - rgb(164,178,127) 2px, rgb(164,178,127) 3px, - transparent 3px); - } - - #main-window[tabsintitlebar][sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme:-moz-window-inactive { - background-image: linear-gradient(to bottom, - rgb(207, 214, 188) 0, rgb(207, 214, 188) 1px, - rgb(224, 226, 200) 1px, rgb(224, 226, 200) 2px, - rgb(214, 216, 190) 2px, rgb(214, 216, 190) 3px, - transparent 3px); - } -} - #TabsToolbar:not([collapsed="true"]) + #nav-bar { /* Move up into the TabsToolbar for the inner highlight at the top of the nav-bar */ margin-top: calc(-1 * var(--navbar-tab-toolbar-highlight-overlap)); @@ -401,12 +345,6 @@ toolbar:-moz-lwtheme { background-color: -moz-dialog; } -@media (-moz-os-version: windows-xp) and (-moz-windows-default-theme) { - #main-window[tabsintitlebar][sizemode="normal"] #toolbar-menubar { - margin-top: 4px; - } -} - /* ::::: titlebar ::::: */ #main-window[sizemode="normal"] > #titlebar { @@ -427,7 +365,7 @@ toolbar:-moz-lwtheme { * click and hover mouse events to work properly for the button in the restored * window state. Otherwise, elements in the navigator-toolbox, like the menubar, * can swallow those events. It will also place the buttons above the fog on - * themes with Aero Glass. + * Windows 7 with Aero Glass. */ #titlebar-buttonbox { z-index: 1; @@ -437,12 +375,6 @@ toolbar:-moz-lwtheme { margin-left: 22px; /* space needed for Aero Snap */ } -@media (-moz-os-version: windows-xp) { - .titlebar-placeholder[type="caption-buttons"] { - margin-left: 10px; /* less space needed on XP because there's no Aero Snap */ - } -} - /* titlebar command buttons */ #titlebar-min { @@ -665,13 +597,6 @@ menuitem.bookmark-item { %include ../shared/toolbarbuttons.inc.css -@media (-moz-windows-theme: luna-silver) and (max-resolution: 1dppx) { - :-moz-any(@primaryToolbarButtons@), - #bookmarks-menu-button.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon { - list-style-image: url("chrome://browser/skin/Toolbar-lunaSilver.png"); - } -} - #main-window:not([customizing]) .toolbarbutton-1[disabled=true] > .toolbarbutton-icon, #main-window:not([customizing]) .toolbarbutton-1[disabled=true] > .toolbarbutton-menu-dropmarker, #main-window:not([customizing]) .toolbarbutton-1[disabled=true] > .toolbarbutton-menubutton-dropmarker, @@ -775,10 +700,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { max-width: 32px; } -@media (-moz-os-version: windows-xp), - (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { - /* < Win8 */ +@media (-moz-os-version: windows-win7) { :root { --toolbarbutton-hover-background: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1)); --toolbarbutton-hover-bordercolor: hsla(210,54%,20%,.15) hsla(210,54%,20%,.2) hsla(210,54%,20%,.25); @@ -1096,9 +1018,7 @@ toolbar[brighttext] #close-button { list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-white); } -@media (-moz-os-version: windows-xp), - (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { +@media (-moz-os-version: windows-win7) { #window-controls { margin-inline-start: 4px; } @@ -1154,8 +1074,7 @@ toolbar[brighttext] #close-button { } } -@media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { +@media (-moz-os-version: windows-win7) { #window-controls { -moz-box-align: start; } @@ -1199,8 +1118,7 @@ toolbar[brighttext] #close-button { } @media (-moz-windows-default-theme) { - @media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7), + @media (-moz-os-version: windows-win7), (-moz-os-version: windows-win8) { #main-window:not(:-moz-lwtheme) { --urlbar-border-color: hsla(210,54%,20%,.25) hsla(210,54%,20%,.27) hsla(210,54%,20%,.3); @@ -1237,8 +1155,7 @@ toolbar[brighttext] #close-button { border-radius: 1px; } - @media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7), + @media (-moz-os-version: windows-win7), (-moz-os-version: windows-win8) { #urlbar:not(:-moz-lwtheme), .searchbar-textbox:not(:-moz-lwtheme) { @@ -1261,11 +1178,9 @@ toolbar[brighttext] #close-button { } } - @media not all and (-moz-os-version: windows-xp) { - #urlbar:not(:-moz-lwtheme)[focused], - .searchbar-textbox:not(:-moz-lwtheme)[focused] { - border-color: Highlight; - } + #urlbar:not(:-moz-lwtheme)[focused], + .searchbar-textbox:not(:-moz-lwtheme)[focused] { + border-color: Highlight; } } @@ -2018,9 +1933,7 @@ html|span.ac-emphasize-text-url { } } -@media (-moz-os-version: windows-xp), - (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { +@media (-moz-os-version: windows-win7) { #sidebar-header > .close-icon { padding-top: 4px; padding-bottom: 4px; @@ -2041,39 +1954,28 @@ html|span.ac-emphasize-text-url { margin-bottom: calc(-1 * var(--tab-toolbar-navbar-overlap)); /* overlap the nav-bar's top border */ } -@media (-moz-os-version: windows-xp) and (-moz-windows-default-theme) { - #main-window[sizemode=normal] #TabsToolbar { - padding-left: 2px; - padding-right: 2px; - } -} - %include ../shared/tabs.inc.css /* Remove border between tab strip and navigation toolbar on Windows 10+ */ -@media not all and (-moz-os-version: windows-xp) { - @media not all and (-moz-os-version: windows-vista) { - @media not all and (-moz-os-version: windows-win7) { - @media not all and (-moz-os-version: windows-win8) { - @media (-moz-windows-default-theme) { - .tab-background-end[selected=true]::after, - .tab-background-start[selected=true]::after { - content: none; - } - - #TabsToolbar { - --tab-stroke-background-size: 0 0; - } - - :root { - --tab-toolbar-navbar-overlap: 0px; - } - - #nav-bar { - border-top-style: none !important; - box-shadow: none; - } - } +@media not all and (-moz-os-version: windows-win7) { + @media not all and (-moz-os-version: windows-win8) { + @media (-moz-windows-default-theme) { + .tab-background-end[selected=true]::after, + .tab-background-start[selected=true]::after { + content: none; + } + + #TabsToolbar { + --tab-stroke-background-size: 0 0; + } + + :root { + --tab-toolbar-navbar-overlap: 0px; + } + + #nav-bar { + border-top-style: none !important; + box-shadow: none; } } } @@ -2558,22 +2460,6 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton { position: relative; } -@media (-moz-os-version: windows-xp) { - @media not all and (-moz-windows-classic) { - #private-browsing-indicator-titlebar > .private-browsing-indicator { - background-image: url("chrome://browser/skin/privatebrowsing-mask-titlebar-XPVista7-tall.png"); - height: 28px; - } - - #main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator { - top: -5px; - } - #main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator { - top: -1px; - } - } -} - @media (-moz-windows-classic) { /** * We have to use top instead of background-position in this case, otherwise @@ -2585,8 +2471,7 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton { } } -@media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { +@media (-moz-os-version: windows-win7) { @media (-moz-windows-glass) { #main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator { top: 1px; @@ -2603,7 +2488,7 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton { @media (-moz-windows-default-theme) { @media not all and (-moz-windows-compositor) { #main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator { - background-image: url("chrome://browser/skin/privatebrowsing-mask-titlebar-XPVista7-tall.png"); + background-image: url("chrome://browser/skin/privatebrowsing-mask-titlebar-win7-tall.png"); height: 28px; } } @@ -2636,19 +2521,14 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton { margin-top: -4px; } - -@media not all and (-moz-os-version: windows-xp) { %include browser-aero.css -} .browser-extension-panel > .panel-arrowcontainer > .panel-arrowcontent { padding: 0; overflow: hidden; } -@media (-moz-os-version: windows-xp), - (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { +@media (-moz-os-version: windows-win7) { .cui-widget-panelview[id^=PanelUI-webext-] { border-radius: 4px; } diff --git a/browser/themes/windows/caption-buttons.svg b/browser/themes/windows/caption-buttons.svg index 3ba4f95a1..9cb42d539 100644 --- a/browser/themes/windows/caption-buttons.svg +++ b/browser/themes/windows/caption-buttons.svg @@ -1,49 +1,61 @@ +<svg width="12" height="12" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<svg width="12" height="12" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <style> + g { + stroke: ButtonText; + stroke-width: 0.9px; + fill: none; + } + g:not(:target) { display: none; } + use:target > g { display: initial; } - g { - stroke: ButtonText; - stroke-width: 0.9px; - fill: none; - } - g:not([id|="close"]) { - shape-rendering: crispEdges; + .highlight > g { + stroke: HighlightText; } - .highcontrast { - stroke-width: 1.9px; + .inactive > g { + stroke: black; } - .highcontrast-hover > g { - stroke: HighlightText; + + .bolder { + stroke-width: 1.6px; + stroke: black; } - .white > g { - stroke: #fff; + + .outline { + stroke-width: 4px; + stroke: white; + opacity: 0.75; } - .themes { - stroke: #fff; - stroke-width: 1.9px; + + .inverted { + stroke-width: 1.6px; + stroke: white; } - .outer-stroke { - stroke: #000; - stroke-width: 3.6; - opacity: .75; + .outline-inverted { + stroke-width: 4px; + stroke: black; + opacity: 0.75; } - .restore-background-window { - stroke-width: .9; + + .outline-thinner { + stroke-width: 3.6px; } + </style> + <g id="close"> - <path d="M1,1 l 10,10 M1,11 l 10,-10"/> + <line x1="1" y1="1" x2="11" y2="11" stroke-width="1px"/> + <line x1="11" y1="1" x2="1" y2="11" stroke-width="1px"/> </g> <g id="maximize"> <rect x="1.5" y="1.5" width="9" height="9"/> @@ -56,45 +68,54 @@ <polyline points="3.5,3.5 3.5,1.5 10.5,1.5 10.5,8.5 8.5,8.5"/> </g> - <use id="close-white" class="white" xlink:href="#close"/> - <use id="maximize-white" class="white" xlink:href="#maximize"/> - <use id="minimize-white" class="white" xlink:href="#minimize"/> - <use id="restore-white" class="white" xlink:href="#restore"/> - - <g id="close-highcontrast" class="highcontrast"> - <path d="M1,1 l 10,10 M1,11 l 10,-10"/> + <g id="close-outline"> + <line x1="1" y1="1" x2="11" y2="11" stroke-linecap="round" class="outline"/> + <line x1="11" y1="1" x2="1" y2="11" stroke-linecap="round" class="outline"/> + <line x1="1" y1="1" x2="11" y2="11" class="bolder"/> + <line x1="11" y1="1" x2="1" y2="11" class="bolder"/> </g> - <g id="maximize-highcontrast" class="highcontrast"> - <rect x="2" y="2" width="8" height="8"/> + <g id="maximize-outline"> + <rect x="1.2" y="1.2" width="9.6" height="9.6" stroke-linecap="round" class="outline"/> + <rect x="1.5" y="1.5" width="9" height="9" class="bolder"/> </g> - <g id="minimize-highcontrast" class="highcontrast"> - <line x1="1" y1="6" x2="11" y2="6"/> + <g id="minimize-outline"> + <line x1="1" y1="5.5" x2="11" y2="5.5" stroke-linecap="round" class="outline outline-thinner"/> + <line x1="1" y1="5.5" x2="11" y2="5.5" class="bolder"/> </g> - <g id="restore-highcontrast" class="highcontrast"> - <rect x="2" y="4" width="6" height="6"/> - <polyline points="3.5,1.5 10.5,1.5 10.5,8.5" class="restore-background-window"/> + <g id="restore-outline"> + <rect x="1.5" y="3.5" width="7" height="7" stroke-linecap="round" class="outline"/> + <polyline points="3.5,3.5 3.5,1.5 10.5,1.5 10.5,8.5 8.5,8.5" stroke-linecap="round" class="outline"/> + <rect x="1.5" y="3.5" width="7" height="7" class="bolder"/> + <polyline points="3.5,3.5 3.5,1.5 10.5,1.5 10.5,8.5 8.5,8.5" class="bolder"/> </g> - <use id="close-highcontrast-hover" class="highcontrast-hover" xlink:href="#close-highcontrast"/> - <use id="maximize-highcontrast-hover" class="highcontrast-hover" xlink:href="#maximize-highcontrast"/> - <use id="minimize-highcontrast-hover" class="highcontrast-hover" xlink:href="#minimize-highcontrast"/> - <use id="restore-highcontrast-hover" class="highcontrast-hover" xlink:href="#restore-highcontrast"/> - - <g id="close-themes" class="themes"> - <path d="M1,1 l 10,10 M1,11 l 10,-10" class="outer-stroke" /> - <path d="M1.75,1.75 l 8.5,8.5 M1.75,10.25 l 8.5,-8.5"/> + <g id="close-outline-inverted"> + <line x1="1" y1="1" x2="11" y2="11" stroke-linecap="round" class="outline-inverted"/> + <line x1="11" y1="1" x2="1" y2="11" stroke-linecap="round" class="outline-inverted"/> + <line x1="1" y1="1" x2="11" y2="11" class="inverted"/> + <line x1="11" y1="1" x2="1" y2="11" class="inverted"/> </g> - <g id="maximize-themes" class="themes"> - <rect x="2" y="2" width="8" height="8" class="outer-stroke"/> - <rect x="2" y="2" width="8" height="8"/> + <g id="maximize-outline-inverted"> + <rect x="1.2" y="1.2" width="9.6" height="9.6" stroke-linecap="round" class="outline-inverted"/> + <rect x="1.5" y="1.5" width="9" height="9" class="inverted"/> </g> - <g id="minimize-themes" class="themes"> - <line x1="0" y1="6" x2="12" y2="6" class="outer-stroke"/> - <line x1="1" y1="6" x2="11" y2="6"/> + <g id="minimize-outline-inverted"> + <line x1="1" y1="5.5" x2="11" y2="5.5" stroke-linecap="round" class="outline-inverted outline-thinner"/> + <line x1="1" y1="5.5" x2="11" y2="5.5" class="inverted"/> </g> - <g id="restore-themes" class="themes"> - <path d="M2,4 l 6,0 l 0,6 l -6,0z M2.5,1.5 l 8,0 l 0,8" class="outer-stroke"/> - <rect x="2" y="4" width="6" height="6"/> - <polyline points="3.5,1.5 10.5,1.5 10.5,8.5" class="restore-background-window"/> + <g id="restore-outline-inverted"> + <rect x="1.5" y="3.5" width="7" height="7" stroke-linecap="round" class="outline-inverted"/> + <polyline points="3.5,3.5 3.5,1.5 10.5,1.5 10.5,8.5 8.5,8.5" stroke-linecap="round" class="outline-inverted"/> + <rect x="1.5" y="3.5" width="7" height="7" class="inverted"/> + <polyline points="3.5,3.5 3.5,1.5 10.5,1.5 10.5,8.5 8.5,8.5" class="inverted"/> </g> + + <use id="close-highlight" class="highlight" xlink:href="#close"/> + <use id="maximize-highlight" class="highlight" xlink:href="#maximize"/> + <use id="minimize-highlight" class="highlight" xlink:href="#minimize"/> + <use id="restore-highlight" class="highlight" xlink:href="#restore"/> + <use id="close-inactive" class="inactive" xlink:href="#close"/> + <use id="maximize-inactive" class="inactive" xlink:href="#maximize"/> + <use id="minimize-inactive" class="inactive" xlink:href="#minimize"/> + <use id="restore-inactive" class="inactive" xlink:href="#restore"/> </svg> diff --git a/browser/themes/windows/customizableui/panelUI.css b/browser/themes/windows/customizableui/panelUI.css index 92080d599..189a163f3 100644 --- a/browser/themes/windows/customizableui/panelUI.css +++ b/browser/themes/windows/customizableui/panelUI.css @@ -131,21 +131,17 @@ menu.subviewbutton > .menu-right:-moz-locale-dir(rtl) { } /* Win8 and beyond. */ -@media not all and (-moz-os-version: windows-xp) { - @media not all and (-moz-os-version: windows-vista) { - @media not all and (-moz-os-version: windows-win7) { - panelview .toolbarbutton-1, - .subviewbutton, - .widget-overflow-list .toolbarbutton-1, - .panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button, - #BMB_bookmarksPopup menupopup[placespopup=true] > hbox, - #edit-controls@inAnyPanel@, - #zoom-controls@inAnyPanel@, - #edit-controls@inAnyPanel@ > toolbarbutton, - #zoom-controls@inAnyPanel@ > toolbarbutton { - border-radius: 0; - } - } +@media not all and (-moz-os-version: windows-win7) { + panelview .toolbarbutton-1, + .subviewbutton, + .widget-overflow-list .toolbarbutton-1, + .panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button, + #BMB_bookmarksPopup menupopup[placespopup=true] > hbox, + #edit-controls@inAnyPanel@, + #zoom-controls@inAnyPanel@, + #edit-controls@inAnyPanel@ > toolbarbutton, + #zoom-controls@inAnyPanel@ > toolbarbutton { + border-radius: 0; } } diff --git a/browser/themes/windows/devedition.css b/browser/themes/windows/devedition.css index 4c25f33a1..bdf4bb80e 100644 --- a/browser/themes/windows/devedition.css +++ b/browser/themes/windows/devedition.css @@ -16,7 +16,7 @@ /* The window background is white due to no accentcolor in the lightweight theme. It can't be changed to transparent when there is no compositor - (Win XP or 7 in classic / basic theme), or else dragging and focus become + (Win 7 in classic / basic theme), or else dragging and focus become broken. So instead just show the normal titlebar in that case, and override the window color as transparent when the compositor is available. */ @media not all and (-moz-windows-compositor) { @@ -116,9 +116,7 @@ } } -@media (-moz-os-version: windows-xp), - (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7), +@media (-moz-os-version: windows-win7), (-moz-os-version: windows-win8) { :root { --space-above-tabbar: 15px; @@ -193,14 +191,12 @@ /* Use proper menu text styling in Win7 classic mode (copied from browser.css) */ @media not all and (-moz-windows-compositor), not all and (-moz-windows-default-theme) { - #main-window[tabsintitlebar]:not([inFullscreen]) #toolbar-menubar, - #main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar { - color: CaptionText; + :root[tabsintitlebar]:not([inFullscreen]) { + --titlebar-text-color: CaptionText; } - #main-window[tabsintitlebar]:not([inFullscreen]) #toolbar-menubar:-moz-window-inactive, - #main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar:-moz-window-inactive { - color: InactiveCaptionText; + :root[tabsintitlebar]:not([inFullscreen]):-moz-window-inactive { + --titlebar-text-color: InactiveCaptionText; } #main-window[tabsintitlebar] #main-menubar > menu { @@ -263,8 +259,7 @@ color: var(--chrome-color); } -@media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7), +@media (-moz-os-version: windows-win7), (-moz-os-version: windows-win8) { /* And then we add them back on toolbars so that they don't look borderless: */ #main-window:not([customizing])[sizemode=normal] #navigator-toolbox::after, diff --git a/browser/themes/windows/downloads/allDownloadsViewOverlay.css b/browser/themes/windows/downloads/allDownloadsViewOverlay.css index e288f1e90..0ee83f669 100644 --- a/browser/themes/windows/downloads/allDownloadsViewOverlay.css +++ b/browser/themes/windows/downloads/allDownloadsViewOverlay.css @@ -18,32 +18,30 @@ /*** Highlighted list items ***/ -@media not all and (-moz-os-version: windows-xp) { - @media (-moz-windows-default-theme) { - /* - -moz-appearance: menuitem is almost right, but the hover effect is not - transparent and is lighter than desired. - - Copied from the autocomplete richlistbox styling in - toolkit/themes/windows/global/autocomplete.css - - This styling should be kept in sync with the style from the above file. - */ - @itemFocused@ { - color: inherit; - background-color: transparent; - /* four gradients for the bevel highlights on each edge, one for blue background */ - background-image: - linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, transparent 3px), - linear-gradient(to right, rgba(255,255,255,0.5) 3px, transparent 3px), - linear-gradient(to left, rgba(255,255,255,0.5) 3px, transparent 3px), - linear-gradient(to top, rgba(255,255,255,0.4) 3px, transparent 3px), - linear-gradient(to bottom, rgba(163,196,247,0.3), rgba(122,180,246,0.3)); - background-clip: content-box; - border-radius: 6px; - outline: 1px solid rgb(124,163,206); - -moz-outline-radius: 3px; - outline-offset: -2px; - } +@media (-moz-windows-default-theme) { + /* + -moz-appearance: menuitem is almost right, but the hover effect is not + transparent and is lighter than desired. + + Copied from the autocomplete richlistbox styling in + toolkit/themes/windows/global/autocomplete.css + + This styling should be kept in sync with the style from the above file. + */ + @itemFocused@ { + color: inherit; + background-color: transparent; + /* four gradients for the bevel highlights on each edge, one for blue background */ + background-image: + linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, transparent 3px), + linear-gradient(to right, rgba(255,255,255,0.5) 3px, transparent 3px), + linear-gradient(to left, rgba(255,255,255,0.5) 3px, transparent 3px), + linear-gradient(to top, rgba(255,255,255,0.4) 3px, transparent 3px), + linear-gradient(to bottom, rgba(163,196,247,0.3), rgba(122,180,246,0.3)); + background-clip: content-box; + border-radius: 6px; + outline: 1px solid rgb(124,163,206); + -moz-outline-radius: 3px; + outline-offset: -2px; } } diff --git a/browser/themes/windows/downloads/download-glow-menuPanel-XPVista7.png b/browser/themes/windows/downloads/download-glow-menuPanel-win7.png Binary files differindex 7ff7e6a03..7ff7e6a03 100644 --- a/browser/themes/windows/downloads/download-glow-menuPanel-XPVista7.png +++ b/browser/themes/windows/downloads/download-glow-menuPanel-win7.png diff --git a/browser/themes/windows/downloads/download-glow-XPVista7.png b/browser/themes/windows/downloads/download-glow-win7.png Binary files differindex e7415e83d..e7415e83d 100644 --- a/browser/themes/windows/downloads/download-glow-XPVista7.png +++ b/browser/themes/windows/downloads/download-glow-win7.png diff --git a/browser/themes/windows/downloads/indicator.css b/browser/themes/windows/downloads/indicator.css index 627265088..7f921f8de 100644 --- a/browser/themes/windows/downloads/indicator.css +++ b/browser/themes/windows/downloads/indicator.css @@ -166,13 +166,9 @@ toolbar[brighttext] #downloads-button:not([counter])[attention="success"] > #dow font-size: 9px; line-height: 9px; text-align: center; -} -@media not all and (-moz-os-version: windows-xp) { - #downloads-indicator-counter { - /* Bug 812345 added this... */ - margin-bottom: -1px; - } + /* Bug 812345 added this... */ + margin-bottom: -1px; } toolbar[brighttext] #downloads-indicator-counter { diff --git a/browser/themes/windows/feeds/feedIcon-XP.png b/browser/themes/windows/feeds/feedIcon-XP.png Binary files differdeleted file mode 100644 index d0cafb1d4..000000000 --- a/browser/themes/windows/feeds/feedIcon-XP.png +++ /dev/null diff --git a/browser/themes/windows/feeds/feedIcon16-XP.png b/browser/themes/windows/feeds/feedIcon16-XP.png Binary files differdeleted file mode 100644 index dd7821f8d..000000000 --- a/browser/themes/windows/feeds/feedIcon16-XP.png +++ /dev/null diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index 89c589aba..410148645 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -11,21 +11,17 @@ browser.jar: * skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css) skin/classic/browser/actionicon-tab.png skin/classic/browser/actionicon-tab@2x.png - skin/classic/browser/actionicon-tab-XPVista7.png + skin/classic/browser/actionicon-tab-win7.png * skin/classic/browser/browser.css * skin/classic/browser/devedition.css * skin/classic/browser/browser-lightweightTheme.css skin/classic/browser/caption-buttons.svg skin/classic/browser/click-to-play-warning-stripes.png skin/classic/browser/Info.png - skin/classic/browser/Info-XP.png skin/classic/browser/keyhole-forward-mask.svg skin/classic/browser/livemark-folder.png - skin/classic/browser/livemark-folder-XP.png skin/classic/browser/menu-back.png - skin/classic/browser/menu-back-XP.png skin/classic/browser/menu-forward.png - skin/classic/browser/menu-forward-XP.png skin/classic/browser/menuPanel-customize.png skin/classic/browser/menuPanel-customize@2x.png skin/classic/browser/menuPanel-exit.png @@ -36,36 +32,33 @@ browser.jar: skin/classic/browser/monitor_16-10.png skin/classic/browser/pageInfo.css skin/classic/browser/pageInfo.png - skin/classic/browser/pageInfo-XP.png skin/classic/browser/privatebrowsing-mask-tabstrip.png - skin/classic/browser/privatebrowsing-mask-tabstrip-XPVista7.png + skin/classic/browser/privatebrowsing-mask-tabstrip-win7.png skin/classic/browser/privatebrowsing-mask-titlebar.png - skin/classic/browser/privatebrowsing-mask-titlebar-XPVista7.png - skin/classic/browser/privatebrowsing-mask-titlebar-XPVista7-tall.png + skin/classic/browser/privatebrowsing-mask-titlebar-win7.png + skin/classic/browser/privatebrowsing-mask-titlebar-win7-tall.png skin/classic/browser/reload-stop-go.png skin/classic/browser/reload-stop-go@2x.png - skin/classic/browser/reload-stop-go-XPVista7.png - skin/classic/browser/reload-stop-go-XPVista7@2x.png + skin/classic/browser/reload-stop-go-win7.png + skin/classic/browser/reload-stop-go-win7@2x.png skin/classic/browser/searchbar.css skin/classic/browser/setDesktopBackground.css skin/classic/browser/slowStartup-16.png skin/classic/browser/Toolbar.png skin/classic/browser/Toolbar@2x.png - skin/classic/browser/Toolbar-aero.png - skin/classic/browser/Toolbar-aero@2x.png + skin/classic/browser/Toolbar-win7.png + skin/classic/browser/Toolbar-win7@2x.png skin/classic/browser/Toolbar-inverted.png skin/classic/browser/Toolbar-inverted@2x.png - skin/classic/browser/Toolbar-lunaSilver.png skin/classic/browser/Toolbar-win8.png skin/classic/browser/Toolbar-win8@2x.png - skin/classic/browser/Toolbar-XP.png - skin/classic/browser/toolbarbutton-dropdown-arrow-XPVista7.png + skin/classic/browser/toolbarbutton-dropdown-arrow-win7.png skin/classic/browser/toolbarbutton-dropdown-arrow-inverted.png skin/classic/browser/urlbar-popup-blocked.png skin/classic/browser/urlbar-history-dropmarker.png skin/classic/browser/urlbar-history-dropmarker@2x.png - skin/classic/browser/urlbar-history-dropmarker-XPVista7.png - skin/classic/browser/urlbar-history-dropmarker-XPVista7@2x.png + skin/classic/browser/urlbar-history-dropmarker-win7.png + skin/classic/browser/urlbar-history-dropmarker-win7@2x.png skin/classic/browser/webRTC-indicator.css * skin/classic/browser/controlcenter/panel.css (controlcenter/panel.css) skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png) @@ -78,57 +71,40 @@ browser.jar: * skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css) * skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css) skin/classic/browser/downloads/download-glow-menuPanel.png (downloads/download-glow-menuPanel.png) - skin/classic/browser/downloads/download-glow-menuPanel-XPVista7.png (downloads/download-glow-menuPanel-XPVista7.png) + skin/classic/browser/downloads/download-glow-menuPanel-win7.png (downloads/download-glow-menuPanel-win7.png) skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png) skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png) * skin/classic/browser/downloads/downloads.css (downloads/downloads.css) skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png) skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png) - skin/classic/browser/feeds/feedIcon-XP.png (feeds/feedIcon-XP.png) - skin/classic/browser/feeds/feedIcon16-XP.png (feeds/feedIcon16-XP.png) skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css) skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css) * skin/classic/browser/newtab/newTab.css (newtab/newTab.css) skin/classic/browser/places/autocomplete-star.png (places/autocomplete-star.png) skin/classic/browser/places/autocomplete-star@2x.png (places/autocomplete-star@2x.png) - skin/classic/browser/places/autocomplete-star-XPVista7.png (places/autocomplete-star-XPVista7.png) + skin/classic/browser/places/autocomplete-star-win7.png (places/autocomplete-star-win7.png) skin/classic/browser/places/places.css (places/places.css) * skin/classic/browser/places/organizer.css (places/organizer.css) skin/classic/browser/places/query.png (places/query.png) - skin/classic/browser/places/query-XP.png (places/query-XP.png) skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png) - skin/classic/browser/places/bookmarksMenu-XP.png (places/bookmarksMenu-XP.png) skin/classic/browser/places/bookmarksToolbar.png (places/bookmarksToolbar.png) - skin/classic/browser/places/bookmarksToolbar-XP.png (places/bookmarksToolbar-XP.png) skin/classic/browser/places/bookmarksToolbar-menuPanel.png (places/bookmarksToolbar-menuPanel.png) - skin/classic/browser/places/bookmarksToolbar-menuPanel-XP.png (places/bookmarksToolbar-menuPanel-XP.png) skin/classic/browser/places/bookmarks-notification-finish.png (places/bookmarks-notification-finish.png) skin/classic/browser/places/calendar.png (places/calendar.png) - skin/classic/browser/places/calendar-XP.png (places/calendar-XP.png) skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png) - skin/classic/browser/places/toolbarDropMarker-XP.png (places/toolbarDropMarker-XP.png) skin/classic/browser/places/editBookmarkOverlay.css (places/editBookmarkOverlay.css) skin/classic/browser/places/libraryToolbar.png (places/libraryToolbar.png) - skin/classic/browser/places/libraryToolbar-XP.png (places/libraryToolbar-XP.png) skin/classic/browser/places/starred48.png (places/starred48.png) - skin/classic/browser/places/starred48-XP.png (places/starred48-XP.png) skin/classic/browser/places/unstarred48.png (places/unstarred48.png) skin/classic/browser/places/tag.png (places/tag.png) - skin/classic/browser/places/tag-XP.png (places/tag-XP.png) skin/classic/browser/places/history.png (places/history.png) - skin/classic/browser/places/history-XP.png (places/history-XP.png) skin/classic/browser/places/allBookmarks.png (places/allBookmarks.png) - skin/classic/browser/places/allBookmarks-XP.png (places/allBookmarks-XP.png) skin/classic/browser/places/unsortedBookmarks.png (places/unsortedBookmarks.png) - skin/classic/browser/places/unsortedBookmarks-XP.png (places/unsortedBookmarks-XP.png) skin/classic/browser/places/downloads.png (places/downloads.png) skin/classic/browser/places/livemark-item.png (places/livemark-item.png) skin/classic/browser/preferences/alwaysAsk.png (preferences/alwaysAsk.png) - skin/classic/browser/preferences/alwaysAsk-XP.png (preferences/alwaysAsk-XP.png) skin/classic/browser/preferences/application.png (preferences/application.png) - skin/classic/browser/preferences/application-XP.png (preferences/application-XP.png) skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png) - skin/classic/browser/preferences/saveFile-XP.png (preferences/saveFile-XP.png) skin/classic/browser/preferences/preferences.css (preferences/preferences.css) * skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css) * skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css) @@ -136,13 +112,13 @@ browser.jar: skin/classic/browser/social/services-16.png (social/services-16.png) skin/classic/browser/social/services-64.png (social/services-64.png) skin/classic/browser/tabbrowser/newtab.svg (tabbrowser/newtab.svg) - skin/classic/browser/tabbrowser/newtab-XPVista7.svg (tabbrowser/newtab-XPVista7.svg) + skin/classic/browser/tabbrowser/newtab-win7.svg (tabbrowser/newtab-win7.svg) skin/classic/browser/tabbrowser/newtab-inverted.svg (tabbrowser/newtab-inverted.svg) - skin/classic/browser/tabbrowser/newtab-inverted-XPVista7.svg (tabbrowser/newtab-inverted-XPVista7.svg) + skin/classic/browser/tabbrowser/newtab-inverted-win7.svg (tabbrowser/newtab-inverted-win7.svg) skin/classic/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png) skin/classic/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png) skin/classic/browser/tabbrowser/tab-arrow-left.svg (tabbrowser/tab-arrow-left.svg) - skin/classic/browser/tabbrowser/tab-arrow-left-XPVista7.svg (tabbrowser/tab-arrow-left-XPVista7.svg) + skin/classic/browser/tabbrowser/tab-arrow-left-win7.svg (tabbrowser/tab-arrow-left-win7.svg) skin/classic/browser/tabbrowser/tab-arrow-left-inverted.svg (tabbrowser/tab-arrow-left-inverted.svg) skin/classic/browser/tabbrowser/tab-background-start.png (tabbrowser/tab-background-start.png) skin/classic/browser/tabbrowser/tab-background-start@2x.png (tabbrowser/tab-background-start@2x.png) @@ -174,8 +150,8 @@ browser.jar: skin/classic/browser/sync-desktopIcon.svg (../shared/sync-desktopIcon.svg) skin/classic/browser/sync-horizontalbar.png skin/classic/browser/sync-horizontalbar@2x.png - skin/classic/browser/sync-horizontalbar-XPVista7.png - skin/classic/browser/sync-horizontalbar-XPVista7@2x.png + skin/classic/browser/sync-horizontalbar-win7.png + skin/classic/browser/sync-horizontalbar-win7@2x.png skin/classic/browser/sync-mobileIcon.svg (../shared/sync-mobileIcon.svg) skin/classic/browser/sync-notification-24.png skin/classic/browser/syncSetup.css @@ -183,19 +159,16 @@ browser.jar: skin/classic/browser/syncQuota.css skin/classic/browser/syncProgress-horizontalbar.png skin/classic/browser/syncProgress-horizontalbar@2x.png - skin/classic/browser/syncProgress-horizontalbar-XPVista7.png - skin/classic/browser/syncProgress-horizontalbar-XPVista7@2x.png + skin/classic/browser/syncProgress-horizontalbar-win7.png + skin/classic/browser/syncProgress-horizontalbar-win7@2x.png skin/classic/browser/syncProgress-menuPanel.png skin/classic/browser/syncProgress-menuPanel@2x.png skin/classic/browser/syncProgress-toolbar.png skin/classic/browser/syncProgress-toolbar@2x.png skin/classic/browser/syncProgress-toolbar-inverted.png skin/classic/browser/syncProgress-toolbar-inverted@2x.png - skin/classic/browser/syncProgress-toolbar-XPVista7.png - skin/classic/browser/syncProgress-toolbar-XPVista7@2x.png -#ifdef E10S_TESTING_ONLY - skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png) -#endif + skin/classic/browser/syncProgress-toolbar-win7.png + skin/classic/browser/syncProgress-toolbar-win7@2x.png [extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar: % override chrome://browser/skin/page-livemarks.png chrome://browser/skin/feeds/feedIcon16.png @@ -205,58 +178,31 @@ browser.jar: % override chrome://browser/skin/feeds/videoFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png % override chrome://browser/skin/aboutSessionRestore-window-icon.png chrome://browser/skin/preferences/application.png os!=WINNT -% override chrome://browser/skin/aboutSessionRestore-window-icon.png chrome://browser/skin/preferences/application.png os=WINNT osversion<6 -% override chrome://browser/skin/Info.png chrome://browser/skin/Info-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/livemark-folder.png chrome://browser/skin/livemark-folder-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/menu-back.png chrome://browser/skin/menu-back-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/menu-forward.png chrome://browser/skin/menu-forward-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/pageInfo.png chrome://browser/skin/pageInfo-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/feeds/feedIcon.png chrome://browser/skin/feeds/feedIcon-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/feeds/feedIcon16.png chrome://browser/skin/feeds/feedIcon16-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/query.png chrome://browser/skin/places/query-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/bookmarksMenu.png chrome://browser/skin/places/bookmarksMenu-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/bookmarksToolbar.png chrome://browser/skin/places/bookmarksToolbar-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/bookmarksToolbar-menuPanel.png chrome://browser/skin/places/bookmarksToolbar-menuPanel-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/calendar.png chrome://browser/skin/places/calendar-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/toolbarDropMarker.png chrome://browser/skin/places/toolbarDropMarker-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/libraryToolbar.png chrome://browser/skin/places/libraryToolbar-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/starred48.png chrome://browser/skin/places/starred48-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/tag.png chrome://browser/skin/places/tag-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/history.png chrome://browser/skin/places/history-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/allBookmarks.png chrome://browser/skin/places/allBookmarks-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/places/unsortedBookmarks.png chrome://browser/skin/places/unsortedBookmarks-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/preferences/alwaysAsk.png chrome://browser/skin/preferences/alwaysAsk-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/preferences/application.png chrome://browser/skin/preferences/application-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/preferences/saveFile.png chrome://browser/skin/preferences/saveFile-XP.png os=WINNT osversion<6 +% override chrome://browser/skin/actionicon-tab.png chrome://browser/skin/actionicon-tab-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/privatebrowsing-mask-tabstrip.png chrome://browser/skin/privatebrowsing-mask-tabstrip-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/privatebrowsing-mask-titlebar.png chrome://browser/skin/privatebrowsing-mask-titlebar-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/reload-stop-go.png chrome://browser/skin/reload-stop-go-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/reload-stop-go@2x.png chrome://browser/skin/reload-stop-go-win7@2x.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/sync-horizontalbar.png chrome://browser/skin/sync-horizontalbar-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/sync-horizontalbar@2x.png chrome://browser/skin/sync-horizontalbar-win7@2x.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/syncProgress-horizontalbar.png chrome://browser/skin/syncProgress-horizontalbar-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/syncProgress-horizontalbar@2x.png chrome://browser/skin/syncProgress-horizontalbar-win7@2x.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/syncProgress-toolbar.png chrome://browser/skin/syncProgress-toolbar-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/syncProgress-toolbar@2x.png chrome://browser/skin/syncProgress-toolbar-win7@2x.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/toolbarbutton-dropdown-arrow.png chrome://browser/skin/toolbarbutton-dropdown-arrow-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/urlbar-history-dropmarker.png chrome://browser/skin/urlbar-history-dropmarker-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/urlbar-history-dropmarker@2x.png chrome://browser/skin/urlbar-history-dropmarker-win7@2x.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/downloads/download-glow-menuPanel.png chrome://browser/skin/downloads/download-glow-menuPanel-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/places/autocomplete-star.png chrome://browser/skin/places/autocomplete-star-win7.png os=WINNT osversion<=6.1 +% override chrome://browser/skin/tabbrowser/newtab.svg chrome://browser/skin/tabbrowser/newtab-win7.svg os=WINNT osversion<=6.1 +% override chrome://browser/skin/tabbrowser/newtab-inverted.svg chrome://browser/skin/tabbrowser/newtab-inverted-win7.svg os=WINNT osversion<=6.1 +% override chrome://browser/skin/tabbrowser/tab-arrow-left.svg chrome://browser/skin/tabbrowser/tab-arrow-left-win7.svg os=WINNT osversion<=6.1 -% override chrome://browser/skin/actionicon-tab.png chrome://browser/skin/actionicon-tab-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/privatebrowsing-mask-tabstrip.png chrome://browser/skin/privatebrowsing-mask-tabstrip-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/privatebrowsing-mask-titlebar.png chrome://browser/skin/privatebrowsing-mask-titlebar-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/reload-stop-go.png chrome://browser/skin/reload-stop-go-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/reload-stop-go@2x.png chrome://browser/skin/reload-stop-go-XPVista7@2x.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/sync-horizontalbar.png chrome://browser/skin/sync-horizontalbar-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/sync-horizontalbar@2x.png chrome://browser/skin/sync-horizontalbar-XPVista7@2x.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/syncProgress-horizontalbar.png chrome://browser/skin/syncProgress-horizontalbar-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/syncProgress-horizontalbar@2x.png chrome://browser/skin/syncProgress-horizontalbar-XPVista7@2x.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/syncProgress-toolbar.png chrome://browser/skin/syncProgress-toolbar-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/syncProgress-toolbar@2x.png chrome://browser/skin/syncProgress-toolbar-XPVista7@2x.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/toolbarbutton-dropdown-arrow.png chrome://browser/skin/toolbarbutton-dropdown-arrow-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/urlbar-history-dropmarker.png chrome://browser/skin/urlbar-history-dropmarker-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/urlbar-history-dropmarker@2x.png chrome://browser/skin/urlbar-history-dropmarker-XPVista7@2x.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/downloads/download-glow-menuPanel.png chrome://browser/skin/downloads/download-glow-menuPanel-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/places/autocomplete-star.png chrome://browser/skin/places/autocomplete-star-XPVista7.png os=WINNT osversion<=6.1 -% override chrome://browser/skin/tabbrowser/newtab.svg chrome://browser/skin/tabbrowser/newtab-XPVista7.svg os=WINNT osversion<=6.1 -% override chrome://browser/skin/tabbrowser/newtab-inverted.svg chrome://browser/skin/tabbrowser/newtab-inverted-XPVista7.svg os=WINNT osversion<=6.1 -% override chrome://browser/skin/tabbrowser/tab-arrow-left.svg chrome://browser/skin/tabbrowser/tab-arrow-left-XPVista7.svg os=WINNT osversion<=6.1 - -% override chrome://browser/skin/Toolbar@2x.png chrome://browser/skin/Toolbar-aero@2x.png os=WINNT osversion=6 -% override chrome://browser/skin/Toolbar@2x.png chrome://browser/skin/Toolbar-aero@2x.png os=WINNT osversion=6.1 +% override chrome://browser/skin/Toolbar@2x.png chrome://browser/skin/Toolbar-win7@2x.png os=WINNT osversion=6.1 % override chrome://browser/skin/Toolbar@2x.png chrome://browser/skin/Toolbar-win8@2x.png os=WINNT osversion=6.2 % override chrome://browser/skin/Toolbar@2x.png chrome://browser/skin/Toolbar-win8@2x.png os=WINNT osversion=6.3 -% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-XP.png os=WINNT osversion<6 -% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-aero.png os=WINNT osversion=6 -% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-aero.png os=WINNT osversion=6.1 +% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-win7.png os=WINNT osversion=6.1 % override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-win8.png os=WINNT osversion=6.2 % override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-win8.png os=WINNT osversion=6.3 diff --git a/browser/themes/windows/livemark-folder-XP.png b/browser/themes/windows/livemark-folder-XP.png Binary files differdeleted file mode 100644 index 00aa0364d..000000000 --- a/browser/themes/windows/livemark-folder-XP.png +++ /dev/null diff --git a/browser/themes/windows/menu-back-XP.png b/browser/themes/windows/menu-back-XP.png Binary files differdeleted file mode 100644 index ecb8ccd1a..000000000 --- a/browser/themes/windows/menu-back-XP.png +++ /dev/null diff --git a/browser/themes/windows/menu-forward-XP.png b/browser/themes/windows/menu-forward-XP.png Binary files differdeleted file mode 100644 index a7460dc27..000000000 --- a/browser/themes/windows/menu-forward-XP.png +++ /dev/null diff --git a/browser/themes/windows/pageInfo-XP.png b/browser/themes/windows/pageInfo-XP.png Binary files differdeleted file mode 100644 index bbf257237..000000000 --- a/browser/themes/windows/pageInfo-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/allBookmarks-XP.png b/browser/themes/windows/places/allBookmarks-XP.png Binary files differdeleted file mode 100644 index f7903cc5f..000000000 --- a/browser/themes/windows/places/allBookmarks-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/autocomplete-star-XPVista7.png b/browser/themes/windows/places/autocomplete-star-win7.png Binary files differindex af694e91c..af694e91c 100644 --- a/browser/themes/windows/places/autocomplete-star-XPVista7.png +++ b/browser/themes/windows/places/autocomplete-star-win7.png diff --git a/browser/themes/windows/places/bookmarksMenu-XP.png b/browser/themes/windows/places/bookmarksMenu-XP.png Binary files differdeleted file mode 100644 index 8f0c8bf58..000000000 --- a/browser/themes/windows/places/bookmarksMenu-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/bookmarksToolbar-XP.png b/browser/themes/windows/places/bookmarksToolbar-XP.png Binary files differdeleted file mode 100644 index 9e988de20..000000000 --- a/browser/themes/windows/places/bookmarksToolbar-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/bookmarksToolbar-menuPanel-XP.png b/browser/themes/windows/places/bookmarksToolbar-menuPanel-XP.png Binary files differdeleted file mode 100644 index 0e4247adb..000000000 --- a/browser/themes/windows/places/bookmarksToolbar-menuPanel-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/calendar-XP.png b/browser/themes/windows/places/calendar-XP.png Binary files differdeleted file mode 100644 index 7645af5cd..000000000 --- a/browser/themes/windows/places/calendar-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/history-XP.png b/browser/themes/windows/places/history-XP.png Binary files differdeleted file mode 100644 index fcc89bbbf..000000000 --- a/browser/themes/windows/places/history-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/libraryToolbar-XP.png b/browser/themes/windows/places/libraryToolbar-XP.png Binary files differdeleted file mode 100644 index 75b390ff6..000000000 --- a/browser/themes/windows/places/libraryToolbar-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/organizer.css b/browser/themes/windows/places/organizer.css index 4de603b9f..9ae4c8370 100644 --- a/browser/themes/windows/places/organizer.css +++ b/browser/themes/windows/places/organizer.css @@ -20,13 +20,6 @@ list-style-image: url("chrome://browser/skin/Toolbar.png"); } -@media (-moz-windows-theme: luna-silver) { - #back-button, - #forward-button { - list-style-image: url("chrome://browser/skin/Toolbar-lunaSilver.png"); - } -} - #back-button { -moz-image-region: rect(0, 54px, 18px, 36px); } @@ -119,11 +112,6 @@ -moz-image-region: rect(16px, 48px, 32px, 32px); } -/* Root View */ -#placesView { - border-top: 1px solid ThreeDDarkShadow; -} - /* Info box */ #detailsDeck { border-top: 1px solid ThreeDShadow; @@ -151,35 +139,28 @@ padding-inline-end: 9px; } - -@media not all and (-moz-os-version: windows-xp) { - #placesView { - border-top: none; +@media not all and (-moz-windows-classic) { + #placesToolbox { + -moz-appearance: none; + background-color: transparent; } - @media not all and (-moz-windows-classic) { - #placesToolbox { - -moz-appearance: none; - background-color: transparent; - } - - #placesToolbar { - -moz-appearance: none; - background-color: -moz-Dialog; - color: -moz-dialogText; - } + #placesToolbar { + -moz-appearance: none; + background-color: -moz-Dialog; + color: -moz-dialogText; } +} - @media (-moz-windows-default-theme) { - #placesView > splitter { - border: 0; - border-inline-end: 1px solid #A9B7C9; - min-width: 0; - width: 3px; - background-color: transparent; - margin-inline-start: -3px; - position: relative; - } +@media (-moz-windows-default-theme) { + #placesView > splitter { + border: 0; + border-inline-end: 1px solid #A9B7C9; + min-width: 0; + width: 3px; + background-color: transparent; + margin-inline-start: -3px; + position: relative; } } @@ -193,8 +174,7 @@ } } -@media (-moz-windows-default-theme) and (-moz-os-version: windows-vista), - (-moz-windows-default-theme) and (-moz-os-version: windows-win7) { +@media (-moz-windows-default-theme) and (-moz-os-version: windows-win7) { #placesView, #infoPane, #placesList, diff --git a/browser/themes/windows/places/places.css b/browser/themes/windows/places/places.css index 4ec8f6555..769cfcc25 100644 --- a/browser/themes/windows/places/places.css +++ b/browser/themes/windows/places/places.css @@ -24,21 +24,17 @@ cursor: default; } -/* Style Places sidebars as Vista media collection */ @media (-moz-windows-default-theme) { - @media not all and (-moz-os-version: windows-xp) { - .sidebar-placesTree { - background-color: transparent; - border-top: none; - } + .sidebar-placesTree { + background-color: transparent; + border-top: none; + } - .sidebar-placesTreechildren::-moz-tree-cell-text(leaf, hover) { - text-decoration: none; - } + .sidebar-placesTreechildren::-moz-tree-cell-text(leaf, hover) { + text-decoration: none; } - @media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { + @media (-moz-os-version: windows-win7) { #bookmarksPanel, #history-panel, #tabs-panel { diff --git a/browser/themes/windows/places/query-XP.png b/browser/themes/windows/places/query-XP.png Binary files differdeleted file mode 100644 index 9e79fc791..000000000 --- a/browser/themes/windows/places/query-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/starred48-XP.png b/browser/themes/windows/places/starred48-XP.png Binary files differdeleted file mode 100644 index 1cb7bc57d..000000000 --- a/browser/themes/windows/places/starred48-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/tag-XP.png b/browser/themes/windows/places/tag-XP.png Binary files differdeleted file mode 100644 index 4b4a13e66..000000000 --- a/browser/themes/windows/places/tag-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/toolbarDropMarker-XP.png b/browser/themes/windows/places/toolbarDropMarker-XP.png Binary files differdeleted file mode 100644 index 9173b7a7a..000000000 --- a/browser/themes/windows/places/toolbarDropMarker-XP.png +++ /dev/null diff --git a/browser/themes/windows/places/unsortedBookmarks-XP.png b/browser/themes/windows/places/unsortedBookmarks-XP.png Binary files differdeleted file mode 100644 index cf73f9464..000000000 --- a/browser/themes/windows/places/unsortedBookmarks-XP.png +++ /dev/null diff --git a/browser/themes/windows/preferences/alwaysAsk-XP.png b/browser/themes/windows/preferences/alwaysAsk-XP.png Binary files differdeleted file mode 100644 index 8693211ac..000000000 --- a/browser/themes/windows/preferences/alwaysAsk-XP.png +++ /dev/null diff --git a/browser/themes/windows/preferences/application-XP.png b/browser/themes/windows/preferences/application-XP.png Binary files differdeleted file mode 100644 index 7d279ff84..000000000 --- a/browser/themes/windows/preferences/application-XP.png +++ /dev/null diff --git a/browser/themes/windows/preferences/saveFile-XP.png b/browser/themes/windows/preferences/saveFile-XP.png Binary files differdeleted file mode 100644 index e115eaa9f..000000000 --- a/browser/themes/windows/preferences/saveFile-XP.png +++ /dev/null diff --git a/browser/themes/windows/privatebrowsing-mask-tabstrip-XPVista7.png b/browser/themes/windows/privatebrowsing-mask-tabstrip-win7.png Binary files differindex bd5d46a76..bd5d46a76 100644 --- a/browser/themes/windows/privatebrowsing-mask-tabstrip-XPVista7.png +++ b/browser/themes/windows/privatebrowsing-mask-tabstrip-win7.png diff --git a/browser/themes/windows/privatebrowsing-mask-titlebar-XPVista7-tall.png b/browser/themes/windows/privatebrowsing-mask-titlebar-win7-tall.png Binary files differindex 4a723c54e..4a723c54e 100644 --- a/browser/themes/windows/privatebrowsing-mask-titlebar-XPVista7-tall.png +++ b/browser/themes/windows/privatebrowsing-mask-titlebar-win7-tall.png diff --git a/browser/themes/windows/privatebrowsing-mask-titlebar-XPVista7.png b/browser/themes/windows/privatebrowsing-mask-titlebar-win7.png Binary files differindex 835912b53..835912b53 100644 --- a/browser/themes/windows/privatebrowsing-mask-titlebar-XPVista7.png +++ b/browser/themes/windows/privatebrowsing-mask-titlebar-win7.png diff --git a/browser/themes/windows/reload-stop-go-XPVista7.png b/browser/themes/windows/reload-stop-go-win7.png Binary files differindex 3ef32c3ce..3ef32c3ce 100644 --- a/browser/themes/windows/reload-stop-go-XPVista7.png +++ b/browser/themes/windows/reload-stop-go-win7.png diff --git a/browser/themes/windows/reload-stop-go-XPVista7@2x.png b/browser/themes/windows/reload-stop-go-win7@2x.png Binary files differindex 38b27bf0c..38b27bf0c 100644 --- a/browser/themes/windows/reload-stop-go-XPVista7@2x.png +++ b/browser/themes/windows/reload-stop-go-win7@2x.png diff --git a/browser/themes/windows/sync-horizontalbar-XPVista7.png b/browser/themes/windows/sync-horizontalbar-win7.png Binary files differindex 2c97ce6db..2c97ce6db 100644 --- a/browser/themes/windows/sync-horizontalbar-XPVista7.png +++ b/browser/themes/windows/sync-horizontalbar-win7.png diff --git a/browser/themes/windows/sync-horizontalbar-XPVista7@2x.png b/browser/themes/windows/sync-horizontalbar-win7@2x.png Binary files differindex ee117ab73..ee117ab73 100644 --- a/browser/themes/windows/sync-horizontalbar-XPVista7@2x.png +++ b/browser/themes/windows/sync-horizontalbar-win7@2x.png diff --git a/browser/themes/windows/syncProgress-horizontalbar-XPVista7.png b/browser/themes/windows/syncProgress-horizontalbar-win7.png Binary files differindex 48cd11055..48cd11055 100644 --- a/browser/themes/windows/syncProgress-horizontalbar-XPVista7.png +++ b/browser/themes/windows/syncProgress-horizontalbar-win7.png diff --git a/browser/themes/windows/syncProgress-horizontalbar-XPVista7@2x.png b/browser/themes/windows/syncProgress-horizontalbar-win7@2x.png Binary files differindex 741dd2ed4..741dd2ed4 100644 --- a/browser/themes/windows/syncProgress-horizontalbar-XPVista7@2x.png +++ b/browser/themes/windows/syncProgress-horizontalbar-win7@2x.png diff --git a/browser/themes/windows/syncProgress-toolbar-XPVista7.png b/browser/themes/windows/syncProgress-toolbar-win7.png Binary files differindex 49e224f0d..49e224f0d 100644 --- a/browser/themes/windows/syncProgress-toolbar-XPVista7.png +++ b/browser/themes/windows/syncProgress-toolbar-win7.png diff --git a/browser/themes/windows/syncProgress-toolbar-XPVista7@2x.png b/browser/themes/windows/syncProgress-toolbar-win7@2x.png Binary files differindex fd2038725..fd2038725 100644 --- a/browser/themes/windows/syncProgress-toolbar-XPVista7@2x.png +++ b/browser/themes/windows/syncProgress-toolbar-win7@2x.png diff --git a/browser/themes/windows/tabbrowser/newtab-inverted-XPVista7.svg b/browser/themes/windows/tabbrowser/newtab-inverted-win7.svg index 10ffbc745..10ffbc745 100644 --- a/browser/themes/windows/tabbrowser/newtab-inverted-XPVista7.svg +++ b/browser/themes/windows/tabbrowser/newtab-inverted-win7.svg diff --git a/browser/themes/windows/tabbrowser/newtab-XPVista7.svg b/browser/themes/windows/tabbrowser/newtab-win7.svg index 3f431c9db..3f431c9db 100644 --- a/browser/themes/windows/tabbrowser/newtab-XPVista7.svg +++ b/browser/themes/windows/tabbrowser/newtab-win7.svg diff --git a/browser/themes/windows/tabbrowser/tab-arrow-left-XPVista7.svg b/browser/themes/windows/tabbrowser/tab-arrow-left-win7.svg index 41bb5ab13..41bb5ab13 100644 --- a/browser/themes/windows/tabbrowser/tab-arrow-left-XPVista7.svg +++ b/browser/themes/windows/tabbrowser/tab-arrow-left-win7.svg diff --git a/browser/themes/windows/toolbarbutton-dropdown-arrow-XPVista7.png b/browser/themes/windows/toolbarbutton-dropdown-arrow-win7.png Binary files differindex 5f892f532..5f892f532 100644 --- a/browser/themes/windows/toolbarbutton-dropdown-arrow-XPVista7.png +++ b/browser/themes/windows/toolbarbutton-dropdown-arrow-win7.png diff --git a/browser/themes/windows/urlbar-history-dropmarker-XPVista7.png b/browser/themes/windows/urlbar-history-dropmarker-win7.png Binary files differindex b03338822..b03338822 100644 --- a/browser/themes/windows/urlbar-history-dropmarker-XPVista7.png +++ b/browser/themes/windows/urlbar-history-dropmarker-win7.png diff --git a/browser/themes/windows/urlbar-history-dropmarker-XPVista7@2x.png b/browser/themes/windows/urlbar-history-dropmarker-win7@2x.png Binary files differindex bff2997f8..bff2997f8 100644 --- a/browser/themes/windows/urlbar-history-dropmarker-XPVista7@2x.png +++ b/browser/themes/windows/urlbar-history-dropmarker-win7@2x.png diff --git a/browser/themes/windows/windowsShared.inc b/browser/themes/windows/windowsShared.inc index 0cb2ab163..199a62292 100644 --- a/browser/themes/windows/windowsShared.inc +++ b/browser/themes/windows/windowsShared.inc @@ -8,6 +8,4 @@ %define fgTabTexture linear-gradient(transparent 2px, @toolbarHighlight@ 2px, @toolbarHighlight@) %define fgTabBackgroundColor -moz-dialog %define fgTabTextureLWT @fgTabTexture@ - -% Aero-only defines %define customToolbarColor hsl(210,75%,92%) |