Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2017-04-03 14:50:18 -07:00
commit 53dde6a1d2
63 changed files with 700 additions and 563 deletions

View file

@ -58,7 +58,6 @@ browser/branding/**/firefox-branding.js
browser/base/content/test/general/file_csp_block_all_mixedcontent.html 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/test/urlbar/file_blank_but_not_blank.html
browser/base/content/newtab/** browser/base/content/newtab/**
browser/components/downloads/**
# Test files that are really json not js, and don't need to be linted. # 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_valid.js
browser/components/sessionstore/test/unit/data/sessionstore_invalid.js browser/components/sessionstore/test/unit/data/sessionstore_invalid.js

View file

@ -37,7 +37,11 @@ ifeq ($(OS_ARCH),WINNT)
# (this dependency should really be just for firefox.exe, not other targets) # (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 # Note the manifest file exists in the tree, so we use the explicit filename
# here. # 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 endif
PROGRAMS_DEST = $(DIST)/bin PROGRAMS_DEST = $(DIST)/bin

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="Firefox"
type="win32"
/>
<description>Firefox</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
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">
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
</ms_asmv3:windowsSettings>
</ms_asmv3:application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
</assembly>

View file

@ -4,9 +4,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <windows.h> #include <windows.h>
#include "mozilla-config.h"
#include "nsNativeAppSupportWin.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_APPICON ICON FIREFOX_ICO
IDI_DOCUMENT ICON DOCUMENT_ICO IDI_DOCUMENT ICON DOCUMENT_ICO

View file

@ -1340,6 +1340,7 @@ var gBrowserInit = {
// [5]: referrerPolicy (int) // [5]: referrerPolicy (int)
// [6]: userContextId (int) // [6]: userContextId (int)
// [7]: originPrincipal (nsIPrincipal) // [7]: originPrincipal (nsIPrincipal)
// [8]: triggeringPrincipal (nsIPrincipal)
let referrerURI = window.arguments[2]; let referrerURI = window.arguments[2];
if (typeof(referrerURI) == "string") { if (typeof(referrerURI) == "string") {
try { try {
@ -1356,7 +1357,7 @@ var gBrowserInit = {
window.arguments[4] || false, referrerPolicy, userContextId, window.arguments[4] || false, referrerPolicy, userContextId,
// pass the origin principal (if any) and force its use to create // pass the origin principal (if any) and force its use to create
// an initial about:blank viewer if present: // an initial about:blank viewer if present:
window.arguments[7], !!window.arguments[7]); window.arguments[7], !!window.arguments[7], window.arguments[8]);
window.focus(); window.focus();
} else { } else {
// Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3. // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
@ -2248,7 +2249,8 @@ function BrowserTryToCloseWindow() {
} }
function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy, function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
userContextId, originPrincipal, forceAboutBlankViewerInCurrent) { userContextId, originPrincipal, forceAboutBlankViewerInCurrent,
triggeringPrincipal) {
try { try {
openLinkIn(uri, "current", openLinkIn(uri, "current",
{ referrerURI: referrer, { referrerURI: referrer,
@ -2257,6 +2259,7 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
allowThirdPartyFixup, allowThirdPartyFixup,
userContextId, userContextId,
originPrincipal, originPrincipal,
triggeringPrincipal,
forceAboutBlankViewerInCurrent, forceAboutBlankViewerInCurrent,
}); });
} catch (e) {} } catch (e) {}
@ -5782,6 +5785,7 @@ function handleLinkClick(event, href, linkNode) {
referrerPolicy, referrerPolicy,
noReferrer: BrowserUtils.linkHasNoReferrer(linkNode), noReferrer: BrowserUtils.linkHasNoReferrer(linkNode),
originPrincipal: doc.nodePrincipal, originPrincipal: doc.nodePrincipal,
triggeringPrincipal: doc.nodePrincipal,
frameOuterWindowID, frameOuterWindowID,
}; };

View file

@ -578,6 +578,7 @@ var ClickEventHandler = {
} catch (e) {} } catch (e) {}
} }
json.originPrincipal = ownerDoc.nodePrincipal; json.originPrincipal = ownerDoc.nodePrincipal;
json.triggeringPrincipal = ownerDoc.nodePrincipal;
sendAsyncMessage("Content:Click", json); sendAsyncMessage("Content:Click", json);
return; return;

View file

@ -985,6 +985,7 @@ nsContextMenu.prototype = {
_openLinkInParameters(extra) { _openLinkInParameters(extra) {
let params = { charset: gContextMenuContentData.charSet, let params = { charset: gContextMenuContentData.charSet,
originPrincipal: this.principal, originPrincipal: this.principal,
triggeringPrincipal: this.principal,
referrerURI: gContextMenuContentData.documentURIObject, referrerURI: gContextMenuContentData.documentURIObject,
referrerPolicy: gContextMenuContentData.referrerPolicy, referrerPolicy: gContextMenuContentData.referrerPolicy,
frameOuterWindowID: gContextMenuContentData.frameOuterWindowID, frameOuterWindowID: gContextMenuContentData.frameOuterWindowID,
@ -1174,7 +1175,7 @@ nsContextMenu.prototype = {
this._canvasToBlobURL(this.target).then(function(blobURL) { this._canvasToBlobURL(this.target).then(function(blobURL) {
openUILink(blobURL, e, { disallowInheritPrincipal: true, openUILink(blobURL, e, { disallowInheritPrincipal: true,
referrerURI, referrerURI,
originPrincipal: systemPrincipal}); triggeringPrincipal: systemPrincipal});
}, Cu.reportError); }, Cu.reportError);
} else { } else {
urlSecurityCheck(this.mediaURL, urlSecurityCheck(this.mediaURL,

View file

@ -220,6 +220,7 @@ function openLinkIn(url, where, params) {
var aUserContextId = params.userContextId; var aUserContextId = params.userContextId;
var aIndicateErrorPageLoad = params.indicateErrorPageLoad; var aIndicateErrorPageLoad = params.indicateErrorPageLoad;
var aPrincipal = params.originPrincipal; var aPrincipal = params.originPrincipal;
var aTriggeringPrincipal = params.triggeringPrincipal;
var aForceAboutBlankViewerInCurrent = var aForceAboutBlankViewerInCurrent =
params.forceAboutBlankViewerInCurrent; params.forceAboutBlankViewerInCurrent;
@ -260,13 +261,18 @@ function openLinkIn(url, where, params) {
// Please note we do not have to do that for SystemPrincipals and we // Please note we do not have to do that for SystemPrincipals and we
// can not do it for NullPrincipals since NullPrincipals are only // can not do it for NullPrincipals since NullPrincipals are only
// identical if they actually are the same object (See Bug: 1346759) // identical if they actually are the same object (See Bug: 1346759)
if (aPrincipal && aPrincipal.isCodebasePrincipal) { function useOAForPrincipal(principal) {
if (principal && principal.isCodebasePrincipal) {
let attrs = { let attrs = {
userContextId: aUserContextId, userContextId: aUserContextId,
privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)), privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)),
}; };
aPrincipal = Services.scriptSecurityManager.createCodebasePrincipal(aPrincipal.URI, attrs); return Services.scriptSecurityManager.createCodebasePrincipal(principal.URI, attrs);
} }
return principal;
}
aPrincipal = useOAForPrincipal(aPrincipal);
aTriggeringPrincipal = useOAForPrincipal(aTriggeringPrincipal);
if (!w || where == "window") { if (!w || where == "window") {
// This propagates to window.arguments. // This propagates to window.arguments.
@ -311,6 +317,7 @@ function openLinkIn(url, where, params) {
sa.appendElement(referrerPolicySupports, /* weak =*/ false); sa.appendElement(referrerPolicySupports, /* weak =*/ false);
sa.appendElement(userContextIdSupports, /* weak =*/ false); sa.appendElement(userContextIdSupports, /* weak =*/ false);
sa.appendElement(aPrincipal, /* weak =*/ false); sa.appendElement(aPrincipal, /* weak =*/ false);
sa.appendElement(aTriggeringPrincipal, /* weak =*/ false);
let features = "chrome,dialog=no,all"; let features = "chrome,dialog=no,all";
if (aIsPrivate) { if (aIsPrivate) {
@ -414,7 +421,7 @@ function openLinkIn(url, where, params) {
} }
targetBrowser.loadURIWithFlags(url, { targetBrowser.loadURIWithFlags(url, {
triggeringPrincipal: aPrincipal, triggeringPrincipal: aTriggeringPrincipal,
flags, flags,
referrerURI: aNoReferrer ? null : aReferrerURI, referrerURI: aNoReferrer ? null : aReferrerURI,
referrerPolicy: aReferrerPolicy, referrerPolicy: aReferrerPolicy,
@ -439,7 +446,7 @@ function openLinkIn(url, where, params) {
noReferrer: aNoReferrer, noReferrer: aNoReferrer,
userContextId: aUserContextId, userContextId: aUserContextId,
originPrincipal: aPrincipal, originPrincipal: aPrincipal,
triggeringPrincipal: aPrincipal, triggeringPrincipal: aTriggeringPrincipal,
}); });
targetBrowser = tabUsedForLoad.linkedBrowser; targetBrowser = tabUsedForLoad.linkedBrowser;

View file

@ -30,8 +30,7 @@ this.EXPORTED_SYMBOLS = [
* the registered download status indicators. * the registered download status indicators.
*/ */
//////////////////////////////////////////////////////////////////////////////// // Globals
//// Globals
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
@ -111,7 +110,7 @@ var PrefObserver = {
observe(aSubject, aTopic, aData) { observe(aSubject, aTopic, aData) {
if (this.prefs.hasOwnProperty(aData)) { if (this.prefs.hasOwnProperty(aData)) {
delete this[aData]; delete this[aData];
return this[aData] = this.getPref(aData); this[aData] = this.getPref(aData);
} }
}, },
register(prefs) { register(prefs) {
@ -119,7 +118,7 @@ var PrefObserver = {
kPrefBranch.addObserver("", this, true); kPrefBranch.addObserver("", this, true);
for (let key in prefs) { for (let key in prefs) {
let name = key; let name = key;
XPCOMUtils.defineLazyGetter(this, name, function () { XPCOMUtils.defineLazyGetter(this, name, function() {
return PrefObserver.getPref(name); return PrefObserver.getPref(name);
}); });
} }
@ -133,8 +132,7 @@ PrefObserver.register({
}); });
//////////////////////////////////////////////////////////////////////////////// // DownloadsCommon
//// DownloadsCommon
/** /**
* This object is exposed directly to the consumers of this JavaScript module, * This object is exposed directly to the consumers of this JavaScript module,
@ -166,14 +164,14 @@ this.DownloadsCommon = {
let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
let stringName = string.key; let stringName = string.key;
if (stringName in kDownloadsStringsRequiringFormatting) { if (stringName in kDownloadsStringsRequiringFormatting) {
strings[stringName] = function () { strings[stringName] = function() {
// Convert "arguments" to a real array before calling into XPCOM. // Convert "arguments" to a real array before calling into XPCOM.
return sb.formatStringFromName(stringName, return sb.formatStringFromName(stringName,
Array.slice(arguments, 0), Array.slice(arguments, 0),
arguments.length); arguments.length);
}; };
} else if (stringName in kDownloadsStringsRequiringPluralForm) { } else if (stringName in kDownloadsStringsRequiringPluralForm) {
strings[stringName] = function (aCount) { strings[stringName] = function(aCount) {
// Convert "arguments" to a real array before calling into XPCOM. // Convert "arguments" to a real array before calling into XPCOM.
let formattedString = sb.formatStringFromName(stringName, let formattedString = sb.formatStringFromName(stringName,
Array.slice(arguments, 0), Array.slice(arguments, 0),
@ -243,9 +241,8 @@ this.DownloadsCommon = {
getData(aWindow) { getData(aWindow) {
if (PrivateBrowsingUtils.isContentWindowPrivate(aWindow)) { if (PrivateBrowsingUtils.isContentWindowPrivate(aWindow)) {
return PrivateDownloadsData; return PrivateDownloadsData;
} else {
return DownloadsData;
} }
return DownloadsData;
}, },
/** /**
@ -265,9 +262,8 @@ this.DownloadsCommon = {
getIndicatorData(aWindow) { getIndicatorData(aWindow) {
if (PrivateBrowsingUtils.isContentWindowPrivate(aWindow)) { if (PrivateBrowsingUtils.isContentWindowPrivate(aWindow)) {
return PrivateDownloadsIndicatorData; return PrivateDownloadsIndicatorData;
} else {
return DownloadsIndicatorData;
} }
return DownloadsIndicatorData;
}, },
/** /**
@ -286,12 +282,11 @@ this.DownloadsCommon = {
return this._privateSummary; return this._privateSummary;
} }
return this._privateSummary = new DownloadsSummaryData(true, aNumToExclude); return this._privateSummary = new DownloadsSummaryData(true, aNumToExclude);
} else { }
if (this._summary) { if (this._summary) {
return this._summary; return this._summary;
} }
return this._summary = new DownloadsSummaryData(false, aNumToExclude); return this._summary = new DownloadsSummaryData(false, aNumToExclude);
}
}, },
_summary: null, _summary: null,
_privateSummary: null, _privateSummary: null,
@ -666,7 +661,7 @@ XPCOMUtils.defineLazyGetter(this.DownloadsCommon, "error", () => {
/** /**
* Returns true if we are executing on Windows Vista or a later version. * 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; let os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
if (os != "WINNT") { if (os != "WINNT") {
return false; return false;
@ -675,8 +670,7 @@ XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () {
return parseFloat(sysInfo.getProperty("version")) >= 6; return parseFloat(sysInfo.getProperty("version")) >= 6;
}); });
//////////////////////////////////////////////////////////////////////////////// // DownloadsData
//// DownloadsData
/** /**
* Retrieves the list of past and completed downloads from the underlying * Retrieves the list of past and completed downloads from the underlying
@ -756,8 +750,7 @@ DownloadsDataCtor.prototype = {
indicatorData.attention = DownloadsCommon.ATTENTION_NONE; indicatorData.attention = DownloadsCommon.ATTENTION_NONE;
}, },
////////////////////////////////////////////////////////////////////////////// // Integration with the asynchronous Downloads back-end
//// Integration with the asynchronous Downloads back-end
onDownloadAdded(download) { onDownloadAdded(download) {
// Download objects do not store the end time of downloads, as the Downloads // Download objects do not store the end time of downloads, as the Downloads
@ -847,8 +840,7 @@ DownloadsDataCtor.prototype = {
} }
}, },
////////////////////////////////////////////////////////////////////////////// // Registration of views
//// Registration of views
/** /**
* Adds an object to be notified when the available download data changes. * Adds an object to be notified when the available download data changes.
@ -896,8 +888,7 @@ DownloadsDataCtor.prototype = {
aView.onDataLoadCompleted(); 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 * Set to true after the first download causes the downloads panel to be
@ -952,16 +943,14 @@ XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() {
return new DownloadsDataCtor(false); return new DownloadsDataCtor(false);
}); });
//////////////////////////////////////////////////////////////////////////////// // DownloadsViewPrototype
//// DownloadsViewPrototype
/** /**
* A prototype for an object that registers itself with DownloadsData as soon * A prototype for an object that registers itself with DownloadsData as soon
* as a view is registered with it. * as a view is registered with it.
*/ */
const DownloadsViewPrototype = { const DownloadsViewPrototype = {
////////////////////////////////////////////////////////////////////////////// // Registration of views
//// Registration of views
/** /**
* Array of view objects that should be notified when the available status * Array of view objects that should be notified when the available status
@ -1036,8 +1025,7 @@ const DownloadsViewPrototype = {
} }
}, },
////////////////////////////////////////////////////////////////////////////// // Callback functions from DownloadsData
//// Callback functions from DownloadsData
/** /**
* Indicates whether we are still loading downloads data asynchronously. * Indicates whether we are still loading downloads data asynchronously.
@ -1136,8 +1124,7 @@ const DownloadsViewPrototype = {
}, },
}; };
//////////////////////////////////////////////////////////////////////////////// // DownloadsIndicatorData
//// DownloadsIndicatorData
/** /**
* This object registers itself with DownloadsData as a view, and transforms the * This object registers itself with DownloadsData as a view, and transforms the
@ -1170,8 +1157,7 @@ DownloadsIndicatorDataCtor.prototype = {
} }
}, },
////////////////////////////////////////////////////////////////////////////// // Callback functions from DownloadsData
//// Callback functions from DownloadsData
onDataLoadCompleted() { onDataLoadCompleted() {
DownloadsViewPrototype.onDataLoadCompleted.call(this); DownloadsViewPrototype.onDataLoadCompleted.call(this);
@ -1228,8 +1214,7 @@ DownloadsIndicatorDataCtor.prototype = {
this._updateViews(); this._updateViews();
}, },
////////////////////////////////////////////////////////////////////////////// // Propagation of properties to our views
//// Propagation of properties to our views
// The following properties are updated by _refreshProperties and are then // The following properties are updated by _refreshProperties and are then
// propagated to the views. See _refreshProperties for details. // propagated to the views. See _refreshProperties for details.
@ -1288,8 +1273,7 @@ DownloadsIndicatorDataCtor.prototype = {
: this._attention; : 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. * Number of download items that are available to be displayed.
@ -1370,8 +1354,7 @@ XPCOMUtils.defineLazyGetter(this, "DownloadsIndicatorData", function() {
return new DownloadsIndicatorDataCtor(false); return new DownloadsIndicatorDataCtor(false);
}); });
//////////////////////////////////////////////////////////////////////////////// // DownloadsSummaryData
//// DownloadsSummaryData
/** /**
* DownloadsSummaryData is a view for DownloadsData that produces a summary * DownloadsSummaryData is a view for DownloadsData that produces a summary
@ -1439,10 +1422,9 @@ DownloadsSummaryData.prototype = {
} }
}, },
////////////////////////////////////////////////////////////////////////////// // Callback functions from DownloadsData - see the documentation in
//// Callback functions from DownloadsData - see the documentation in // DownloadsViewPrototype for more information on what these functions
//// DownloadsViewPrototype for more information on what these functions // are used for.
//// are used for.
onDataLoadCompleted() { onDataLoadCompleted() {
DownloadsViewPrototype.onDataLoadCompleted.call(this); DownloadsViewPrototype.onDataLoadCompleted.call(this);
@ -1475,8 +1457,7 @@ DownloadsSummaryData.prototype = {
this._updateViews(); this._updateViews();
}, },
////////////////////////////////////////////////////////////////////////////// // Propagation of properties to our views
//// Propagation of properties to our views
/** /**
* Computes aggregate values and propagates the changes to our views. * Computes aggregate values and propagates the changes to our views.
@ -1504,8 +1485,7 @@ DownloadsSummaryData.prototype = {
aView.details = this._details; 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 * A generator function for the Download objects this summary is currently

View file

@ -14,8 +14,7 @@ this.EXPORTED_SYMBOLS = [
"DownloadsTaskbar", "DownloadsTaskbar",
]; ];
//////////////////////////////////////////////////////////////////////////////// // Globals
//// Globals
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
@ -31,7 +30,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
XPCOMUtils.defineLazyModuleGetter(this, "Services", XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm"); "resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function () { XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function() {
if (!("@mozilla.org/windows-taskbar;1" in Cc)) { if (!("@mozilla.org/windows-taskbar;1" in Cc)) {
return null; return null;
} }
@ -40,14 +39,13 @@ XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function () {
return winTaskbar.available && winTaskbar; return winTaskbar.available && winTaskbar;
}); });
XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function () { XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function() {
return ("@mozilla.org/widget/macdocksupport;1" in Cc) && return ("@mozilla.org/widget/macdocksupport;1" in Cc) &&
Cc["@mozilla.org/widget/macdocksupport;1"] Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsITaskbarProgress); .getService(Ci.nsITaskbarProgress);
}); });
//////////////////////////////////////////////////////////////////////////////// // DownloadsTaskbar
//// DownloadsTaskbar
/** /**
* Handles the download progress indicator in the taskbar. * Handles the download progress indicator in the taskbar.
@ -111,7 +109,6 @@ this.DownloadsTaskbar = {
return; return;
} }
this._summary = summary; this._summary = summary;
return this._summary.addView(this);
}).then(null, Cu.reportError); }).then(null, Cu.reportError);
} }
}, },
@ -150,8 +147,7 @@ this.DownloadsTaskbar = {
}); });
}, },
////////////////////////////////////////////////////////////////////////////// // DownloadSummary view
//// DownloadSummary view
onSummaryChanged() { onSummaryChanged() {
// If the last browser window has been closed, we have no indicator any more. // If the last browser window has been closed, we have no indicator any more.

View file

@ -49,7 +49,7 @@ this.DownloadsViewUI = {
* HistoryDownloadElementShell and the DownloadsViewItem for the panel. The * HistoryDownloadElementShell and the DownloadsViewItem for the panel. The
* history view may use a HistoryDownload object in place of a Download object. * 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 = { this.DownloadsViewUI.DownloadElementShell.prototype = {
/** /**
@ -242,10 +242,10 @@ this.DownloadsViewUI.DownloadElementShell.prototype = {
} }
let referrer = this.download.source.referrer || this.download.source.url; 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 date = new Date(this.download.endTime);
let [displayDate, fullDate] = DownloadUtils.getReadableDates(date); let [displayDate /* ,fullDate */] = DownloadUtils.getReadableDates(date);
let firstPart = s.statusSeparator(stateLabel, displayHost); let firstPart = s.statusSeparator(stateLabel, displayHost);
fullStatus = s.statusSeparator(firstPart, displayDate); fullStatus = s.statusSeparator(firstPart, displayDate);
@ -279,8 +279,6 @@ this.DownloadsViewUI.DownloadElementShell.prototype = {
} }
throw new Error("Unexpected reputationCheckVerdict: " + throw new Error("Unexpected reputationCheckVerdict: " +
this.download.error.reputationCheckVerdict); this.download.error.reputationCheckVerdict);
// return anyway to avoid a JS strict warning.
return [null, null];
}, },
/** /**
@ -306,6 +304,7 @@ this.DownloadsViewUI.DownloadElementShell.prototype = {
} else if (action == "confirmBlock") { } else if (action == "confirmBlock") {
return this.download.confirmBlock(); return this.download.confirmBlock();
} }
return Promise.resolve();
}).catch(Cu.reportError); }).catch(Cu.reportError);
}, },

View file

@ -1,6 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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, * 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/. */ * 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; var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
@ -943,9 +944,7 @@ DownloadsPlacesView.prototype = {
}, },
get selectedNodes() { get selectedNodes() {
return [for (element of this._richlistbox.selectedItems) return this._richlistbox.selectedItems.filter(element => element._placesNode);
if (element._placesNode)
element._placesNode];
}, },
get selectedNode() { get selectedNode() {
@ -1178,8 +1177,7 @@ DownloadsPlacesView.prototype = {
}, },
_copySelectedDownloadsToClipboard() { _copySelectedDownloadsToClipboard() {
let urls = [for (element of this._richlistbox.selectedItems) let urls = this._richlistbox.selectedItems.map(element => element._shell.download.source.url);
element._shell.download.source.url];
Cc["@mozilla.org/widget/clipboardhelper;1"] Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper) .getService(Ci.nsIClipboardHelper)
@ -1211,7 +1209,7 @@ DownloadsPlacesView.prototype = {
}, },
_canDownloadClipboardURL() { _canDownloadClipboardURL() {
let [url, name] = this._getURLFromClipboardData(); let [url /* ,name */] = this._getURLFromClipboardData();
return url != ""; return url != "";
}, },
@ -1308,8 +1306,7 @@ DownloadsPlacesView.prototype = {
element._shell.doDefaultCommand(); element._shell.doDefaultCommand();
} }
} }
} } else if (aEvent.charCode == " ".charCodeAt(0)) {
else if (aEvent.charCode == " ".charCodeAt(0)) {
// Pause/Resume every selected download // Pause/Resume every selected download
for (let element of selectedElements) { for (let element of selectedElements) {
if (element._shell.isCommandEnabled("downloadsCmd_pauseResume")) { if (element._shell.isCommandEnabled("downloadsCmd_pauseResume")) {
@ -1409,7 +1406,7 @@ DownloadsPlacesView.prototype = {
}; };
for (let methodName of ["load", "applyFilter", "selectNode", "selectItems"]) { for (let methodName of ["load", "applyFilter", "selectNode", "selectItems"]) {
DownloadsPlacesView.prototype[methodName] = function () { DownloadsPlacesView.prototype[methodName] = function() {
throw new Error("|" + methodName + throw new Error("|" + methodName +
"| is not implemented by the downloads view."); "| is not implemented by the downloads view.");
} }

View file

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
/* import-globals-from allDownloadsViewOverlay.js */
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
var ContentAreaDownloadsView = { var ContentAreaDownloadsView = {

View file

@ -3,6 +3,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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, * 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/. */ * 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. * Handles the Downloads panel user interface for each browser window.
@ -78,15 +79,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
XPCOMUtils.defineLazyModuleGetter(this, "Services", XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm"); "resource://gre/modules/Services.jsm");
//////////////////////////////////////////////////////////////////////////////// // DownloadsPanel
//// DownloadsPanel
/** /**
* Main entry point for the downloads panel interface. * Main entry point for the downloads panel interface.
*/ */
const DownloadsPanel = { const DownloadsPanel = {
////////////////////////////////////////////////////////////////////////////// // Initialization and termination
//// Initialization and termination
/** /**
* Internal state of the downloads panel, based on one of the kState * Internal state of the downloads panel, based on one of the kState
@ -192,8 +191,7 @@ const DownloadsPanel = {
DownloadsCommon.log("DownloadsPanel terminated."); DownloadsCommon.log("DownloadsPanel terminated.");
}, },
////////////////////////////////////////////////////////////////////////////// // Panel interface
//// Panel interface
/** /**
* Main panel element in the browser window, or null if the panel overlay * Main panel element in the browser window, or null if the panel overlay
@ -308,9 +306,11 @@ const DownloadsPanel = {
this.keyFocusing = false; this.keyFocusing = false;
break; break;
case "keydown": case "keydown":
return this._onKeyDown(aEvent); this._onKeyDown(aEvent);
break;
case "keypress": case "keypress":
return this._onKeyPress(aEvent); this._onKeyPress(aEvent);
break;
case "popupshown": case "popupshown":
if (this.setHeightToFitOnShow) { if (this.setHeightToFitOnShow) {
this.setHeightToFitOnShow = false; this.setHeightToFitOnShow = false;
@ -328,8 +328,7 @@ const DownloadsPanel = {
} }
}, },
////////////////////////////////////////////////////////////////////////////// // Callback functions from DownloadsView
//// Callback functions from DownloadsView
/** /**
* Called after data loading finished. * Called after data loading finished.
@ -338,8 +337,7 @@ const DownloadsPanel = {
this._openPopupIfDataReady(); this._openPopupIfDataReady();
}, },
////////////////////////////////////////////////////////////////////////////// // User interface event functions
//// User interface event functions
onWindowUnload() { onWindowUnload() {
// This function is registered as an event listener, we can't use "this". // This function is registered as an event listener, we can't use "this".
@ -407,8 +405,7 @@ const DownloadsPanel = {
.removeAttribute("showingdropdown"); .removeAttribute("showingdropdown");
}, },
////////////////////////////////////////////////////////////////////////////// // Related operations
//// Related operations
/** /**
* Shows or focuses the user interface dedicated to downloads history. * Shows or focuses the user interface dedicated to downloads history.
@ -429,8 +426,7 @@ const DownloadsPanel = {
this.hidePanel(); this.hidePanel();
}, },
////////////////////////////////////////////////////////////////////////////// // Internal functions
//// Internal functions
/** /**
* Attach event listeners to a panel element. These listeners should be * Attach event listeners to a panel element. These listeners should be
@ -625,8 +621,7 @@ const DownloadsPanel = {
XPCOMUtils.defineConstant(this, "DownloadsPanel", DownloadsPanel); XPCOMUtils.defineConstant(this, "DownloadsPanel", DownloadsPanel);
//////////////////////////////////////////////////////////////////////////////// // DownloadsOverlayLoader
//// DownloadsOverlayLoader
/** /**
* Allows loading the downloads panel and the status indicator interfaces on * Allows loading the downloads panel and the status indicator interfaces on
@ -705,8 +700,7 @@ const DownloadsOverlayLoader = {
XPCOMUtils.defineConstant(this, "DownloadsOverlayLoader", DownloadsOverlayLoader); XPCOMUtils.defineConstant(this, "DownloadsOverlayLoader", DownloadsOverlayLoader);
//////////////////////////////////////////////////////////////////////////////// // DownloadsView
//// DownloadsView
/** /**
* Builds and updates the downloads list widget, responding to changes in the * Builds and updates the downloads list widget, responding to changes in the
@ -714,8 +708,7 @@ XPCOMUtils.defineConstant(this, "DownloadsOverlayLoader", DownloadsOverlayLoader
* interaction events raised by the downloads list widget. * interaction events raised by the downloads list widget.
*/ */
const DownloadsView = { 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. * Maximum number of items shown by the list at any given time.
@ -791,8 +784,7 @@ const DownloadsView = {
return this.downloadsHistory = document.getElementById("downloadsHistory"); return this.downloadsHistory = document.getElementById("downloadsHistory");
}, },
////////////////////////////////////////////////////////////////////////////// // Callback functions from DownloadsData
//// Callback functions from DownloadsData
/** /**
* Called before multiple downloads are about to be loaded. * Called before multiple downloads are about to be loaded.
@ -918,8 +910,7 @@ const DownloadsView = {
* Creates a new view item associated with the specified data item, and adds * Creates a new view item associated with the specified data item, and adds
* it to the top or the bottom of the list. * 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.", DownloadsCommon.log("Adding a new DownloadsViewItem to the downloads list.",
"aNewest =", aNewest); "aNewest =", aNewest);
@ -950,8 +941,7 @@ const DownloadsView = {
this._itemsForElements.delete(element); this._itemsForElements.delete(element);
}, },
////////////////////////////////////////////////////////////////////////////// // User interface event functions
//// User interface event functions
/** /**
* Helper function to do commands on a specific download item. * Helper function to do commands on a specific download item.
@ -1118,8 +1108,7 @@ const DownloadsView = {
XPCOMUtils.defineConstant(this, "DownloadsView", DownloadsView); XPCOMUtils.defineConstant(this, "DownloadsView", DownloadsView);
//////////////////////////////////////////////////////////////////////////////// // DownloadsViewItem
//// DownloadsViewItem
/** /**
* Builds and updates a single item in the downloads list widget, responding to * Builds and updates a single item in the downloads list widget, responding to
@ -1199,8 +1188,7 @@ DownloadsViewItem.prototype = {
} }
}, },
////////////////////////////////////////////////////////////////////////////// // Item commands
//// Item commands
cmd_delete() { cmd_delete() {
DownloadsCommon.removeAndFinalizeDownload(this.download); DownloadsCommon.removeAndFinalizeDownload(this.download);
@ -1268,8 +1256,7 @@ DownloadsViewItem.prototype = {
}, },
}; };
//////////////////////////////////////////////////////////////////////////////// // DownloadsViewController
//// DownloadsViewController
/** /**
* Handles part of the user interaction events raised by the downloads list * Handles part of the user interaction events raised by the downloads list
@ -1277,8 +1264,7 @@ DownloadsViewItem.prototype = {
* dispatches the commands that apply to individual items. * dispatches the commands that apply to individual items.
*/ */
const DownloadsViewController = { const DownloadsViewController = {
////////////////////////////////////////////////////////////////////////////// // Initialization and termination
//// Initialization and termination
initialize() { initialize() {
window.controllers.insertControllerAt(0, this); window.controllers.insertControllerAt(0, this);
@ -1288,8 +1274,7 @@ const DownloadsViewController = {
window.controllers.removeController(this); window.controllers.removeController(this);
}, },
////////////////////////////////////////////////////////////////////////////// // nsIController
//// nsIController
supportsCommand(aCommand) { supportsCommand(aCommand) {
if (aCommand === "downloadsCmd_clearList") { if (aCommand === "downloadsCmd_clearList") {
@ -1352,8 +1337,7 @@ const DownloadsViewController = {
onEvent() {}, onEvent() {},
////////////////////////////////////////////////////////////////////////////// // Other functions
//// Other functions
updateCommands() { updateCommands() {
function updateCommandsForObject(object) { function updateCommandsForObject(object) {
@ -1367,8 +1351,7 @@ const DownloadsViewController = {
updateCommandsForObject(DownloadsViewItem.prototype); updateCommandsForObject(DownloadsViewItem.prototype);
}, },
////////////////////////////////////////////////////////////////////////////// // Selection-independent commands
//// Selection-independent commands
downloadsCmd_clearList() { downloadsCmd_clearList() {
DownloadsCommon.getData(window).removeFinished(); DownloadsCommon.getData(window).removeFinished();
@ -1377,8 +1360,7 @@ const DownloadsViewController = {
XPCOMUtils.defineConstant(this, "DownloadsViewController", DownloadsViewController); XPCOMUtils.defineConstant(this, "DownloadsViewController", DownloadsViewController);
//////////////////////////////////////////////////////////////////////////////// // DownloadsSummary
//// DownloadsSummary
/** /**
* Manages the summary at the bottom of the downloads panel list if the number * Manages the summary at the bottom of the downloads panel list if the number
@ -1562,8 +1544,7 @@ const DownloadsSummary = {
XPCOMUtils.defineConstant(this, "DownloadsSummary", DownloadsSummary); XPCOMUtils.defineConstant(this, "DownloadsSummary", DownloadsSummary);
//////////////////////////////////////////////////////////////////////////////// // DownloadsFooter
//// DownloadsFooter
/** /**
* Manages events sent to to the footer vbox, which contains both the * Manages events sent to to the footer vbox, which contains both the
@ -1622,8 +1603,7 @@ const DownloadsFooter = {
XPCOMUtils.defineConstant(this, "DownloadsFooter", DownloadsFooter); XPCOMUtils.defineConstant(this, "DownloadsFooter", DownloadsFooter);
//////////////////////////////////////////////////////////////////////////////// // DownloadsBlockedSubview
//// DownloadsBlockedSubview
/** /**
* Manages the blocked subview that slides in when you click a blocked download. * Manages the blocked subview that slides in when you click a blocked download.

View file

@ -3,6 +3,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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, * 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/. */ * 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 * Handles the indicator that displays the progress of ongoing downloads, which
@ -26,8 +27,7 @@
"use strict"; "use strict";
//////////////////////////////////////////////////////////////////////////////// // DownloadsButton
//// DownloadsButton
/** /**
* Main entry point for the downloads indicator. Depending on how the toolbars * Main entry point for the downloads indicator. Depending on how the toolbars
@ -187,8 +187,7 @@ Object.defineProperty(this, "DownloadsButton", {
writable: false writable: false
}); });
//////////////////////////////////////////////////////////////////////////////// // DownloadsIndicatorView
//// DownloadsIndicatorView
/** /**
* Builds and updates the actual downloads status widget, responding to changes * Builds and updates the actual downloads status widget, responding to changes
@ -287,8 +286,7 @@ const DownloadsIndicatorView = {
}); });
}, },
////////////////////////////////////////////////////////////////////////////// // Direct control functions
//// Direct control functions
/** /**
* Set while we are waiting for a notification to fade out. * Set while we are waiting for a notification to fade out.
@ -357,7 +355,7 @@ const DownloadsIndicatorView = {
// the notification isn't clipped by overflow properties of the anchor's // the notification isn't clipped by overflow properties of the anchor's
// container. // container.
let notifier = this.notifier; let notifier = this.notifier;
if (notifier.style.transform == '') { if (notifier.style.transform == "") {
let anchorRect = anchor.getBoundingClientRect(); let anchorRect = anchor.getBoundingClientRect();
let notifierRect = notifier.getBoundingClientRect(); let notifierRect = notifier.getBoundingClientRect();
let topDiff = anchorRect.top - notifierRect.top; let topDiff = anchorRect.top - notifierRect.top;
@ -373,13 +371,12 @@ const DownloadsIndicatorView = {
this._notificationTimeout = setTimeout(() => { this._notificationTimeout = setTimeout(() => {
anchor.removeAttribute("notification"); anchor.removeAttribute("notification");
notifier.removeAttribute("notification"); notifier.removeAttribute("notification");
notifier.style.transform = ''; notifier.style.transform = "";
// This value is determined by the overall duration of animation in CSS. // This value is determined by the overall duration of animation in CSS.
}, 2000); }, 2000);
}, },
////////////////////////////////////////////////////////////////////////////// // Callback functions from DownloadsIndicatorData
//// Callback functions from DownloadsIndicatorData
/** /**
* Indicates whether the indicator should be shown because there are some * Indicates whether the indicator should be shown because there are some
@ -524,8 +521,7 @@ const DownloadsIndicatorView = {
}, },
_attention: DownloadsCommon.ATTENTION_NONE, _attention: DownloadsCommon.ATTENTION_NONE,
////////////////////////////////////////////////////////////////////////////// // User interface event functions
//// User interface event functions
onWindowUnload() { onWindowUnload() {
// This function is registered as an event listener, we can't use "this". // This function is registered as an event listener, we can't use "this".

View file

@ -30,7 +30,7 @@ add_task(function* test_basic_functionality() {
// For testing purposes, show all the download items at once. // For testing purposes, show all the download items at once.
var originalCountLimit = DownloadsView.kItemCountLimit; var originalCountLimit = DownloadsView.kItemCountLimit;
DownloadsView.kItemCountLimit = DownloadData.length; DownloadsView.kItemCountLimit = DownloadData.length;
registerCleanupFunction(function () { registerCleanupFunction(function() {
DownloadsView.kItemCountLimit = originalCountLimit; DownloadsView.kItemCountLimit = originalCountLimit;
}); });

View file

@ -108,8 +108,7 @@ function* openPanel() {
clearInterval(interval); clearInterval(interval);
resolve(); resolve();
} }
} else { } else if (iBackoff < backoff) {
if (iBackoff < backoff) {
// Keep backing off before trying again. // Keep backing off before trying again.
iBackoff++; iBackoff++;
} else { } else {
@ -122,7 +121,6 @@ function* openPanel() {
} }
DownloadsPanel.showPanel(); DownloadsPanel.showPanel();
} }
}
}, 100); }, 100);
}); });
} }
@ -162,7 +160,6 @@ function promiseSubviewShown(shown) {
!DownloadsBlockedSubview.view._transitioning) { !DownloadsBlockedSubview.view._transitioning) {
clearInterval(interval); clearInterval(interval);
setTimeout(resolve, 1000); setTimeout(resolve, 1000);
return;
} }
}, 0); }, 0);
}); });

View file

@ -41,7 +41,7 @@ add_task(function* test_clearList() {
], ],
expectClearListShown: true, expectClearListShown: true,
expectedItemNumber: 0, expectedItemNumber: 0,
},{ }, {
downloads: [ downloads: [
{ state: nsIDM.DOWNLOAD_NOTSTARTED }, { state: nsIDM.DOWNLOAD_NOTSTARTED },
{ state: nsIDM.DOWNLOAD_FINISHED }, { state: nsIDM.DOWNLOAD_FINISHED },
@ -51,7 +51,7 @@ add_task(function* test_clearList() {
], ],
expectClearListShown: true, expectClearListShown: true,
expectedItemNumber: 1, expectedItemNumber: 1,
},{ }, {
downloads: [ downloads: [
{ state: nsIDM.DOWNLOAD_PAUSED }, { state: nsIDM.DOWNLOAD_PAUSED },
], ],

View file

@ -44,7 +44,7 @@ add_task(function* test_first_download_panel() {
// Next, make sure that if we start another download, we don't open the // Next, make sure that if we start another download, we don't open the
// panel automatically. // panel automatically.
let originalOnPopupShown = DownloadsPanel.onPopupShown; let originalOnPopupShown = DownloadsPanel.onPopupShown;
DownloadsPanel.onPopupShown = function () { DownloadsPanel.onPopupShown = function() {
originalOnPopupShown.apply(this, arguments); originalOnPopupShown.apply(this, arguments);
ok(false, "Should not have opened the downloads panel."); ok(false, "Should not have opened the downloads panel.");
}; };

View file

@ -1,6 +1,6 @@
const SAVE_PER_SITE_PREF = "browser.download.lastDir.savePerSite"; const SAVE_PER_SITE_PREF = "browser.download.lastDir.savePerSite";
function test_deleted_iframe(perSitePref, windowOptions={}) { function test_deleted_iframe(perSitePref, windowOptions = {}) {
return function*() { return function*() {
Services.prefs.setBoolPref(SAVE_PER_SITE_PREF, perSitePref); Services.prefs.setBoolPref(SAVE_PER_SITE_PREF, perSitePref);
let {DownloadLastDir} = Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}); let {DownloadLastDir} = Cu.import("resource://gre/modules/DownloadLastDir.jsm", {});

View file

@ -29,10 +29,10 @@ add_task(function* test_indicatorDrop() {
let succeeded = new Set(); let succeeded = new Set();
yield new Promise(function(resolve) { yield new Promise(function(resolve) {
let view = { let view = {
onDownloadAdded: function(download) { onDownloadAdded(download) {
added.add(download.source.url); added.add(download.source.url);
}, },
onDownloadChanged: function(download) { onDownloadChanged(download) {
if (!added.has(download.source.url)) if (!added.has(download.source.url))
return; return;
if (!download.succeeded) if (!download.succeeded)

View file

@ -29,10 +29,10 @@ add_task(function* test_indicatorDrop() {
let succeeded = new Set(); let succeeded = new Set();
await new Promise(resolve => { await new Promise(resolve => {
let view = { let view = {
onDownloadAdded: function(download) { onDownloadAdded(download) {
added.add(download.source.url); added.add(download.source.url);
}, },
onDownloadChanged: function(download) { onDownloadChanged(download) {
if (!added.has(download.source.url)) if (!added.has(download.source.url))
return; return;
if (!download.succeeded) if (!download.succeeded)

View file

@ -7,8 +7,7 @@
* Provides infrastructure for automated download components tests. * Provides infrastructure for automated download components tests.
*/ */
//////////////////////////////////////////////////////////////////////////////// // Globals
//// Globals
XPCOMUtils.defineLazyModuleGetter(this, "Downloads", XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
"resource://gre/modules/Downloads.jsm"); "resource://gre/modules/Downloads.jsm");
@ -22,6 +21,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm"); "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm"); "resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
"resource://testing-common/httpd.js");
const nsIDM = Ci.nsIDownloadManager; const nsIDM = Ci.nsIDownloadManager;
var gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]); var gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]);
@ -29,9 +31,10 @@ gTestTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
// Load mocking/stubbing library, sinon // Load mocking/stubbing library, sinon
// docs: http://sinonjs.org/docs/ // docs: http://sinonjs.org/docs/
/* global sinon:false */
Services.scriptloader.loadSubScript("resource://testing-common/sinon-1.16.1.js"); Services.scriptloader.loadSubScript("resource://testing-common/sinon-1.16.1.js");
registerCleanupFunction(function () { registerCleanupFunction(function() {
gTestTargetFile.remove(false); gTestTargetFile.remove(false);
delete window.sinon; delete window.sinon;
@ -39,11 +42,9 @@ registerCleanupFunction(function () {
delete window.clearImmediate; delete window.clearImmediate;
}); });
//////////////////////////////////////////////////////////////////////////////// // Asynchronous support subroutines
//// Asynchronous support subroutines
function promiseOpenAndLoadWindow(aOptions) function promiseOpenAndLoadWindow(aOptions) {
{
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let win = OpenBrowserWindow(aOptions); let win = OpenBrowserWindow(aOptions);
win.addEventListener("load", function() { win.addEventListener("load", function() {
@ -66,8 +67,7 @@ function promiseOpenAndLoadWindow(aOptions)
* @resolves to the received event * @resolves to the received event
* @rejects if a valid load event is not received within a meaningful interval * @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(); let deferred = Promise.defer();
info("Wait tab event: " + eventType); info("Wait tab event: " + eventType);
@ -96,8 +96,7 @@ function promiseTabLoadEvent(tab, url, eventType="load")
return deferred.promise; return deferred.promise;
} }
function promiseWindowClosed(win) function promiseWindowClosed(win) {
{
let promise = new Promise((resolve, reject) => { let promise = new Promise((resolve, reject) => {
Services.obs.addObserver(function obs(subject, topic) { Services.obs.addObserver(function obs(subject, topic) {
if (subject == win) { if (subject == win) {
@ -111,15 +110,13 @@ function promiseWindowClosed(win)
} }
function promiseFocus() function promiseFocus() {
{
let deferred = Promise.defer(); let deferred = Promise.defer();
waitForFocus(deferred.resolve); waitForFocus(deferred.resolve);
return deferred.promise; return deferred.promise;
} }
function promisePanelOpened() function promisePanelOpened() {
{
let deferred = Promise.defer(); let deferred = Promise.defer();
if (DownloadsPanel.panel && DownloadsPanel.panel.state == "open") { if (DownloadsPanel.panel && DownloadsPanel.panel.state == "open") {
@ -128,7 +125,7 @@ function promisePanelOpened()
// Hook to wait until the panel is shown. // Hook to wait until the panel is shown.
let originalOnPopupShown = DownloadsPanel.onPopupShown; let originalOnPopupShown = DownloadsPanel.onPopupShown;
DownloadsPanel.onPopupShown = function () { DownloadsPanel.onPopupShown = function() {
DownloadsPanel.onPopupShown = originalOnPopupShown; DownloadsPanel.onPopupShown = originalOnPopupShown;
originalOnPopupShown.apply(this, arguments); originalOnPopupShown.apply(this, arguments);
@ -140,8 +137,7 @@ function promisePanelOpened()
return deferred.promise; return deferred.promise;
} }
function* task_resetState() function* task_resetState() {
{
// Remove all downloads. // Remove all downloads.
let publicList = yield Downloads.getList(Downloads.PUBLIC); let publicList = yield Downloads.getList(Downloads.PUBLIC);
let downloads = yield publicList.getAll(); let downloads = yield publicList.getAll();
@ -155,8 +151,7 @@ function* task_resetState()
yield promiseFocus(); yield promiseFocus();
} }
function* task_addDownloads(aItems) function* task_addDownloads(aItems) {
{
let startTimeMs = Date.now(); let startTimeMs = Date.now();
let publicList = yield Downloads.getList(Downloads.PUBLIC); let publicList = yield Downloads.getList(Downloads.PUBLIC);
@ -184,8 +179,7 @@ function* task_addDownloads(aItems)
} }
} }
function* task_openPanel() function* task_openPanel() {
{
yield promiseFocus(); yield promiseFocus();
let promise = promisePanelOpened(); let promise = promisePanelOpened();
@ -198,7 +192,7 @@ function* setDownloadDir() {
tmpDir.append("testsavedir"); tmpDir.append("testsavedir");
if (!tmpDir.exists()) { if (!tmpDir.exists()) {
tmpDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); tmpDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
registerCleanupFunction(function () { registerCleanupFunction(function() {
try { try {
tmpDir.remove(true); tmpDir.remove(true);
} catch (e) { } catch (e) {

View file

@ -7,8 +7,7 @@
* Provides infrastructure for automated download components tests. * Provides infrastructure for automated download components tests.
*/ */
//////////////////////////////////////////////////////////////////////////////// // Globals
//// Globals
var Cc = Components.classes; var Cc = Components.classes;
var Ci = Components.interfaces; var Ci = Components.interfaces;

View file

@ -7,8 +7,7 @@
* Tests for the functions located directly in the "DownloadsCommon" object. * Tests for the functions located directly in the "DownloadsCommon" object.
*/ */
function testFormatTimeLeft(aSeconds, aExpectedValue, aExpectedUnitString) function testFormatTimeLeft(aSeconds, aExpectedValue, aExpectedUnitString) {
{
let expected = ""; let expected = "";
if (aExpectedValue) { if (aExpectedValue) {
// Format the expected result based on the current language. // Format the expected result based on the current language.
@ -17,21 +16,20 @@ function testFormatTimeLeft(aSeconds, aExpectedValue, aExpectedUnitString)
do_check_eq(DownloadsCommon.formatTimeLeft(aSeconds), expected); do_check_eq(DownloadsCommon.formatTimeLeft(aSeconds), expected);
} }
function run_test() function run_test() {
{ testFormatTimeLeft(0, "", "");
testFormatTimeLeft( 0, "", ""); testFormatTimeLeft(1, "1", "shortTimeLeftSeconds");
testFormatTimeLeft( 1, "1", "shortTimeLeftSeconds"); testFormatTimeLeft(29, "29", "shortTimeLeftSeconds");
testFormatTimeLeft( 29, "29", "shortTimeLeftSeconds"); testFormatTimeLeft(30, "30", "shortTimeLeftSeconds");
testFormatTimeLeft( 30, "30", "shortTimeLeftSeconds"); testFormatTimeLeft(31, "1", "shortTimeLeftMinutes");
testFormatTimeLeft( 31, "1", "shortTimeLeftMinutes"); testFormatTimeLeft(60, "1", "shortTimeLeftMinutes");
testFormatTimeLeft( 60, "1", "shortTimeLeftMinutes"); testFormatTimeLeft(89, "1", "shortTimeLeftMinutes");
testFormatTimeLeft( 89, "1", "shortTimeLeftMinutes"); testFormatTimeLeft(90, "2", "shortTimeLeftMinutes");
testFormatTimeLeft( 90, "2", "shortTimeLeftMinutes"); testFormatTimeLeft(91, "2", "shortTimeLeftMinutes");
testFormatTimeLeft( 91, "2", "shortTimeLeftMinutes"); testFormatTimeLeft(3600, "1", "shortTimeLeftHours");
testFormatTimeLeft( 3600, "1", "shortTimeLeftHours"); testFormatTimeLeft(86400, "24", "shortTimeLeftHours");
testFormatTimeLeft( 86400, "24", "shortTimeLeftHours"); testFormatTimeLeft(169200, "47", "shortTimeLeftHours");
testFormatTimeLeft( 169200, "47", "shortTimeLeftHours"); testFormatTimeLeft(172800, "2", "shortTimeLeftDays");
testFormatTimeLeft( 172800, "2", "shortTimeLeftDays");
testFormatTimeLeft(8553600, "99", "shortTimeLeftDays"); testFormatTimeLeft(8553600, "99", "shortTimeLeftDays");
testFormatTimeLeft(8640000, "99", "shortTimeLeftDays"); testFormatTimeLeft(8640000, "99", "shortTimeLeftDays");
} }

View file

@ -85,6 +85,7 @@ var ContentClick = {
allowMixedContent: json.allowMixedContent, allowMixedContent: json.allowMixedContent,
isContentWindowPrivate: json.isContentWindowPrivate, isContentWindowPrivate: json.isContentWindowPrivate,
originPrincipal: json.originPrincipal, originPrincipal: json.originPrincipal,
triggeringPrincipal: json.triggeringPrincipal,
frameOuterWindowID: json.frameOuterWindowID, frameOuterWindowID: json.frameOuterWindowID,
}; };

View file

@ -280,7 +280,8 @@ TooltipsOverlay.prototype = {
let {naturalWidth, naturalHeight} = yield getImageDimensions(doc, imageUrl); let {naturalWidth, naturalHeight} = yield getImageDimensions(doc, imageUrl);
yield setImageTooltip(this.previewTooltip, doc, imageUrl, yield setImageTooltip(this.previewTooltip, doc, imageUrl,
{hideDimensionLabel: true, maxDim, naturalWidth, naturalHeight}); {hideDimensionLabel: true, hideCheckeredBackground: true,
maxDim, naturalWidth, naturalHeight});
}), }),
_onNewSelection: function () { _onNewSelection: function () {

View file

@ -204,6 +204,7 @@ const PropertiesView = createClass({
}, },
enableInput, enableInput,
expandableStrings, expandableStrings,
useQuotes: false,
expandedNodes: this.getExpandedNodes(object), expandedNodes: this.getExpandedNodes(object),
onFilter: (props) => this.onFilter(props, sectionNames), onFilter: (props) => this.onFilter(props, sectionNames),
renderRow: renderRow || this.renderRowWithEditor, renderRow: renderRow || this.renderRowWithEditor,

View file

@ -30,31 +30,31 @@ add_task(function* () {
EventUtils.sendMouseEvent({ type: "click" }, EventUtils.sendMouseEvent({ type: "click" },
document.querySelector("#params-tab")); document.querySelector("#params-tab"));
yield wait; yield wait;
testParamsTab1("a", '""', '{ "foo": "bar" }', '""'); testParamsTab1("a", "", '{ "foo": "bar" }', "");
wait = waitForDOM(document, "#params-panel .tree-section", 2); wait = waitForDOM(document, "#params-panel .tree-section", 2);
EventUtils.sendMouseEvent({ type: "mousedown" }, EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[1]); document.querySelectorAll(".request-list-item")[1]);
yield wait; yield wait;
testParamsTab1("a", '"b"', '{ "foo": "bar" }', '""'); testParamsTab1("a", "b", '{ "foo": "bar" }', "");
wait = waitForDOM(document, "#params-panel .tree-section", 2); wait = waitForDOM(document, "#params-panel .tree-section", 2);
EventUtils.sendMouseEvent({ type: "mousedown" }, EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[2]); document.querySelectorAll(".request-list-item")[2]);
yield wait; yield wait;
testParamsTab1("a", '"b"', "?foo", '"bar"'); testParamsTab1("a", "b", "?foo", "bar");
wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2); wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2);
EventUtils.sendMouseEvent({ type: "mousedown" }, EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[3]); document.querySelectorAll(".request-list-item")[3]);
yield wait; yield wait;
testParamsTab2("a", '""', '{ "foo": "bar" }', "js"); testParamsTab2("a", "", '{ "foo": "bar" }', "js");
wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2); wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2);
EventUtils.sendMouseEvent({ type: "mousedown" }, EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[4]); document.querySelectorAll(".request-list-item")[4]);
yield wait; yield wait;
testParamsTab2("a", '"b"', '{ "foo": "bar" }', "js"); testParamsTab2("a", "b", '{ "foo": "bar" }', "js");
// Wait for all tree sections and editor updated by react // Wait for all tree sections and editor updated by react
let waitSections = waitForDOM(document, "#params-panel .tree-section", 2); let waitSections = waitForDOM(document, "#params-panel .tree-section", 2);
@ -64,7 +64,7 @@ add_task(function* () {
let [, editorFrames] = yield Promise.all([waitSections, waitEditor]); let [, editorFrames] = yield Promise.all([waitSections, waitEditor]);
yield once(editorFrames[0], "DOMContentLoaded"); yield once(editorFrames[0], "DOMContentLoaded");
yield waitForDOM(editorFrames[0].contentDocument, ".CodeMirror-code"); yield waitForDOM(editorFrames[0].contentDocument, ".CodeMirror-code");
testParamsTab2("a", '"b"', "?foo=bar", "text"); testParamsTab2("a", "b", "?foo=bar", "text");
EventUtils.sendMouseEvent({ type: "mousedown" }, EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[6]); document.querySelectorAll(".request-list-item")[6]);

View file

@ -228,7 +228,7 @@ add_task(function* () {
is(labels[0].textContent, "greeting", is(labels[0].textContent, "greeting",
"The first json property name was incorrect."); "The first json property name was incorrect.");
is(values[0].textContent, is(values[0].textContent,
"\"Hello JSON!\"", "The first json property value was incorrect."); "Hello JSON!", "The first json property value was incorrect.");
break; break;
} }
case "html": { case "html": {

View file

@ -56,7 +56,7 @@ add_task(function* () {
is(labels[0].textContent, "greeting", is(labels[0].textContent, "greeting",
"The first json property name was incorrect."); "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."); "The first json property value was incorrect.");
yield teardown(monitor); yield teardown(monitor);

View file

@ -80,7 +80,7 @@ add_task(function* () {
is(labels[0].textContent, "greeting", is(labels[0].textContent, "greeting",
"The first json property name was incorrect."); "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."); "The first json property value was incorrect.");
} }
}); });

View file

@ -81,7 +81,7 @@ add_task(function* () {
is(labels[0].textContent, "greeting", is(labels[0].textContent, "greeting",
"The first json property name was incorrect."); "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."); "The first json property value was incorrect.");
} }
}); });

View file

@ -64,14 +64,14 @@ add_task(function* () {
document.querySelector("#response-tab")); document.querySelector("#response-tab"));
yield wait; yield wait;
testResponseTab("$_0123Fun", "\"Hello JSONP!\""); testResponseTab("$_0123Fun", "Hello JSONP!");
wait = waitForDOM(document, "#response-panel .tree-section"); wait = waitForDOM(document, "#response-panel .tree-section");
EventUtils.sendMouseEvent({ type: "mousedown" }, EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[1]); document.querySelectorAll(".request-list-item")[1]);
yield wait; yield wait;
testResponseTab("$_4567Sad", "\"Hello weird JSONP!\""); testResponseTab("$_4567Sad", "Hello weird JSONP!");
yield teardown(monitor); yield teardown(monitor);

View file

@ -115,20 +115,19 @@ add_task(function* () {
.querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox");
is(labels[0].textContent, "foo", "The first query param name was incorrect."); 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(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(labels[2].textContent, "type", "The third query param name was incorrect.");
is(values[2].textContent, "\"" + type + "\"", is(values[2].textContent, type, "The third query param value was incorrect.");
"The third query param value was incorrect.");
if (type == "urlencoded") { if (type == "urlencoded") {
checkVisibility("params"); checkVisibility("params");
is(labels.length, 5, "There should be 5 param values displayed in this tabpanel."); 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(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(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 { } else {
checkVisibility("params editor"); checkVisibility("params editor");

View file

@ -55,9 +55,9 @@ add_task(function* () {
.querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox");
is(labels[0].textContent, "foo", "The first query param name was incorrect."); 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(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); return teardown(monitor);
}); });

View file

@ -50,11 +50,11 @@ add_task(function* () {
is(labels[labels.length - 2].textContent, "content-type", is(labels[labels.length - 2].textContent, "content-type",
"The first request header name was incorrect."); "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."); "The first request header value was incorrect.");
is(labels[labels.length - 1].textContent, "custom-header", is(labels[labels.length - 1].textContent, "custom-header",
"The second request header name was incorrect."); "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."); "The second request header value was incorrect.");
// Wait for all tree sections updated by react // Wait for all tree sections updated by react
@ -80,9 +80,9 @@ add_task(function* () {
.querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox"); .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox");
is(labels[0].textContent, "foo", "The first payload param name was incorrect."); 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(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); return teardown(monitor);
}); });

View file

@ -182,7 +182,6 @@ add_task(function* () {
let panel = document.querySelector("#params-panel"); let panel = document.querySelector("#params-panel");
let statusParamValue = data.uri.split("=").pop(); let statusParamValue = data.uri.split("=").pop();
let statusParamShownValue = "\"" + statusParamValue + "\"";
let treeSections = panel.querySelectorAll(".tree-section"); let treeSections = panel.querySelectorAll(".tree-section");
is(treeSections.length, 1, is(treeSections.length, 1,
@ -202,7 +201,7 @@ add_task(function* () {
"The params scope doesn't have the correct title."); "The params scope doesn't have the correct title.");
is(labels[0].textContent, "sts", "The param name was incorrect."); 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"), ok(panel.querySelector(".treeTable"),
"The request params tree view should be displayed."); "The request params tree view should be displayed.");

View file

@ -56,9 +56,12 @@ function getImageDimensions(doc, imageUrl) {
* - {Number} naturalHeight mandatory, height of the image to display * - {Number} naturalHeight mandatory, height of the image to display
* - {Number} maxDim optional, max width/height of the preview * - {Number} maxDim optional, max width/height of the preview
* - {Boolean} hideDimensionLabel optional, pass true to hide the label * - {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) { function setImageTooltip(tooltip, doc, imageUrl, options) {
let {naturalWidth, naturalHeight, hideDimensionLabel, maxDim} = options; let {naturalWidth, naturalHeight, hideDimensionLabel,
hideCheckeredBackground, maxDim} = options;
maxDim = maxDim || MAX_DIMENSION; maxDim = maxDim || MAX_DIMENSION;
let imgHeight = naturalHeight; let imgHeight = naturalHeight;
@ -70,6 +73,11 @@ function setImageTooltip(tooltip, doc, imageUrl, options) {
imgWidth = Math.ceil(scale * naturalWidth); imgWidth = Math.ceil(scale * naturalWidth);
} }
let imageClass = "";
if (!hideCheckeredBackground) {
imageClass = "devtools-tooltip-tiles";
}
// Create tooltip content // Create tooltip content
let div = doc.createElementNS(XHTML_NS, "div"); let div = doc.createElementNS(XHTML_NS, "div");
div.style.cssText = ` div.style.cssText = `
@ -85,7 +93,7 @@ function setImageTooltip(tooltip, doc, imageUrl, options) {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
min-height: 1px;"> min-height: 1px;">
<img class="devtools-tooltip-tiles" <img class="${imageClass}"
style="height: ${imgHeight}px; max-height: 100%;" style="height: ${imgHeight}px; max-height: 100%;"
src="${imageUrl}"/> src="${imageUrl}"/>
</div>`; </div>`;

View file

@ -2297,10 +2297,8 @@ function runKeyTests()
desc + ".defaultPrevented is wrong"); desc + ".defaultPrevented is wrong");
is(aEvent.key, expectedValue("key"), is(aEvent.key, expectedValue("key"),
desc + ".key is wrong"); desc + ".key is wrong");
if (SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled")) {
is(aEvent.code, expectedValue("code"), is(aEvent.code, expectedValue("code"),
desc + ".code is wrong"); desc + ".code is wrong");
}
is(aEvent.location, expectedValue("location"), is(aEvent.location, expectedValue("location"),
desc + ".location is wrong"); desc + ".location is wrong");
is(aEvent.repeat, expectedValue("repeat"), is(aEvent.repeat, expectedValue("repeat"),
@ -2875,10 +2873,8 @@ function runKeyTests()
} }
is(aEvent.key, aKey, is(aEvent.key, aKey,
desc + ", .key value is wrong"); desc + ", .key value is wrong");
if (SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled")) {
is(aEvent.code, aCode, is(aEvent.code, aCode,
desc + ", .code value is wrong"); desc + ", .code value is wrong");
}
is(aEvent.altKey, aModifiers.indexOf("Alt") >= 0, is(aEvent.altKey, aModifiers.indexOf("Alt") >= 0,
desc + ", .altKey value is wrong"); desc + ", .altKey value is wrong");
is(aEvent.ctrlKey, aModifiers.indexOf("Control") >= 0, is(aEvent.ctrlKey, aModifiers.indexOf("Control") >= 0,

View file

@ -14,8 +14,6 @@
<pre id="test"> <pre id="test">
<script type="application/javascript"> <script type="application/javascript">
var gCodeEnabled = SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled");
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests, window); SimpleTest.waitForFocus(runTests, window);
@ -126,9 +124,7 @@ function testInitializingUntrustedEvent()
// key and code values cannot be initialized with initKeyEvent(). // key and code values cannot be initialized with initKeyEvent().
is(e.key, "", description + "key must return empty string"); 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 // getModifierState() tests
is(e.getModifierState("Shift"), kTest.shiftKey, is(e.getModifierState("Shift"), kTest.shiftKey,

View file

@ -433,13 +433,9 @@ var testKeyboardProps =
{ keyCode: 11, charCode: 12, which: 13 }, { keyCode: 11, charCode: 12, which: 13 },
]; ];
var codeEnabled = SpecialPowers.getBoolPref("dom.keyboardevent.code.enabled");
var defaultKeyboardEventValues = {}; var defaultKeyboardEventValues = {};
for (var i = 0; i < keyboardEventProps.length; ++i) { for (var i = 0; i < keyboardEventProps.length; ++i) {
for (prop in keyboardEventProps[i]) { for (prop in keyboardEventProps[i]) {
if (!codeEnabled && prop == "code") {
continue;
}
if (!isMethodResultInitializer(prop)) { if (!isMethodResultInitializer(prop)) {
ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!"); ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!");
} }
@ -451,9 +447,6 @@ while (testKeyboardProps.length) {
var p = testKeyboardProps.shift(); var p = testKeyboardProps.shift();
e = new KeyboardEvent("foo", p); e = new KeyboardEvent("foo", p);
for (var def in defaultKeyboardEventValues) { for (var def in defaultKeyboardEventValues) {
if (!codeEnabled && def == "code") {
continue;
}
if (!(def in p)) { if (!(def in p)) {
is(getPropValue(e, def), defaultKeyboardEventValues[def], is(getPropValue(e, def), defaultKeyboardEventValues[def],
"KeyboardEvent: Wrong default value for " + def + "!"); "KeyboardEvent: Wrong default value for " + def + "!");

View file

@ -1,4 +1,4 @@
function testSimpleURLSearchParams() { function testSimpleURLSearchParams() {
var u = new URLSearchParams(); var u = new URLSearchParams();
ok(u, "URLSearchParams created"); ok(u, "URLSearchParams created");
is(u.has('foo'), false, 'URLSearchParams.has(foo)'); is(u.has('foo'), false, 'URLSearchParams.has(foo)');
@ -19,9 +19,9 @@
u.delete('foo'); u.delete('foo');
runTest(); runTest();
} }
function testCopyURLSearchParams() { function testCopyURLSearchParams() {
var u = new URLSearchParams(); var u = new URLSearchParams();
ok(u, "URLSearchParams created"); ok(u, "URLSearchParams created");
u.append('foo', 'bar'); u.append('foo', 'bar');
@ -34,9 +34,9 @@
is(uu.getAll('foo').length, 1, "uu.getAll()"); is(uu.getAll('foo').length, 1, "uu.getAll()");
runTest(); runTest();
} }
function testURL() { function testURL() {
var url = new URL('http://www.example.net?a=b&c=d'); var url = new URL('http://www.example.net?a=b&c=d');
ok(url.searchParams, "URL searchParams exists!"); ok(url.searchParams, "URL searchParams exists!");
ok(url.searchParams.has('a'), "URL.searchParams.has('a')"); ok(url.searchParams.has('a'), "URL.searchParams.has('a')");
@ -48,8 +48,8 @@
ok(url.href.indexOf('e=f') != 1, 'URL right'); ok(url.href.indexOf('e=f') != 1, 'URL right');
runTest(); runTest();
} }
function testParserURLSearchParams() { function testParserURLSearchParams() {
var checks = [ var checks = [
{ input: '', data: {} }, { input: '', data: {} },
{ input: 'a', data: { 'a' : [''] } }, { input: 'a', data: { 'a' : [''] } },
@ -99,9 +99,9 @@
} }
runTest(); runTest();
} }
function testEncoding() { function testEncoding() {
var encoding = [ [ '1', '1' ], var encoding = [ [ '1', '1' ],
[ 'a b', 'a+b' ], [ 'a b', 'a+b' ],
[ '<>', '%3C%3E' ], [ '<>', '%3C%3E' ],
@ -117,9 +117,9 @@
} }
runTest(); runTest();
} }
function testCopyConstructor() { function testCopyConstructor() {
var url = new URL("http://example.com/"); var url = new URL("http://example.com/");
var p = url.searchParams; var p = url.searchParams;
var q = new URLSearchParams(p); var q = new URLSearchParams(p);
@ -131,9 +131,9 @@
"Messing with URLSearchParams should affect URL"); "Messing with URLSearchParams should affect URL");
runTest(); runTest();
} }
function testOrdering() { function testOrdering() {
var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6"); 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.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()"); is(a.getAll('a').length, 3, "Correct length of getAll()");
@ -146,9 +146,9 @@
is(b.getAll('a').length, 2, "Correct length of getAll()"); is(b.getAll('a').length, 2, "Correct length of getAll()");
runTest(); runTest();
} }
function testDelete() { function testDelete() {
var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6"); 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.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()"); is(a.getAll('a').length, 3, "Correct length of getAll()");
@ -158,9 +158,9 @@
is(a.toString(), "b=3&c=4&c=5", "Order is correct"); is(a.toString(), "b=3&c=4&c=5", "Order is correct");
runTest(); runTest();
} }
function testGetNULL() { function testGetNULL() {
var u = new URLSearchParams(); var u = new URLSearchParams();
is(typeof u.get(''), "object", "typeof URL.searchParams.get('')"); is(typeof u.get(''), "object", "typeof URL.searchParams.get('')");
is(u.get(''), null, "URL.searchParams.get('') should be null"); is(u.get(''), null, "URL.searchParams.get('') should be null");
@ -170,9 +170,9 @@
is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')"); is(url.searchParams.get('a'), 'b', "URL.searchParams.get('a')");
runTest(); runTest();
} }
function testSet() { function testSet() {
var u = new URLSearchParams(); var u = new URLSearchParams();
u.set('a','b'); u.set('a','b');
u.set('e','c'); u.set('e','c');
@ -208,9 +208,9 @@
is(u.getAll('name1').length, 1, "URLSearchParams.getAll('name1').length should be 1"); is(u.getAll('name1').length, 1, "URLSearchParams.getAll('name1').length should be 1");
runTest(); runTest();
} }
function testIterable() { function testIterable() {
var u = new URLSearchParams(); var u = new URLSearchParams();
u.set('1','2'); u.set('1','2');
u.set('2','4'); u.set('2','4');
@ -260,8 +260,8 @@
is(last.value, undefined, "Undefined is the last key"); is(last.value, undefined, "Undefined is the last key");
runTest(); runTest();
} }
function testZeroHandling() { function testZeroHandling() {
var u = new URLSearchParams; var u = new URLSearchParams;
u.set("a", "b\0c"); u.set("a", "b\0c");
u.set("d\0e", "f"); u.set("d\0e", "f");
@ -270,9 +270,9 @@
"Should encode U+0000 as %00"); "Should encode U+0000 as %00");
runTest(); runTest();
} }
function testCTORs() { function testCTORs() {
var a = new URLSearchParams("a=b"); var a = new URLSearchParams("a=b");
is(a.get("a"), "b", "CTOR with string"); is(a.get("a"), "b", "CTOR with string");
@ -298,6 +298,12 @@
} }
is(result, 43, "CTOR throws if the sequence doesn't contain exactly 2 elements"); is(result, 43, "CTOR throws if the sequence doesn't contain exactly 2 elements");
runTest(); 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<>");
runTest();
}

View file

@ -27,7 +27,6 @@ interface KeyboardEvent : UIEvent
readonly attribute boolean isComposing; readonly attribute boolean isComposing;
readonly attribute DOMString key; readonly attribute DOMString key;
[Pref="dom.keyboardevent.code.enabled"]
readonly attribute DOMString code; readonly attribute DOMString code;
// This returns the initialized dictionary for generating a // This returns the initialized dictionary for generating a

View file

@ -165,12 +165,11 @@ gfxMacFont::gfxMacFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyl
mCGFont(nullptr), mCGFont(nullptr),
mCTFont(nullptr), mCTFont(nullptr),
mFontFace(nullptr), mFontFace(nullptr),
mVariationFont(false) mVariationFont(aFontEntry->HasVariations())
{ {
mApplySyntheticBold = aNeedsBold; mApplySyntheticBold = aNeedsBold;
auto varCount = aFontStyle->variationSettings.Length(); if (mVariationFont && aFontStyle->variationSettings.Length() > 0) {
if (varCount > 0) {
CGFontRef baseFont = aFontEntry->GetFontRef(); CGFontRef baseFont = aFontEntry->GetFontRef();
if (!baseFont) { if (!baseFont) {
mIsValid = false; mIsValid = false;
@ -181,7 +180,6 @@ gfxMacFont::gfxMacFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyl
if (variations) { if (variations) {
mCGFont = ::CGFontCreateCopyWithVariations(baseFont, variations); mCGFont = ::CGFontCreateCopyWithVariations(baseFont, variations);
::CFRelease(variations); ::CFRelease(variations);
mVariationFont = true;
} else { } else {
::CFRetain(baseFont); ::CFRetain(baseFont);
mCGFont = baseFont; mCGFont = baseFont;

View file

@ -106,7 +106,7 @@ protected:
Metrics mMetrics; Metrics mMetrics;
uint32_t mSpaceGlyph; uint32_t mSpaceGlyph;
bool mVariationFont; // true if variations are in effect bool mVariationFont; // true if font has OpenType variations
}; };
#endif /* GFX_MACFONT_H */ #endif /* GFX_MACFONT_H */

View file

@ -54,6 +54,7 @@ public:
bool RequiresAATLayout() const { return mRequiresAAT; } bool RequiresAATLayout() const { return mRequiresAAT; }
bool HasVariations();
bool IsCFF(); bool IsCFF();
protected: protected:
@ -72,6 +73,8 @@ protected:
bool mRequiresAAT; bool mRequiresAAT;
bool mIsCFF; bool mIsCFF;
bool mIsCFFInitialized; bool mIsCFFInitialized;
bool mHasVariations;
bool mHasVariationsInitialized;
nsTHashtable<nsUint32HashKey> mAvailableTables; nsTHashtable<nsUint32HashKey> mAvailableTables;
}; };

View file

@ -247,6 +247,17 @@ MacOSFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBo
return new gfxMacFont(this, aFontStyle, 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 bool
MacOSFontEntry::IsCFF() MacOSFontEntry::IsCFF()
{ {
@ -268,7 +279,9 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
mFontRefInitialized(false), mFontRefInitialized(false),
mRequiresAAT(false), mRequiresAAT(false),
mIsCFF(false), mIsCFF(false),
mIsCFFInitialized(false) mIsCFFInitialized(false),
mHasVariations(false),
mHasVariationsInitialized(false)
{ {
mWeight = aWeight; mWeight = aWeight;
} }
@ -285,7 +298,9 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
mFontRefInitialized(false), mFontRefInitialized(false),
mRequiresAAT(false), mRequiresAAT(false),
mIsCFF(false), mIsCFF(false),
mIsCFFInitialized(false) mIsCFFInitialized(false),
mHasVariations(false),
mHasVariationsInitialized(false)
{ {
mFontRef = aFontRef; mFontRef = aFontRef;
mFontRefInitialized = true; mFontRefInitialized = true;

View file

@ -25,7 +25,11 @@ endif
ifeq ($(OS_ARCH),WINNT) #{ ifeq ($(OS_ARCH),WINNT) #{
# Note the manifest file exists in the tree, so we use the explicit filename # Note the manifest file exists in the tree, so we use the explicit filename
# here. # 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 #} endif #}
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{ ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{

View file

@ -53,6 +53,8 @@ if CONFIG['OS_ARCH'] == 'WINNT':
'xul.dll', 'xul.dll',
] ]
RCINCLUDE = 'plugin-container.rc'
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin': if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
# For sandbox includes and the include dependencies those have # For sandbox includes and the include dependencies those have
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="plugin-container"
type="win32"
/>
<description>Firefox Runtime</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
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">
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
</ms_asmv3:windowsSettings>
</ms_asmv3:application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
</assembly>

View file

@ -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

View file

@ -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

View file

@ -0,0 +1 @@
<span style="font:36px -apple-system;font-weight:normal;padding:2px;background:black">abcdefghijklmnopqrstuvwxyz

View file

@ -187,6 +187,7 @@ HTTP(..) != fallback-mark-stacking-1.html fallback-mark-stacking-1-notref.html
HTTP(..) != 1170688.html 1170688-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 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 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); # ensure emoji chars don't render blank (bug 715798, bug 779042);
# should at least render hexboxes if there's no font support # should at least render hexboxes if there's no font support

View file

@ -400,13 +400,14 @@ nsXULPopupManager::GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain)
NS_ASSERTION(aWidgetChain, "null parameter"); NS_ASSERTION(aWidgetChain, "null parameter");
nsMenuChainItem* item = GetTopVisibleMenu(); nsMenuChainItem* item = GetTopVisibleMenu();
while (item) { while (item) {
nsMenuChainItem* parent = item->GetParent();
if (!item->IsNoAutoHide()) {
nsCOMPtr<nsIWidget> widget = item->Frame()->GetWidget(); nsCOMPtr<nsIWidget> widget = item->Frame()->GetWidget();
NS_ASSERTION(widget, "open popup has no widget"); NS_ASSERTION(widget, "open popup has no widget");
aWidgetChain->AppendElement(widget.get()); aWidgetChain->AppendElement(widget.get());
// In the case when a menulist inside a panel is open, clicking in the // 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, // panel should still roll up the menu, so if a different type is found,
// stop scanning. // stop scanning.
nsMenuChainItem* parent = item->GetParent();
if (!sameTypeCount) { if (!sameTypeCount) {
count++; count++;
if (!parent || item->Frame()->PopupType() != parent->Frame()->PopupType() || if (!parent || item->Frame()->PopupType() != parent->Frame()->PopupType() ||
@ -414,6 +415,8 @@ nsXULPopupManager::GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain)
sameTypeCount = count; sameTypeCount = count;
} }
} }
}
item = parent; item = parent;
} }
@ -1048,8 +1051,14 @@ nsXULPopupManager::HidePopup(nsIContent* aPopup,
// entire chain or the item to hide isn't the topmost popup. // entire chain or the item to hide isn't the topmost popup.
nsMenuChainItem* parent = topMenu->GetParent(); nsMenuChainItem* parent = topMenu->GetParent();
if (parent && (aHideChain || topMenu != foundPopup)) { if (parent && (aHideChain || topMenu != foundPopup)) {
while (parent && parent->IsNoAutoHide()) {
parent = parent->GetParent();
}
if (parent) {
nextPopup = parent->Content(); nextPopup = parent->Content();
} }
}
lastPopup = aLastPopup ? aLastPopup : (aHideChain ? nullptr : aPopup); lastPopup = aLastPopup ? aLastPopup : (aHideChain ? nullptr : aPopup);
} }

View file

@ -49,11 +49,18 @@ public class WebAppActivity extends GeckoApp {
private static final String LOGTAG = "WebAppActivity"; private static final String LOGTAG = "WebAppActivity";
private TextView mUrlView; private TextView mUrlView;
private String mManifestPath;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(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); final Toolbar toolbar = (Toolbar) findViewById(R.id.actionbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
@ -108,6 +115,13 @@ public class WebAppActivity extends GeckoApp {
} }
} }
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(WebAppActivity.MANIFEST_PATH, mManifestPath);
}
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
@ -140,23 +154,22 @@ public class WebAppActivity extends GeckoApp {
.equals(Uri.parse(launchUrl).getHost()); .equals(Uri.parse(launchUrl).getHost());
if (!isSameDomain) { if (!isSameDomain) {
loadManifest(externalIntent); mManifestPath = externalIntent.getStringExtra(WebAppActivity.MANIFEST_PATH);
loadManifest(mManifestPath);
Tabs.getInstance().loadUrl(launchUrl); Tabs.getInstance().loadUrl(launchUrl);
} }
} }
private void loadManifest(Intent intent) { private void loadManifest(String manifestPath) {
String manifestPath = intent.getStringExtra(WebAppActivity.MANIFEST_PATH); if (manifestPath == null) {
if (manifestPath != null) { Log.e(LOGTAG, "Missing manifest");
updateFromManifest(manifestPath); return;
}
} }
private void updateFromManifest(String manifestPath) {
try { try {
final File manifestFile = new File(manifestPath); final File manifestFile = new File(manifestPath);
final JSONObject manifest = FileUtils.readJSONObjectFromFile(manifestFile); 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 Integer color = readColorFromManifest(manifestField);
final String name = readNameFromManifest(manifestField); final String name = readNameFromManifest(manifestField);
final Bitmap icon = readIconFromManifest(manifest); final Bitmap icon = readIconFromManifest(manifest);
@ -180,27 +193,27 @@ public class WebAppActivity extends GeckoApp {
} }
} }
private Integer readColorFromManifest(JSONObject manifest) throws JSONException { private Integer readColorFromManifest(JSONObject manifest) {
final String colorStr = (String) manifest.get("theme_color"); final String colorStr = manifest.optString("theme_color", null);
if (colorStr != null) { if (colorStr != null) {
return ColorUtil.parseStringColor(colorStr); return ColorUtil.parseStringColor(colorStr);
} }
return null; return null;
} }
private String readNameFromManifest(JSONObject manifest) throws JSONException { private String readNameFromManifest(JSONObject manifest) {
String name = (String) manifest.get("name"); String name = manifest.optString("name", null);
if (name == null) { if (name == null) {
name = (String) manifest.get("short_name"); name = manifest.optString("short_name", null);
} }
if (name == null) { if (name == null) {
name = (String) manifest.get("start_url"); name = manifest.optString("start_url", null);
} }
return name; return name;
} }
private Bitmap readIconFromManifest(JSONObject manifest) throws JSONException { private Bitmap readIconFromManifest(JSONObject manifest) {
final String iconStr = (String) manifest.get("cached_icon"); final String iconStr = manifest.optString("cached_icon", null);
if (iconStr != null) { if (iconStr != null) {
return FaviconDecoder return FaviconDecoder
.decodeDataURI(getContext(), iconStr) .decodeDataURI(getContext(), iconStr)

View file

@ -198,9 +198,6 @@ pref("dom.gamepad.non_standard_events.enabled", true);
#endif #endif
pref("dom.gamepad.extensions.enabled", false); 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 // If this is true, TextEventDispatcher dispatches keydown and keyup events
// even during composition (keypress events are never fired during composition // even during composition (keypress events are never fired during composition
// even if this is true). // even if this is true).
@ -3081,6 +3078,9 @@ pref("dom.ipc.processCount", 4);
pref("dom.ipc.processCount", 1); pref("dom.ipc.processCount", 1);
#endif #endif
// Default to allow only one file:// URL content process.
pref("dom.ipc.processCount.file", 1);
// WebExtensions only support a single extension process. // WebExtensions only support a single extension process.
pref("dom.ipc.processCount.extension", 1); pref("dom.ipc.processCount.extension", 1);

View file

@ -24,6 +24,7 @@ nsHtml5AtomEntry::~nsHtml5AtomEntry()
} }
nsHtml5AtomTable::nsHtml5AtomTable() nsHtml5AtomTable::nsHtml5AtomTable()
: mRecentlyUsedParserAtoms{}
{ {
#ifdef DEBUG #ifdef DEBUG
NS_GetMainThread(getter_AddRefs(mPermittedLookupThread)); NS_GetMainThread(getter_AddRefs(mPermittedLookupThread));
@ -44,13 +45,23 @@ nsHtml5AtomTable::GetAtom(const nsAString& aKey)
NS_ASSERTION(mPermittedLookupThread == currentThread, "Wrong thread!"); NS_ASSERTION(mPermittedLookupThread == currentThread, "Wrong thread!");
} }
#endif #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); nsIAtom* atom = NS_GetStaticAtom(aKey);
if (atom) { if (atom) {
mRecentlyUsedParserAtoms[index] = atom;
return atom; return atom;
} }
nsHtml5AtomEntry* entry = mTable.PutEntry(aKey); nsHtml5AtomEntry* entry = mTable.PutEntry(aKey);
if (!entry) { if (!entry) {
return nullptr; return nullptr;
} }
mRecentlyUsedParserAtoms[index] = entry->GetAtom();
return entry->GetAtom(); return entry->GetAtom();
} }

View file

@ -11,6 +11,8 @@
#include "nsIAtom.h" #include "nsIAtom.h"
#include "nsIThread.h" #include "nsIThread.h"
#define RECENTLY_USED_PARSER_ATOMS_SIZE 31
class nsHtml5Atom; class nsHtml5Atom;
class nsHtml5AtomEntry : public nsStringHashKey class nsHtml5AtomEntry : public nsStringHashKey
@ -87,6 +89,9 @@ class nsHtml5AtomTable
*/ */
void Clear() void Clear()
{ {
for (uint32_t i = 0; i < RECENTLY_USED_PARSER_ATOMS_SIZE; ++i) {
mRecentlyUsedParserAtoms[i] = nullptr;
}
mTable.Clear(); mTable.Clear();
} }
@ -99,6 +104,7 @@ class nsHtml5AtomTable
private: private:
nsTHashtable<nsHtml5AtomEntry> mTable; nsTHashtable<nsHtml5AtomEntry> mTable;
nsIAtom* mRecentlyUsedParserAtoms[RECENTLY_USED_PARSER_ATOMS_SIZE];
#ifdef DEBUG #ifdef DEBUG
nsCOMPtr<nsIThread> mPermittedLookupThread; nsCOMPtr<nsIThread> mPermittedLookupThread;
#endif #endif

View file

@ -53,7 +53,7 @@ class PublishBalrog(MercurialScript, BuildbotMixin):
# TODO: version and appVersion should come from repo # TODO: version and appVersion should come from repo
props = self.buildbot_config["properties"] props = self.buildbot_config["properties"]
for prop in ['product', 'version', 'build_number', 'channels', for prop in ['product', 'version', 'build_number', 'channels',
'balrog_api_root']: 'balrog_api_root', 'schedule_at', 'background_rate']:
if props.get(prop): if props.get(prop):
self.info("Overriding %s with %s" % (prop, props[prop])) self.info("Overriding %s with %s" % (prop, props[prop]))
self.config[prop] = props.get(prop) self.config[prop] = props.get(prop)
@ -107,6 +107,10 @@ class PublishBalrog(MercurialScript, BuildbotMixin):
]) ])
for r in channel_config["publish_rules"]: for r in channel_config["publish_rules"]:
cmd.extend(["--rules", r]) 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)) self.retry(lambda: self.run_command(cmd, halt_on_failure=True))