author | Wes Kocher <wkocher@mozilla.com> |
Mon, 03 Apr 2017 14:50:18 -0700 | |
changeset 351002 | b5d8b27a753725c1de41ffae2e338798f3b5cacd |
parent 351001 | 2a593ea93f6637df49eedc998b1f5ae4781a0f56 (current diff) |
parent 350934 | d4e6fb6fb40afe99415863dcdc771dcd6f6e9e02 (diff) |
child 351003 | a31c259f06ac5ca1f5211cc1b66724b07b0176a7 |
child 351094 | 381d637f43a18df25ccd7e759793080cff040d66 |
push id | 88767 |
push user | kwierso@gmail.com |
push date | Mon, 03 Apr 2017 21:51:16 +0000 |
treeherder | mozilla-inbound@a31c259f06ac [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 55.0a1 |
first release with | nightly linux32
b5d8b27a7537
/
55.0a1
/
20170404100210
/
files
nightly linux64
b5d8b27a7537
/
55.0a1
/
20170404100210
/
files
nightly mac
b5d8b27a7537
/
55.0a1
/
20170404030204
/
files
nightly win32
b5d8b27a7537
/
55.0a1
/
20170404030204
/
files
nightly win64
b5d8b27a7537
/
55.0a1
/
20170404030204
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
55.0a1
/
20170404100210
/
pushlog to previous
nightly linux64
55.0a1
/
20170404100210
/
pushlog to previous
nightly mac
55.0a1
/
20170404030204
/
pushlog to previous
nightly win32
55.0a1
/
20170404030204
/
pushlog to previous
nightly win64
55.0a1
/
20170404030204
/
pushlog to previous
|
.eslintignore | file | annotate | diff | comparison | revisions | |
browser/app/firefox.exe.manifest | file | annotate | diff | comparison | revisions | |
ipc/app/plugin-container.exe.manifest | file | annotate | diff | comparison | revisions | |
modules/libpref/init/all.js | file | annotate | diff | comparison | revisions |
--- a/.eslintignore +++ b/.eslintignore @@ -53,17 +53,16 @@ b2g/graphene/graphene.js b2g/locales/en-US/b2g-l10n.js # browser/ exclusions browser/app/** browser/branding/**/firefox-branding.js browser/base/content/test/general/file_csp_block_all_mixedcontent.html browser/base/content/test/urlbar/file_blank_but_not_blank.html browser/base/content/newtab/** -browser/components/downloads/** # Test files that are really json not js, and don't need to be linted. browser/components/sessionstore/test/unit/data/sessionstore_valid.js browser/components/sessionstore/test/unit/data/sessionstore_invalid.js browser/components/tabview/** # generated & special files in cld2 browser/components/translation/cld2/** browser/extensions/pdfjs/content/build** browser/extensions/pdfjs/content/web**
--- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -32,17 +32,21 @@ CXXFLAGS += -mno-sse -mno-sse2 -mfpmath= CXX += -march=pentiumpro endif ifeq ($(OS_ARCH),WINNT) # Rebuild firefox.exe if the manifest changes - it's included by splash.rc. # (this dependency should really be just for firefox.exe, not other targets) # Note the manifest file exists in the tree, so we use the explicit filename # here. -EXTRA_DEPS += firefox.exe.manifest +ifdef HAVE_64BIT_BUILD +EXTRA_DEPS += firefox.exe.64.manifest +else +EXTRA_DEPS += firefox.exe.32.manifest +endif endif PROGRAMS_DEST = $(DIST)/bin include $(topsrcdir)/config/rules.mk ifneq (,$(filter-out WINNT,$(OS_ARCH)))
rename from browser/app/firefox.exe.manifest rename to browser/app/firefox.exe.32.manifest --- a/browser/app/firefox.exe.manifest +++ b/browser/app/firefox.exe.32.manifest @@ -14,16 +14,22 @@ name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> +<comInterfaceExternalProxyStub + iid="{618736E0-3C3D-11CF-810C-00AA00389B71}" + proxyStubClsid32="{00020424-0000-0000-C000-000000000046}" + name="IAccessible" + tlbid="{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}" +/> <ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3"> <ms_asmv3:security> <ms_asmv3:requestedPrivileges> <ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" /> </ms_asmv3:requestedPrivileges> </ms_asmv3:security> </ms_asmv3:trustInfo> <ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
--- a/browser/app/splash.rc +++ b/browser/app/splash.rc @@ -1,17 +1,22 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include <windows.h> +#include "mozilla-config.h" #include "nsNativeAppSupportWin.h" -1 24 "firefox.exe.manifest" +#if defined(HAVE_64BIT_BUILD) +1 24 "firefox.exe.64.manifest" +#else +1 24 "firefox.exe.32.manifest" +#endif IDI_APPICON ICON FIREFOX_ICO IDI_DOCUMENT ICON DOCUMENT_ICO IDI_APPLICATION ICON FIREFOX_ICO IDI_NEWWINDOW ICON NEWWINDOW_ICO IDI_NEWTAB ICON NEWTAB_ICO IDI_PBMODE ICON PBMODE_ICO
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1335,33 +1335,34 @@ var gBrowserInit = { } } else if (window.arguments.length >= 3) { // window.arguments[2]: referrer (nsIURI | string) // [3]: postData (nsIInputStream) // [4]: allowThirdPartyFixup (bool) // [5]: referrerPolicy (int) // [6]: userContextId (int) // [7]: originPrincipal (nsIPrincipal) + // [8]: triggeringPrincipal (nsIPrincipal) let referrerURI = window.arguments[2]; if (typeof(referrerURI) == "string") { try { referrerURI = makeURI(referrerURI); } catch (e) { referrerURI = null; } } let referrerPolicy = (window.arguments[5] != undefined ? window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_UNSET); let userContextId = (window.arguments[6] != undefined ? window.arguments[6] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID); loadURI(uriToLoad, referrerURI, window.arguments[3] || null, window.arguments[4] || false, referrerPolicy, userContextId, // pass the origin principal (if any) and force its use to create // an initial about:blank viewer if present: - window.arguments[7], !!window.arguments[7]); + window.arguments[7], !!window.arguments[7], window.arguments[8]); window.focus(); } else { // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3. // Such callers expect that window.arguments[0] is handled as a single URI. loadOneOrMoreURIs(uriToLoad); } } @@ -2243,25 +2244,27 @@ function BrowserCloseTabOrWindow() { } function BrowserTryToCloseWindow() { if (WindowIsClosing()) window.close(); // WindowIsClosing does all the necessary checks } function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy, - userContextId, originPrincipal, forceAboutBlankViewerInCurrent) { + userContextId, originPrincipal, forceAboutBlankViewerInCurrent, + triggeringPrincipal) { try { openLinkIn(uri, "current", { referrerURI: referrer, referrerPolicy, postData, allowThirdPartyFixup, userContextId, originPrincipal, + triggeringPrincipal, forceAboutBlankViewerInCurrent, }); } catch (e) {} } /** * Given a string, will generate a more appropriate urlbar value if a Places * keyword or a search alias is found at the beginning of it. @@ -5777,16 +5780,17 @@ function handleLinkClick(event, href, li urlSecurityCheck(href, doc.nodePrincipal); let params = { charset: doc.characterSet, allowMixedContent: persistAllowMixedContentInChildTab, referrerURI, referrerPolicy, noReferrer: BrowserUtils.linkHasNoReferrer(linkNode), originPrincipal: doc.nodePrincipal, + triggeringPrincipal: doc.nodePrincipal, frameOuterWindowID, }; // The new tab/window must use the same userContextId if (doc.nodePrincipal.originAttributes.userContextId) { params.userContextId = doc.nodePrincipal.originAttributes.userContextId; }
--- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -573,16 +573,17 @@ var ClickEventHandler = { const sm = Services.scriptSecurityManager; try { let targetURI = BrowserUtils.makeURI(href); sm.checkSameOriginURI(docshell.mixedContentChannel.URI, targetURI, false); json.allowMixedContent = true; } catch (e) {} } json.originPrincipal = ownerDoc.nodePrincipal; + json.triggeringPrincipal = ownerDoc.nodePrincipal; sendAsyncMessage("Content:Click", json); return; } // This might be middle mouse navigation. if (event.button == 1) { sendAsyncMessage("Content:Click", json);
--- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -980,16 +980,17 @@ nsContextMenu.prototype = { _isProprietaryDRM() { return this.target.isEncrypted && this.target.mediaKeys && this.target.mediaKeys.keySystem != "org.w3.clearkey"; }, _openLinkInParameters(extra) { let params = { charset: gContextMenuContentData.charSet, originPrincipal: this.principal, + triggeringPrincipal: this.principal, referrerURI: gContextMenuContentData.documentURIObject, referrerPolicy: gContextMenuContentData.referrerPolicy, frameOuterWindowID: gContextMenuContentData.frameOuterWindowID, noReferrer: this.linkHasNoReferrer }; for (let p in extra) { params[p] = extra[p]; } @@ -1169,17 +1170,17 @@ nsContextMenu.prototype = { // Change current window to the URL of the image, video, or audio. viewMedia(e) { let referrerURI = gContextMenuContentData.documentURIObject; let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); if (this.onCanvas) { this._canvasToBlobURL(this.target).then(function(blobURL) { openUILink(blobURL, e, { disallowInheritPrincipal: true, referrerURI, - originPrincipal: systemPrincipal}); + triggeringPrincipal: systemPrincipal}); }, Cu.reportError); } else { urlSecurityCheck(this.mediaURL, this.browser.contentPrincipal, Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT); openUILink(this.mediaURL, e, { disallowInheritPrincipal: true, referrerURI }); }
--- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -215,16 +215,17 @@ function openLinkIn(url, where, params) var aIsPrivate = params.private; var aSkipTabAnimation = params.skipTabAnimation; var aAllowPinnedTabHostChange = !!params.allowPinnedTabHostChange; var aNoReferrer = params.noReferrer; var aAllowPopups = !!params.allowPopups; var aUserContextId = params.userContextId; var aIndicateErrorPageLoad = params.indicateErrorPageLoad; var aPrincipal = params.originPrincipal; + var aTriggeringPrincipal = params.triggeringPrincipal; var aForceAboutBlankViewerInCurrent = params.forceAboutBlankViewerInCurrent; if (where == "save") { // TODO(1073187): propagate referrerPolicy. // ContentClick.jsm passes isContentWindowPrivate for saveURL instead of passing a CPOW initiatingDoc if ("isContentWindowPrivate" in params) { @@ -255,23 +256,28 @@ function openLinkIn(url, where, params) aRelatedToCurrent = false; } // Teach the principal about the right OA to use, e.g. in case when // opening a link in a new private window, or in a new container tab. // Please note we do not have to do that for SystemPrincipals and we // can not do it for NullPrincipals since NullPrincipals are only // identical if they actually are the same object (See Bug: 1346759) - if (aPrincipal && aPrincipal.isCodebasePrincipal) { - let attrs = { - userContextId: aUserContextId, - privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)), - }; - aPrincipal = Services.scriptSecurityManager.createCodebasePrincipal(aPrincipal.URI, attrs); + function useOAForPrincipal(principal) { + if (principal && principal.isCodebasePrincipal) { + let attrs = { + userContextId: aUserContextId, + privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)), + }; + return Services.scriptSecurityManager.createCodebasePrincipal(principal.URI, attrs); + } + return principal; } + aPrincipal = useOAForPrincipal(aPrincipal); + aTriggeringPrincipal = useOAForPrincipal(aTriggeringPrincipal); if (!w || where == "window") { // This propagates to window.arguments. var sa = Cc["@mozilla.org/array;1"]. createInstance(Ci.nsIMutableArray); var wuri = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); @@ -306,16 +312,17 @@ function openLinkIn(url, where, params) sa.appendElement(wuri, /* weak =*/ false); sa.appendElement(charset, /* weak =*/ false); sa.appendElement(referrerURISupports, /* weak =*/ false); sa.appendElement(aPostData, /* weak =*/ false); sa.appendElement(allowThirdPartyFixupSupports, /* weak =*/ false); sa.appendElement(referrerPolicySupports, /* weak =*/ false); sa.appendElement(userContextIdSupports, /* weak =*/ false); sa.appendElement(aPrincipal, /* weak =*/ false); + sa.appendElement(aTriggeringPrincipal, /* weak =*/ false); let features = "chrome,dialog=no,all"; if (aIsPrivate) { features += ",private"; } const sourceWindow = (w || window); let win; @@ -409,17 +416,17 @@ function openLinkIn(url, where, params) flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ERROR_LOAD_CHANGES_RV; } if (aForceAboutBlankViewerInCurrent) { targetBrowser.createAboutBlankContentViewer(aPrincipal); } targetBrowser.loadURIWithFlags(url, { - triggeringPrincipal: aPrincipal, + triggeringPrincipal: aTriggeringPrincipal, flags, referrerURI: aNoReferrer ? null : aReferrerURI, referrerPolicy: aReferrerPolicy, postData: aPostData, userContextId: aUserContextId }); break; case "tabshifted": @@ -434,17 +441,17 @@ function openLinkIn(url, where, params) inBackground: loadInBackground, allowThirdPartyFixup: aAllowThirdPartyFixup, relatedToCurrent: aRelatedToCurrent, skipAnimation: aSkipTabAnimation, allowMixedContent: aAllowMixedContent, noReferrer: aNoReferrer, userContextId: aUserContextId, originPrincipal: aPrincipal, - triggeringPrincipal: aPrincipal, + triggeringPrincipal: aTriggeringPrincipal, }); targetBrowser = tabUsedForLoad.linkedBrowser; if (params.frameOuterWindowID && w) { // Only notify it as a WebExtensions' webNavigation.onCreatedNavigationTarget // event if it contains the expected frameOuterWindowID params. // (e.g. we should not notify it as a onCreatedNavigationTarget if the user is // opening a new tab using the keyboard shortcut).
--- a/browser/components/downloads/DownloadsCommon.jsm +++ b/browser/components/downloads/DownloadsCommon.jsm @@ -25,18 +25,17 @@ this.EXPORTED_SYMBOLS = [ * to build a consistent view of the available data. * * DownloadsIndicatorData * This object registers itself with DownloadsData as a view, and transforms the * notifications it receives into overall status data, that is then broadcast to * the registered download status indicators. */ -//////////////////////////////////////////////////////////////////////////////// -//// Globals +// Globals const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); @@ -106,40 +105,39 @@ var PrefObserver = { return kPrefBranch.getBoolPref(name); } } catch (ex) { } return this.prefs[name]; }, observe(aSubject, aTopic, aData) { if (this.prefs.hasOwnProperty(aData)) { delete this[aData]; - return this[aData] = this.getPref(aData); + this[aData] = this.getPref(aData); } }, register(prefs) { this.prefs = prefs; kPrefBranch.addObserver("", this, true); for (let key in prefs) { let name = key; - XPCOMUtils.defineLazyGetter(this, name, function () { + XPCOMUtils.defineLazyGetter(this, name, function() { return PrefObserver.getPref(name); }); } }, }; PrefObserver.register({ // prefName: defaultValue animateNotifications: true, showPanelDropmarker: true, }); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsCommon +// DownloadsCommon /** * This object is exposed directly to the consumers of this JavaScript module, * and provides shared methods for all the instances of the user interface. */ this.DownloadsCommon = { ATTENTION_NONE: "", ATTENTION_SUCCESS: "success", @@ -161,24 +159,24 @@ this.DownloadsCommon = { get strings() { let strings = {}; let sb = Services.strings.createBundle(kDownloadsStringBundleUrl); let enumerator = sb.getSimpleEnumeration(); while (enumerator.hasMoreElements()) { let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); let stringName = string.key; if (stringName in kDownloadsStringsRequiringFormatting) { - strings[stringName] = function () { + strings[stringName] = function() { // Convert "arguments" to a real array before calling into XPCOM. return sb.formatStringFromName(stringName, Array.slice(arguments, 0), arguments.length); }; } else if (stringName in kDownloadsStringsRequiringPluralForm) { - strings[stringName] = function (aCount) { + strings[stringName] = function(aCount) { // Convert "arguments" to a real array before calling into XPCOM. let formattedString = sb.formatStringFromName(stringName, Array.slice(arguments, 0), arguments.length); return PluralForm.get(aCount, formattedString); }; } else { strings[stringName] = string.value; @@ -238,19 +236,18 @@ this.DownloadsCommon = { * depending on the privacy status of the window in question. * * @param aWindow * The browser window which owns the download button. */ getData(aWindow) { if (PrivateBrowsingUtils.isContentWindowPrivate(aWindow)) { return PrivateDownloadsData; - } else { - return DownloadsData; } + return DownloadsData; }, /** * Initializes the Downloads back-end and starts receiving events for both the * private and non-private downloads data objects. */ initializeAllDataLinks() { DownloadsData.initializeDataLink(); @@ -260,19 +257,18 @@ this.DownloadsCommon = { /** * Get access to one of the DownloadsIndicatorData or * PrivateDownloadsIndicatorData objects, depending on the privacy status of * the window in question. */ getIndicatorData(aWindow) { if (PrivateBrowsingUtils.isContentWindowPrivate(aWindow)) { return PrivateDownloadsIndicatorData; - } else { - return DownloadsIndicatorData; } + return DownloadsIndicatorData; }, /** * Returns a reference to the DownloadsSummaryData singleton - creating one * in the process if one hasn't been instantiated yet. * * @param aWindow * The browser window which owns the download button. @@ -281,22 +277,21 @@ this.DownloadsCommon = { * from the summary. */ getSummary(aWindow, aNumToExclude) { if (PrivateBrowsingUtils.isContentWindowPrivate(aWindow)) { if (this._privateSummary) { return this._privateSummary; } return this._privateSummary = new DownloadsSummaryData(true, aNumToExclude); - } else { - if (this._summary) { - return this._summary; - } - return this._summary = new DownloadsSummaryData(false, aNumToExclude); } + if (this._summary) { + return this._summary; + } + return this._summary = new DownloadsSummaryData(false, aNumToExclude); }, _summary: null, _privateSummary: null, /** * Returns the legacy state integer value for the provided Download object. */ stateOfDownload(download) { @@ -661,27 +656,26 @@ XPCOMUtils.defineLazyGetter(this.Downloa }); XPCOMUtils.defineLazyGetter(this.DownloadsCommon, "error", () => { return DownloadsLogger.error.bind(DownloadsLogger); }); /** * Returns true if we are executing on Windows Vista or a later version. */ -XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () { +XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function() { let os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; if (os != "WINNT") { return false; } let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2); return parseFloat(sysInfo.getProperty("version")) >= 6; }); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsData +// DownloadsData /** * Retrieves the list of past and completed downloads from the underlying * Download Manager data, and provides asynchronous notifications allowing to * build a consistent view of the available data. * * This object responds to real-time changes in the underlying Download Manager * data. For example, the deletion of one or more downloads is notified through @@ -751,18 +745,17 @@ DownloadsDataCtor.prototype = { : Downloads.PUBLIC); promiseList.then(list => list.removeFinished()) .then(null, Cu.reportError); let indicatorData = this._isPrivate ? PrivateDownloadsIndicatorData : DownloadsIndicatorData; indicatorData.attention = DownloadsCommon.ATTENTION_NONE; }, - ////////////////////////////////////////////////////////////////////////////// - //// Integration with the asynchronous Downloads back-end + // Integration with the asynchronous Downloads back-end onDownloadAdded(download) { // Download objects do not store the end time of downloads, as the Downloads // API does not need to persist this information for all platforms. Once a // download terminates on a Desktop browser, it becomes a history download, // for which the end time is stored differently, as a Places annotation. download.endTime = Date.now(); @@ -842,18 +835,17 @@ DownloadsDataCtor.prototype = { onDownloadRemoved(download) { this.oldDownloadStates.delete(download); for (let view of this._views) { view.onDownloadRemoved(download); } }, - ////////////////////////////////////////////////////////////////////////////// - //// Registration of views + // Registration of views /** * Adds an object to be notified when the available download data changes. * The specified object is initialized with the currently available downloads. * * @param aView * DownloadsView object to be added. This reference must be passed to * removeView before termination. @@ -891,18 +883,17 @@ DownloadsDataCtor.prototype = { let downloadsArray = [...this.downloads]; downloadsArray.sort((a, b) => b.startTime - a.startTime); downloadsArray.forEach(download => aView.onDownloadAdded(download, false)); // Notify the view that all data is available. aView.onDataLoadCompleted(); }, - ////////////////////////////////////////////////////////////////////////////// - //// Notifications sent to the most recent browser window only + // Notifications sent to the most recent browser window only /** * Set to true after the first download causes the downloads panel to be * displayed. */ get panelHasShownBefore() { try { return Services.prefs.getBoolPref("browser.download.panel.shown"); @@ -947,26 +938,24 @@ DownloadsDataCtor.prototype = { XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsData", function() { return new DownloadsDataCtor(true); }); XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() { return new DownloadsDataCtor(false); }); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsViewPrototype +// DownloadsViewPrototype /** * A prototype for an object that registers itself with DownloadsData as soon * as a view is registered with it. */ const DownloadsViewPrototype = { - ////////////////////////////////////////////////////////////////////////////// - //// Registration of views + // Registration of views /** * Array of view objects that should be notified when the available status * data changes. * * SUBCLASSES MUST OVERRIDE THIS PROPERTY. */ _views: null, @@ -1031,18 +1020,17 @@ const DownloadsViewPrototype = { if (this._isPrivate) { PrivateDownloadsData.removeView(this); } else { DownloadsData.removeView(this); } } }, - ////////////////////////////////////////////////////////////////////////////// - //// Callback functions from DownloadsData + // Callback functions from DownloadsData /** * Indicates whether we are still loading downloads data asynchronously. */ _loading: false, /** * Called before multiple downloads are about to be loaded. @@ -1131,18 +1119,17 @@ const DownloadsViewPrototype = { * * @note Subclasses should override this. */ _updateView() { throw Components.results.NS_ERROR_NOT_IMPLEMENTED; }, }; -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsIndicatorData +// DownloadsIndicatorData /** * This object registers itself with DownloadsData as a view, and transforms the * notifications it receives into overall status data, that is then broadcast to * the registered download status indicators. * * Note that using this object does not automatically start the Download Manager * service. Consumers will see an empty list of downloads until the service is @@ -1165,18 +1152,17 @@ DownloadsIndicatorDataCtor.prototype = { removeView(aView) { DownloadsViewPrototype.removeView.call(this, aView); if (this._views.length == 0) { this._itemCount = 0; } }, - ////////////////////////////////////////////////////////////////////////////// - //// Callback functions from DownloadsData + // Callback functions from DownloadsData onDataLoadCompleted() { DownloadsViewPrototype.onDataLoadCompleted.call(this); this._updateViews(); }, onDownloadAdded(download, newest) { this._itemCount++; @@ -1223,18 +1209,17 @@ DownloadsIndicatorDataCtor.prototype = { this._updateViews(); }, onDownloadRemoved(download) { this._itemCount--; this._updateViews(); }, - ////////////////////////////////////////////////////////////////////////////// - //// Propagation of properties to our views + // Propagation of properties to our views // The following properties are updated by _refreshProperties and are then // propagated to the views. See _refreshProperties for details. _hasDownloads: false, _counter: "", _percentComplete: -1, _paused: false, @@ -1283,18 +1268,17 @@ DownloadsIndicatorDataCtor.prototype = { aView.hasDownloads = this._hasDownloads; aView.counter = this._counter; aView.percentComplete = this._percentComplete; aView.paused = this._paused; aView.attention = this._attentionSuppressed ? DownloadsCommon.ATTENTION_NONE : this._attention; }, - ////////////////////////////////////////////////////////////////////////////// - //// Property updating based on current download status + // Property updating based on current download status /** * Number of download items that are available to be displayed. */ _itemCount: 0, /** * Floating point value indicating the last number of seconds estimated until @@ -1365,18 +1349,17 @@ DownloadsIndicatorDataCtor.prototype = { XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsIndicatorData", function() { return new DownloadsIndicatorDataCtor(true); }); XPCOMUtils.defineLazyGetter(this, "DownloadsIndicatorData", function() { return new DownloadsIndicatorDataCtor(false); }); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsSummaryData +// DownloadsSummaryData /** * DownloadsSummaryData is a view for DownloadsData that produces a summary * of all downloads after a certain exclusion point aNumToExclude. For example, * if there were 5 downloads in progress, and a DownloadsSummaryData was * constructed with aNumToExclude equal to 3, then that DownloadsSummaryData * would produce a summary of the last 2 downloads. * @@ -1434,20 +1417,19 @@ DownloadsSummaryData.prototype = { if (this._views.length == 0) { // Clear out our collection of Download objects. If we ever have // another view registered with us, this will get re-populated. this._downloads = []; } }, - ////////////////////////////////////////////////////////////////////////////// - //// Callback functions from DownloadsData - see the documentation in - //// DownloadsViewPrototype for more information on what these functions - //// are used for. + // Callback functions from DownloadsData - see the documentation in + // DownloadsViewPrototype for more information on what these functions + // are used for. onDataLoadCompleted() { DownloadsViewPrototype.onDataLoadCompleted.call(this); this._updateViews(); }, onDownloadAdded(download, newest) { if (newest) { @@ -1470,18 +1452,17 @@ DownloadsSummaryData.prototype = { }, onDownloadRemoved(download) { let itemIndex = this._downloads.indexOf(download); this._downloads.splice(itemIndex, 1); this._updateViews(); }, - ////////////////////////////////////////////////////////////////////////////// - //// Propagation of properties to our views + // Propagation of properties to our views /** * Computes aggregate values and propagates the changes to our views. */ _updateViews() { // Do not update the status indicators during batch loads of download items. if (this._loading) { return; @@ -1499,18 +1480,17 @@ DownloadsSummaryData.prototype = { */ _updateView(aView) { aView.showingProgress = this._showingProgress; aView.percentComplete = this._percentComplete; aView.description = this._description; aView.details = this._details; }, - ////////////////////////////////////////////////////////////////////////////// - //// Property updating based on current download status + // Property updating based on current download status /** * A generator function for the Download objects this summary is currently * interested in. This generator is passed off to summarizeDownloads in order * to generate statistics about the downloads we care about - in this case, * it's the downloads in this._downloads after the first few to exclude, * which was set when constructing this DownloadsSummaryData instance. */
--- a/browser/components/downloads/DownloadsTaskbar.jsm +++ b/browser/components/downloads/DownloadsTaskbar.jsm @@ -9,50 +9,48 @@ */ "use strict"; this.EXPORTED_SYMBOLS = [ "DownloadsTaskbar", ]; -//////////////////////////////////////////////////////////////////////////////// -//// Globals +// Globals const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Downloads", "resource://gre/modules/Downloads.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow", "resource:///modules/RecentWindow.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function () { +XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function() { if (!("@mozilla.org/windows-taskbar;1" in Cc)) { return null; } let winTaskbar = Cc["@mozilla.org/windows-taskbar;1"] .getService(Ci.nsIWinTaskbar); return winTaskbar.available && winTaskbar; }); -XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function () { +XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function() { return ("@mozilla.org/widget/macdocksupport;1" in Cc) && Cc["@mozilla.org/widget/macdocksupport;1"] .getService(Ci.nsITaskbarProgress); }); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsTaskbar +// DownloadsTaskbar /** * Handles the download progress indicator in the taskbar. */ this.DownloadsTaskbar = { /** * Underlying DownloadSummary providing the aggregate download information, or * null if the indicator has never been initialized. @@ -106,17 +104,16 @@ this.DownloadsTaskbar = { if (!this._summary) { Downloads.getSummary(Downloads.ALL).then(summary => { // In case the method is re-entered, we simply ignore redundant // invocations of the callback, instead of keeping separate state. if (this._summary) { return; } this._summary = summary; - return this._summary.addView(this); }).then(null, Cu.reportError); } }, /** * On Windows, attaches the taskbar indicator to the specified browser window. */ _attachIndicator(aWindow) { @@ -145,18 +142,17 @@ this.DownloadsTaskbar = { // The last browser window has been closed. We remove the reference to // the taskbar progress object so that the indicator will be registered // again on the next browser window that is opened. this._taskbarProgress = null; } }); }, - ////////////////////////////////////////////////////////////////////////////// - //// DownloadSummary view + // DownloadSummary view onSummaryChanged() { // If the last browser window has been closed, we have no indicator any more. if (!this._taskbarProgress) { return; } if (this._summary.allHaveStopped || this._summary.progressTotalBytes == 0) {
--- a/browser/components/downloads/DownloadsViewUI.jsm +++ b/browser/components/downloads/DownloadsViewUI.jsm @@ -44,17 +44,17 @@ this.DownloadsViewUI = { * from the JavaScript API for downloads, and commands are executed using a * combination of Download methods and DownloadsCommon.jsm helper functions. * * Specialized versions of this shell must be defined, and they are required to * implement the "download" property or getter. Currently these objects are the * HistoryDownloadElementShell and the DownloadsViewItem for the panel. The * history view may use a HistoryDownload object in place of a Download object. */ -this.DownloadsViewUI.DownloadElementShell = function () {} +this.DownloadsViewUI.DownloadElementShell = function() {} this.DownloadsViewUI.DownloadElementShell.prototype = { /** * The richlistitem for the download, initialized by the derived object. */ element: null, /** @@ -237,20 +237,20 @@ this.DownloadsViewUI.DownloadElementShel stateLabel = s.stateBlockedParentalControls; } else if (this.download.error.becauseBlockedByReputationCheck) { stateLabel = this.rawBlockedTitleAndDetails[0]; } else { stateLabel = s.stateFailed; } let referrer = this.download.source.referrer || this.download.source.url; - let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer); + let [displayHost /* ,fullHost */] = DownloadUtils.getURIHost(referrer); let date = new Date(this.download.endTime); - let [displayDate, fullDate] = DownloadUtils.getReadableDates(date); + let [displayDate /* ,fullDate */] = DownloadUtils.getReadableDates(date); let firstPart = s.statusSeparator(stateLabel, displayHost); fullStatus = s.statusSeparator(firstPart, displayDate); status = status || stateLabel; } return { status, @@ -274,18 +274,16 @@ this.DownloadsViewUI.DownloadElementShel case Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED: return [s.blockedPotentiallyUnwanted, [s.unblockTypePotentiallyUnwanted2, s.unblockTip2]]; case Downloads.Error.BLOCK_VERDICT_MALWARE: return [s.blockedMalware, [s.unblockTypeMalware, s.unblockTip2]]; } throw new Error("Unexpected reputationCheckVerdict: " + this.download.error.reputationCheckVerdict); - // return anyway to avoid a JS strict warning. - return [null, null]; }, /** * Shows the appropriate unblock dialog based on the verdict, and executes the * action selected by the user in the dialog, which may involve unblocking, * opening or removing the file. * * @param window @@ -301,16 +299,17 @@ this.DownloadsViewUI.DownloadElementShel }).then(action => { if (action == "open") { return this.unblockAndOpenDownload(); } else if (action == "unblock") { return this.download.unblock(); } else if (action == "confirmBlock") { return this.download.confirmBlock(); } + return Promise.resolve(); }).catch(Cu.reportError); }, /** * Unblocks the downloaded file and opens it. * * @return A promise that's resolved after the file has been opened. */
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js +++ b/browser/components/downloads/content/allDownloadsViewOverlay.js @@ -1,11 +1,12 @@ /* 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/. */ +/* eslint-env mozilla/browser-window */ var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils", "resource://gre/modules/DownloadUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon", @@ -938,19 +939,17 @@ DownloadsPlacesView.prototype = { delete this._resultNode; delete this._result; } return val; }, get selectedNodes() { - return [for (element of this._richlistbox.selectedItems) - if (element._placesNode) - element._placesNode]; + return this._richlistbox.selectedItems.filter(element => element._placesNode); }, get selectedNode() { let selectedNodes = this.selectedNodes; return selectedNodes.length == 1 ? selectedNodes[0] : null; }, get hasSelection() { @@ -1173,18 +1172,17 @@ DownloadsPlacesView.prototype = { if (download.stopped && !(download.canceled && download.hasPartialData)) { return true; } } return false; }, _copySelectedDownloadsToClipboard() { - let urls = [for (element of this._richlistbox.selectedItems) - element._shell.download.source.url]; + let urls = this._richlistbox.selectedItems.map(element => element._shell.download.source.url); Cc["@mozilla.org/widget/clipboardhelper;1"] .getService(Ci.nsIClipboardHelper) .copyString(urls.join("\n")); }, _getURLFromClipboardData() { let trans = Cc["@mozilla.org/widget/transferable;1"]. @@ -1206,17 +1204,17 @@ DownloadsPlacesView.prototype = { return [NetUtil.newURI(url).spec, name]; } } catch (ex) {} return ["", ""]; }, _canDownloadClipboardURL() { - let [url, name] = this._getURLFromClipboardData(); + let [url /* ,name */] = this._getURLFromClipboardData(); return url != ""; }, _downloadURLFromClipboard() { let [url, name] = this._getURLFromClipboardData(); let browserWin = RecentWindow.getMostRecentBrowserWindow(); let initiatingDoc = browserWin ? browserWin.document : document; DownloadURL(url, name, initiatingDoc); @@ -1303,18 +1301,17 @@ DownloadsPlacesView.prototype = { // supported when a single item is selected. To be consistent, do the // same here. if (selectedElements.length == 1) { let element = selectedElements[0]; if (element._shell) { element._shell.doDefaultCommand(); } } - } - else if (aEvent.charCode == " ".charCodeAt(0)) { + } else if (aEvent.charCode == " ".charCodeAt(0)) { // Pause/Resume every selected download for (let element of selectedElements) { if (element._shell.isCommandEnabled("downloadsCmd_pauseResume")) { element._shell.doCommand("downloadsCmd_pauseResume"); } } } }, @@ -1404,17 +1401,17 @@ DownloadsPlacesView.prototype = { if (link.url.startsWith("about:")) continue; DownloadURL(link.url, link.name, initiatingDoc); } }, }; for (let methodName of ["load", "applyFilter", "selectNode", "selectItems"]) { - DownloadsPlacesView.prototype[methodName] = function () { + DownloadsPlacesView.prototype[methodName] = function() { throw new Error("|" + methodName + "| is not implemented by the downloads view."); } } function goUpdateDownloadCommands() { function updateCommandsForObject(object) { for (let name in object) {
--- a/browser/components/downloads/content/contentAreaDownloadsView.js +++ b/browser/components/downloads/content/contentAreaDownloadsView.js @@ -1,12 +1,14 @@ /* 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/. */ +/* import-globals-from allDownloadsViewOverlay.js */ + Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); var ContentAreaDownloadsView = { init() { let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox")); // Do not display the Places downloads in private windows if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) { view.place = "place:transition=7&sort=4";
--- a/browser/components/downloads/content/downloads.js +++ b/browser/components/downloads/content/downloads.js @@ -1,13 +1,14 @@ /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* 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/. */ +/* eslint-env mozilla/browser-window */ /** * Handles the Downloads panel user interface for each browser window. * * This file includes the following constructors and global objects: * * DownloadsPanel * Main entry point for the downloads panel interface. @@ -73,25 +74,23 @@ XPCOMUtils.defineLazyModuleGetter(this, "resource://gre/modules/FileUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsPanel +// DownloadsPanel /** * Main entry point for the downloads panel interface. */ const DownloadsPanel = { - ////////////////////////////////////////////////////////////////////////////// - //// Initialization and termination + // Initialization and termination /** * Internal state of the downloads panel, based on one of the kState * constants. This is not the same state as the XUL panel element. */ _state: 0, /** The panel is not linked to downloads data yet. */ @@ -187,18 +186,17 @@ const DownloadsPanel = { this._unattachEventListeners(); this._state = this.kStateUninitialized; DownloadsSummary.active = false; DownloadsCommon.log("DownloadsPanel terminated."); }, - ////////////////////////////////////////////////////////////////////////////// - //// Panel interface + // Panel interface /** * Main panel element in the browser window, or null if the panel overlay * hasn't been loaded yet. */ get panel() { // If the downloads panel overlay hasn't loaded yet, just return null // without resetting this.panel. @@ -303,19 +301,21 @@ const DownloadsPanel = { * visualization. */ handleEvent(aEvent) { switch (aEvent.type) { case "mousemove": this.keyFocusing = false; break; case "keydown": - return this._onKeyDown(aEvent); + this._onKeyDown(aEvent); + break; case "keypress": - return this._onKeyPress(aEvent); + this._onKeyPress(aEvent); + break; case "popupshown": if (this.setHeightToFitOnShow) { this.setHeightToFitOnShow = false; this.setHeightToFit(); } break; } }, @@ -323,28 +323,26 @@ const DownloadsPanel = { setHeightToFit() { if (this._state == this.kStateShown) { DownloadsBlockedSubview.view.setHeightToFit(); } else { this.setHeightToFitOnShow = true; } }, - ////////////////////////////////////////////////////////////////////////////// - //// Callback functions from DownloadsView + // Callback functions from DownloadsView /** * Called after data loading finished. */ onViewLoadCompleted() { this._openPopupIfDataReady(); }, - ////////////////////////////////////////////////////////////////////////////// - //// User interface event functions + // User interface event functions onWindowUnload() { // This function is registered as an event listener, we can't use "this". DownloadsPanel.terminate(); }, onPopupShown(aEvent) { // Ignore events raised by nested popups. @@ -402,18 +400,17 @@ const DownloadsPanel = { .setAttribute("showingdropdown", true); }, onFooterPopupHidden(aEvent) { document.getElementById("downloadsFooter") .removeAttribute("showingdropdown"); }, - ////////////////////////////////////////////////////////////////////////////// - //// Related operations + // Related operations /** * Shows or focuses the user interface dedicated to downloads history. */ showDownloadsHistory() { DownloadsCommon.log("Showing download history."); // Hide the panel before showing another window, otherwise focus will return // to the browser window when the panel closes automatically. @@ -424,18 +421,17 @@ const DownloadsPanel = { openDownloadsFolder() { Downloads.getPreferredDownloadsDirectory().then(downloadsPath => { DownloadsCommon.showDirectory(new FileUtils.File(downloadsPath)); }).catch(Cu.reportError); this.hidePanel(); }, - ////////////////////////////////////////////////////////////////////////////// - //// Internal functions + // Internal functions /** * Attach event listeners to a panel element. These listeners should be * removed in _unattachEventListeners. This is called automatically after the * panel has successfully loaded. */ _attachEventListeners() { // Handle keydown to support accel-V. @@ -620,18 +616,17 @@ const DownloadsPanel = { DownloadsCommon.log("Opening downloads panel popup."); this.panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, null); }); }, }; XPCOMUtils.defineConstant(this, "DownloadsPanel", DownloadsPanel); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsOverlayLoader +// DownloadsOverlayLoader /** * Allows loading the downloads panel and the status indicator interfaces on * demand, to improve startup performance. */ const DownloadsOverlayLoader = { /** * We cannot load two overlays at the same time, thus we use a queue of @@ -700,27 +695,25 @@ const DownloadsOverlayLoader = { // for the associated overlay to load. this.ensureOverlayLoaded(request.overlay, request.callback); } }, }; XPCOMUtils.defineConstant(this, "DownloadsOverlayLoader", DownloadsOverlayLoader); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsView +// DownloadsView /** * Builds and updates the downloads list widget, responding to changes in the * download state and real-time data. In addition, handles part of the user * interaction events raised by the downloads list widget. */ const DownloadsView = { - ////////////////////////////////////////////////////////////////////////////// - //// Functions handling download items in the list + // Functions handling download items in the list /** * Maximum number of items shown by the list at any given time. */ kItemCountLimit: 5, /** * Indicates whether there is an open contextMenu for a download item. @@ -786,18 +779,17 @@ const DownloadsView = { /** * Element corresponding to the button for showing more downloads. */ get downloadsHistory() { delete this.downloadsHistory; return this.downloadsHistory = document.getElementById("downloadsHistory"); }, - ////////////////////////////////////////////////////////////////////////////// - //// Callback functions from DownloadsData + // Callback functions from DownloadsData /** * Called before multiple downloads are about to be loaded. */ onDataLoadStarting() { DownloadsCommon.log("onDataLoadStarting called for DownloadsView."); this.loading = true; }, @@ -913,18 +905,17 @@ const DownloadsView = { itemForElement(element) { return this._itemsForElements.get(element); }, /** * Creates a new view item associated with the specified data item, and adds * it to the top or the bottom of the list. */ - _addViewItem(download, aNewest) - { + _addViewItem(download, aNewest) { DownloadsCommon.log("Adding a new DownloadsViewItem to the downloads list.", "aNewest =", aNewest); let element = document.createElement("richlistitem"); let viewItem = new DownloadsViewItem(download, element); this._visibleViewItems.set(download, viewItem); this._itemsForElements.set(element, viewItem); if (aNewest) { @@ -945,18 +936,17 @@ const DownloadsView = { if (previousSelectedIndex != -1) { this.richListBox.selectedIndex = Math.min(previousSelectedIndex, this.richListBox.itemCount - 1); } this._visibleViewItems.delete(download); this._itemsForElements.delete(element); }, - ////////////////////////////////////////////////////////////////////////////// - //// User interface event functions + // User interface event functions /** * Helper function to do commands on a specific download item. * * @param aEvent * Event object for the event being handled. If the event target is * not a richlistitem that represents a download, this function will * walk up the parent nodes until it finds a DOM node that is. @@ -1113,18 +1103,17 @@ const DownloadsView = { dataTransfer.addElement(element); aEvent.stopPropagation(); }, } XPCOMUtils.defineConstant(this, "DownloadsView", DownloadsView); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsViewItem +// DownloadsViewItem /** * Builds and updates a single item in the downloads list widget, responding to * changes in the download state and real-time data, and handles the user * interaction events related to a single item in the downloads list widgets. * * @param download * Download object to be associated with the view item. @@ -1194,18 +1183,17 @@ DownloadsViewItem.prototype = { }, doCommand(aCommand) { if (this.isCommandEnabled(aCommand)) { this[aCommand](); } }, - ////////////////////////////////////////////////////////////////////////////// - //// Item commands + // Item commands cmd_delete() { DownloadsCommon.removeAndFinalizeDownload(this.download); PlacesUtils.history.remove(this.download.source.url).catch(Cu.reportError); }, downloadsCmd_unblock() { DownloadsPanel.hidePanel(); @@ -1263,38 +1251,35 @@ DownloadsViewItem.prototype = { downloadsCmd_doDefault() { let defaultCommand = this.currentDefaultCommandName; if (defaultCommand && this.isCommandEnabled(defaultCommand)) { this.doCommand(defaultCommand); } }, }; -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsViewController +// DownloadsViewController /** * Handles part of the user interaction events raised by the downloads list * widget, in particular the "commands" that apply to multiple items, and * dispatches the commands that apply to individual items. */ const DownloadsViewController = { - ////////////////////////////////////////////////////////////////////////////// - //// Initialization and termination + // Initialization and termination initialize() { window.controllers.insertControllerAt(0, this); }, terminate() { window.controllers.removeController(this); }, - ////////////////////////////////////////////////////////////////////////////// - //// nsIController + // nsIController supportsCommand(aCommand) { if (aCommand === "downloadsCmd_clearList") { return true; } // Firstly, determine if this is a command that we can handle. if (!DownloadsViewUI.isCommandName(aCommand)) { return false; @@ -1347,43 +1332,40 @@ const DownloadsViewController = { if (element) { // The doCommand function also checks if the command is enabled. DownloadsView.itemForElement(element).doCommand(aCommand); } }, onEvent() {}, - ////////////////////////////////////////////////////////////////////////////// - //// Other functions + // Other functions updateCommands() { function updateCommandsForObject(object) { for (let name in object) { if (DownloadsViewUI.isCommandName(name)) { goUpdateCommand(name); } } } updateCommandsForObject(this); updateCommandsForObject(DownloadsViewItem.prototype); }, - ////////////////////////////////////////////////////////////////////////////// - //// Selection-independent commands + // Selection-independent commands downloadsCmd_clearList() { DownloadsCommon.getData(window).removeFinished(); }, }; XPCOMUtils.defineConstant(this, "DownloadsViewController", DownloadsViewController); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsSummary +// DownloadsSummary /** * Manages the summary at the bottom of the downloads panel list if the number * of items in the list exceeds the panels limit. */ const DownloadsSummary = { /** @@ -1557,18 +1539,17 @@ const DownloadsSummary = { } delete this._detailsNode; return this._detailsNode = node; } }; XPCOMUtils.defineConstant(this, "DownloadsSummary", DownloadsSummary); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsFooter +// DownloadsFooter /** * Manages events sent to to the footer vbox, which contains both the * DownloadsSummary as well as the "Show All Downloads" button. */ const DownloadsFooter = { /** @@ -1617,18 +1598,17 @@ const DownloadsFooter = { delete this._footerNode; return this._footerNode = node; } }; XPCOMUtils.defineConstant(this, "DownloadsFooter", DownloadsFooter); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsBlockedSubview +// DownloadsBlockedSubview /** * Manages the blocked subview that slides in when you click a blocked download. */ const DownloadsBlockedSubview = { get subview() { let subview = document.getElementById("downloadsPanel-blockedSubview");
--- a/browser/components/downloads/content/indicator.js +++ b/browser/components/downloads/content/indicator.js @@ -1,13 +1,14 @@ /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* 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/. */ +/* eslint-env mozilla/browser-window */ /** * Handles the indicator that displays the progress of ongoing downloads, which * is also used as the anchor for the downloads panel. * * This module includes the following constructors and global objects: * * DownloadsButton @@ -21,18 +22,17 @@ * Builds and updates the actual downloads status widget, responding to changes * in the global status data, or provides a neutral view if the indicator is * removed from the toolbars and only used as a temporary anchor. In addition, * handles the user interaction events raised by the widget. */ "use strict"; -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsButton +// DownloadsButton /** * Main entry point for the downloads indicator. Depending on how the toolbars * have been customized, this object determines if we should show a fully * functional indicator, a placeholder used during customization and in the * customization palette, or a neutral view as a temporary anchor for the * downloads panel. */ @@ -182,18 +182,17 @@ const DownloadsButton = { }; Object.defineProperty(this, "DownloadsButton", { value: DownloadsButton, enumerable: true, writable: false }); -//////////////////////////////////////////////////////////////////////////////// -//// DownloadsIndicatorView +// DownloadsIndicatorView /** * Builds and updates the actual downloads status widget, responding to changes * in the global status data, or provides a neutral view if the indicator is * removed from the toolbars and only used as a temporary anchor. In addition, * handles the user interaction events raised by the widget. */ const DownloadsIndicatorView = { @@ -282,18 +281,17 @@ const DownloadsIndicatorView = { } if (aCallback) { aCallback(); } }); }, - ////////////////////////////////////////////////////////////////////////////// - //// Direct control functions + // Direct control functions /** * Set while we are waiting for a notification to fade out. */ _notificationTimeout: null, /** * Check if the panel containing aNode is open. @@ -352,39 +350,38 @@ const DownloadsIndicatorView = { } // The notification element is positioned to show in the same location as // the downloads button. It's not in the downloads button itself in order to // be able to anchor the notification elsewhere if required, and to ensure // the notification isn't clipped by overflow properties of the anchor's // container. let notifier = this.notifier; - if (notifier.style.transform == '') { + if (notifier.style.transform == "") { let anchorRect = anchor.getBoundingClientRect(); let notifierRect = notifier.getBoundingClientRect(); let topDiff = anchorRect.top - notifierRect.top; let leftDiff = anchorRect.left - notifierRect.left; let heightDiff = anchorRect.height - notifierRect.height; let widthDiff = anchorRect.width - notifierRect.width; let translateX = (leftDiff + .5 * widthDiff) + "px"; let translateY = (topDiff + .5 * heightDiff) + "px"; - notifier.style.transform = "translate(" + translateX + ", " + translateY + ")"; + notifier.style.transform = "translate(" + translateX + ", " + translateY + ")"; } notifier.setAttribute("notification", aType); anchor.setAttribute("notification", aType); this._notificationTimeout = setTimeout(() => { anchor.removeAttribute("notification"); notifier.removeAttribute("notification"); - notifier.style.transform = ''; + notifier.style.transform = ""; // This value is determined by the overall duration of animation in CSS. }, 2000); }, - ////////////////////////////////////////////////////////////////////////////// - //// Callback functions from DownloadsIndicatorData + // Callback functions from DownloadsIndicatorData /** * Indicates whether the indicator should be shown because there are some * downloads to be displayed. */ set hasDownloads(aValue) { if (this._hasDownloads != aValue || (!this._operational && aValue)) { this._hasDownloads = aValue; @@ -519,18 +516,17 @@ const DownloadsIndicatorView = { let badgeClass = "download-" + this._attention; gMenuButtonBadgeManager.addBadge( gMenuButtonBadgeManager.BADGEID_DOWNLOAD, badgeClass); } } }, _attention: DownloadsCommon.ATTENTION_NONE, - ////////////////////////////////////////////////////////////////////////////// - //// User interface event functions + // User interface event functions onWindowUnload() { // This function is registered as an event listener, we can't use "this". DownloadsIndicatorView.ensureTerminated(); }, onCommand(aEvent) { // If the downloads button is in the menu panel, open the Library
--- a/browser/components/downloads/test/browser/browser_basic_functionality.js +++ b/browser/components/downloads/test/browser/browser_basic_functionality.js @@ -25,17 +25,17 @@ add_task(function* test_basic_functional yield promiseFocus(); // Ensure that state is reset in case previous tests didn't finish. yield task_resetState(); // For testing purposes, show all the download items at once. var originalCountLimit = DownloadsView.kItemCountLimit; DownloadsView.kItemCountLimit = DownloadData.length; - registerCleanupFunction(function () { + registerCleanupFunction(function() { DownloadsView.kItemCountLimit = originalCountLimit; }); // Populate the downloads database with the data required by this test. yield task_addDownloads(DownloadData); // Open the user interface and wait for data to be fully loaded. yield task_openPanel();
--- a/browser/components/downloads/test/browser/browser_downloads_panel_block.js +++ b/browser/components/downloads/test/browser/browser_downloads_panel_block.js @@ -103,30 +103,28 @@ function* openPanel() { let interval = setInterval(() => { if (DownloadsPanel.panel && DownloadsPanel.panel.state == "open") { if (verifyCount > 0) { verifyCount--; } else { clearInterval(interval); resolve(); } - } else { - if (iBackoff < backoff) { + } else if (iBackoff < backoff) { // Keep backing off before trying again. iBackoff++; - } else { + } else { // Try (or retry) opening the panel. verifyCount = 5; backoff = Math.max(1, 2 * backoff); iBackoff = 0; if (DownloadsPanel._state != DownloadsPanel.kStateUninitialized) { - DownloadsPanel._state = DownloadsPanel.kStateHidden; + DownloadsPanel._state = DownloadsPanel.kStateHidden; } DownloadsPanel.showPanel(); - } } }, 100); }); } function promisePanelHidden() { return new Promise(resolve => { if (!DownloadsPanel.panel || DownloadsPanel.panel.state == "closed") { @@ -157,17 +155,16 @@ function promiseSubviewShown(shown) { // More terribleness, but I'm tired of fighting intermittent timeouts on try. // Just poll for the subview and wait a second before resolving the promise. return new Promise(resolve => { let interval = setInterval(() => { if (shown == DownloadsBlockedSubview.view.showingSubView && !DownloadsBlockedSubview.view._transitioning) { clearInterval(interval); setTimeout(resolve, 1000); - return; } }, 0); }); } function promiseUnblockAndOpenDownloadCalled(item) { return new Promise(resolve => { let realFn = item._shell.unblockAndOpenDownload;
--- a/browser/components/downloads/test/browser/browser_downloads_panel_footer.js +++ b/browser/components/downloads/test/browser/browser_downloads_panel_footer.js @@ -36,27 +36,27 @@ add_task(function* test_clearList() { downloads: [ { state: nsIDM.DOWNLOAD_NOTSTARTED }, { state: nsIDM.DOWNLOAD_FINISHED }, { state: nsIDM.DOWNLOAD_FAILED }, { state: nsIDM.DOWNLOAD_CANCELED }, ], expectClearListShown: true, expectedItemNumber: 0, - },{ + }, { downloads: [ { state: nsIDM.DOWNLOAD_NOTSTARTED }, { state: nsIDM.DOWNLOAD_FINISHED }, { state: nsIDM.DOWNLOAD_FAILED }, { state: nsIDM.DOWNLOAD_PAUSED }, { state: nsIDM.DOWNLOAD_CANCELED }, ], expectClearListShown: true, expectedItemNumber: 1, - },{ + }, { downloads: [ { state: nsIDM.DOWNLOAD_PAUSED }, ], expectClearListShown: false, expectedItemNumber: 1, }]; for (let testCase of kTestCases) {
--- a/browser/components/downloads/test/browser/browser_first_download_panel.js +++ b/browser/components/downloads/test/browser/browser_first_download_panel.js @@ -39,17 +39,17 @@ add_task(function* test_first_download_p DownloadsPanel.hidePanel(); ok(DownloadsCommon.getData(window).panelHasShownBefore, "Should have recorded that the panel was opened on a download.") // Next, make sure that if we start another download, we don't open the // panel automatically. let originalOnPopupShown = DownloadsPanel.onPopupShown; - DownloadsPanel.onPopupShown = function () { + DownloadsPanel.onPopupShown = function() { originalOnPopupShown.apply(this, arguments); ok(false, "Should not have opened the downloads panel."); }; DownloadsCommon.getData(window)._notifyDownloadEvent("start"); // Wait 2 seconds to ensure that the panel does not open. yield new Promise(resolve => setTimeout(resolve, 2000));
--- a/browser/components/downloads/test/browser/browser_iframe_gone_mid_download.js +++ b/browser/components/downloads/test/browser/browser_iframe_gone_mid_download.js @@ -1,11 +1,11 @@ const SAVE_PER_SITE_PREF = "browser.download.lastDir.savePerSite"; -function test_deleted_iframe(perSitePref, windowOptions={}) { +function test_deleted_iframe(perSitePref, windowOptions = {}) { return function*() { Services.prefs.setBoolPref(SAVE_PER_SITE_PREF, perSitePref); let {DownloadLastDir} = Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}); let win = yield promiseOpenAndLoadWindow(windowOptions); let tab = win.gBrowser.addTab(); yield promiseTabLoadEvent(tab, "about:mozilla");
--- a/browser/components/downloads/test/browser/browser_indicatorDrop.js +++ b/browser/components/downloads/test/browser/browser_indicatorDrop.js @@ -24,20 +24,20 @@ add_task(function* test_indicatorDrop() let dragData = [[{type: "text/plain", data: urls.join("\n")}]]; let list = yield Downloads.getList(Downloads.ALL); let added = new Set(); let succeeded = new Set(); yield new Promise(function(resolve) { let view = { - onDownloadAdded: function(download) { + onDownloadAdded(download) { added.add(download.source.url); }, - onDownloadChanged: function(download) { + onDownloadChanged(download) { if (!added.has(download.source.url)) return; if (!download.succeeded) return; succeeded.add(download.source.url); if (succeeded.size == urls.length) { list.removeView(view).then(resolve); }
--- a/browser/components/downloads/test/browser/browser_libraryDrop.js +++ b/browser/components/downloads/test/browser/browser_libraryDrop.js @@ -24,20 +24,20 @@ add_task(function* test_indicatorDrop() ok(listBox, "download list box present"); let list = await Downloads.getList(Downloads.ALL); let added = new Set(); let succeeded = new Set(); await new Promise(resolve => { let view = { - onDownloadAdded: function(download) { + onDownloadAdded(download) { added.add(download.source.url); }, - onDownloadChanged: function(download) { + onDownloadChanged(download) { if (!added.has(download.source.url)) return; if (!download.succeeded) return; succeeded.add(download.source.url); if (succeeded.size == urls.length) { list.removeView(view).then(resolve); }
--- a/browser/components/downloads/test/browser/head.js +++ b/browser/components/downloads/test/browser/head.js @@ -2,53 +2,54 @@ /* vim: set ts=2 et sw=2 tw=80: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Provides infrastructure for automated download components tests. */ -//////////////////////////////////////////////////////////////////////////////// -//// Globals +// Globals XPCOMUtils.defineLazyModuleGetter(this, "Downloads", "resource://gre/modules/Downloads.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon", "resource:///modules/DownloadsCommon.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "HttpServer", + "resource://testing-common/httpd.js"); + const nsIDM = Ci.nsIDownloadManager; var gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]); gTestTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); // Load mocking/stubbing library, sinon // docs: http://sinonjs.org/docs/ +/* global sinon:false */ Services.scriptloader.loadSubScript("resource://testing-common/sinon-1.16.1.js"); -registerCleanupFunction(function () { +registerCleanupFunction(function() { gTestTargetFile.remove(false); delete window.sinon; delete window.setImmediate; delete window.clearImmediate; }); -//////////////////////////////////////////////////////////////////////////////// -//// Asynchronous support subroutines +// Asynchronous support subroutines -function promiseOpenAndLoadWindow(aOptions) -{ +function promiseOpenAndLoadWindow(aOptions) { return new Promise((resolve, reject) => { let win = OpenBrowserWindow(aOptions); win.addEventListener("load", function() { resolve(win); }, {once: true}); }); } @@ -61,18 +62,17 @@ function promiseOpenAndLoadWindow(aOptio * @param [optional] url * The url to load, or the current url. * @param [optional] event * The load event type to wait for. Defaults to "load". * @return {Promise} resolved when the event is handled. * @resolves to the received event * @rejects if a valid load event is not received within a meaningful interval */ -function promiseTabLoadEvent(tab, url, eventType="load") -{ +function promiseTabLoadEvent(tab, url, eventType = "load") { let deferred = Promise.defer(); info("Wait tab event: " + eventType); function handle(event) { if (event.originalTarget != tab.linkedBrowser.contentDocument || event.target.location.href == "about:blank" || (url && event.target.location.href != url)) { info("Skipping spurious '" + eventType + "'' event" + @@ -91,77 +91,72 @@ function promiseTabLoadEvent(tab, url, e registerCleanupFunction(() => realCleanup()); tab.linkedBrowser.addEventListener(eventType, handle, true, true); if (url) tab.linkedBrowser.loadURI(url); return deferred.promise; } -function promiseWindowClosed(win) -{ +function promiseWindowClosed(win) { let promise = new Promise((resolve, reject) => { Services.obs.addObserver(function obs(subject, topic) { if (subject == win) { Services.obs.removeObserver(obs, topic); resolve(); } }, "domwindowclosed", false); }); win.close(); return promise; } -function promiseFocus() -{ +function promiseFocus() { let deferred = Promise.defer(); waitForFocus(deferred.resolve); return deferred.promise; } -function promisePanelOpened() -{ +function promisePanelOpened() { let deferred = Promise.defer(); if (DownloadsPanel.panel && DownloadsPanel.panel.state == "open") { return deferred.resolve(); } // Hook to wait until the panel is shown. let originalOnPopupShown = DownloadsPanel.onPopupShown; - DownloadsPanel.onPopupShown = function () { + DownloadsPanel.onPopupShown = function() { DownloadsPanel.onPopupShown = originalOnPopupShown; originalOnPopupShown.apply(this, arguments); // Defer to the next tick of the event loop so that we don't continue // processing during the DOM event handler itself. setTimeout(deferred.resolve, 0); }; return deferred.promise; } -function* task_resetState() -{ +function* task_resetState() { // Remove all downloads. let publicList = yield Downloads.getList(Downloads.PUBLIC); let downloads = yield publicList.getAll(); for (let download of downloads) { publicList.remove(download); yield download.finalize(true); } DownloadsPanel.hidePanel(); yield promiseFocus(); } -function* task_addDownloads(aItems) -{ +function* task_addDownloads(aItems) { let startTimeMs = Date.now(); let publicList = yield Downloads.getList(Downloads.PUBLIC); for (let item of aItems) { let download = { source: { url: "http://www.example.com/test-download.txt", }, @@ -179,31 +174,30 @@ function* task_addDownloads(aItems) // `"errorObj" in download` must be false when there's no error. if (item.errorObj) { download.errorObj = item.errorObj; } yield publicList.add(yield Downloads.createDownload(download)); } } -function* task_openPanel() -{ +function* task_openPanel() { yield promiseFocus(); let promise = promisePanelOpened(); DownloadsPanel.showPanel(); yield promise; } function* setDownloadDir() { let tmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile); tmpDir.append("testsavedir"); if (!tmpDir.exists()) { tmpDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); - registerCleanupFunction(function () { + registerCleanupFunction(function() { try { tmpDir.remove(true); } catch (e) { // On Windows debug build this may fail. } }); }
--- a/browser/components/downloads/test/unit/head.js +++ b/browser/components/downloads/test/unit/head.js @@ -2,17 +2,16 @@ /* vim: set ts=2 et sw=2 tw=80: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Provides infrastructure for automated download components tests. */ -//////////////////////////////////////////////////////////////////////////////// -//// Globals +// Globals var Cc = Components.classes; var Ci = Components.interfaces; var Cu = Components.utils; var Cr = Components.results; Cu.import("resource:///modules/DownloadsCommon.jsm");
--- a/browser/components/downloads/test/unit/test_DownloadsCommon.js +++ b/browser/components/downloads/test/unit/test_DownloadsCommon.js @@ -2,36 +2,34 @@ /* vim: set ts=2 et sw=2 tw=80: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests for the functions located directly in the "DownloadsCommon" object. */ -function testFormatTimeLeft(aSeconds, aExpectedValue, aExpectedUnitString) -{ +function testFormatTimeLeft(aSeconds, aExpectedValue, aExpectedUnitString) { let expected = ""; if (aExpectedValue) { // Format the expected result based on the current language. expected = DownloadsCommon.strings[aExpectedUnitString](aExpectedValue); } do_check_eq(DownloadsCommon.formatTimeLeft(aSeconds), expected); } -function run_test() -{ - testFormatTimeLeft( 0, "", ""); - testFormatTimeLeft( 1, "1", "shortTimeLeftSeconds"); - testFormatTimeLeft( 29, "29", "shortTimeLeftSeconds"); - testFormatTimeLeft( 30, "30", "shortTimeLeftSeconds"); - testFormatTimeLeft( 31, "1", "shortTimeLeftMinutes"); - testFormatTimeLeft( 60, "1", "shortTimeLeftMinutes"); - testFormatTimeLeft( 89, "1", "shortTimeLeftMinutes"); - testFormatTimeLeft( 90, "2", "shortTimeLeftMinutes"); - testFormatTimeLeft( 91, "2", "shortTimeLeftMinutes"); - testFormatTimeLeft( 3600, "1", "shortTimeLeftHours"); - testFormatTimeLeft( 86400, "24", "shortTimeLeftHours"); - testFormatTimeLeft( 169200, "47", "shortTimeLeftHours"); - testFormatTimeLeft( 172800, "2", "shortTimeLeftDays"); +function run_test() { + testFormatTimeLeft(0, "", ""); + testFormatTimeLeft(1, "1", "shortTimeLeftSeconds"); + testFormatTimeLeft(29, "29", "shortTimeLeftSeconds"); + testFormatTimeLeft(30, "30", "shortTimeLeftSeconds"); + testFormatTimeLeft(31, "1", "shortTimeLeftMinutes"); + testFormatTimeLeft(60, "1", "shortTimeLeftMinutes"); + testFormatTimeLeft(89, "1", "shortTimeLeftMinutes"); + testFormatTimeLeft(90, "2", "shortTimeLeftMinutes"); + testFormatTimeLeft(91, "2", "shortTimeLeftMinutes"); + testFormatTimeLeft(3600, "1", "shortTimeLeftHours"); + testFormatTimeLeft(86400, "24", "shortTimeLeftHours"); + testFormatTimeLeft(169200, "47", "shortTimeLeftHours"); + testFormatTimeLeft(172800, "2", "shortTimeLeftDays"); testFormatTimeLeft(8553600, "99", "shortTimeLeftDays"); testFormatTimeLeft(8640000, "99", "shortTimeLeftDays"); }
--- a/browser/modules/ContentClick.jsm +++ b/browser/modules/ContentClick.jsm @@ -80,16 +80,17 @@ var ContentClick = { let params = { charset: browser.characterSet, referrerURI: browser.documentURI, referrerPolicy: json.referrerPolicy, noReferrer: json.noReferrer, allowMixedContent: json.allowMixedContent, isContentWindowPrivate: json.isContentWindowPrivate, originPrincipal: json.originPrincipal, + triggeringPrincipal: json.triggeringPrincipal, frameOuterWindowID: json.frameOuterWindowID, }; // The new tab/window must use the same userContextId. if (json.originAttributes.userContextId) { params.userContextId = json.originAttributes.userContextId; }
--- a/devtools/client/inspector/shared/tooltips-overlay.js +++ b/devtools/client/inspector/shared/tooltips-overlay.js @@ -275,17 +275,18 @@ TooltipsOverlay.prototype = { let fillStyle = getColor("body-color"); let {data, size: maxDim} = yield nodeFront.getFontFamilyDataURL(font, fillStyle); let imageUrl = yield data.string(); let doc = this.view.inspector.panelDoc; let {naturalWidth, naturalHeight} = yield getImageDimensions(doc, imageUrl); yield setImageTooltip(this.previewTooltip, doc, imageUrl, - {hideDimensionLabel: true, maxDim, naturalWidth, naturalHeight}); + {hideDimensionLabel: true, hideCheckeredBackground: true, + maxDim, naturalWidth, naturalHeight}); }), _onNewSelection: function () { if (this.previewTooltip) { this.previewTooltip.hide(); } if (this.colorPicker) {
--- a/devtools/client/netmonitor/src/components/properties-view.js +++ b/devtools/client/netmonitor/src/components/properties-view.js @@ -199,16 +199,17 @@ const PropertiesView = createClass({ id: "value", width: "100%", }], decorator: decorator || { getRowClass: (rowObject) => this.getRowClass(rowObject, sectionNames), }, enableInput, expandableStrings, + useQuotes: false, expandedNodes: this.getExpandedNodes(object), onFilter: (props) => this.onFilter(props, sectionNames), renderRow: renderRow || this.renderRowWithEditor, renderValue: renderValue || this.renderValueWithRep, }), ), ) );
--- a/devtools/client/netmonitor/test/browser_net_complex-params.js +++ b/devtools/client/netmonitor/test/browser_net_complex-params.js @@ -25,51 +25,51 @@ add_task(function* () { yield wait; wait = waitForDOM(document, "#params-panel .tree-section", 2); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[0]); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#params-tab")); yield wait; - testParamsTab1("a", '""', '{ "foo": "bar" }', '""'); + testParamsTab1("a", "", '{ "foo": "bar" }', ""); wait = waitForDOM(document, "#params-panel .tree-section", 2); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[1]); yield wait; - testParamsTab1("a", '"b"', '{ "foo": "bar" }', '""'); + testParamsTab1("a", "b", '{ "foo": "bar" }', ""); wait = waitForDOM(document, "#params-panel .tree-section", 2); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[2]); yield wait; - testParamsTab1("a", '"b"', "?foo", '"bar"'); + testParamsTab1("a", "b", "?foo", "bar"); wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[3]); yield wait; - testParamsTab2("a", '""', '{ "foo": "bar" }', "js"); + testParamsTab2("a", "", '{ "foo": "bar" }', "js"); wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[4]); yield wait; - testParamsTab2("a", '"b"', '{ "foo": "bar" }', "js"); + testParamsTab2("a", "b", '{ "foo": "bar" }', "js"); // Wait for all tree sections and editor updated by react let waitSections = waitForDOM(document, "#params-panel .tree-section", 2); let waitEditor = waitForDOM(document, "#params-panel .editor-mount iframe"); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[5]); let [, editorFrames] = yield Promise.all([waitSections, waitEditor]); yield once(editorFrames[0], "DOMContentLoaded"); yield waitForDOM(editorFrames[0].contentDocument, ".CodeMirror-code"); - testParamsTab2("a", '"b"', "?foo=bar", "text"); + testParamsTab2("a", "b", "?foo=bar", "text"); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[6]); testParamsTab3(); yield teardown(monitor); function testParamsTab1(queryStringParamName, queryStringParamValue,
--- a/devtools/client/netmonitor/test/browser_net_content-type.js +++ b/devtools/client/netmonitor/test/browser_net_content-type.js @@ -223,17 +223,17 @@ add_task(function* () { let labels = tabpanel .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel"); let values = tabpanel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[0].textContent, "greeting", "The first json property name was incorrect."); is(values[0].textContent, - "\"Hello JSON!\"", "The first json property value was incorrect."); + "Hello JSON!", "The first json property value was incorrect."); break; } case "html": { checkVisibility("textarea"); let editor = document.querySelector(".editor-mount iframe"); let text = editor.contentDocument.querySelector(".CodeMirror-line").textContent;
--- a/devtools/client/netmonitor/test/browser_net_json-b64.js +++ b/devtools/client/netmonitor/test/browser_net_json-b64.js @@ -51,13 +51,13 @@ add_task(function* () { let labels = tabpanel .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel"); let values = tabpanel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[0].textContent, "greeting", "The first json property name was incorrect."); - is(values[0].textContent, "\"This is a base 64 string.\"", + is(values[0].textContent, "This is a base 64 string.", "The first json property value was incorrect."); yield teardown(monitor); });
--- a/devtools/client/netmonitor/test/browser_net_json_custom_mime.js +++ b/devtools/client/netmonitor/test/browser_net_json_custom_mime.js @@ -75,12 +75,12 @@ add_task(function* () { let labels = tabpanel .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel"); let values = tabpanel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[0].textContent, "greeting", "The first json property name was incorrect."); - is(values[0].textContent, "\"Hello oddly-named JSON!\"", + is(values[0].textContent, "Hello oddly-named JSON!", "The first json property value was incorrect."); } });
--- a/devtools/client/netmonitor/test/browser_net_json_text_mime.js +++ b/devtools/client/netmonitor/test/browser_net_json_text_mime.js @@ -76,12 +76,12 @@ add_task(function* () { let labels = tabpanel .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel"); let values = tabpanel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[0].textContent, "greeting", "The first json property name was incorrect."); - is(values[0].textContent, "\"Hello third-party JSON!\"", + is(values[0].textContent, "Hello third-party JSON!", "The first json property value was incorrect."); } });
--- a/devtools/client/netmonitor/test/browser_net_jsonp.js +++ b/devtools/client/netmonitor/test/browser_net_jsonp.js @@ -59,24 +59,24 @@ add_task(function* () { wait = waitForDOM(document, "#response-panel"); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector(".network-details-panel-toggle")); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); yield wait; - testResponseTab("$_0123Fun", "\"Hello JSONP!\""); + testResponseTab("$_0123Fun", "Hello JSONP!"); wait = waitForDOM(document, "#response-panel .tree-section"); EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[1]); yield wait; - testResponseTab("$_4567Sad", "\"Hello weird JSONP!\""); + testResponseTab("$_4567Sad", "Hello weird JSONP!"); yield teardown(monitor); function testResponseTab(func, greeting) { let tabpanel = document.querySelector("#response-panel"); is(tabpanel.querySelector(".response-error-header") === null, true, "The response error header doesn't have the intended visibility.");
--- a/devtools/client/netmonitor/test/browser_net_post-data-01.js +++ b/devtools/client/netmonitor/test/browser_net_post-data-01.js @@ -110,30 +110,29 @@ add_task(function* () { "The post section doesn't have the correct title."); let labels = tabpanel .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel"); let values = tabpanel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[0].textContent, "foo", "The first query param name was incorrect."); - is(values[0].textContent, "\"bar\"", "The first query param value was incorrect."); + is(values[0].textContent, "bar", "The first query param value was incorrect."); is(labels[1].textContent, "baz", "The second query param name was incorrect."); - is(values[1].textContent, "\"42\"", "The second query param value was incorrect."); + is(values[1].textContent, "42", "The second query param value was incorrect."); is(labels[2].textContent, "type", "The third query param name was incorrect."); - is(values[2].textContent, "\"" + type + "\"", - "The third query param value was incorrect."); + is(values[2].textContent, type, "The third query param value was incorrect."); if (type == "urlencoded") { checkVisibility("params"); is(labels.length, 5, "There should be 5 param values displayed in this tabpanel."); is(labels[3].textContent, "foo", "The first post param name was incorrect."); - is(values[3].textContent, "\"bar\"", "The first post param value was incorrect."); + is(values[3].textContent, "bar", "The first post param value was incorrect."); is(labels[4].textContent, "baz", "The second post param name was incorrect."); - is(values[4].textContent, "\"123\"", "The second post param value was incorrect."); + is(values[4].textContent, "123", "The second post param value was incorrect."); } else { checkVisibility("params editor"); is(labels.length, 3, "There should be 3 param values displayed in this tabpanel."); let text = editorFrames[0].contentDocument.querySelector(".CodeMirror-code") .textContent;
--- a/devtools/client/netmonitor/test/browser_net_post-data-02.js +++ b/devtools/client/netmonitor/test/browser_net_post-data-02.js @@ -50,14 +50,14 @@ add_task(function* () { "The post section doesn't have the correct title."); let labels = tabpanel .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel"); let values = tabpanel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[0].textContent, "foo", "The first query param name was incorrect."); - is(values[0].textContent, "\"bar\"", "The first query param value was incorrect."); + is(values[0].textContent, "bar", "The first query param value was incorrect."); is(labels[1].textContent, "baz", "The second query param name was incorrect."); - is(values[1].textContent, "\"123\"", "The second query param value was incorrect."); + is(values[1].textContent, "123", "The second query param value was incorrect."); return teardown(monitor); });
--- a/devtools/client/netmonitor/test/browser_net_post-data-03.js +++ b/devtools/client/netmonitor/test/browser_net_post-data-03.js @@ -45,21 +45,21 @@ add_task(function* () { let labels = tabpanel .querySelectorAll(".properties-view tr:not(.tree-section) .treeLabelCell .treeLabel"); let values = tabpanel .querySelectorAll(".properties-view tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[labels.length - 2].textContent, "content-type", "The first request header name was incorrect."); - is(values[values.length - 2].textContent, "\"application/x-www-form-urlencoded\"", + is(values[values.length - 2].textContent, "application/x-www-form-urlencoded", "The first request header value was incorrect."); is(labels[labels.length - 1].textContent, "custom-header", "The second request header name was incorrect."); - is(values[values.length - 1].textContent, "\"hello world!\"", + is(values[values.length - 1].textContent, "hello world!", "The second request header value was incorrect."); // Wait for all tree sections updated by react wait = waitForDOM(document, "#params-panel .tree-section"); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#params-tab")); yield wait; @@ -75,14 +75,14 @@ add_task(function* () { "The form data section doesn't have the correct title."); labels = tabpanel .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel"); values = tabpanel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(labels[0].textContent, "foo", "The first payload param name was incorrect."); - is(values[0].textContent, "\"bar\"", "The first payload param value was incorrect."); + is(values[0].textContent, "bar", "The first payload param value was incorrect."); is(labels[1].textContent, "baz", "The second payload param name was incorrect."); - is(values[1].textContent, "\"123\"", "The second payload param value was incorrect."); + is(values[1].textContent, "123", "The second payload param value was incorrect."); return teardown(monitor); });
--- a/devtools/client/netmonitor/test/browser_net_status-codes.js +++ b/devtools/client/netmonitor/test/browser_net_status-codes.js @@ -177,17 +177,16 @@ add_task(function* () { function* testParams(data, index) { EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll(".request-list-item")[index]); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#params-tab")); let panel = document.querySelector("#params-panel"); let statusParamValue = data.uri.split("=").pop(); - let statusParamShownValue = "\"" + statusParamValue + "\""; let treeSections = panel.querySelectorAll(".tree-section"); is(treeSections.length, 1, "There should be 1 param section displayed in this panel."); is(panel.querySelectorAll("tr:not(.tree-section).treeRow").length, 1, "There should be 1 param row displayed in this panel."); is(panel.querySelectorAll(".empty-notice").length, 0, "The empty notice should not be displayed in this panel."); @@ -197,17 +196,17 @@ add_task(function* () { let values = panel .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); is(treeSections[0].querySelector(".treeLabel").textContent, L10N.getStr("paramsQueryString"), "The params scope doesn't have the correct title."); is(labels[0].textContent, "sts", "The param name was incorrect."); - is(values[0].textContent, statusParamShownValue, "The param value was incorrect."); + is(values[0].textContent, statusParamValue, "The param value was incorrect."); ok(panel.querySelector(".treeTable"), "The request params tree view should be displayed."); is(panel.querySelector(".editor-mount") === null, true, "The request post data editor should be hidden."); } });
--- a/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js +++ b/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js @@ -51,46 +51,54 @@ function getImageDimensions(doc, imageUr * A document element to create the HTML elements needed for the tooltip * @param {String} imageUrl * Absolute URL of the image to display in the tooltip * @param {Object} options * - {Number} naturalWidth mandatory, width of the image to display * - {Number} naturalHeight mandatory, height of the image to display * - {Number} maxDim optional, max width/height of the preview * - {Boolean} hideDimensionLabel optional, pass true to hide the label + * - {Boolean} hideCheckeredBackground optional, pass true to hide + the checkered background */ function setImageTooltip(tooltip, doc, imageUrl, options) { - let {naturalWidth, naturalHeight, hideDimensionLabel, maxDim} = options; + let {naturalWidth, naturalHeight, hideDimensionLabel, + hideCheckeredBackground, maxDim} = options; maxDim = maxDim || MAX_DIMENSION; let imgHeight = naturalHeight; let imgWidth = naturalWidth; if (imgHeight > maxDim || imgWidth > maxDim) { let scale = maxDim / Math.max(imgHeight, imgWidth); // Only allow integer values to avoid rounding errors. imgHeight = Math.floor(scale * naturalHeight); imgWidth = Math.ceil(scale * naturalWidth); } + let imageClass = ""; + if (!hideCheckeredBackground) { + imageClass = "devtools-tooltip-tiles"; + } + // Create tooltip content let div = doc.createElementNS(XHTML_NS, "div"); div.style.cssText = ` height: 100%; min-width: 100px; display: flex; flex-direction: column; text-align: center;`; let html = ` <div style="flex: 1; display: flex; padding: ${IMAGE_PADDING}px; align-items: center; justify-content: center; min-height: 1px;"> - <img class="devtools-tooltip-tiles" + <img class="${imageClass}" style="height: ${imgHeight}px; max-height: 100%;" src="${imageUrl}"/> </div>`; if (!hideDimensionLabel) { let label = naturalWidth + " \u00D7 " + naturalHeight; html += ` <div style="height: ${LABEL_HEIGHT}px;
--- a/dom/base/test/chrome/window_nsITextInputProcessor.xul +++ b/dom/base/test/chrome/window_nsITextInputProcessor.xul @@ -2292,20 +2292,18 @@ function runKeyTests() desc + " should cause keydown event"); if (aEvent.type != aExpectedData.type) { return; } is(aEvent.defaultPrevented, expectedValue("defaultPrevented"), desc + ".defaultPrevented is wrong"); is(aEvent.key, expectedValue("key"), desc + ".key is wrong"); - if (SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled")) { - is(aEvent.code, expectedValue("code"), - desc + ".code is wrong"); - } + is(aEvent.code, expectedValue("code"), + desc + ".code is wrong"); is(aEvent.location, expectedValue("location"), desc + ".location is wrong"); is(aEvent.repeat, expectedValue("repeat"), desc + ".repeat is wrong"); is(aEvent.isComposing, expectedValue("isComposing"), desc + ".isComposing is wrong"); is(aEvent.keyCode, expectedValue("keyCode"), desc + ".keyCode is wrong"); @@ -2870,20 +2868,18 @@ function runKeyTests() var desc = description + aTestDesc + ", type=\"" + aEvent.type + "\", key=\"" + aEvent.key + "\", code=\"" + aEvent.code + "\""; is(aEvent.type, aType, desc + ", .type value is wrong"); if (aEvent.type != aType) { return; } is(aEvent.key, aKey, desc + ", .key value is wrong"); - if (SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled")) { - is(aEvent.code, aCode, - desc + ", .code value is wrong"); - } + is(aEvent.code, aCode, + desc + ", .code value is wrong"); is(aEvent.altKey, aModifiers.indexOf("Alt") >= 0, desc + ", .altKey value is wrong"); is(aEvent.ctrlKey, aModifiers.indexOf("Control") >= 0, desc + ", .ctrlKey value is wrong"); is(aEvent.metaKey, aModifiers.indexOf("Meta") >= 0, desc + ", .metaKey value is wrong"); is(aEvent.shiftKey, aModifiers.indexOf("Shift") >= 0, desc + ", .shiftKey value is wrong");
--- a/dom/events/test/test_dom_keyboard_event.html +++ b/dom/events/test/test_dom_keyboard_event.html @@ -9,18 +9,16 @@ <body> <p id="display"></p> <div id="content" style="display: none"> </div> <pre id="test"> <script type="application/javascript"> -var gCodeEnabled = SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled"); - SimpleTest.waitForExplicitFinish(); SimpleTest.waitForFocus(runTests, window); function testInitializingUntrustedEvent() { const kTests = [ { createEventArg: "KeyboardEvent", type: "keydown", bubbles: true, cancelable: true, view: null, @@ -121,19 +119,17 @@ function testInitializingUntrustedEvent( } else { is(e[attr], kTest[attr], description + attr + " returns wrong value"); } } is(e.isTrusted, false, description + "isTrusted returns wrong value"); // key and code values cannot be initialized with initKeyEvent(). is(e.key, "", description + "key must return empty string"); - if (gCodeEnabled) { - is(e.code, "", description + "code must be empty string"); - } + is(e.code, "", description + "code must be empty string"); // getModifierState() tests is(e.getModifierState("Shift"), kTest.shiftKey, description + "getModifierState(\"Shift\") returns wrong value"); is(e.getModifierState("Control"), kTest.ctrlKey, description + "getModifierState(\"Control\") returns wrong value"); is(e.getModifierState("Alt"), kTest.altKey, description + "getModifierState(\"Alt\") returns wrong value");
--- a/dom/events/test/test_eventctors.html +++ b/dom/events/test/test_eventctors.html @@ -428,37 +428,30 @@ var testKeyboardProps = { keyCode: 3 }, { which: 4 }, { charCode: 5, which: 6 }, { keyCode: 7, which: 8 }, { keyCode: 9, charCode: 10 }, { keyCode: 11, charCode: 12, which: 13 }, ]; -var codeEnabled = SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled"); var defaultKeyboardEventValues = {}; for (var i = 0; i < keyboardEventProps.length; ++i) { for (prop in keyboardEventProps[i]) { - if (!codeEnabled && prop == "code") { - continue; - } if (!isMethodResultInitializer(prop)) { ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!"); } defaultKeyboardEventValues[prop] = keyboardEventProps[i][prop]; } } while (testKeyboardProps.length) { var p = testKeyboardProps.shift(); e = new KeyboardEvent("foo", p); for (var def in defaultKeyboardEventValues) { - if (!codeEnabled && def == "code") { - continue; - } if (!(def in p)) { is(getPropValue(e, def), defaultKeyboardEventValues[def], "KeyboardEvent: Wrong default value for " + def + "!"); } else { is(getPropValue(e, def), p[def], "KeyboardEvent: Wrong event init value for " + def + "!"); } }
--- a/dom/url/tests/urlSearchParams_commons.js +++ b/dom/url/tests/urlSearchParams_commons.js @@ -1,303 +1,309 @@ - function testSimpleURLSearchParams() { - var u = new URLSearchParams(); - ok(u, "URLSearchParams created"); - is(u.has('foo'), false, 'URLSearchParams.has(foo)'); - is(u.get('foo'), null, 'URLSearchParams.get(foo)'); - is(u.getAll('foo').length, 0, 'URLSearchParams.getAll(foo)'); +function testSimpleURLSearchParams() { + var u = new URLSearchParams(); + ok(u, "URLSearchParams created"); + is(u.has('foo'), false, 'URLSearchParams.has(foo)'); + is(u.get('foo'), null, 'URLSearchParams.get(foo)'); + is(u.getAll('foo').length, 0, 'URLSearchParams.getAll(foo)'); + + u.append('foo', 'bar'); + is(u.has('foo'), true, 'URLSearchParams.has(foo)'); + is(u.get('foo'), 'bar', 'URLSearchParams.get(foo)'); + is(u.getAll('foo').length, 1, 'URLSearchParams.getAll(foo)'); + + u.set('foo', 'bar2'); + is(u.get('foo'), 'bar2', 'URLSearchParams.get(foo)'); + is(u.getAll('foo').length, 1, 'URLSearchParams.getAll(foo)'); + + is(u + "", "foo=bar2", "stringifier"); + + u.delete('foo'); + + runTest(); +} - u.append('foo', 'bar'); - is(u.has('foo'), true, 'URLSearchParams.has(foo)'); - is(u.get('foo'), 'bar', 'URLSearchParams.get(foo)'); - is(u.getAll('foo').length, 1, 'URLSearchParams.getAll(foo)'); +function testCopyURLSearchParams() { + var u = new URLSearchParams(); + ok(u, "URLSearchParams created"); + u.append('foo', 'bar'); + + var uu = new URLSearchParams(u); + is(uu.get('foo'), 'bar', 'uu.get()'); + + u.append('foo', 'bar2'); + is(u.getAll('foo').length, 2, "u.getAll()"); + is(uu.getAll('foo').length, 1, "uu.getAll()"); - u.set('foo', 'bar2'); - is(u.get('foo'), 'bar2', 'URLSearchParams.get(foo)'); - is(u.getAll('foo').length, 1, 'URLSearchParams.getAll(foo)'); + runTest(); +} - is(u + "", "foo=bar2", "stringifier"); +function testURL() { + var url = new URL('http://www.example.net?a=b&c=d'); + ok(url.searchParams, "URL searchParams exists!"); + ok(url.searchParams.has('a'), "URL.searchParams.has('a')"); + is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')"); + ok(url.searchParams.has('c'), "URL.searchParams.has('c')"); + is(url.searchParams.get('c'), 'd', "URL.searchParams.get('c')"); + + url.searchParams.set('e', 'f'); + ok(url.href.indexOf('e=f') != 1, 'URL right'); - u.delete('foo'); - - runTest(); - } + runTest(); +} +function testParserURLSearchParams() { + var checks = [ + { input: '', data: {} }, + { input: 'a', data: { 'a' : [''] } }, + { input: 'a=b', data: { 'a' : ['b'] } }, + { input: 'a=', data: { 'a' : [''] } }, + { input: '=b', data: { '' : ['b'] } }, + { input: '&', data: {} }, + { input: '&a', data: { 'a' : [''] } }, + { input: 'a&', data: { 'a' : [''] } }, + { input: 'a&a', data: { 'a' : ['', ''] } }, + { input: 'a&b&c', data: { 'a' : [''], 'b' : [''], 'c' : [''] } }, + { input: 'a=b&c=d', data: { 'a' : ['b'], 'c' : ['d'] } }, + { input: 'a=b&c=d&', data: { 'a' : ['b'], 'c' : ['d'] } }, + { input: '&&&a=b&&&&c=d&', data: { 'a' : ['b'], 'c' : ['d'] } }, + { input: 'a=a&a=b&a=c', data: { 'a' : ['a', 'b', 'c'] } }, + { input: 'a==a', data: { 'a' : ['=a'] } }, + { input: 'a=a+b+c+d', data: { 'a' : ['a b c d'] } }, + { input: '%=a', data: { '%' : ['a'] } }, + { input: '%a=a', data: { '%a' : ['a'] } }, + { input: '%a_=a', data: { '%a_' : ['a'] } }, + { input: '%61=a', data: { 'a' : ['a'] } }, + { input: '%=a', data: { '%' : ['a'] } }, + { input: '%a=a', data: { '%a' : ['a'] } }, + { input: '%a_=a', data: { '%a_' : ['a'] } }, + { input: '%61=a', data: { 'a' : ['a'] } }, + { input: '%61+%4d%4D=', data: { 'a MM' : [''] } }, + { input: '?a=1', data: { 'a' : ['1'] } }, + { input: '?', data: {} }, + { input: '?=b', data: { '' : ['b'] } }, + ]; - function testCopyURLSearchParams() { - var u = new URLSearchParams(); - ok(u, "URLSearchParams created"); - u.append('foo', 'bar'); + for (var i = 0; i < checks.length; ++i) { + var u = new URLSearchParams(checks[i].input); + + var count = 0; + for (var key in checks[i].data) { + ++count; + ok(u.has(key), "key " + key + " found"); - var uu = new URLSearchParams(u); - is(uu.get('foo'), 'bar', 'uu.get()'); + var all = u.getAll(key); + is(all.length, checks[i].data[key].length, "same number of elements"); - u.append('foo', 'bar2'); - is(u.getAll('foo').length, 2, "u.getAll()"); - is(uu.getAll('foo').length, 1, "uu.getAll()"); - - runTest(); + for (var k = 0; k < all.length; ++k) { + is(all[k], checks[i].data[key][k], "value matches"); + } + } } - function testURL() { - var url = new URL('http://www.example.net?a=b&c=d'); - ok(url.searchParams, "URL searchParams exists!"); - ok(url.searchParams.has('a'), "URL.searchParams.has('a')"); - is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')"); - ok(url.searchParams.has('c'), "URL.searchParams.has('c')"); - is(url.searchParams.get('c'), 'd', "URL.searchParams.get('c')"); - - url.searchParams.set('e', 'f'); - ok(url.href.indexOf('e=f') != 1, 'URL right'); - - runTest(); - } - function testParserURLSearchParams() { - var checks = [ - { input: '', data: {} }, - { input: 'a', data: { 'a' : [''] } }, - { input: 'a=b', data: { 'a' : ['b'] } }, - { input: 'a=', data: { 'a' : [''] } }, - { input: '=b', data: { '' : ['b'] } }, - { input: '&', data: {} }, - { input: '&a', data: { 'a' : [''] } }, - { input: 'a&', data: { 'a' : [''] } }, - { input: 'a&a', data: { 'a' : ['', ''] } }, - { input: 'a&b&c', data: { 'a' : [''], 'b' : [''], 'c' : [''] } }, - { input: 'a=b&c=d', data: { 'a' : ['b'], 'c' : ['d'] } }, - { input: 'a=b&c=d&', data: { 'a' : ['b'], 'c' : ['d'] } }, - { input: '&&&a=b&&&&c=d&', data: { 'a' : ['b'], 'c' : ['d'] } }, - { input: 'a=a&a=b&a=c', data: { 'a' : ['a', 'b', 'c'] } }, - { input: 'a==a', data: { 'a' : ['=a'] } }, - { input: 'a=a+b+c+d', data: { 'a' : ['a b c d'] } }, - { input: '%=a', data: { '%' : ['a'] } }, - { input: '%a=a', data: { '%a' : ['a'] } }, - { input: '%a_=a', data: { '%a_' : ['a'] } }, - { input: '%61=a', data: { 'a' : ['a'] } }, - { input: '%=a', data: { '%' : ['a'] } }, - { input: '%a=a', data: { '%a' : ['a'] } }, - { input: '%a_=a', data: { '%a_' : ['a'] } }, - { input: '%61=a', data: { 'a' : ['a'] } }, - { input: '%61+%4d%4D=', data: { 'a MM' : [''] } }, - { input: '?a=1', data: { 'a' : ['1'] } }, - { input: '?', data: {} }, - { input: '?=b', data: { '' : ['b'] } }, - ]; - - for (var i = 0; i < checks.length; ++i) { - var u = new URLSearchParams(checks[i].input); - - var count = 0; - for (var key in checks[i].data) { - ++count; - ok(u.has(key), "key " + key + " found"); + runTest(); +} - var all = u.getAll(key); - is(all.length, checks[i].data[key].length, "same number of elements"); - - for (var k = 0; k < all.length; ++k) { - is(all[k], checks[i].data[key][k], "value matches"); - } - } - } - - runTest(); - } - - function testEncoding() { - var encoding = [ [ '1', '1' ], - [ 'a b', 'a+b' ], - [ '<>', '%3C%3E' ], - [ '\u0541', '%D5%81'] ]; - - for (var i = 0; i < encoding.length; ++i) { - var url = new URL('http://www.example.net'); - url.searchParams.set('a', encoding[i][0]); - is(url.href, 'http://www.example.net/?a=' + encoding[i][1]); - - var url2 = new URL(url.href); - is(url2.searchParams.get('a'), encoding[i][0], 'a is still there'); - } +function testEncoding() { + var encoding = [ [ '1', '1' ], + [ 'a b', 'a+b' ], + [ '<>', '%3C%3E' ], + [ '\u0541', '%D5%81'] ]; - runTest(); - } - - function testCopyConstructor() { - var url = new URL("http://example.com/"); - var p = url.searchParams; - var q = new URLSearchParams(p); - q.set("a", "b"); - is(url.href, "http://example.com/", - "Messing with copy of URLSearchParams should not affect URL"); - p.set("c", "d"); - is(url.href, "http://example.com/?c=d", - "Messing with URLSearchParams should affect URL"); + for (var i = 0; i < encoding.length; ++i) { + var url = new URL('http://www.example.net'); + url.searchParams.set('a', encoding[i][0]); + is(url.href, 'http://www.example.net/?a=' + encoding[i][1]); - runTest(); - } - - function testOrdering() { - var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6"); - is(a.toString(), "a=1&a=2&b=3&c=4&c=5&a=6", "Order is correct"); - is(a.getAll('a').length, 3, "Correct length of getAll()"); - - var b = new URLSearchParams(); - b.append('a', '1'); - b.append('b', '2'); - b.append('a', '3'); - is(b.toString(), "a=1&b=2&a=3", "Order is correct"); - is(b.getAll('a').length, 2, "Correct length of getAll()"); - - runTest(); + var url2 = new URL(url.href); + is(url2.searchParams.get('a'), encoding[i][0], 'a is still there'); } - function testDelete() { - var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6"); - is(a.toString(), "a=1&a=2&b=3&c=4&c=5&a=6", "Order is correct"); - is(a.getAll('a').length, 3, "Correct length of getAll()"); + runTest(); +} - a.delete('a'); - is(a.getAll('a').length, 0, "Correct length of getAll()"); - is(a.toString(), "b=3&c=4&c=5", "Order is correct"); +function testCopyConstructor() { + var url = new URL("http://example.com/"); + var p = url.searchParams; + var q = new URLSearchParams(p); + q.set("a", "b"); + is(url.href, "http://example.com/", + "Messing with copy of URLSearchParams should not affect URL"); + p.set("c", "d"); + is(url.href, "http://example.com/?c=d", + "Messing with URLSearchParams should affect URL"); - runTest(); - } + runTest(); +} + +function testOrdering() { + var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6"); + is(a.toString(), "a=1&a=2&b=3&c=4&c=5&a=6", "Order is correct"); + is(a.getAll('a').length, 3, "Correct length of getAll()"); - function testGetNULL() { - var u = new URLSearchParams(); - is(typeof u.get(''), "object", "typeof URL.searchParams.get('')"); - is(u.get(''), null, "URL.searchParams.get('') should be null"); + var b = new URLSearchParams(); + b.append('a', '1'); + b.append('b', '2'); + b.append('a', '3'); + is(b.toString(), "a=1&b=2&a=3", "Order is correct"); + is(b.getAll('a').length, 2, "Correct length of getAll()"); + + runTest(); +} + +function testDelete() { + var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6"); + is(a.toString(), "a=1&a=2&b=3&c=4&c=5&a=6", "Order is correct"); + is(a.getAll('a').length, 3, "Correct length of getAll()"); - var url = new URL('http://www.example.net?a=b'); - is(url.searchParams.get('b'), null, "URL.searchParams.get('b') should be null"); - is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')"); + a.delete('a'); + is(a.getAll('a').length, 0, "Correct length of getAll()"); + is(a.toString(), "b=3&c=4&c=5", "Order is correct"); + + runTest(); +} - runTest(); - } +function testGetNULL() { + var u = new URLSearchParams(); + is(typeof u.get(''), "object", "typeof URL.searchParams.get('')"); + is(u.get(''), null, "URL.searchParams.get('') should be null"); + + var url = new URL('http://www.example.net?a=b'); + is(url.searchParams.get('b'), null, "URL.searchParams.get('b') should be null"); + is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')"); + + runTest(); +} - function testSet() { - var u = new URLSearchParams(); - u.set('a','b'); - u.set('e','c'); - u.set('i','d'); - u.set('o','f'); - u.set('u','g'); +function testSet() { + var u = new URLSearchParams(); + u.set('a','b'); + u.set('e','c'); + u.set('i','d'); + u.set('o','f'); + u.set('u','g'); + + is(u.get('a'), 'b', "URL.searchParams.get('a') should return b"); + is(u.getAll('a').length, 1, "URLSearchParams.getAll('a').length should be 1"); - is(u.get('a'), 'b', "URL.searchParams.get('a') should return b"); - is(u.getAll('a').length, 1, "URLSearchParams.getAll('a').length should be 1"); + u.set('a','h1'); + u.set('a','h2'); + u.set('a','h3'); + u.set('a','h4'); + is(u.get('a'), 'h4', "URL.searchParams.get('a') should return h4"); + is(u.getAll('a').length, 1, "URLSearchParams.getAll('a').length should be 1"); - u.set('a','h1'); - u.set('a','h2'); - u.set('a','h3'); - u.set('a','h4'); - is(u.get('a'), 'h4', "URL.searchParams.get('a') should return h4"); - is(u.getAll('a').length, 1, "URLSearchParams.getAll('a').length should be 1"); + is(u.get('e'), 'c', "URL.searchParams.get('e') should return c"); + is(u.get('i'), 'd', "URL.searchParams.get('i') should return d"); + is(u.get('o'), 'f', "URL.searchParams.get('o') should return f"); + is(u.get('u'), 'g', "URL.searchParams.get('u') should return g"); + + is(u.getAll('e').length, 1, "URLSearchParams.getAll('e').length should be 1"); + is(u.getAll('i').length, 1, "URLSearchParams.getAll('i').length should be 1"); + is(u.getAll('o').length, 1, "URLSearchParams.getAll('o').length should be 1"); + is(u.getAll('u').length, 1, "URLSearchParams.getAll('u').length should be 1"); - is(u.get('e'), 'c', "URL.searchParams.get('e') should return c"); - is(u.get('i'), 'd', "URL.searchParams.get('i') should return d"); - is(u.get('o'), 'f', "URL.searchParams.get('o') should return f"); - is(u.get('u'), 'g', "URL.searchParams.get('u') should return g"); + u = new URLSearchParams("name1=value1&name1=value2&name1=value3"); + is(u.get('name1'), 'value1', "URL.searchParams.get('name1') should return value1"); + is(u.getAll('name1').length, 3, "URLSearchParams.getAll('name1').length should be 3"); + u.set('name1','firstPair'); + is(u.get('name1'), 'firstPair', "URL.searchParams.get('name1') should return firstPair"); + is(u.getAll('name1').length, 1, "URLSearchParams.getAll('name1').length should be 1"); + + runTest(); +} - is(u.getAll('e').length, 1, "URLSearchParams.getAll('e').length should be 1"); - is(u.getAll('i').length, 1, "URLSearchParams.getAll('i').length should be 1"); - is(u.getAll('o').length, 1, "URLSearchParams.getAll('o').length should be 1"); - is(u.getAll('u').length, 1, "URLSearchParams.getAll('u').length should be 1"); +function testIterable() { + var u = new URLSearchParams(); + u.set('1','2'); + u.set('2','4'); + u.set('3','6'); + u.set('4','8'); + u.set('5','10'); - u = new URLSearchParams("name1=value1&name1=value2&name1=value3"); - is(u.get('name1'), 'value1', "URL.searchParams.get('name1') should return value1"); - is(u.getAll('name1').length, 3, "URLSearchParams.getAll('name1').length should be 3"); - u.set('name1','firstPair'); - is(u.get('name1'), 'firstPair', "URL.searchParams.get('name1') should return firstPair"); - is(u.getAll('name1').length, 1, "URLSearchParams.getAll('name1').length should be 1"); - - runTest(); + var key_iter = u.keys(); + var value_iter = u.values(); + var entries_iter = u.entries(); + for (var i = 0; i < 5; ++i) { + var v = i + 1; + var key = key_iter.next(); + var value = value_iter.next(); + var entry = entries_iter.next(); + is(key.value, v.toString(), "Correct Key iterator: " + v.toString()); + ok(!key.done, "Key.done is false"); + is(value.value, (v * 2).toString(), "Correct Value iterator: " + (v * 2).toString()); + ok(!value.done, "Value.done is false"); + is(entry.value[0], v.toString(), "Correct Entry 0 iterator: " + v.toString()); + is(entry.value[1], (v * 2).toString(), "Correct Entry 1 iterator: " + (v * 2).toString()); + ok(!entry.done, "Entry.done is false"); } - function testIterable() { - var u = new URLSearchParams(); - u.set('1','2'); - u.set('2','4'); - u.set('3','6'); - u.set('4','8'); - u.set('5','10'); + var last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); + + last = value_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last value"); + + last = entries_iter.next(); + ok(last.done, "Nothing more to read."); - var key_iter = u.keys(); - var value_iter = u.values(); - var entries_iter = u.entries(); - for (var i = 0; i < 5; ++i) { - var v = i + 1; - var key = key_iter.next(); - var value = value_iter.next(); - var entry = entries_iter.next(); - is(key.value, v.toString(), "Correct Key iterator: " + v.toString()); - ok(!key.done, "Key.done is false"); - is(value.value, (v * 2).toString(), "Correct Value iterator: " + (v * 2).toString()); - ok(!value.done, "Value.done is false"); - is(entry.value[0], v.toString(), "Correct Entry 0 iterator: " + v.toString()); - is(entry.value[1], (v * 2).toString(), "Correct Entry 1 iterator: " + (v * 2).toString()); - ok(!entry.done, "Entry.done is false"); - } + key_iter = u.keys(); + key_iter.next(); + key_iter.next(); + u.delete('1'); + u.delete('2'); + u.delete('3'); + u.delete('4'); + u.delete('5'); - var last = key_iter.next(); - ok(last.done, "Nothing more to read."); - is(last.value, undefined, "Undefined is the last key"); + last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); - last = value_iter.next(); - ok(last.done, "Nothing more to read."); - is(last.value, undefined, "Undefined is the last value"); - - last = entries_iter.next(); - ok(last.done, "Nothing more to read."); + runTest(); +} +function testZeroHandling() { + var u = new URLSearchParams; + u.set("a", "b\0c"); + u.set("d\0e", "f"); + u.set("g\0h", "i\0j"); + is(u.toString(), "a=b%00c&d%00e=f&g%00h=i%00j", + "Should encode U+0000 as %00"); - key_iter = u.keys(); - key_iter.next(); - key_iter.next(); - u.delete('1'); - u.delete('2'); - u.delete('3'); - u.delete('4'); - u.delete('5'); + runTest(); +} - last = key_iter.next(); - ok(last.done, "Nothing more to read."); - is(last.value, undefined, "Undefined is the last key"); +function testCTORs() { + var a = new URLSearchParams("a=b"); + is(a.get("a"), "b", "CTOR with string"); + + var b = new URLSearchParams([['a', 'b'], ['c', 'd']]); + is(b.get("a"), "b", "CTOR with sequence"); + is(b.get("c"), "d", "CTOR with sequence"); - runTest(); - } - function testZeroHandling() { - var u = new URLSearchParams; - u.set("a", "b\0c"); - u.set("d\0e", "f"); - u.set("g\0h", "i\0j"); - is(u.toString(), "a=b%00c&d%00e=f&g%00h=i%00j", - "Should encode U+0000 as %00"); + ok(new URLSearchParams([]), "CTOR with empty sequence"); - runTest(); + let result; + try { + result = new URLSearchParams([[1]]); + } catch(e) { + result = 42; } - function testCTORs() { - var a = new URLSearchParams("a=b"); - is(a.get("a"), "b", "CTOR with string"); + is(result, 42, "CTOR throws if the sequence doesn't contain exactly 2 elements"); - var b = new URLSearchParams([['a', 'b'], ['c', 'd']]); - is(b.get("a"), "b", "CTOR with sequence"); - is(b.get("c"), "d", "CTOR with sequence"); - - ok(new URLSearchParams([]), "CTOR with empty sequence"); + try { + result = new URLSearchParams([[1,2,3]]); + } catch(e) { + result = 43; + } + is(result, 43, "CTOR throws if the sequence doesn't contain exactly 2 elements"); - let result; - try { - result = new URLSearchParams([[1]]); - } catch(e) { - result = 42; - } - - is(result, 42, "CTOR throws if the sequence doesn't contain exactly 2 elements"); + var c = new URLSearchParams({ a: 'b', c: 42, d: null, e: [1,2,3], f: {a:42} }); + is(c.get('a'), 'b', "CTOR with record<>"); + is(c.get('c'), '42', "CTOR with record<>"); + is(c.get('d'), 'null', "CTOR with record<>"); + is(c.get('e'), [1,2,3].toString(), "CTOR with record<>"); + is(c.get('f'), {a:42}.toString(), "CTOR with record<>"); - try { - result = new URLSearchParams([[1,2,3]]); - } catch(e) { - result = 43; - } - is(result, 43, "CTOR throws if the sequence doesn't contain exactly 2 elements"); - - runTest(); - } - + runTest(); +}
--- a/dom/webidl/KeyboardEvent.webidl +++ b/dom/webidl/KeyboardEvent.webidl @@ -22,17 +22,16 @@ interface KeyboardEvent : UIEvent const unsigned long DOM_KEY_LOCATION_RIGHT = 0x02; const unsigned long DOM_KEY_LOCATION_NUMPAD = 0x03; readonly attribute unsigned long location; readonly attribute boolean repeat; readonly attribute boolean isComposing; readonly attribute DOMString key; - [Pref="dom.keyboardevent.code.enabled"] readonly attribute DOMString code; // This returns the initialized dictionary for generating a // same-type keyboard event [Cached, ChromeOnly, Constant] readonly attribute KeyboardEventInit initDict; };
--- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -160,33 +160,31 @@ CreateVariationDictionaryOrNull(CGFontRe } gfxMacFont::gfxMacFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyle, bool aNeedsBold) : gfxFont(aFontEntry, aFontStyle), mCGFont(nullptr), mCTFont(nullptr), mFontFace(nullptr), - mVariationFont(false) + mVariationFont(aFontEntry->HasVariations()) { mApplySyntheticBold = aNeedsBold; - auto varCount = aFontStyle->variationSettings.Length(); - if (varCount > 0) { + if (mVariationFont && aFontStyle->variationSettings.Length() > 0) { CGFontRef baseFont = aFontEntry->GetFontRef(); if (!baseFont) { mIsValid = false; return; } CFDictionaryRef variations = CreateVariationDictionaryOrNull(baseFont, aFontStyle->variationSettings); if (variations) { mCGFont = ::CGFontCreateCopyWithVariations(baseFont, variations); ::CFRelease(variations); - mVariationFont = true; } else { ::CFRetain(baseFont); mCGFont = baseFont; } } else { mCGFont = aFontEntry->GetFontRef(); if (!mCGFont) { mIsValid = false;
--- a/gfx/thebes/gfxMacFont.h +++ b/gfx/thebes/gfxMacFont.h @@ -101,12 +101,12 @@ protected: cairo_font_face_t *mFontFace; mozilla::UniquePtr<gfxFontShaper> mCoreTextShaper; Metrics mMetrics; uint32_t mSpaceGlyph; - bool mVariationFont; // true if variations are in effect + bool mVariationFont; // true if font has OpenType variations }; #endif /* GFX_MACFONT_H */
--- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -49,16 +49,17 @@ public: void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const override; nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override; bool RequiresAATLayout() const { return mRequiresAAT; } + bool HasVariations(); bool IsCFF(); protected: gfxFont* CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) override; bool HasFontTable(uint32_t aTableTag) override; @@ -67,16 +68,18 @@ protected: CGFontRef mFontRef; // owning reference to the CGFont, released on destruction double mSizeHint; bool mFontRefInitialized; bool mRequiresAAT; bool mIsCFF; bool mIsCFFInitialized; + bool mHasVariations; + bool mHasVariationsInitialized; nsTHashtable<nsUint32HashKey> mAvailableTables; }; class gfxMacPlatformFontList : public gfxPlatformFontList { public: static gfxMacPlatformFontList* PlatformFontList() { return static_cast<gfxMacPlatformFontList*>(sPlatformFontList); }
--- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -243,16 +243,27 @@ MacOSFontEntry::ReadCMAP(FontInfoData *a gfxFont* MacOSFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) { return new gfxMacFont(this, aFontStyle, aNeedsBold); } bool +MacOSFontEntry::HasVariations() +{ + if (!mHasVariationsInitialized) { + mHasVariationsInitialized = true; + mHasVariations = HasFontTable(TRUETYPE_TAG('f','v','a','r')); + } + + return mHasVariations; +} + +bool MacOSFontEntry::IsCFF() { if (!mIsCFFInitialized) { mIsCFFInitialized = true; mIsCFF = HasFontTable(TRUETYPE_TAG('C','F','F',' ')); } return mIsCFF; @@ -263,34 +274,38 @@ MacOSFontEntry::MacOSFontEntry(const nsA bool aIsStandardFace, double aSizeHint) : gfxFontEntry(aPostscriptName, aIsStandardFace), mFontRef(NULL), mSizeHint(aSizeHint), mFontRefInitialized(false), mRequiresAAT(false), mIsCFF(false), - mIsCFFInitialized(false) + mIsCFFInitialized(false), + mHasVariations(false), + mHasVariationsInitialized(false) { mWeight = aWeight; } MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, CGFontRef aFontRef, uint16_t aWeight, uint16_t aStretch, uint8_t aStyle, bool aIsDataUserFont, bool aIsLocalUserFont) : gfxFontEntry(aPostscriptName, false), mFontRef(NULL), mSizeHint(0.0), mFontRefInitialized(false), mRequiresAAT(false), mIsCFF(false), - mIsCFFInitialized(false) + mIsCFFInitialized(false), + mHasVariations(false), + mHasVariationsInitialized(false) { mFontRef = aFontRef; mFontRefInitialized = true; ::CFRetain(mFontRef); mWeight = aWeight; mStretch = aStretch; mFixedPitch = false; // xxx - do we need this for downloaded fonts?
--- a/ipc/app/Makefile.in +++ b/ipc/app/Makefile.in @@ -20,17 +20,21 @@ include $(topsrcdir)/config/rules.mk ifneq ($(MOZ_WIDGET_TOOLKIT),android) #LIBS += ../contentproc/$(LIB_PREFIX)plugin-container.$(LIB_SUFFIX) endif ifeq ($(OS_ARCH),WINNT) #{ # Note the manifest file exists in the tree, so we use the explicit filename # here. -EXTRA_DEPS += plugin-container.exe.manifest +ifdef HAVE_64BIT_BUILD +EXTRA_DEPS += plugin-container.exe.64.manifest +else +EXTRA_DEPS += plugin-container.exe.32.manifest +endif endif #} ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{ libs:: $(NSINSTALL) -D $(DIST)/bin/$(PROGRAM).app rsync -a -C --exclude '*.in' $(srcdir)/macbuild/Contents $(DIST)/bin/$(MOZ_CHILD_PROCESS_NAME).app sed -e 's/%PROGRAM%/$(MOZ_CHILD_PROCESS_NAME)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/bin/$(MOZ_CHILD_PROCESS_NAME).app/Contents/Info.plist
--- a/ipc/app/moz.build +++ b/ipc/app/moz.build @@ -48,16 +48,18 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'winmm.dll', 'user32.dll', ] DELAYLOAD_DLLS += [ 'xul.dll', ] + RCINCLUDE = 'plugin-container.rc' + if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin': # For sandbox includes and the include dependencies those have LOCAL_INCLUDES += [ '/security/sandbox/chromium', '/security/sandbox/chromium-shim', ] USE_LIBS += [ 'mozsandbox',
rename from ipc/app/plugin-container.exe.manifest rename to ipc/app/plugin-container.exe.32.manifest --- a/ipc/app/plugin-container.exe.manifest +++ b/ipc/app/plugin-container.exe.32.manifest @@ -14,16 +14,22 @@ name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> +<comInterfaceExternalProxyStub + iid="{618736E0-3C3D-11CF-810C-00AA00389B71}" + proxyStubClsid32="{00020424-0000-0000-C000-000000000046}" + name="IAccessible" + tlbid="{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}" +/> <ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3"> <ms_asmv3:security> <ms_asmv3:requestedPrivileges> <ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" /> </ms_asmv3:requestedPrivileges> </ms_asmv3:security> </ms_asmv3:trustInfo> <ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
new file mode 100644 --- /dev/null +++ b/ipc/app/plugin-container.rc @@ -0,0 +1,14 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 <windows.h> +#include "mozilla-config.h" + +#if defined(HAVE_64BIT_BUILD) +1 RT_MANIFEST "plugin-container.exe.64.manifest" +#else +1 RT_MANIFEST "plugin-container.exe.32.manifest" +#endif
new file mode 100644 --- /dev/null +++ b/layout/reftests/text/1349308-1.html @@ -0,0 +1,2 @@ +<!-- bold font should *not* have the same glyph widths as regular face --> +<span style="font:36px -apple-system;font-weight:bold;padding:2px;background:black">abcdefghijklmnopqrstuvwxyz
new file mode 100644 --- /dev/null +++ b/layout/reftests/text/1349308-notref.html @@ -0,0 +1,1 @@ +<span style="font:36px -apple-system;font-weight:normal;padding:2px;background:black">abcdefghijklmnopqrstuvwxyz
--- a/layout/reftests/text/reftest.list +++ b/layout/reftests/text/reftest.list @@ -182,16 +182,17 @@ HTTP(..) != fallback-mark-stacking-1.htm == 726392-2.html 726392-2-ref.html == 726392-3.html 726392-3-ref.html == 745555-1.html 745555-1-ref.html == 745555-2.html 745555-2-ref.html == 820255.html 820255-ref.html HTTP(..) != 1170688.html 1170688-ref.html fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1320665-cmap-format-13.html 1320665-cmap-format-13-ref.html # see bug 1320665 comments 8-9 HTTP(..) == 1331339-script-extensions-shaping-1.html 1331339-script-extensions-shaping-1-ref.html +skip-if(!cocoaWidget) != 1349308-1.html 1349308-notref.html # macOS-specific test for -apple-system glyph metrics # ensure emoji chars don't render blank (bug 715798, bug 779042); # should at least render hexboxes if there's no font support != emoji-01.html emoji-01-notref.html != emoji-02.html emoji-02-notref.html # Bug 727276: tests with variation selectors 15 and 16 to control emoji rendering style == emoji-03.html emoji-03-ref.html
--- a/layout/xul/nsXULPopupManager.cpp +++ b/layout/xul/nsXULPopupManager.cpp @@ -395,30 +395,33 @@ nsXULPopupManager::GetSubmenuWidgetChain // this method is used by the widget code to determine the list of popups // that are open. If a mouse click occurs outside one of these popups, the // panels will roll up. If the click is inside a popup, they will not roll up uint32_t count = 0, sameTypeCount = 0; NS_ASSERTION(aWidgetChain, "null parameter"); nsMenuChainItem* item = GetTopVisibleMenu(); while (item) { - nsCOMPtr<nsIWidget> widget = item->Frame()->GetWidget(); - NS_ASSERTION(widget, "open popup has no widget"); - aWidgetChain->AppendElement(widget.get()); - // In the case when a menulist inside a panel is open, clicking in the - // panel should still roll up the menu, so if a different type is found, - // stop scanning. nsMenuChainItem* parent = item->GetParent(); - if (!sameTypeCount) { - count++; - if (!parent || item->Frame()->PopupType() != parent->Frame()->PopupType() || - item->IsContextMenu() != parent->IsContextMenu()) { - sameTypeCount = count; + if (!item->IsNoAutoHide()) { + nsCOMPtr<nsIWidget> widget = item->Frame()->GetWidget(); + NS_ASSERTION(widget, "open popup has no widget"); + aWidgetChain->AppendElement(widget.get()); + // In the case when a menulist inside a panel is open, clicking in the + // panel should still roll up the menu, so if a different type is found, + // stop scanning. + if (!sameTypeCount) { + count++; + if (!parent || item->Frame()->PopupType() != parent->Frame()->PopupType() || + item->IsContextMenu() != parent->IsContextMenu()) { + sameTypeCount = count; + } } } + item = parent; } return sameTypeCount; } nsIWidget* nsXULPopupManager::GetRollupWidget() @@ -1043,17 +1046,23 @@ nsXULPopupManager::HidePopup(nsIContent* deselectMenu = aDeselectMenu; popupToHide = topMenu->Content(); popupFrame = topMenu->Frame(); // Close up another popup if there is one, and we are either hiding the // entire chain or the item to hide isn't the topmost popup. nsMenuChainItem* parent = topMenu->GetParent(); if (parent && (aHideChain || topMenu != foundPopup)) { - nextPopup = parent->Content(); + while (parent && parent->IsNoAutoHide()) { + parent = parent->GetParent(); + } + + if (parent) { + nextPopup = parent->Content(); + } } lastPopup = aLastPopup ? aLastPopup : (aHideChain ? nullptr : aPopup); } } else if (popupFrame->PopupState() == ePopupPositioning) { // When the popup is in the popuppositioning state, it will not be in the // mPopups list. We need another way to find it and make sure it does not // continue the popup showing process.
--- a/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java +++ b/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java @@ -44,21 +44,28 @@ import org.mozilla.gecko.util.GeckoBundl public class WebAppActivity extends GeckoApp { public static final String INTENT_KEY = "IS_A_WEBAPP"; public static final String MANIFEST_PATH = "MANIFEST_PATH"; private static final String LOGTAG = "WebAppActivity"; private TextView mUrlView; + private String mManifestPath; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - loadManifest(getIntent()); + + if (savedInstanceState != null) { + mManifestPath = savedInstanceState.getString(WebAppActivity.MANIFEST_PATH, null); + } else { + mManifestPath = getIntent().getStringExtra(WebAppActivity.MANIFEST_PATH); + } + loadManifest(mManifestPath); final Toolbar toolbar = (Toolbar) findViewById(R.id.actionbar); setSupportActionBar(toolbar); final ProgressBar progressBar = (ProgressBar) findViewById(R.id.page_progress); progressBar.setVisibility(View.GONE); final ActionBar actionBar = getSupportActionBar(); @@ -104,16 +111,23 @@ public class WebAppActivity extends Geck } if (msg == Tabs.TabEvents.LOCATION_CHANGE) { mUrlView.setText(tab.getURL()); } } @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putString(WebAppActivity.MANIFEST_PATH, mManifestPath); + } + + @Override public void onDestroy() { super.onDestroy(); EventDispatcher.getInstance().unregisterUiThreadListener(this, "Website:AppEntered", "Website:AppLeft", null); Tabs.unregisterOnTabsChangedListener(this); } @@ -135,33 +149,32 @@ public class WebAppActivity extends Geck final SafeIntent intent = new SafeIntent(externalIntent); final String launchUrl = intent.getDataString(); final String currentUrl = Tabs.getInstance().getSelectedTab().getURL(); final boolean isSameDomain = Uri.parse(currentUrl).getHost() .equals(Uri.parse(launchUrl).getHost()); if (!isSameDomain) { - loadManifest(externalIntent); + mManifestPath = externalIntent.getStringExtra(WebAppActivity.MANIFEST_PATH); + loadManifest(mManifestPath); Tabs.getInstance().loadUrl(launchUrl); } } - private void loadManifest(Intent intent) { - String manifestPath = intent.getStringExtra(WebAppActivity.MANIFEST_PATH); - if (manifestPath != null) { - updateFromManifest(manifestPath); + private void loadManifest(String manifestPath) { + if (manifestPath == null) { + Log.e(LOGTAG, "Missing manifest"); + return; } - } - private void updateFromManifest(String manifestPath) { try { final File manifestFile = new File(manifestPath); final JSONObject manifest = FileUtils.readJSONObjectFromFile(manifestFile); - final JSONObject manifestField = (JSONObject) manifest.get("manifest"); + final JSONObject manifestField = manifest.getJSONObject("manifest"); final Integer color = readColorFromManifest(manifestField); final String name = readNameFromManifest(manifestField); final Bitmap icon = readIconFromManifest(manifest); final ActivityManager.TaskDescription taskDescription = (color == null) ? new ActivityManager.TaskDescription(name, icon) : new ActivityManager.TaskDescription(name, icon, color); updateStatusBarColor(color); @@ -175,37 +188,37 @@ public class WebAppActivity extends Geck private void updateStatusBarColor(final Integer themeColor) { if (themeColor != null && !AppConstants.Versions.preLollipop) { final Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(ColorUtil.darken(themeColor, 0.25)); } } - private Integer readColorFromManifest(JSONObject manifest) throws JSONException { - final String colorStr = (String) manifest.get("theme_color"); + private Integer readColorFromManifest(JSONObject manifest) { + final String colorStr = manifest.optString("theme_color", null); if (colorStr != null) { return ColorUtil.parseStringColor(colorStr); } return null; } - private String readNameFromManifest(JSONObject manifest) throws JSONException { - String name = (String) manifest.get("name"); + private String readNameFromManifest(JSONObject manifest) { + String name = manifest.optString("name", null); if (name == null) { - name = (String) manifest.get("short_name"); + name = manifest.optString("short_name", null); } if (name == null) { - name = (String) manifest.get("start_url"); + name = manifest.optString("start_url", null); } return name; } - private Bitmap readIconFromManifest(JSONObject manifest) throws JSONException { - final String iconStr = (String) manifest.get("cached_icon"); + private Bitmap readIconFromManifest(JSONObject manifest) { + final String iconStr = manifest.optString("cached_icon", null); if (iconStr != null) { return FaviconDecoder .decodeDataURI(getContext(), iconStr) .getBestBitmap(GeckoAppShell.getPreferredIconSize()); } return null; } }
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -193,19 +193,16 @@ pref("dom.gamepad.enabled", true); pref("dom.gamepad.test.enabled", false); #ifdef RELEASE_OR_BETA pref("dom.gamepad.non_standard_events.enabled", false); #else pref("dom.gamepad.non_standard_events.enabled", true); #endif pref("dom.gamepad.extensions.enabled", false); -// Whether the KeyboardEvent.code is enabled -pref("dom.keyboardevent.code.enabled", true); - // If this is true, TextEventDispatcher dispatches keydown and keyup events // even during composition (keypress events are never fired during composition // even if this is true). pref("dom.keyboardevent.dispatch_during_composition", false); // Whether to run add-on code in different compartments from browser code. This // causes a separate compartment for each (addon, global) combination, which may // significantly increase the number of compartments in the system. @@ -3076,16 +3073,19 @@ pref("dom.ipc.plugins.forcedirect.enable #endif #ifdef NIGHTLY_BUILD pref("dom.ipc.processCount", 4); #else pref("dom.ipc.processCount", 1); #endif +// Default to allow only one file:// URL content process. +pref("dom.ipc.processCount.file", 1); + // WebExtensions only support a single extension process. pref("dom.ipc.processCount.extension", 1); // Disable support for SVG pref("svg.disabled", false); // Override default dom.ipc.processCount for some remote content process types. pref("dom.ipc.processCount.webLargeAllocation", 10);
--- a/parser/html/nsHtml5AtomTable.cpp +++ b/parser/html/nsHtml5AtomTable.cpp @@ -19,16 +19,17 @@ nsHtml5AtomEntry::nsHtml5AtomEntry(const NS_NOTREACHED("nsHtml5AtomTable is broken and tried to copy an entry"); } nsHtml5AtomEntry::~nsHtml5AtomEntry() { } nsHtml5AtomTable::nsHtml5AtomTable() + : mRecentlyUsedParserAtoms{} { #ifdef DEBUG NS_GetMainThread(getter_AddRefs(mPermittedLookupThread)); #endif } nsHtml5AtomTable::~nsHtml5AtomTable() { @@ -39,18 +40,28 @@ nsHtml5AtomTable::GetAtom(const nsAStrin { #ifdef DEBUG { nsCOMPtr<nsIThread> currentThread; NS_GetCurrentThread(getter_AddRefs(currentThread)); NS_ASSERTION(mPermittedLookupThread == currentThread, "Wrong thread!"); } #endif + + uint32_t index = mozilla::HashString(aKey) % RECENTLY_USED_PARSER_ATOMS_SIZE; + nsIAtom* cachedAtom = mRecentlyUsedParserAtoms[index]; + if (cachedAtom && cachedAtom->Equals(aKey)) { + return cachedAtom; + } + nsIAtom* atom = NS_GetStaticAtom(aKey); if (atom) { + mRecentlyUsedParserAtoms[index] = atom; return atom; } nsHtml5AtomEntry* entry = mTable.PutEntry(aKey); if (!entry) { return nullptr; } + + mRecentlyUsedParserAtoms[index] = entry->GetAtom(); return entry->GetAtom(); }
--- a/parser/html/nsHtml5AtomTable.h +++ b/parser/html/nsHtml5AtomTable.h @@ -6,16 +6,18 @@ #define nsHtml5AtomTable_h #include "nsHashKeys.h" #include "nsTHashtable.h" #include "nsAutoPtr.h" #include "nsIAtom.h" #include "nsIThread.h" +#define RECENTLY_USED_PARSER_ATOMS_SIZE 31 + class nsHtml5Atom; class nsHtml5AtomEntry : public nsStringHashKey { public: explicit nsHtml5AtomEntry(KeyTypePointer aStr); nsHtml5AtomEntry(const nsHtml5AtomEntry& aOther); ~nsHtml5AtomEntry(); @@ -82,26 +84,30 @@ class nsHtml5AtomTable */ nsIAtom* GetAtom(const nsAString& aKey); /** * Empties the table. */ void Clear() { + for (uint32_t i = 0; i < RECENTLY_USED_PARSER_ATOMS_SIZE; ++i) { + mRecentlyUsedParserAtoms[i] = nullptr; + } mTable.Clear(); } #ifdef DEBUG void SetPermittedLookupThread(nsIThread* aThread) { mPermittedLookupThread = aThread; } #endif private: nsTHashtable<nsHtml5AtomEntry> mTable; + nsIAtom* mRecentlyUsedParserAtoms[RECENTLY_USED_PARSER_ATOMS_SIZE]; #ifdef DEBUG nsCOMPtr<nsIThread> mPermittedLookupThread; #endif }; #endif // nsHtml5AtomTable_h
--- a/testing/mozharness/scripts/release/publish_balrog.py +++ b/testing/mozharness/scripts/release/publish_balrog.py @@ -48,17 +48,17 @@ class PublishBalrog(MercurialScript, Bui # taskcluster properties self.read_buildbot_config() if not self.buildbot_config: self.warning("Skipping buildbot properties overrides") return # TODO: version and appVersion should come from repo props = self.buildbot_config["properties"] for prop in ['product', 'version', 'build_number', 'channels', - 'balrog_api_root']: + 'balrog_api_root', 'schedule_at', 'background_rate']: if props.get(prop): self.info("Overriding %s with %s" % (prop, props[prop])) self.config[prop] = props.get(prop) def query_abs_dirs(self): if self.abs_dirs: return self.abs_dirs self.abs_dirs = super(PublishBalrog, self).query_abs_dirs() @@ -102,14 +102,18 @@ class PublishBalrog(MercurialScript, Bui "--username", self.config["balrog_username"], "--version", self.config["version"], "--product", self.config["product"], "--build-number", str(self.config["build_number"]), "--verbose", ]) for r in channel_config["publish_rules"]: cmd.extend(["--rules", r]) + if self.config.get("schedule_at"): + cmd.extend(["--schedule-at", self.config["schedule_at"]]) + if self.config.get("background_rate"): + cmd.extend(["--background-rate", str(self.config["background_rate"])]) self.retry(lambda: self.run_command(cmd, halt_on_failure=True)) # __main__ {{{1 if __name__ == '__main__': PublishBalrog().run_and_exit()