mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Merge latest green b2g-inbound changeset and mozilla-central; a=merge
This commit is contained in:
commit
acd103862f
@ -9,9 +9,14 @@
|
||||
display: none;
|
||||
border-radius: 2px;
|
||||
box-shadow: 1px 1px 1px #444;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#virtual-cursor-inset {
|
||||
#virtual-cursor-box.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#virtual-cursor-box > div {
|
||||
border-radius: 1px;
|
||||
box-shadow: inset 1px 1px 1px #444;
|
||||
display: block;
|
||||
|
@ -394,23 +394,19 @@ this.AccessFu = { // jshint ignore:line
|
||||
_processedMessageManagers: [],
|
||||
|
||||
/**
|
||||
* Adjusts the given bounds relative to the given browser. Converts from
|
||||
* screen or device pixels to either device or CSS pixels.
|
||||
* Adjusts the given bounds relative to the given browser.
|
||||
* @param {Rect} aJsonBounds the bounds to adjust
|
||||
* @param {browser} aBrowser the browser we want the bounds relative to
|
||||
* @param {bool} aToCSSPixels whether to convert to CSS pixels (as opposed to
|
||||
* device pixels)
|
||||
* @param {bool} aFromDevicePixels whether to convert from device pixels (as
|
||||
* opposed to screen pixels)
|
||||
*/
|
||||
adjustContentBounds:
|
||||
function(aJsonBounds, aBrowser, aToCSSPixels, aFromDevicePixels) {
|
||||
function(aJsonBounds, aBrowser, aToCSSPixels) {
|
||||
let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
|
||||
aJsonBounds.right - aJsonBounds.left,
|
||||
aJsonBounds.bottom - aJsonBounds.top);
|
||||
let win = Utils.win;
|
||||
let dpr = win.devicePixelRatio;
|
||||
let vp = Utils.getViewport(win);
|
||||
let offset = { left: -win.mozInnerScreenX, top: -win.mozInnerScreenY };
|
||||
|
||||
if (!aBrowser.contentWindow) {
|
||||
@ -421,16 +417,6 @@ this.AccessFu = { // jshint ignore:line
|
||||
offset.left += clientRect.left + win.mozInnerScreenX;
|
||||
offset.top += clientRect.top + win.mozInnerScreenY;
|
||||
}
|
||||
|
||||
// Here we scale from screen pixels to layout device pixels by dividing by
|
||||
// the resolution (caused by pinch-zooming). The resolution is the
|
||||
// viewport zoom divided by the devicePixelRatio. If there's no viewport,
|
||||
// then we're on a platform without pinch-zooming and we can just ignore
|
||||
// this.
|
||||
if (!aFromDevicePixels && vp) {
|
||||
bounds = bounds.scale(vp.zoom / dpr, vp.zoom / dpr);
|
||||
}
|
||||
|
||||
// Add the offset; the offset is in CSS pixels, so multiply the
|
||||
// devicePixelRatio back in before adding to preserve unit consistency.
|
||||
bounds = bounds.translate(offset.left * dpr, offset.top * dpr);
|
||||
@ -545,11 +531,10 @@ var Output = {
|
||||
highlightBox.id = 'virtual-cursor-box';
|
||||
|
||||
// Add highlight inset for inner shadow
|
||||
let inset = Utils.win.document.
|
||||
createElementNS('http://www.w3.org/1999/xhtml', 'div');
|
||||
inset.id = 'virtual-cursor-inset';
|
||||
highlightBox.appendChild(
|
||||
Utils.win.document.createElementNS(
|
||||
'http://www.w3.org/1999/xhtml', 'div'));
|
||||
|
||||
highlightBox.appendChild(inset);
|
||||
this.highlightBox = Cu.getWeakReference(highlightBox);
|
||||
} else {
|
||||
highlightBox = this.highlightBox.get();
|
||||
@ -559,12 +544,12 @@ var Output = {
|
||||
let r = AccessFu.adjustContentBounds(aDetail.bounds, aBrowser, true);
|
||||
|
||||
// First hide it to avoid flickering when changing the style.
|
||||
highlightBox.style.display = 'none';
|
||||
highlightBox.classList.remove('show');
|
||||
highlightBox.style.top = (r.top - padding) + 'px';
|
||||
highlightBox.style.left = (r.left - padding) + 'px';
|
||||
highlightBox.style.width = (r.width + padding*2) + 'px';
|
||||
highlightBox.style.height = (r.height + padding*2) + 'px';
|
||||
highlightBox.style.display = 'block';
|
||||
highlightBox.classList.add('show');
|
||||
|
||||
break;
|
||||
}
|
||||
@ -572,7 +557,7 @@ var Output = {
|
||||
{
|
||||
let highlightBox = this.highlightBox ? this.highlightBox.get() : null;
|
||||
if (highlightBox) {
|
||||
highlightBox.style.display = 'none';
|
||||
highlightBox.classList.remove('show');
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -889,8 +874,7 @@ var Input = {
|
||||
activateContextMenu: function activateContextMenu(aDetails) {
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
let p = AccessFu.adjustContentBounds(aDetails.bounds,
|
||||
Utils.CurrentBrowser,
|
||||
true, true).center();
|
||||
Utils.CurrentBrowser, true).center();
|
||||
Services.obs.notifyObservers(null, 'Gesture:LongPress',
|
||||
JSON.stringify({x: p.x, y: p.y}));
|
||||
}
|
||||
@ -915,8 +899,8 @@ var Input = {
|
||||
doScroll: function doScroll(aDetails) {
|
||||
let horizontal = aDetails.horizontal;
|
||||
let page = aDetails.page;
|
||||
let p = AccessFu.adjustContentBounds(aDetails.bounds, Utils.CurrentBrowser,
|
||||
true, true).center();
|
||||
let p = AccessFu.adjustContentBounds(
|
||||
aDetails.bounds, Utils.CurrentBrowser, true).center();
|
||||
Utils.winUtils.sendWheelEvent(p.x, p.y,
|
||||
horizontal ? page : 0, horizontal ? 0 : page, 0,
|
||||
Utils.win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
|
||||
|
@ -255,15 +255,6 @@ this.Utils = { // jshint ignore:line
|
||||
}
|
||||
},
|
||||
|
||||
getViewport: function getViewport(aWindow) {
|
||||
switch (this.MozBuildApp) {
|
||||
case 'mobile/android':
|
||||
return aWindow.BrowserApp.selectedTab.getViewport();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
getState: function getState(aAccessibleOrEvent) {
|
||||
if (aAccessibleOrEvent instanceof Ci.nsIAccessibleStateChangeEvent) {
|
||||
return new State(
|
||||
@ -302,18 +293,37 @@ this.Utils = { // jshint ignore:line
|
||||
return doc.QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
|
||||
},
|
||||
|
||||
getBounds: function getBounds(aAccessible) {
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
aAccessible.getBounds(objX, objY, objW, objH);
|
||||
return new Rect(objX.value, objY.value, objW.value, objH.value);
|
||||
getContentResolution: function _getContentResolution(aAccessible) {
|
||||
let resX = { value: 1 }, resY = { value: 1 };
|
||||
aAccessible.document.window.QueryInterface(
|
||||
Ci.nsIInterfaceRequestor).getInterface(
|
||||
Ci.nsIDOMWindowUtils).getResolution(resX, resY);
|
||||
return [resX.value, resY.value];
|
||||
},
|
||||
|
||||
getTextBounds: function getTextBounds(aAccessible, aStart, aEnd) {
|
||||
let accText = aAccessible.QueryInterface(Ci.nsIAccessibleText);
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
accText.getRangeExtents(aStart, aEnd, objX, objY, objW, objH,
|
||||
Ci.nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE);
|
||||
return new Rect(objX.value, objY.value, objW.value, objH.value);
|
||||
getBounds: function getBounds(aAccessible, aPreserveContentScale) {
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
aAccessible.getBounds(objX, objY, objW, objH);
|
||||
|
||||
let [scaleX, scaleY] = aPreserveContentScale ? [1, 1] :
|
||||
this.getContentResolution(aAccessible);
|
||||
|
||||
return new Rect(objX.value, objY.value, objW.value, objH.value).scale(
|
||||
scaleX, scaleY);
|
||||
},
|
||||
|
||||
getTextBounds: function getTextBounds(aAccessible, aStart, aEnd,
|
||||
aPreserveContentScale) {
|
||||
let accText = aAccessible.QueryInterface(Ci.nsIAccessibleText);
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
accText.getRangeExtents(aStart, aEnd, objX, objY, objW, objH,
|
||||
Ci.nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE);
|
||||
|
||||
let [scaleX, scaleY] = aPreserveContentScale ? [1, 1] :
|
||||
this.getContentResolution(aAccessible);
|
||||
|
||||
return new Rect(objX.value, objY.value, objW.value, objH.value).scale(
|
||||
scaleX, scaleY);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -65,14 +65,10 @@ function forwardToChild(aMessage, aListener, aVCPosition) {
|
||||
}
|
||||
|
||||
function activateContextMenu(aMessage) {
|
||||
function sendContextMenuCoordinates(aAccessible) {
|
||||
let bounds = Utils.getBounds(aAccessible);
|
||||
sendAsyncMessage('AccessFu:ActivateContextMenu', {bounds: bounds});
|
||||
}
|
||||
|
||||
let position = Utils.getVirtualCursor(content.document).position;
|
||||
if (!forwardToChild(aMessage, activateContextMenu, position)) {
|
||||
sendContextMenuCoordinates(position);
|
||||
sendAsyncMessage('AccessFu:ActivateContextMenu',
|
||||
{ bounds: Utils.getBounds(position, true) });
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,16 +81,12 @@ function presentCaretChange(aText, aOldOffset, aNewOffset) {
|
||||
}
|
||||
|
||||
function scroll(aMessage) {
|
||||
function sendScrollCoordinates(aAccessible) {
|
||||
let bounds = Utils.getBounds(aAccessible);
|
||||
sendAsyncMessage('AccessFu:DoScroll',
|
||||
{ bounds: bounds,
|
||||
page: aMessage.json.page,
|
||||
horizontal: aMessage.json.horizontal });
|
||||
}
|
||||
|
||||
let position = Utils.getVirtualCursor(content.document).position;
|
||||
if (!forwardToChild(aMessage, scroll, position)) {
|
||||
sendAsyncMessage('AccessFu:DoScroll',
|
||||
{ bounds: Utils.getBounds(position, true),
|
||||
page: aMessage.json.page,
|
||||
horizontal: aMessage.json.horizontal });
|
||||
sendScrollCoordinates(position);
|
||||
}
|
||||
}
|
||||
|
@ -407,18 +407,18 @@ const nodeResolve = iced(function nodeResolve(id, requirer, { rootURI }) {
|
||||
let fullId = join(rootURI, id);
|
||||
|
||||
let resolvedPath;
|
||||
if (resolvedPath = loadAsFile(fullId))
|
||||
if ((resolvedPath = loadAsFile(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
else if (resolvedPath = loadAsDirectory(fullId))
|
||||
else if ((resolvedPath = loadAsDirectory(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
// If manifest has dependencies, attempt to look up node modules
|
||||
// in the `dependencies` list
|
||||
else {
|
||||
let dirs = getNodeModulePaths(dirname(join(rootURI, requirer))).map(dir => join(dir, id));
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
if (resolvedPath = loadAsFile(dirs[i]))
|
||||
if ((resolvedPath = loadAsFile(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
if (resolvedPath = loadAsDirectory(dirs[i]))
|
||||
if ((resolvedPath = loadAsDirectory(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
}
|
||||
}
|
||||
@ -459,7 +459,7 @@ function loadAsDirectory (path) {
|
||||
let main = getManifestMain(JSON.parse(readURI(path + '/package.json')));
|
||||
if (main != null) {
|
||||
let tmpPath = join(path, main);
|
||||
if (found = loadAsFile(tmpPath))
|
||||
if ((found = loadAsFile(tmpPath)))
|
||||
return found
|
||||
}
|
||||
try {
|
||||
|
@ -1201,8 +1201,7 @@ const kTransferContractId = "@mozilla.org/transfer;1";
|
||||
|
||||
// Override Toolkit's nsITransfer implementation with the one from the
|
||||
// JavaScript API for downloads. This will eventually be removed when
|
||||
// nsIDownloadManager will not be available anymore (bug 851471). The
|
||||
// old code in this module will be removed in bug 899110.
|
||||
// nsIDownloadManager will not be available anymore (bug 851471).
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
|
||||
.registerFactory(kTransferCid, "",
|
||||
kTransferContractId, null);
|
||||
|
@ -980,7 +980,11 @@ pref("browser.safebrowsing.reportMalwareURL", "http://%LOCALE%.malware-report.mo
|
||||
pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%");
|
||||
|
||||
pref("browser.safebrowsing.malware.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
|
||||
// Turn off remote lookups in beta and stable channel.
|
||||
#ifndef RELEASE_BUILD
|
||||
pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
|
||||
#endif
|
||||
|
||||
#ifdef MOZILLA_OFFICIAL
|
||||
// Normally the "client ID" sent in updates is appinfo.name, but for
|
||||
|
@ -438,6 +438,13 @@ var gPopupBlockerObserver = {
|
||||
// Hide the icon in the location bar (if the location bar exists)
|
||||
if (gURLBar)
|
||||
this._reportButton.hidden = true;
|
||||
|
||||
// Hide the notification box (if it's visible).
|
||||
var notificationBox = gBrowser.getNotificationBox();
|
||||
var notification = notificationBox.getNotificationWithValue("popup-blocked");
|
||||
if (notification) {
|
||||
notificationBox.removeNotification(notification, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -293,7 +293,14 @@ AppCacheUtils.prototype = {
|
||||
},
|
||||
|
||||
clearAll: function ACU_clearAll() {
|
||||
Services.cache.evictEntries(Ci.nsICache.STORE_OFFLINE);
|
||||
if (!Services.prefs.getBoolPref("browser.cache.disk.enable")) {
|
||||
throw new Error(l10n.GetStringFromName("cacheDisabled"));
|
||||
}
|
||||
|
||||
let appCacheStorage = Services.cache2.appCacheStorage(LoadContextInfo.default, null);
|
||||
appCacheStorage.asyncEvictStorage({
|
||||
onCacheEntryDoomed: function(result) {}
|
||||
});
|
||||
},
|
||||
|
||||
_getManifestURI: function ACU__getManifestURI() {
|
||||
|
@ -15,7 +15,7 @@ let test = asyncTest(function*() {
|
||||
|
||||
info("Creating the test document");
|
||||
content.document.body.innerHTML = '<style type="text/css"> ' +
|
||||
'span { font-variant: small-caps; color: #000000; } ' +
|
||||
'span { font-variant-caps: small-caps; color: #000000; } ' +
|
||||
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
|
||||
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
|
||||
'<h1>Some header text</h1>\n' +
|
||||
@ -58,7 +58,7 @@ function checkCopySelection(view) {
|
||||
|
||||
let expectedPattern = "font-family: helvetica,sans-serif;[\\r\\n]+" +
|
||||
"font-size: 16px;[\\r\\n]+" +
|
||||
"font-variant: small-caps;[\\r\\n]*";
|
||||
"font-variant-caps: small-caps;[\\r\\n]*";
|
||||
|
||||
return waitForClipboard(() => {
|
||||
fireCopyEvent(props[0]);
|
||||
@ -80,7 +80,7 @@ function checkSelectAll(view) {
|
||||
let expectedPattern = "color: #FF0;[\\r\\n]+" +
|
||||
"font-family: helvetica,sans-serif;[\\r\\n]+" +
|
||||
"font-size: 16px;[\\r\\n]+" +
|
||||
"font-variant: small-caps;[\\r\\n]*";
|
||||
"font-variant-caps: small-caps;[\\r\\n]*";
|
||||
|
||||
return waitForClipboard(() => {
|
||||
fireCopyEvent(prop);
|
||||
|
@ -816,6 +816,7 @@ bin/libfreebl_32int64_3.so
|
||||
@BINPATH@/webapprt/components/PaymentUIGlue.js
|
||||
@BINPATH@/webapprt/components/components.manifest
|
||||
@BINPATH@/webapprt/defaults/preferences/prefs.js
|
||||
@BINPATH@/webapprt/modules/DownloadView.jsm
|
||||
@BINPATH@/webapprt/modules/Startup.jsm
|
||||
@BINPATH@/webapprt/modules/WebappRT.jsm
|
||||
@BINPATH@/webapprt/modules/WebappManager.jsm
|
||||
|
@ -28,12 +28,43 @@ leak:GI___strdup
|
||||
|
||||
|
||||
###
|
||||
### Many leaks only affect some test suites. The suite annotations are not checked.
|
||||
### Bug 979928 - WebRTC leaks. m2, m3.
|
||||
###
|
||||
|
||||
# Bug 979928 - WebRTC is leaky. m2, m3
|
||||
leak:/media/mtransport/
|
||||
leak:/media/webrtc/signaling/
|
||||
# WebRTC leaks added for Mochitest 2.
|
||||
leak:NR_reg_init
|
||||
leak:fsmdef_init
|
||||
leak:r_log_register
|
||||
leak:nr_reg_set
|
||||
leak:ccsnap_device_init
|
||||
leak:ccsnap_line_init
|
||||
leak:media/webrtc/signaling/src/sipcc/core/common/init.c
|
||||
leak:cprPostMessage
|
||||
leak:mozilla::NrIceStunServer::Create
|
||||
|
||||
# Additional WebRTC leak suppressions added for Mochitest 3.
|
||||
leak:mozilla::TransportLayerDtls::Setup
|
||||
leak:mozilla::NrIceTurnServer::Create
|
||||
# There are about 228KB of leaks from the call to |pmsg->sdp = cpr_malloc(sdp_size);|
|
||||
# in send_message_helper.
|
||||
leak:send_message_helper
|
||||
leak:fsmdef_ev_createoffer
|
||||
leak:fsmdef_ev_setremotedesc
|
||||
leak:fsmdef_ev_setlocaldesc
|
||||
leak:fsmdef_ev_createanswer
|
||||
# About 70KB of leaks under this stack.
|
||||
leak:vcmRxAllocICE_s
|
||||
leak:vcmRxStartICE_m
|
||||
# About 50KB of leaks under this stack.
|
||||
leak:ccsnap_EscapeStrToLocaleStr
|
||||
leak:gsmsdp_add_default_audio_formats_to_local_sdp
|
||||
leak:gsmsdp_add_default_video_formats_to_local_sdp
|
||||
leak:CCAPI_CallInfo_getMediaStreams
|
||||
|
||||
|
||||
###
|
||||
### Many leaks only affect some test suites. The suite annotations are not checked.
|
||||
###
|
||||
|
||||
# Bug 981195 - Small leak in the parser. m4
|
||||
leak:TypeCompartment::fixObjectType
|
||||
|
@ -728,7 +728,7 @@ public:
|
||||
int32_t ScrollTop()
|
||||
{
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
return sf ? sf->GetScrollPositionCSSPixels().y : 0;
|
||||
return sf ? sf->GetScrollPositionCSSPixels().y.value : 0;
|
||||
}
|
||||
void SetScrollTop(int32_t aScrollTop)
|
||||
{
|
||||
@ -741,7 +741,7 @@ public:
|
||||
int32_t ScrollLeft()
|
||||
{
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
return sf ? sf->GetScrollPositionCSSPixels().x : 0;
|
||||
return sf ? sf->GetScrollPositionCSSPixels().x.value : 0;
|
||||
}
|
||||
void SetScrollLeft(int32_t aScrollLeft)
|
||||
{
|
||||
|
@ -405,15 +405,6 @@ public:
|
||||
static bool CanCallerAccess(nsPIDOMWindow* aWindow);
|
||||
|
||||
/**
|
||||
* Get the window through the JS context that's currently on the stack.
|
||||
* If there's no JS context currently on the stack, returns null.
|
||||
*/
|
||||
static nsPIDOMWindow *GetWindowFromCaller();
|
||||
|
||||
/**
|
||||
* The two GetDocumentFrom* functions below allow a caller to get at a
|
||||
* document that is relevant to the currently executing script.
|
||||
*
|
||||
* GetDocumentFromCaller gets its document by looking at the last called
|
||||
* function and finding the document that the function itself relates to.
|
||||
* For example, consider two windows A and B in the same origin. B has a
|
||||
@ -421,28 +412,10 @@ public:
|
||||
* If a script in window A were to call B's function, GetDocumentFromCaller
|
||||
* would find that function (in B) and return B's document.
|
||||
*
|
||||
* GetDocumentFromContext gets its document by looking at the currently
|
||||
* executing context's global object and returning its document. Thus,
|
||||
* given the example above, GetDocumentFromCaller would see that the
|
||||
* currently executing script was in window A, and return A's document.
|
||||
*/
|
||||
/**
|
||||
* Get the document from the currently executing function. This will return
|
||||
* the document that the currently executing function is in/from.
|
||||
*
|
||||
* @return The document or null if no JS Context.
|
||||
*/
|
||||
static nsIDocument* GetDocumentFromCaller();
|
||||
|
||||
/**
|
||||
* Get the document through the JS context that's currently on the stack.
|
||||
* If there's no JS context currently on the stack it will return null.
|
||||
* This will return the document of the calling script.
|
||||
*
|
||||
* @return The document or null if no JS context
|
||||
*/
|
||||
static nsIDocument* GetDocumentFromContext();
|
||||
|
||||
// Check if a node is in the document prolog, i.e. before the document
|
||||
// element.
|
||||
static bool InProlog(nsINode *aNode);
|
||||
@ -2279,9 +2252,7 @@ private:
|
||||
|
||||
static bool sInitialized;
|
||||
static uint32_t sScriptBlockerCount;
|
||||
#ifdef DEBUG
|
||||
static uint32_t sDOMNodeRemovedSuppressCount;
|
||||
#endif
|
||||
static uint32_t sMicroTaskLevel;
|
||||
// Not an nsCOMArray because removing elements from those is slower
|
||||
static nsTArray< nsCOMPtr<nsIRunnable> >* sBlockedScriptRunners;
|
||||
@ -2338,14 +2309,10 @@ class MOZ_STACK_CLASS nsAutoScriptBlockerSuppressNodeRemoved :
|
||||
public nsAutoScriptBlocker {
|
||||
public:
|
||||
nsAutoScriptBlockerSuppressNodeRemoved() {
|
||||
#ifdef DEBUG
|
||||
++nsContentUtils::sDOMNodeRemovedSuppressCount;
|
||||
#endif
|
||||
}
|
||||
~nsAutoScriptBlockerSuppressNodeRemoved() {
|
||||
#ifdef DEBUG
|
||||
--nsContentUtils::sDOMNodeRemovedSuppressCount;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -686,7 +686,7 @@ WebSocket::Init(JSContext* aCx,
|
||||
// Confirmed we are opening plain ws:// and want to prevent this from a
|
||||
// secure context (e.g. https). Check the principal's uri to determine if
|
||||
// we were loaded from https.
|
||||
nsCOMPtr<nsIGlobalObject> globalObject(BrokenGetEntryGlobal());
|
||||
nsCOMPtr<nsIGlobalObject> globalObject(GetEntryGlobal());
|
||||
if (globalObject) {
|
||||
nsCOMPtr<nsIPrincipal> principal(globalObject->PrincipalOrNull());
|
||||
if (principal) {
|
||||
|
@ -214,9 +214,7 @@ nsILineBreaker *nsContentUtils::sLineBreaker;
|
||||
nsIWordBreaker *nsContentUtils::sWordBreaker;
|
||||
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
|
||||
uint32_t nsContentUtils::sScriptBlockerCount = 0;
|
||||
#ifdef DEBUG
|
||||
uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
|
||||
#endif
|
||||
uint32_t nsContentUtils::sMicroTaskLevel = 0;
|
||||
nsTArray< nsCOMPtr<nsIRunnable> >* nsContentUtils::sBlockedScriptRunners = nullptr;
|
||||
uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
|
||||
@ -1953,19 +1951,6 @@ nsContentUtils::TraceSafeJSContext(JSTracer* aTrc)
|
||||
}
|
||||
}
|
||||
|
||||
nsPIDOMWindow *
|
||||
nsContentUtils::GetWindowFromCaller()
|
||||
{
|
||||
JSContext *cx = GetCurrentJSContext();
|
||||
if (cx) {
|
||||
nsCOMPtr<nsPIDOMWindow> win =
|
||||
do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
|
||||
return win;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsContentUtils::GetDocumentFromCaller()
|
||||
{
|
||||
@ -1980,24 +1965,6 @@ nsContentUtils::GetDocumentFromCaller()
|
||||
return win->GetExtantDoc();
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsContentUtils::GetDocumentFromContext()
|
||||
{
|
||||
JSContext *cx = GetCurrentJSContext();
|
||||
if (cx) {
|
||||
nsIScriptGlobalObject *sgo = nsJSUtils::GetDynamicScriptGlobal(cx);
|
||||
|
||||
if (sgo) {
|
||||
nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(sgo);
|
||||
if (pwin) {
|
||||
return pwin->GetExtantDoc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsCallerChrome()
|
||||
{
|
||||
@ -3920,30 +3887,27 @@ nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
|
||||
NS_PRECONDITION(aChild->GetParentNode() == aParent, "Wrong parent");
|
||||
NS_PRECONDITION(aChild->OwnerDoc() == aOwnerDoc, "Wrong owner-doc");
|
||||
|
||||
// This checks that IsSafeToRunScript is true since we don't want to fire
|
||||
// events when that is false. We can't rely on EventDispatcher to assert
|
||||
// this in this situation since most of the time there are no mutation
|
||||
// event listeners, in which case we won't even attempt to dispatch events.
|
||||
// However this also allows for two exceptions. First off, we don't assert
|
||||
// if the mutation happens to native anonymous content since we never fire
|
||||
// mutation events on such content anyway.
|
||||
// Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
|
||||
// that is a know case when we'd normally fire a mutation event, but can't
|
||||
// make that safe and so we suppress it at this time. Ideally this should
|
||||
// go away eventually.
|
||||
NS_ASSERTION((aChild->IsNodeOfType(nsINode::eCONTENT) &&
|
||||
static_cast<nsIContent*>(aChild)->
|
||||
IsInNativeAnonymousSubtree()) ||
|
||||
IsSafeToRunScript() ||
|
||||
sDOMNodeRemovedSuppressCount,
|
||||
"Want to fire DOMNodeRemoved event, but it's not safe");
|
||||
|
||||
// Having an explicit check here since it's an easy mistake to fall into,
|
||||
// and there might be existing code with problems. We'd rather be safe
|
||||
// than fire DOMNodeRemoved in all corner cases. We also rely on it for
|
||||
// nsAutoScriptBlockerSuppressNodeRemoved.
|
||||
if (!IsSafeToRunScript()) {
|
||||
WarnScriptWasIgnored(aOwnerDoc);
|
||||
// This checks that IsSafeToRunScript is true since we don't want to fire
|
||||
// events when that is false. We can't rely on EventDispatcher to assert
|
||||
// this in this situation since most of the time there are no mutation
|
||||
// event listeners, in which case we won't even attempt to dispatch events.
|
||||
// However this also allows for two exceptions. First off, we don't assert
|
||||
// if the mutation happens to native anonymous content since we never fire
|
||||
// mutation events on such content anyway.
|
||||
// Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
|
||||
// that is a know case when we'd normally fire a mutation event, but can't
|
||||
// make that safe and so we suppress it at this time. Ideally this should
|
||||
// go away eventually.
|
||||
if (!(aChild->IsContent() && aChild->AsContent()->IsInNativeAnonymousSubtree()) &&
|
||||
!sDOMNodeRemovedSuppressCount) {
|
||||
NS_ERROR("Want to fire DOMNodeRemoved event, but it's not safe");
|
||||
WarnScriptWasIgnored(aOwnerDoc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1429,10 +1429,10 @@ nsHTMLDocument::Open(JSContext* cx,
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
// Note: We want to use GetDocumentFromContext here because this document
|
||||
// Note: We want to use GetEntryDocument here because this document
|
||||
// should inherit the security information of the document that's opening us,
|
||||
// (since if it's secure, then it's presumably trusted).
|
||||
nsCOMPtr<nsIDocument> callerDoc = nsContentUtils::GetDocumentFromContext();
|
||||
nsCOMPtr<nsIDocument> callerDoc = GetEntryDocument();
|
||||
if (!callerDoc) {
|
||||
// If we're called from C++ or in some other way without an originating
|
||||
// document we can't do a document.open w/o changing the principal of the
|
||||
|
@ -128,14 +128,15 @@ GMPChild::Init(const std::string& aPluginPath,
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
||||
mPluginPath = aPluginPath;
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
|
||||
#endif
|
||||
#if defined(XP_WIN)
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#endif
|
||||
|
@ -75,6 +75,7 @@ private:
|
||||
public:
|
||||
ResourceQueue() :
|
||||
nsDeque(new ResourceQueueDeallocator()),
|
||||
mLogicalLength(0),
|
||||
mOffset(0)
|
||||
{
|
||||
}
|
||||
@ -87,12 +88,7 @@ private:
|
||||
// Returns the length of all items in the queue plus the offset.
|
||||
// This is the logical length of the resource.
|
||||
inline uint64_t GetLength() {
|
||||
uint64_t s = mOffset;
|
||||
for (uint32_t i = 0; i < GetSize(); ++i) {
|
||||
ResourceItem* item = ResourceAt(i);
|
||||
s += item->mData.Length();
|
||||
}
|
||||
return s;
|
||||
return mLogicalLength;
|
||||
}
|
||||
|
||||
// Copies aCount bytes from aOffset in the queue into aDest.
|
||||
@ -113,6 +109,7 @@ private:
|
||||
}
|
||||
|
||||
inline void PushBack(ResourceItem* aItem) {
|
||||
mLogicalLength += aItem->mData.Length();
|
||||
nsDeque::Push(aItem);
|
||||
}
|
||||
|
||||
@ -184,8 +181,10 @@ private:
|
||||
return static_cast<ResourceItem*>(nsDeque::PopFront());
|
||||
}
|
||||
|
||||
// Logical offset into the resource of the first element
|
||||
// in the queue.
|
||||
// Logical length of the resource.
|
||||
uint64_t mLogicalLength;
|
||||
|
||||
// Logical offset into the resource of the first element in the queue.
|
||||
uint64_t mOffset;
|
||||
};
|
||||
|
||||
|
@ -67,9 +67,6 @@ EXPORTS += [
|
||||
'AudioCompactor.h',
|
||||
'AudioEventTimeline.h',
|
||||
'AudioMixer.h',
|
||||
'AudioNodeEngine.h',
|
||||
'AudioNodeExternalInputStream.h',
|
||||
'AudioNodeStream.h',
|
||||
'AudioSampleFormat.h',
|
||||
'AudioSegment.h',
|
||||
'AudioStream.h',
|
||||
@ -130,9 +127,6 @@ EXPORTS.mozilla.dom += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AudioChannelFormat.cpp',
|
||||
'AudioCompactor.cpp',
|
||||
'AudioNodeEngine.cpp',
|
||||
'AudioNodeExternalInputStream.cpp',
|
||||
'AudioNodeStream.cpp',
|
||||
'AudioSegment.cpp',
|
||||
'AudioSink.cpp',
|
||||
'AudioStream.cpp',
|
||||
@ -185,10 +179,6 @@ SOURCES += [
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
|
||||
SOURCES += ['AudioNodeEngineNEON.cpp']
|
||||
SOURCES['AudioNodeEngineNEON.cpp'].flags += ['-mfpu=neon']
|
||||
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
@ -19,6 +19,9 @@ BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
EXPORTS += [
|
||||
'AudioContext.h',
|
||||
'AudioNodeEngine.h',
|
||||
'AudioNodeExternalInputStream.h',
|
||||
'AudioNodeStream.h',
|
||||
'AudioParamTimeline.h',
|
||||
'MediaBufferDecoder.h',
|
||||
'ThreeDPoint.h',
|
||||
@ -65,6 +68,9 @@ UNIFIED_SOURCES += [
|
||||
'AudioDestinationNode.cpp',
|
||||
'AudioListener.cpp',
|
||||
'AudioNode.cpp',
|
||||
'AudioNodeEngine.cpp',
|
||||
'AudioNodeExternalInputStream.cpp',
|
||||
'AudioNodeStream.cpp',
|
||||
'AudioParam.cpp',
|
||||
'AudioProcessingEvent.cpp',
|
||||
'BiquadFilterNode.cpp',
|
||||
@ -90,8 +96,15 @@ UNIFIED_SOURCES += [
|
||||
'WebAudioUtils.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
|
||||
SOURCES += ['AudioNodeEngineNEON.cpp']
|
||||
SOURCES['AudioNodeEngineNEON.cpp'].flags += ['-mfpu=neon']
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'..'
|
||||
]
|
||||
|
@ -128,6 +128,7 @@ skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_periodicWave.html]
|
||||
[test_scriptProcessorNode.html]
|
||||
[test_scriptProcessorNodeChannelCount.html]
|
||||
[test_scriptProcessorNodePassThrough.html]
|
||||
[test_scriptProcessorNode_playbackTime1.html]
|
||||
[test_scriptProcessorNodeZeroInputOutput.html]
|
||||
[test_scriptProcessorNodeNotConnected.html]
|
||||
|
@ -26,7 +26,7 @@ addLoadEvent(function() {
|
||||
for (var i = 0; i < 2048; ++i) {
|
||||
// Make sure our first sample won't be zero
|
||||
e.outputBuffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * (i + 1) / context.sampleRate);
|
||||
e.outputBuffer.getChannelData(0)[i] = Math.sin(880 * 2 * Math.PI * (i + 1) / context.sampleRate);
|
||||
e.outputBuffer.getChannelData(1)[i] = Math.sin(880 * 2 * Math.PI * (i + 1) / context.sampleRate);
|
||||
}
|
||||
// Remember our generated audio
|
||||
buffer = e.outputBuffer;
|
||||
|
@ -0,0 +1,103 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test ScriptProcessorNode with passthrough</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="webaudio.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
// We do not use our generic graph test framework here because
|
||||
// the testing logic here is sort of complicated, and would
|
||||
// not be easy to map to OfflineAudioContext, as ScriptProcessorNodes
|
||||
// can experience delays.
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
var context = new AudioContext();
|
||||
var buffer = null;
|
||||
|
||||
var sourceSP = context.createScriptProcessor(2048);
|
||||
sourceSP.addEventListener("audioprocess", function(e) {
|
||||
// generate the audio
|
||||
for (var i = 0; i < 2048; ++i) {
|
||||
// Make sure our first sample won't be zero
|
||||
e.outputBuffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * (i + 1) / context.sampleRate);
|
||||
e.outputBuffer.getChannelData(1)[i] = Math.sin(880 * 2 * Math.PI * (i + 1) / context.sampleRate);
|
||||
}
|
||||
// Remember our generated audio
|
||||
buffer = e.outputBuffer;
|
||||
|
||||
sourceSP.removeEventListener("audioprocess", arguments.callee);
|
||||
}, false);
|
||||
|
||||
function findFirstNonZeroSample(buffer) {
|
||||
for (var i = 0; i < buffer.length; ++i) {
|
||||
if (buffer.getChannelData(0)[i] != 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return buffer.length;
|
||||
}
|
||||
|
||||
var sp = context.createScriptProcessor(2048);
|
||||
sourceSP.connect(sp);
|
||||
|
||||
var spWrapped = SpecialPowers.wrap(sp);
|
||||
ok("passThrough" in spWrapped, "ScriptProcessorNode should support the passThrough API");
|
||||
spWrapped.passThrough = true;
|
||||
|
||||
sp.onaudioprocess = function() {
|
||||
ok(false, "The audioprocess event must never be dispatched on the passthrough ScriptProcessorNode");
|
||||
};
|
||||
|
||||
var sp2 = context.createScriptProcessor(2048);
|
||||
sp.connect(sp2);
|
||||
sp2.connect(context.destination);
|
||||
|
||||
var emptyBuffer = context.createBuffer(1, 2048, context.sampleRate);
|
||||
|
||||
sp2.onaudioprocess = function(e) {
|
||||
// Because of the initial latency added by the second script processor node,
|
||||
// we will never see any generated audio frames in the first callback.
|
||||
compareChannels(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
|
||||
compareChannels(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0));
|
||||
|
||||
sp2.onaudioprocess = function(e) {
|
||||
var firstNonZero = findFirstNonZeroSample(e.inputBuffer);
|
||||
ok(firstNonZero <= 2048, "First non-zero sample within range");
|
||||
|
||||
compareChannels(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0), firstNonZero);
|
||||
compareChannels(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0), firstNonZero);
|
||||
compareChannels(e.inputBuffer.getChannelData(0), buffer.getChannelData(0), 2048 - firstNonZero, firstNonZero, 0);
|
||||
compareChannels(e.inputBuffer.getChannelData(1), buffer.getChannelData(1), 2048 - firstNonZero, firstNonZero, 0);
|
||||
|
||||
if (firstNonZero == 0) {
|
||||
// If we did not experience any delays, the test is done!
|
||||
sp2.onaudioprocess = null;
|
||||
|
||||
SimpleTest.finish();
|
||||
} else if (firstNonZero != 2048) {
|
||||
// In case we just saw a zero buffer this time, wait one more round
|
||||
sp2.onaudioprocess = function(e) {
|
||||
compareChannels(e.inputBuffer.getChannelData(0), buffer.getChannelData(0), firstNonZero, 0, 2048 - firstNonZero);
|
||||
compareChannels(e.inputBuffer.getChannelData(1), buffer.getChannelData(1), firstNonZero, 0, 2048 - firstNonZero);
|
||||
compareChannels(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0), undefined, firstNonZero);
|
||||
compareChannels(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0), undefined, firstNonZero);
|
||||
|
||||
sp2.onaudioprocess = null;
|
||||
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -60,7 +60,7 @@ void WebMBufferedParser::Append(const unsigned char* aBuffer, uint32_t aLength,
|
||||
// and return to CLUSTER_SYNC.
|
||||
if (mClusterIDPos == sizeof(CLUSTER_ID)) {
|
||||
mClusterIDPos = 0;
|
||||
mClusterOffset = mCurrentOffset + (p - aBuffer) - 1;
|
||||
mClusterOffset = mCurrentOffset + (p - aBuffer) - sizeof(CLUSTER_ID);
|
||||
mState = READ_VINT;
|
||||
mNextState = TIMECODE_SYNC;
|
||||
}
|
||||
|
@ -1965,16 +1965,16 @@ Navigator::GetMozCameras(ErrorResult& aRv)
|
||||
return mCameraManager;
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorkerContainer>
|
||||
already_AddRefed<ServiceWorkerContainer>
|
||||
Navigator::ServiceWorker()
|
||||
{
|
||||
MOZ_ASSERT(mWindow);
|
||||
|
||||
if (!mServiceWorkerContainer) {
|
||||
mServiceWorkerContainer = new workers::ServiceWorkerContainer(mWindow);
|
||||
mServiceWorkerContainer = new ServiceWorkerContainer(mWindow);
|
||||
}
|
||||
|
||||
nsRefPtr<workers::ServiceWorkerContainer> ref = mServiceWorkerContainer;
|
||||
nsRefPtr<ServiceWorkerContainer> ref = mServiceWorkerContainer;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ struct MediaStreamConstraints;
|
||||
class WakeLock;
|
||||
class ArrayBufferViewOrBlobOrStringOrFormData;
|
||||
struct MobileIdOptions;
|
||||
class ServiceWorkerContainer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,10 +105,6 @@ class AudioChannelManager;
|
||||
#endif
|
||||
} // namespace system
|
||||
|
||||
namespace workers {
|
||||
class ServiceWorkerContainer;
|
||||
} // namespace workers
|
||||
|
||||
class Navigator : public nsIDOMNavigator
|
||||
, public nsIMozNavigatorNetwork
|
||||
, public nsWrapperCache
|
||||
@ -262,7 +259,7 @@ public:
|
||||
ErrorResult& aRv);
|
||||
#endif // MOZ_MEDIA_NAVIGATOR
|
||||
|
||||
already_AddRefed<workers::ServiceWorkerContainer> ServiceWorker();
|
||||
already_AddRefed<ServiceWorkerContainer> ServiceWorker();
|
||||
|
||||
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
@ -340,7 +337,7 @@ private:
|
||||
nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
|
||||
nsRefPtr<time::TimeManager> mTimeManager;
|
||||
nsRefPtr<workers::ServiceWorkerContainer> mServiceWorkerContainer;
|
||||
nsRefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
// Hashtable for saving cached objects newresolve created, so we don't create
|
||||
|
@ -122,27 +122,18 @@ ScriptSettingsStackEntry::~ScriptSettingsStackEntry()
|
||||
ScriptSettingsStack::Pop(this);
|
||||
}
|
||||
|
||||
// This mostly gets the entry global, but doesn't entirely match the spec in
|
||||
// certain edge cases. It's good enough for some purposes, but not others. If
|
||||
// you want to call this function, ping bholley and describe your use-case.
|
||||
nsIGlobalObject*
|
||||
BrokenGetEntryGlobal()
|
||||
GetEntryGlobal()
|
||||
{
|
||||
// We need the current JSContext in order to check the JS for
|
||||
// scripted frames that may have appeared since anyone last
|
||||
// manipulated the stack. If it's null, that means that there
|
||||
// must be no entry global on the stack.
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContextForThread();
|
||||
if (!cx) {
|
||||
MOZ_ASSERT(ScriptSettingsStack::EntryGlobal() == nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nsJSUtils::GetDynamicScriptGlobal(cx);
|
||||
return ScriptSettingsStack::EntryGlobal();
|
||||
}
|
||||
|
||||
// Note: When we're ready to expose it, GetEntryGlobal will look similar to
|
||||
// GetIncumbentGlobal below.
|
||||
nsIDocument*
|
||||
GetEntryDocument()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> entryWin = do_QueryInterface(GetEntryGlobal());
|
||||
return entryWin ? entryWin->GetExtantDoc() : nullptr;
|
||||
}
|
||||
|
||||
nsIGlobalObject*
|
||||
GetIncumbentGlobal()
|
||||
@ -171,6 +162,22 @@ GetIncumbentGlobal()
|
||||
return ScriptSettingsStack::IncumbentGlobal();
|
||||
}
|
||||
|
||||
nsIGlobalObject*
|
||||
GetCurrentGlobal()
|
||||
{
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContextForThread();
|
||||
if (!cx) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject *global = JS::CurrentGlobalOrNull(cx);
|
||||
if (!global) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return xpc::GetNativeForGlobal(global);
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
GetWebIDLCallerPrincipal()
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
class nsPIDOMWindow;
|
||||
class nsGlobalWindow;
|
||||
class nsIScriptContext;
|
||||
class nsIDocument;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -63,17 +64,57 @@ private:
|
||||
void InitScriptSettings();
|
||||
void DestroyScriptSettings();
|
||||
|
||||
// This mostly gets the entry global, but doesn't entirely match the spec in
|
||||
// certain edge cases. It's good enough for some purposes, but not others. If
|
||||
// you want to call this function, ping bholley and describe your use-case.
|
||||
nsIGlobalObject* BrokenGetEntryGlobal();
|
||||
// To implement a web-compatible browser, it is often necessary to obtain the
|
||||
// global object that is "associated" with the currently-running code. This
|
||||
// process is made more complicated by the fact that, historically, different
|
||||
// algorithms have operated with different definitions of the "associated"
|
||||
// global.
|
||||
//
|
||||
// HTML5 formalizes this into two concepts: the "incumbent global" and the
|
||||
// "entry global". The incumbent global corresponds to the global of the
|
||||
// current script being executed, whereas the entry global corresponds to the
|
||||
// global of the script where the current JS execution began.
|
||||
//
|
||||
// There is also a potentially-distinct third global that is determined by the
|
||||
// current compartment. This roughly corresponds with the notion of Realms in
|
||||
// ECMAScript.
|
||||
//
|
||||
// Suppose some event triggers an event listener in window |A|, which invokes a
|
||||
// scripted function in window |B|, which invokes the |window.location.href|
|
||||
// setter in window |C|. The entry global would be |A|, the incumbent global
|
||||
// would be |B|, and the current compartment would be that of |C|.
|
||||
//
|
||||
// In general, it's best to use to use the most-closely-associated global
|
||||
// unless the spec says to do otherwise. In 95% of the cases, the global of
|
||||
// the current compartment (GetCurrentGlobal()) is the right thing. For
|
||||
// example, WebIDL constructors (new C.XMLHttpRequest()) are initialized with
|
||||
// the global of the current compartment (i.e. |C|).
|
||||
//
|
||||
// The incumbent global is very similar, but differs in a few edge cases. For
|
||||
// example, if window |B| does |C.location.href = "..."|, the incumbent global
|
||||
// used for the navigation algorithm is B, because no script from |C| was ever run.
|
||||
//
|
||||
// The entry global is used for various things like computing base URIs, mostly
|
||||
// for historical reasons.
|
||||
//
|
||||
// Note that all of these functions return bonafide global objects. This means
|
||||
// that, for Windows, they always return the inner.
|
||||
|
||||
// Note: We don't yet expose GetEntryGlobal, because in order for it to be
|
||||
// correct, we first need to replace a bunch of explicit cx pushing in the
|
||||
// browser with AutoEntryScript. But GetIncumbentGlobal is simpler, because it
|
||||
// can mostly be inferred from the JS stack.
|
||||
// Returns the global associated with the top-most Candidate Entry Point on
|
||||
// the Script Settings Stack. See the HTML spec. This may be null.
|
||||
nsIGlobalObject* GetEntryGlobal();
|
||||
|
||||
// If the entry global is a window, returns its extant document. Otherwise,
|
||||
// returns null.
|
||||
nsIDocument* GetEntryDocument();
|
||||
|
||||
// Returns the global associated with the top-most entry of the the Script
|
||||
// Settings Stack. See the HTML spec. This may be null.
|
||||
nsIGlobalObject* GetIncumbentGlobal();
|
||||
|
||||
// Returns the global associated with the current compartment. This may be null.
|
||||
nsIGlobalObject* GetCurrentGlobal();
|
||||
|
||||
// JS-implemented WebIDL presents an interesting situation with respect to the
|
||||
// subject principal. A regular C++-implemented API can simply examine the
|
||||
// compartment of the most-recently-executed script, and use that to infer the
|
||||
|
@ -2501,11 +2501,6 @@ OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct,
|
||||
}
|
||||
}
|
||||
|
||||
// Don't expose CSSFontFeatureValuesRule unless the pref is enabled
|
||||
if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) {
|
||||
return nsCSSFontFeatureValuesRule::PrefEnabled();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -420,7 +420,7 @@ nsFocusManager::GetLastFocusMethod(nsIDOMWindow* aWindow, uint32_t* aLastFocusMe
|
||||
{
|
||||
// the focus method is stored on the inner window
|
||||
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
|
||||
if (window)
|
||||
if (window && window->IsOuterWindow())
|
||||
window = window->GetCurrentInnerWindow();
|
||||
if (!window)
|
||||
window = mFocusedWindow;
|
||||
|
@ -1482,10 +1482,11 @@ nsGlobalWindow::CleanUp()
|
||||
mChromeEventHandler = nullptr; // Forces Release
|
||||
mParentTarget = nullptr;
|
||||
|
||||
nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
|
||||
|
||||
if (inner) {
|
||||
inner->CleanUp();
|
||||
if (IsOuterWindow()) {
|
||||
nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
|
||||
if (inner) {
|
||||
inner->CleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsInnerWindow()) {
|
||||
@ -5915,15 +5916,8 @@ nsGlobalWindow::RefreshCompartmentPrincipal()
|
||||
static already_AddRefed<nsIDocShellTreeItem>
|
||||
GetCallerDocShellTreeItem()
|
||||
{
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
nsCOMPtr<nsIDocShellTreeItem> callerItem;
|
||||
|
||||
if (cx) {
|
||||
nsCOMPtr<nsIWebNavigation> callerWebNav =
|
||||
do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
|
||||
|
||||
callerItem = do_QueryInterface(callerWebNav);
|
||||
}
|
||||
nsCOMPtr<nsIWebNavigation> callerWebNav = do_GetInterface(GetEntryGlobal());
|
||||
nsCOMPtr<nsIDocShellTreeItem> callerItem = do_QueryInterface(callerWebNav);
|
||||
|
||||
return callerItem.forget();
|
||||
}
|
||||
@ -6557,7 +6551,7 @@ nsGlobalWindow::Focus(ErrorResult& aError)
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDOMWindow *caller = nsContentUtils::GetWindowFromCaller();
|
||||
nsCOMPtr<nsIDOMWindow> caller = do_QueryInterface(GetEntryGlobal());
|
||||
nsCOMPtr<nsIDOMWindow> opener;
|
||||
GetOpener(getter_AddRefs(opener));
|
||||
|
||||
@ -7535,20 +7529,7 @@ nsGlobalWindow::FireAbuseEvents(bool aBlocked, bool aWindow,
|
||||
|
||||
nsIURI *baseURL = nullptr;
|
||||
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
nsCOMPtr<nsPIDOMWindow> contextWindow;
|
||||
|
||||
if (cx) {
|
||||
nsIScriptContext *currentCX = nsJSUtils::GetDynamicScriptContext(cx);
|
||||
if (currentCX) {
|
||||
contextWindow = do_QueryInterface(currentCX->GetGlobalObject());
|
||||
}
|
||||
}
|
||||
if (!contextWindow) {
|
||||
contextWindow = this;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = contextWindow->GetDoc();
|
||||
nsCOMPtr<nsIDocument> doc = GetEntryDocument();
|
||||
if (doc)
|
||||
baseURL = doc->GetDocBaseURI();
|
||||
|
||||
@ -8253,7 +8234,7 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
nsCOMPtr<nsIPrincipal> providedPrincipal;
|
||||
|
||||
if (aTargetOrigin.EqualsASCII("/")) {
|
||||
providedPrincipal = BrokenGetEntryGlobal()->PrincipalOrNull();
|
||||
providedPrincipal = GetEntryGlobal()->PrincipalOrNull();
|
||||
if (NS_WARN_IF(!providedPrincipal))
|
||||
return;
|
||||
}
|
||||
@ -12803,11 +12784,7 @@ nsGlobalWindow::GetScrollFrame()
|
||||
nsresult
|
||||
nsGlobalWindow::SecurityCheckURL(const char *aURL)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> sourceWindow;
|
||||
JSContext* topCx = nsContentUtils::GetCurrentJSContext();
|
||||
if (topCx) {
|
||||
sourceWindow = do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(topCx));
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindow> sourceWindow = do_QueryInterface(GetEntryGlobal());
|
||||
if (!sourceWindow) {
|
||||
sourceWindow = this;
|
||||
}
|
||||
|
@ -599,6 +599,7 @@ public:
|
||||
|
||||
nsGlobalWindow *GetCurrentInnerWindowInternal() const
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
return static_cast<nsGlobalWindow *>(mInnerWindow);
|
||||
}
|
||||
|
||||
|
@ -557,46 +557,38 @@ NS_ScriptErrorReporter(JSContext *cx,
|
||||
}
|
||||
}
|
||||
|
||||
// XXX this means we are not going to get error reports on non DOM contexts
|
||||
nsIScriptContext *context = nsJSUtils::GetDynamicScriptContext(cx);
|
||||
|
||||
JS::Rooted<JS::Value> exception(cx);
|
||||
::JS_GetPendingException(cx, &exception);
|
||||
|
||||
// Note: we must do this before running any more code on cx (if cx is the
|
||||
// dynamic script context).
|
||||
// Note: we must do this before running any more code on cx.
|
||||
::JS_ClearPendingException(cx);
|
||||
|
||||
if (context) {
|
||||
nsIScriptGlobalObject *globalObject = context->GetGlobalObject();
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
nsCOMPtr<nsIGlobalObject> globalObject = GetEntryGlobal();
|
||||
if (globalObject) {
|
||||
|
||||
if (globalObject) {
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
|
||||
if (win) {
|
||||
win = win->GetCurrentInnerWindow();
|
||||
}
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
|
||||
do_QueryInterface(globalObject);
|
||||
NS_ASSERTION(scriptPrincipal, "Global objects must implement "
|
||||
"nsIScriptObjectPrincipal");
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new ScriptErrorEvent(JS_GetRuntime(cx),
|
||||
report,
|
||||
message,
|
||||
nsJSPrincipals::get(report->originPrincipals),
|
||||
scriptPrincipal->GetPrincipal(),
|
||||
win,
|
||||
exception,
|
||||
/* We do not try to report Out Of Memory via a dom
|
||||
* event because the dom event handler would
|
||||
* encounter an OOM exception trying to process the
|
||||
* event, and then we'd need to generate a new OOM
|
||||
* event for that new OOM instance -- this isn't
|
||||
* pretty.
|
||||
*/
|
||||
report->errorNumber != JSMSG_OUT_OF_MEMORY));
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
|
||||
MOZ_ASSERT_IF(win, win->IsInnerWindow());
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
|
||||
do_QueryInterface(globalObject);
|
||||
NS_ASSERTION(scriptPrincipal, "Global objects must implement "
|
||||
"nsIScriptObjectPrincipal");
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new ScriptErrorEvent(JS_GetRuntime(cx),
|
||||
report,
|
||||
message,
|
||||
nsJSPrincipals::get(report->originPrincipals),
|
||||
scriptPrincipal->GetPrincipal(),
|
||||
win,
|
||||
exception,
|
||||
/* We do not try to report Out Of Memory via a dom
|
||||
* event because the dom event handler would
|
||||
* encounter an OOM exception trying to process the
|
||||
* event, and then we'd need to generate a new OOM
|
||||
* event for that new OOM instance -- this isn't
|
||||
* pretty.
|
||||
*/
|
||||
report->errorNumber != JSMSG_OUT_OF_MEMORY));
|
||||
}
|
||||
|
||||
if (nsContentUtils::DOMWindowDumpEnabled()) {
|
||||
|
@ -63,21 +63,6 @@ nsJSUtils::GetStaticScriptContext(JSObject* aObj)
|
||||
return nativeGlobal->GetScriptContext();
|
||||
}
|
||||
|
||||
nsIScriptGlobalObject *
|
||||
nsJSUtils::GetDynamicScriptGlobal(JSContext* aContext)
|
||||
{
|
||||
nsIScriptContext *scriptCX = GetDynamicScriptContext(aContext);
|
||||
if (!scriptCX)
|
||||
return nullptr;
|
||||
return scriptCX->GetGlobalObject();
|
||||
}
|
||||
|
||||
nsIScriptContext *
|
||||
nsJSUtils::GetDynamicScriptContext(JSContext *aContext)
|
||||
{
|
||||
return GetScriptContextFromJSContext(aContext);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext)
|
||||
{
|
||||
|
@ -32,10 +32,6 @@ public:
|
||||
|
||||
static nsIScriptContext *GetStaticScriptContext(JSObject* aObj);
|
||||
|
||||
static nsIScriptGlobalObject *GetDynamicScriptGlobal(JSContext *aContext);
|
||||
|
||||
static nsIScriptContext *GetDynamicScriptContext(JSContext *aContext);
|
||||
|
||||
/**
|
||||
* Retrieve the inner window ID based on the given JSContext.
|
||||
*
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "nsITextToSubURI.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
@ -42,15 +43,8 @@ GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
|
||||
{
|
||||
aCharset.Truncate();
|
||||
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (cx) {
|
||||
nsCOMPtr<nsPIDOMWindow> window =
|
||||
do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
if (nsIDocument* doc = window->GetDoc()) {
|
||||
aCharset = doc->GetDocumentCharacterSet();
|
||||
}
|
||||
if (nsIDocument* doc = GetEntryDocument()) {
|
||||
aCharset = doc->GetDocumentCharacterSet();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -545,23 +539,23 @@ nsLocation::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
|
||||
* anywhere else. This is part of solution for bug # 39938, 72197
|
||||
*
|
||||
*/
|
||||
bool inScriptTag=false;
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (cx) {
|
||||
nsIScriptContext *scriptContext =
|
||||
nsJSUtils::GetDynamicScriptContext(cx);
|
||||
bool inScriptTag = false;
|
||||
nsIScriptContext* scriptContext = nullptr;
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(GetEntryGlobal());
|
||||
if (win) {
|
||||
scriptContext = static_cast<nsGlobalWindow*>(win.get())->GetContextInternal();
|
||||
}
|
||||
|
||||
if (scriptContext) {
|
||||
if (scriptContext->GetProcessingScriptTag()) {
|
||||
// Now check to make sure that the script is running in our window,
|
||||
// since we only want to replace if the location is set by a
|
||||
// <script> tag in the same window. See bug 178729.
|
||||
nsCOMPtr<nsIScriptGlobalObject> ourGlobal =
|
||||
docShell ? docShell->GetScriptGlobalObject() : nullptr;
|
||||
inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
|
||||
}
|
||||
}
|
||||
} //cx
|
||||
if (scriptContext) {
|
||||
if (scriptContext->GetProcessingScriptTag()) {
|
||||
// Now check to make sure that the script is running in our window,
|
||||
// since we only want to replace if the location is set by a
|
||||
// <script> tag in the same window. See bug 178729.
|
||||
nsCOMPtr<nsIScriptGlobalObject> ourGlobal =
|
||||
docShell ? docShell->GetScriptGlobalObject() : nullptr;
|
||||
inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
|
||||
}
|
||||
}
|
||||
|
||||
return SetURI(newUri, aReplace || inScriptTag);
|
||||
}
|
||||
@ -1020,22 +1014,20 @@ nsLocation::ValueOf(nsIDOMLocation** aReturn)
|
||||
nsresult
|
||||
nsLocation::GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL)
|
||||
{
|
||||
|
||||
*sourceURL = nullptr;
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo = nsJSUtils::GetDynamicScriptGlobal(cx);
|
||||
// If this JS context doesn't have an associated DOM window, we effectively
|
||||
// have no script entry point stack. This doesn't generally happen with the DOM,
|
||||
nsIDocument* doc = GetEntryDocument();
|
||||
// If there's no entry document, we either have no Script Entry Point or one
|
||||
// that isn't a DOM Window. This doesn't generally happen with the DOM,
|
||||
// but can sometimes happen with extension code in certain IPC configurations.
|
||||
// If this happens, try falling back on the current document associated with
|
||||
// the docshell. If that fails, just return null and hope that the caller passed
|
||||
// an absolute URI.
|
||||
if (!sgo && GetDocShell()) {
|
||||
sgo = GetDocShell()->GetScriptGlobalObject();
|
||||
if (!doc && GetDocShell()) {
|
||||
nsCOMPtr<nsPIDOMWindow> docShellWin = do_QueryInterface(GetDocShell()->GetScriptGlobalObject());
|
||||
if (docShellWin) {
|
||||
doc = docShellWin->GetDoc();
|
||||
}
|
||||
}
|
||||
NS_ENSURE_TRUE(sgo, NS_OK);
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(sgo);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
|
||||
nsIDocument* doc = window->GetDoc();
|
||||
NS_ENSURE_TRUE(doc, NS_OK);
|
||||
*sourceURL = doc->GetBaseURI().take();
|
||||
return NS_OK;
|
||||
|
@ -192,12 +192,7 @@ public:
|
||||
|
||||
bool IsLoadingOrRunningTimeout() const
|
||||
{
|
||||
const nsPIDOMWindow *win = GetCurrentInnerWindow();
|
||||
|
||||
if (!win) {
|
||||
win = this;
|
||||
}
|
||||
|
||||
const nsPIDOMWindow* win = IsInnerWindow() ? this : GetCurrentInnerWindow();
|
||||
return !win->mIsDocumentLoaded || win->mRunningTimeout;
|
||||
}
|
||||
|
||||
@ -299,6 +294,7 @@ public:
|
||||
|
||||
nsPIDOMWindow *GetCurrentInnerWindow() const
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
return mInnerWindow;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,8 @@ AddNonJSSizeOfWindowAndItsDescendents(nsGlobalWindow* aWindow,
|
||||
|
||||
// Measure the inner window, if there is one.
|
||||
nsWindowSizes innerWindowSizes(moz_malloc_size_of);
|
||||
nsGlobalWindow* inner = aWindow->GetCurrentInnerWindowInternal();
|
||||
nsGlobalWindow* inner = aWindow->IsOuterWindow() ? aWindow->GetCurrentInnerWindowInternal()
|
||||
: nullptr;
|
||||
if (inner) {
|
||||
inner->AddSizeOfIncludingThis(&innerWindowSizes);
|
||||
innerWindowSizes.addToTabSizes(aSizes);
|
||||
|
@ -2645,5 +2645,12 @@ AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitInfo,
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
CallerSubsumes(JSObject *aObject)
|
||||
{
|
||||
nsIPrincipal* objPrin = nsContentUtils::ObjectPrincipal(js::UncheckedUnwrap(aObject));
|
||||
return nsContentUtils::SubjectPrincipal()->Subsumes(objPrin);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -2937,6 +2937,18 @@ AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitinfo,
|
||||
bool
|
||||
CheckPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
|
||||
|
||||
bool
|
||||
CallerSubsumes(JSObject* aObject);
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
CallerSubsumes(JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
if (!aValue.isObject()) {
|
||||
return true;
|
||||
}
|
||||
return CallerSubsumes(&aValue.toObject());
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -1053,11 +1053,6 @@ DOMInterfaces = {
|
||||
'headerFile': 'mozilla/dom/workers/bindings/ServiceWorker.h',
|
||||
},
|
||||
|
||||
'ServiceWorkerContainer': {
|
||||
'nativeType': 'mozilla::dom::workers::ServiceWorkerContainer',
|
||||
'headerFile': 'mozilla/dom/ServiceWorkerContainer.h',
|
||||
},
|
||||
|
||||
'ServiceWorkerGlobalScope': {
|
||||
'headerFile': 'mozilla/dom/WorkerScope.h',
|
||||
'workers': True,
|
||||
|
@ -3572,6 +3572,9 @@ class JSToNativeConversionInfo():
|
||||
for whether we have a JS::Value. Only used when
|
||||
defaultValue is not None or when True is passed for
|
||||
checkForValue to instantiateJSToNativeConversion.
|
||||
${passedToJSImpl} replaced by an expression that evaluates to a boolean
|
||||
for whether this value is being passed to a JS-
|
||||
implemented interface.
|
||||
|
||||
declType: A CGThing representing the native C++ type we're converting
|
||||
to. This is allowed to be None if the conversion code is
|
||||
@ -3827,7 +3830,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
return templateBody
|
||||
|
||||
# A helper function for converting things that look like a JSObject*.
|
||||
def handleJSObjectType(type, isMember, failureCode):
|
||||
def handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription):
|
||||
if not isMember:
|
||||
if isOptional:
|
||||
# We have a specialization of Optional that will use a
|
||||
@ -3843,6 +3846,19 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
declType = CGGeneric("JSObject*")
|
||||
declArgs = None
|
||||
templateBody = "${declName} = &${val}.toObject();\n"
|
||||
|
||||
# For JS-implemented APIs, we refuse to allow passing objects that the
|
||||
# API consumer does not subsume.
|
||||
if not isinstance(descriptorProvider, Descriptor) or descriptorProvider.interface.isJSImplemented():
|
||||
templateBody = fill("""
|
||||
if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
|
||||
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
|
||||
$*{exceptionCode}
|
||||
}
|
||||
""",
|
||||
sourceDescription=sourceDescription,
|
||||
exceptionCode=exceptionCode) + templateBody
|
||||
|
||||
setToNullCode = "${declName} = nullptr;\n"
|
||||
template = wrapObjectTemplate(templateBody, type, setToNullCode,
|
||||
failureCode)
|
||||
@ -3917,7 +3933,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
# We only need holderName here to handle isExternal()
|
||||
# interfaces, which use an internal holder for the
|
||||
# conversion even when forceOwningType ends up true.
|
||||
"holderName": "tempHolder"
|
||||
"holderName": "tempHolder",
|
||||
"passedToJSImpl": "${passedToJSImpl}"
|
||||
})
|
||||
|
||||
# NOTE: Keep this in sync with variadic conversions as needed
|
||||
@ -4021,7 +4038,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
# We only need holderName here to handle isExternal()
|
||||
# interfaces, which use an internal holder for the
|
||||
# conversion even when forceOwningType ends up true.
|
||||
"holderName": "tempHolder"
|
||||
"holderName": "tempHolder",
|
||||
"passedToJSImpl": "${passedToJSImpl}"
|
||||
})
|
||||
|
||||
templateBody = fill(
|
||||
@ -4114,7 +4132,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
for memberType in interfaceMemberTypes:
|
||||
name = getUnionMemberName(memberType)
|
||||
interfaceObject.append(
|
||||
CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext" %
|
||||
CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext" %
|
||||
(unionArgumentObj, name)))
|
||||
names.append(name)
|
||||
interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"),
|
||||
@ -4127,7 +4145,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
assert len(arrayObjectMemberTypes) == 1
|
||||
name = getUnionMemberName(arrayObjectMemberTypes[0])
|
||||
arrayObject = CGGeneric(
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
|
||||
(unionArgumentObj, name))
|
||||
names.append(name)
|
||||
else:
|
||||
@ -4151,7 +4169,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
memberType = callbackMemberTypes[0]
|
||||
name = getUnionMemberName(memberType)
|
||||
callbackObject = CGGeneric(
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
|
||||
(unionArgumentObj, name))
|
||||
names.append(name)
|
||||
else:
|
||||
@ -4162,7 +4180,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
assert len(dictionaryMemberTypes) == 1
|
||||
name = getUnionMemberName(dictionaryMemberTypes[0])
|
||||
setDictionary = CGGeneric(
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
|
||||
(unionArgumentObj, name))
|
||||
names.append(name)
|
||||
else:
|
||||
@ -4173,7 +4191,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
assert len(mozMapMemberTypes) == 1
|
||||
name = getUnionMemberName(mozMapMemberTypes[0])
|
||||
mozMapObject = CGGeneric(
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext)) || !tryNext;\n" %
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
|
||||
(unionArgumentObj, name))
|
||||
names.append(name)
|
||||
else:
|
||||
@ -4185,8 +4203,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
# Very important to NOT construct a temporary Rooted here, since the
|
||||
# SetToObject call can call a Rooted constructor and we need to keep
|
||||
# stack discipline for Rooted.
|
||||
object = CGGeneric("%s.SetToObject(cx, &${val}.toObject());\n"
|
||||
"done = true;\n" % unionArgumentObj)
|
||||
object = CGGeneric("if (!%s.SetToObject(cx, &${val}.toObject(), ${passedToJSImpl})) {\n"
|
||||
"%s"
|
||||
"}\n"
|
||||
"done = true;\n" % (unionArgumentObj, indent(exceptionCode)))
|
||||
names.append(objectMemberTypes[0].name)
|
||||
else:
|
||||
object = None
|
||||
@ -4425,7 +4445,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
if descriptor.nativeType == 'JSObject':
|
||||
# XXXbz Workers code does this sometimes
|
||||
assert descriptor.workers
|
||||
return handleJSObjectType(type, isMember, failureCode)
|
||||
return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
|
||||
|
||||
if descriptor.interface.isCallback():
|
||||
name = descriptor.interface.identifier.name
|
||||
@ -4507,7 +4527,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
isCallbackReturnValue,
|
||||
firstCap(sourceDescription)))
|
||||
elif descriptor.workers:
|
||||
return handleJSObjectType(type, isMember, failureCode)
|
||||
return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
|
||||
else:
|
||||
# Either external, or new-binding non-castable. We always have a
|
||||
# holder for these, because we don't actually know whether we have
|
||||
@ -4826,6 +4846,19 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
|
||||
assert not isOptional
|
||||
templateBody = "${declName} = ${val};\n"
|
||||
|
||||
# For JS-implemented APIs, we refuse to allow passing objects that the
|
||||
# API consumer does not subsume.
|
||||
if not isinstance(descriptorProvider, Descriptor) or descriptorProvider.interface.isJSImplemented():
|
||||
templateBody = fill("""
|
||||
if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
|
||||
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
|
||||
$*{exceptionCode}
|
||||
}
|
||||
""",
|
||||
sourceDescription=sourceDescription,
|
||||
exceptionCode=exceptionCode) + templateBody
|
||||
|
||||
# We may not have a default value if we're being converted for
|
||||
# a setter, say.
|
||||
if defaultValue:
|
||||
@ -4841,7 +4874,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
|
||||
if type.isObject():
|
||||
assert not isEnforceRange and not isClamp
|
||||
return handleJSObjectType(type, isMember, failureCode)
|
||||
return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
|
||||
|
||||
if type.isDictionary():
|
||||
# There are no nullable dictionaries
|
||||
@ -4891,7 +4924,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
if type.nullable():
|
||||
dictLoc += ".SetValue()"
|
||||
|
||||
template += ('if (!%s.Init(cx, %s, "%s")) {\n'
|
||||
template += ('if (!%s.Init(cx, %s, "%s", ${passedToJSImpl})) {\n'
|
||||
"%s"
|
||||
"}\n" % (dictLoc, val, firstCap(sourceDescription),
|
||||
exceptionCodeIndented.define()))
|
||||
@ -5167,7 +5200,8 @@ class CGArgumentConverter(CGThing):
|
||||
self.replacementVariables = {
|
||||
"declName": "arg%d" % index,
|
||||
"holderName": ("arg%d" % index) + "_holder",
|
||||
"obj": "obj"
|
||||
"obj": "obj",
|
||||
"passedToJSImpl": toStringBool(isJSImplementedDescriptor(descriptorProvider))
|
||||
}
|
||||
self.replacementVariables["val"] = string.Template(
|
||||
"args[${index}]").substitute(replacer)
|
||||
@ -5245,7 +5279,8 @@ class CGArgumentConverter(CGThing):
|
||||
# conversion even when forceOwningType ends up true.
|
||||
"holderName": "tempHolder",
|
||||
# Use the same ${obj} as for the variadic arg itself
|
||||
"obj": replacer["obj"]
|
||||
"obj": replacer["obj"],
|
||||
"passedToJSImpl": toStringBool(isJSImplementedDescriptor(self.descriptorProvider))
|
||||
}), 4)
|
||||
|
||||
variadicConversion += (" }\n"
|
||||
@ -6741,7 +6776,8 @@ class CGMethodCall(CGThing):
|
||||
"holderName": ("arg%d" % distinguishingIndex) + "_holder",
|
||||
"val": distinguishingArg,
|
||||
"obj": "obj",
|
||||
"haveValue": "args.hasDefined(%d)" % distinguishingIndex
|
||||
"haveValue": "args.hasDefined(%d)" % distinguishingIndex,
|
||||
"passedToJSImpl": toStringBool(isJSImplementedDescriptor(descriptor))
|
||||
},
|
||||
checkForValue=argIsOptional)
|
||||
caseBody.append(CGIndenter(testCode, indent))
|
||||
@ -8316,9 +8352,22 @@ def getUnionTypeTemplateVars(unionType, type, descriptorProvider,
|
||||
mUnion.mValue.mObject.SetValue(cx, obj);
|
||||
mUnion.mType = mUnion.eObject;
|
||||
""")
|
||||
setter = ClassMethod("SetToObject", "void",
|
||||
|
||||
# It's a bit sketchy to do the security check after setting the value,
|
||||
# but it keeps the code cleaner and lets us avoid rooting |obj| over the
|
||||
# call to CallerSubsumes().
|
||||
body = body + dedent("""
|
||||
if (passedToJSImpl && !CallerSubsumes(obj)) {
|
||||
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "%s");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
""")
|
||||
|
||||
setter = ClassMethod("SetToObject", "bool",
|
||||
[Argument("JSContext*", "cx"),
|
||||
Argument("JSObject*", "obj")],
|
||||
Argument("JSObject*", "obj"),
|
||||
Argument("bool", "passedToJSImpl", default="false")],
|
||||
inline=True, bodyInHeader=True,
|
||||
body=body)
|
||||
|
||||
@ -8338,7 +8387,8 @@ def getUnionTypeTemplateVars(unionType, type, descriptorProvider,
|
||||
val="value",
|
||||
declName="memberSlot",
|
||||
holderName=(holderName if ownsMembers else "%s.ref()" % holderName),
|
||||
destroyHolder=destroyHolder)
|
||||
destroyHolder=destroyHolder,
|
||||
passedToJSImpl="passedToJSImpl")
|
||||
|
||||
jsConversion = fill(
|
||||
"""
|
||||
@ -8357,7 +8407,8 @@ def getUnionTypeTemplateVars(unionType, type, descriptorProvider,
|
||||
setter = ClassMethod("TrySetTo" + name, "bool",
|
||||
[Argument("JSContext*", "cx"),
|
||||
Argument("JS::Handle<JS::Value>", "value"),
|
||||
Argument("bool&", "tryNext")],
|
||||
Argument("bool&", "tryNext"),
|
||||
Argument("bool", "passedToJSImpl", default="false")],
|
||||
inline=not ownsMembers,
|
||||
bodyInHeader=not ownsMembers,
|
||||
body=jsConversion)
|
||||
@ -9463,7 +9514,8 @@ class CGProxySpecialOperation(CGPerSignatureCall):
|
||||
"declName": argument.identifier.name,
|
||||
"holderName": argument.identifier.name + "_holder",
|
||||
"val": argumentMutableValue,
|
||||
"obj": "obj"
|
||||
"obj": "obj",
|
||||
"passedToJSImpl": "false"
|
||||
}
|
||||
self.cgRoot.prepend(instantiateJSToNativeConversion(info, templateValues))
|
||||
elif operation.isGetter() or operation.isDeleter():
|
||||
@ -11087,7 +11139,8 @@ class CGDictionary(CGThing):
|
||||
return ClassMethod("Init", "bool", [
|
||||
Argument('JSContext*', 'cx'),
|
||||
Argument('JS::Handle<JS::Value>', 'val'),
|
||||
Argument('const char*', 'sourceDescription', default='"Value"')
|
||||
Argument('const char*', 'sourceDescription', default='"Value"'),
|
||||
Argument('bool', 'passedToJSImpl', default='false')
|
||||
], body=body)
|
||||
|
||||
def initFromJSONMethod(self):
|
||||
@ -11322,7 +11375,8 @@ class CGDictionary(CGThing):
|
||||
# We need a holder name for external interfaces, but
|
||||
# it's scoped down to the conversion so we can just use
|
||||
# anything we want.
|
||||
"holderName": "holder"
|
||||
"holderName": "holder",
|
||||
"passedToJSImpl": "passedToJSImpl"
|
||||
}
|
||||
# We can't handle having a holderType here
|
||||
assert conversionInfo.holderType is None
|
||||
@ -11458,6 +11512,11 @@ class CGDictionary(CGThing):
|
||||
trace = CGGeneric('%s.TraceSelf(trc);\n' % memberData)
|
||||
if type.nullable():
|
||||
trace = CGIfWrapper(trace, "!%s.IsNull()" % memberNullable)
|
||||
elif type.isMozMap():
|
||||
# If you implement this, add a MozMap<object> to
|
||||
# TestInterfaceJSDictionary and test it in test_bug1036214.html
|
||||
# to make sure we end up with the correct security properties.
|
||||
assert False
|
||||
else:
|
||||
assert False # unknown type
|
||||
|
||||
@ -13389,7 +13448,8 @@ class CallbackMember(CGNativeMember):
|
||||
# We actually want to pass in a null scope object here, because
|
||||
# wrapping things into our current compartment (that of mCallback)
|
||||
# is what we want.
|
||||
"obj": "nullptr"
|
||||
"obj": "nullptr",
|
||||
"passedToJSImpl": "false"
|
||||
}
|
||||
|
||||
if isJSImplementedDescriptor(self.descriptorProvider):
|
||||
|
@ -58,3 +58,4 @@ MSG_DEF(MSG_HEADERS_IMMUTABLE, 0, "Headers are immutable and cannot be modified.
|
||||
MSG_DEF(MSG_INVALID_HEADER_NAME, 1, "{0} is an invalid header name.")
|
||||
MSG_DEF(MSG_INVALID_HEADER_VALUE, 1, "{0} is an invalid header value.")
|
||||
MSG_DEF(MSG_INVALID_HEADER_SEQUENCE, 0, "Headers require name/value tuples when being initialized by a sequence.")
|
||||
MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, "Permission denied to pass cross-origin object as {0}.")
|
||||
|
@ -9,17 +9,6 @@ const Ci = Components.interfaces;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var gGlobal = this;
|
||||
function checkGlobal(obj) {
|
||||
if (Object(obj) === obj && Cu.getGlobalForObject(obj) != gGlobal) {
|
||||
// This message may not make it to the caller in a useful form, so dump
|
||||
// as well.
|
||||
var msg = "TestInterfaceJS received an object from a different scope!";
|
||||
dump(msg + "\n");
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function TestInterfaceJS(anyArg, objectArg) {}
|
||||
|
||||
TestInterfaceJS.prototype = {
|
||||
@ -27,23 +16,32 @@ TestInterfaceJS.prototype = {
|
||||
contractID: "@mozilla.org/dom/test-interface-js;1",
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
|
||||
|
||||
__init: function (anyArg, objectArg) {
|
||||
__init: function (anyArg, objectArg, dictionaryArg) {
|
||||
this._anyAttr = undefined;
|
||||
this._objectAttr = null;
|
||||
this._anyArg = anyArg;
|
||||
this._objectArg = objectArg;
|
||||
checkGlobal(anyArg);
|
||||
checkGlobal(objectArg);
|
||||
this._dictionaryArg = dictionaryArg;
|
||||
},
|
||||
|
||||
get anyArg() { return this._anyArg; },
|
||||
get objectArg() { return this._objectArg; },
|
||||
get dictionaryArg() { return this._dictionaryArg; },
|
||||
get anyAttr() { return this._anyAttr; },
|
||||
set anyAttr(val) { checkGlobal(val); this._anyAttr = val; },
|
||||
set anyAttr(val) { this._anyAttr = val; },
|
||||
get objectAttr() { return this._objectAttr; },
|
||||
set objectAttr(val) { checkGlobal(val); this._objectAttr = val; },
|
||||
pingPongAny: function(any) { checkGlobal(any); return any; },
|
||||
pingPongObject: function(obj) { checkGlobal(obj); return obj; },
|
||||
set objectAttr(val) { this._objectAttr = val; },
|
||||
get dictionaryAttr() { return this._dictionaryAttr; },
|
||||
set dictionaryAttr(val) { this._dictionaryAttr = val; },
|
||||
pingPongAny: function(any) { return any; },
|
||||
pingPongObject: function(obj) { return obj; },
|
||||
pingPongObjectOrString: function(objectOrString) { return objectOrString; },
|
||||
pingPongDictionary: function(dict) { return dict; },
|
||||
pingPongDictionaryOrLong: function(dictOrLong) { return dictOrLong.anyMember || dictOrLong; },
|
||||
pingPongMap: function(map) { return JSON.stringify(map); },
|
||||
objectSequenceLength: function(seq) { return seq.length; },
|
||||
anySequenceLength: function(seq) { return seq.length; },
|
||||
|
||||
|
||||
getCallerPrincipal: function() { return Cu.getWebIDLCallerPrincipal().origin; },
|
||||
|
||||
|
@ -17,10 +17,8 @@ support-files =
|
||||
[test_bug788369.html]
|
||||
[test_bug852846.html]
|
||||
[test_bug862092.html]
|
||||
# When bug 923904 lands, this test can be turned on, but only for debug builds
|
||||
# where we have our test component. So this should become skip-if = debug == false.
|
||||
[test_bug923904.html]
|
||||
skip-if = true
|
||||
[test_bug1036214.html]
|
||||
skip-if = debug == false
|
||||
[test_bug1041646.html]
|
||||
[test_barewordGetsWindow.html]
|
||||
[test_callback_default_thisval.html]
|
||||
|
123
dom/bindings/test/test_bug1036214.html
Normal file
123
dom/bindings/test/test_bug1036214.html
Normal file
@ -0,0 +1,123 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1036214
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1036214</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for subsumes-checking |any| and |object| for js-implemented WebIDL. **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var xoObjects = [];
|
||||
function setup() {
|
||||
xoObjects.push(window[0]);
|
||||
xoObjects.push(window[0].location);
|
||||
xoObjects.push(SpecialPowers.unwrap(SpecialPowers.wrap(window[0]).document));
|
||||
xoObjects.push(SpecialPowers);
|
||||
xoObjects.push(SpecialPowers.wrap);
|
||||
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, go);
|
||||
}
|
||||
|
||||
function checkThrows(f, msg) {
|
||||
try {
|
||||
f();
|
||||
ok(false, "Should have thrown: " + msg);
|
||||
} catch (e) {
|
||||
ok(true, "Threw correctly: " + msg);
|
||||
ok(/denied|insecure/.test(e), "Threw security exception: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
function go() {
|
||||
|
||||
//
|
||||
// Test the basics of the test interface.
|
||||
//
|
||||
|
||||
var any = { a: 11 };
|
||||
var obj = { b: 22, c: "str" };
|
||||
var obj2 = { foo: "baz" };
|
||||
var myDict = { anyMember: 42, objectMember: { answer: 42 }, objectOrStringMember: { answer: "anobject" },
|
||||
anySequenceMember: [{}, 1, "thirdinsequence"],
|
||||
innerDictionary: { innerObject: { answer: "rabbithole" } } };
|
||||
var t = new TestInterfaceJS(any, obj, myDict);
|
||||
is(Object.getPrototypeOf(t), TestInterfaceJS.prototype, "Prototype setup works correctly");
|
||||
is(t.anyArg, any, "anyArg is correct");
|
||||
is(t.objectArg, obj, "objectArg is correct");
|
||||
is(t.dictionaryArg.anyMember, 42, "dictionaryArg looks correct");
|
||||
is(t.dictionaryArg.objectMember.answer, 42, "dictionaryArg looks correct");
|
||||
t.anyAttr = 2;
|
||||
is(t.anyAttr, 2, "ping-pong any attribute works");
|
||||
t.objAttr = obj2;
|
||||
is(t.objAttr, obj2, "ping-pong object attribute works");
|
||||
t.dictionaryAttr = myDict;
|
||||
is(t.dictionaryAttr.anyMember, 42, "ping-pong dictionary attribute works");
|
||||
is(t.dictionaryAttr.objectMember.answer, 42, "ping-pong dictionary attribute works");
|
||||
|
||||
is(any, t.pingPongAny(any), "ping-pong works with any");
|
||||
is(obj, t.pingPongObject(obj), "ping-pong works with obj");
|
||||
is(obj, t.pingPongObjectOrString(obj), "ping-pong works with obj or string");
|
||||
is("foo", t.pingPongObjectOrString("foo"), "ping-pong works with obj or string");
|
||||
is(t.pingPongDictionary(myDict).anyMember, 42, "ping pong works with dict");
|
||||
is(t.pingPongDictionary(myDict).objectMember.answer, 42, "ping pong works with dict");
|
||||
is(t.pingPongDictionary(myDict).objectOrStringMember.answer, "anobject", "ping pong works with dict");
|
||||
is(t.pingPongDictionary(myDict).anySequenceMember[2], "thirdinsequence", "ping pong works with dict");
|
||||
is(t.pingPongDictionary(myDict).innerDictionary.innerObject.answer, "rabbithole", "ping pong works with layered dicts");
|
||||
is(t.pingPongDictionaryOrLong({anyMember: 42}), 42, "ping pong (dict or long) works with dict");
|
||||
is(t.pingPongDictionaryOrLong(42), 42, "ping pong (dict or long) works with long");
|
||||
ok(/canary/.test(t.pingPongMap({ someVal: 42, someOtherVal: "canary" })), "ping pong works with mozmap");
|
||||
is(t.objectSequenceLength([{}, {}, {}]), 3, "ping pong works with object sequence");
|
||||
is(t.anySequenceLength([42, 'string', {}, undefined]), 4, "ping pong works with any sequence");
|
||||
|
||||
//
|
||||
// Test that we throw in the cross-origin cases.
|
||||
//
|
||||
|
||||
xoObjects.forEach(function(xoObj) {
|
||||
var blank = new TestInterfaceJS();
|
||||
checkThrows(() => new TestInterfaceJS(xoObj, undefined), "any param for constructor");
|
||||
checkThrows(() => new TestInterfaceJS(undefined, xoObj), "obj param for constructor");
|
||||
checkThrows(() => new TestInterfaceJS(undefined, undefined, { anyMember: xoObj }), "any dict param for constructor");
|
||||
checkThrows(() => new TestInterfaceJS(undefined, undefined, { objectMember: xoObj }), "object dict param for constructor");
|
||||
checkThrows(() => new TestInterfaceJS(undefined, undefined, { objectOrStringMember: xoObj }), "union dict param for constructor");
|
||||
checkThrows(() => new TestInterfaceJS(undefined, undefined, { anySequenceMember: [0, xoObj, 'hi' ] }), "sequence dict param for constructor");
|
||||
checkThrows(() => new TestInterfaceJS(undefined, undefined, { innerDictionary: { innerObject: xoObj } }), "inner dict param for constructor");
|
||||
checkThrows(() => t.anyAttr = xoObj, "anyAttr");
|
||||
checkThrows(() => t.objectAttr = xoObj, "objAttr");
|
||||
checkThrows(() => t.dictionaryAttr = { anyMember: xoObj }, "dictionaryAttr any");
|
||||
checkThrows(() => t.dictionaryAttr = { objectMember: xoObj }, "dictionaryAttr object");
|
||||
checkThrows(() => t.pingPongAny(xoObj), "pingpong any");
|
||||
checkThrows(() => t.pingPongObject(xoObj), "pingpong obj");
|
||||
checkThrows(() => t.pingPongObjectOrString(xoObj), "pingpong union");
|
||||
checkThrows(() => t.pingPongDictionary({ anyMember: xoObj }), "dictionary pingpong any");
|
||||
checkThrows(() => t.pingPongDictionary({ objectMember: xoObj }), "dictionary pingpong object");
|
||||
checkThrows(() => t.pingPongDictionary({ anyMember: xoObj, objectMember: xoObj }), "dictionary pingpong both");
|
||||
checkThrows(() => t.pingPongDictionary({ objectOrStringMember: xoObj }), "dictionary pingpong objectorstring");
|
||||
checkThrows(() => t.pingPongDictionaryOrLong({ objectMember: xoObj }), "unionable dictionary");
|
||||
checkThrows(() => t.pingPongDictionaryOrLong({ anyMember: xoObj }), "unionable dictionary");
|
||||
checkThrows(() => t.pingPongMap({ someMember: 42, someOtherMember: {}, crossOriginMember: xoObj }), "mozmap");
|
||||
checkThrows(() => t.objectSequenceLength([{}, {}, xoObj, {}]), "object sequence");
|
||||
checkThrows(() => t.anySequenceLength([42, 'someString', xoObj, {}]), "any sequence");
|
||||
});
|
||||
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1036214">Mozilla Bug 1036214</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<iframe id="ifr" onload="setup();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -1,66 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=923904
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 923904</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for cloning of |any| and |object| for JS-Implemented WebIDL. **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, go);
|
||||
|
||||
function go() {
|
||||
var someAny = { a: 11 };
|
||||
var someObj = { b: 22, c: "str" };
|
||||
var t = new TestInterfaceJS(someAny, someObj);
|
||||
is(Object.getPrototypeOf(t), TestInterfaceJS.prototype, "Prototype setup works correctly");
|
||||
is(t.anyArg.toSource(), someAny.toSource(), "anyArg comes back looking like what we sent");
|
||||
is(t.objectArg.toSource(), someObj.toSource(), "objectArg comes back looking like what we sent");
|
||||
isnot(t.anyArg, t.anyArg, "get a new anyArg each time");
|
||||
isnot(t.objectArg, t.objectArg, "get a new objectArg each time");
|
||||
|
||||
t.anyAttr = 2;
|
||||
is(t.anyAttr, 2, "ping-pong works");
|
||||
testObjectCloned(t, 'anyAttr');
|
||||
testObjectCloned(t, 'objectAttr');
|
||||
|
||||
is(someAny.toSource(), t.pingPongAny(someAny).toSource(), "ping-pong works with any");
|
||||
is(someObj.toSource(), t.pingPongObject(someObj).toSource(), "ping-pong works with obj");
|
||||
isnot(someAny, t.pingPongAny(someAny), "Clone works for ping-pong any");
|
||||
isnot(someObj, t.pingPongObject(someObj), "Clone works for ping-pong obj");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function testObjectCloned(iface, propname) {
|
||||
var obj = { prop: 42 };
|
||||
iface[propname] = obj;
|
||||
is(iface[propname].prop, 42, "objects come back as well");
|
||||
is(iface[propname].__proto__, Object.prototype, "vanilla object");
|
||||
isnot(iface[propname], obj, "Should not be the original object");
|
||||
isnot(iface[propname], iface[propname], "Should get cloned each time");
|
||||
try {
|
||||
iface[propname] = { stringProp: "hi", reflectorProp: document };
|
||||
ok(false, "Should throw when trying to clone reflector");
|
||||
} catch (e) {
|
||||
ok(/cloned/.test(e), "Should throw clone error: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=923904">Mozilla Bug 923904</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1985,7 +1985,7 @@ CanvasRenderingContext2D::ArcTo(double x1, double y1, double x2,
|
||||
}
|
||||
|
||||
// Check for colinearity
|
||||
dir = (p2.x - p1.x) * (p0.y - p1.y) + (p2.y - p1.y) * (p1.x - p0.x);
|
||||
dir = (p2.x - p1.x).value * (p0.y - p1.y).value + (p2.y - p1.y).value * (p1.x - p0.x).value;
|
||||
if (dir == 0) {
|
||||
LineTo(p1.x, p1.y);
|
||||
return;
|
||||
@ -4500,7 +4500,7 @@ CanvasPath::ArcTo(double x1, double y1, double x2, double y2, double radius,
|
||||
}
|
||||
|
||||
// Check for colinearity
|
||||
dir = (p2.x - p1.x) * (p0.y - p1.y) + (p2.y - p1.y) * (p1.x - p0.x);
|
||||
dir = (p2.x - p1.x).value * (p0.y - p1.y).value + (p2.y - p1.y).value * (p1.x - p0.x).value;
|
||||
if (dir == 0) {
|
||||
LineTo(p1.x, p1.y);
|
||||
return;
|
||||
|
@ -790,7 +790,7 @@ protected:
|
||||
// The spec says we should not draw shadows if the operator is OVER.
|
||||
// If it's over and the alpha value is zero, nothing needs to be drawn.
|
||||
return NS_GET_A(state.shadowColor) != 0 &&
|
||||
(state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0);
|
||||
(state.shadowBlur != 0.f || state.shadowOffset.x != 0.f || state.shadowOffset.y != 0.f);
|
||||
}
|
||||
|
||||
mozilla::gfx::CompositionOp UsedOperation()
|
||||
|
@ -1595,8 +1595,9 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
|
||||
// fire drag gesture if mouse has moved enough
|
||||
LayoutDeviceIntPoint pt = aEvent->refPoint +
|
||||
LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
|
||||
if (DeprecatedAbs(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
|
||||
DeprecatedAbs(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
|
||||
LayoutDeviceIntPoint distance = pt - mGestureDownPoint;
|
||||
if (Abs(distance.x.value) > SafeCast<uint32_t>(pixelThresholdX) ||
|
||||
Abs(distance.y.value) > SafeCast<uint32_t>(pixelThresholdY)) {
|
||||
if (Prefs::ClickHoldContextMenu()) {
|
||||
// stop the click-hold before we fire off the drag gesture, in case
|
||||
// it takes a long time
|
||||
|
@ -8,7 +8,7 @@
|
||||
interface nsIDocument;
|
||||
interface nsIURI;
|
||||
|
||||
[uuid(cc539f1e-1ce6-4af5-bf94-195b30bde010)]
|
||||
[uuid(9b5acea4-2601-4ac7-8836-4352ceb88178)]
|
||||
interface nsIServiceWorkerManager : nsISupports
|
||||
{
|
||||
// Returns a Promise
|
||||
@ -17,9 +17,9 @@ interface nsIServiceWorkerManager : nsISupports
|
||||
// Returns a Promise
|
||||
nsISupports unregister(in nsIDOMWindow aWindow, in DOMString aScope);
|
||||
|
||||
// aTarget MUST be a ServiceWorkerContainer.
|
||||
[noscript] void AddContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||
[noscript] void RemoveContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||
// aTarget MUST be a ServiceWorkerRegistration.
|
||||
[noscript] void AddRegistrationEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||
[noscript] void RemoveRegistrationEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||
|
||||
/**
|
||||
* Call this to request that document `aDoc` be controlled by a ServiceWorker
|
||||
|
@ -2102,12 +2102,12 @@ MediaManager::MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVide
|
||||
// results.
|
||||
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
|
||||
if (piWin) {
|
||||
if (piWin->GetCurrentInnerWindow() || piWin->IsInnerWindow()) {
|
||||
if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) {
|
||||
uint64_t windowID;
|
||||
if (piWin->GetCurrentInnerWindow()) {
|
||||
windowID = piWin->GetCurrentInnerWindow()->WindowID();
|
||||
} else {
|
||||
if (piWin->IsInnerWindow()) {
|
||||
windowID = piWin->WindowID();
|
||||
} else {
|
||||
windowID = piWin->GetCurrentInnerWindow()->WindowID();
|
||||
}
|
||||
StreamListeners* listeners = GetActiveWindows()->Get(windowID);
|
||||
if (listeners) {
|
||||
|
@ -55,14 +55,14 @@ var SMILUtil =
|
||||
},
|
||||
|
||||
// Smart wrapper for getComputedStyle, which will generate a "fake" computed
|
||||
// style for recognized shorthand properties (font, overflow, marker)
|
||||
// style for recognized shorthand properties (font, font-variant, overflow, marker)
|
||||
getComputedStyleWrapper : function(elem, propName)
|
||||
{
|
||||
// Special cases for shorthand properties (which aren't directly queriable
|
||||
// via getComputedStyle)
|
||||
var computedStyle;
|
||||
if (propName == "font") {
|
||||
var subProps = ["font-style", "font-variant", "font-weight",
|
||||
var subProps = ["font-style", "font-variant-caps", "font-weight",
|
||||
"font-size", "line-height", "font-family"];
|
||||
for (var i in subProps) {
|
||||
var subPropStyle = SMILUtil.getComputedStyleSimple(elem, subProps[i]);
|
||||
@ -78,6 +78,10 @@ var SMILUtil =
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (propName == "font-variant") {
|
||||
// xxx - this isn't completely correct but it's sufficient for what's
|
||||
// being tested here
|
||||
computedStyle = SMILUtil.getComputedStyleSimple(elem, "font-variant-caps");
|
||||
} else if (propName == "marker") {
|
||||
var subProps = ["marker-end", "marker-mid", "marker-start"];
|
||||
for (var i in subProps) {
|
||||
|
@ -8,29 +8,27 @@
|
||||
*
|
||||
*/
|
||||
|
||||
[Pref="dom.serviceWorkers.enabled"]
|
||||
interface ServiceWorkerContainer {
|
||||
[Pref="dom.serviceWorkers.enabled",
|
||||
Exposed=Window]
|
||||
interface ServiceWorkerContainer : EventTarget {
|
||||
// FIXME(nsm):
|
||||
// https://github.com/slightlyoff/ServiceWorker/issues/198
|
||||
// and discussion at https://etherpad.mozilla.org/serviceworker07apr
|
||||
[Unforgeable] readonly attribute ServiceWorker? installing;
|
||||
[Unforgeable] readonly attribute ServiceWorker? waiting;
|
||||
[Unforgeable] readonly attribute ServiceWorker? active;
|
||||
[Unforgeable] readonly attribute ServiceWorker? controller;
|
||||
|
||||
[Throws]
|
||||
readonly attribute Promise<any> ready;
|
||||
readonly attribute Promise<ServiceWorkerRegistration> ready;
|
||||
|
||||
[Throws]
|
||||
Promise<any> getAll();
|
||||
Promise<ServiceWorkerRegistration> register(ScalarValueString scriptURL,
|
||||
optional RegistrationOptionList options);
|
||||
|
||||
[Throws]
|
||||
Promise<ServiceWorker> register(DOMString url, optional RegistrationOptionList options);
|
||||
Promise<ServiceWorkerRegistration> getRegistration(optional ScalarValueString documentURL = "");
|
||||
|
||||
[Throws]
|
||||
Promise<any> unregister(DOMString? scope);
|
||||
Promise<sequence<ServiceWorkerRegistration>> getRegistrations();
|
||||
|
||||
attribute EventHandler onupdatefound;
|
||||
attribute EventHandler oncontrollerchange;
|
||||
attribute EventHandler onreloadpage;
|
||||
attribute EventHandler onerror;
|
||||
@ -49,5 +47,5 @@ partial interface ServiceWorkerContainer {
|
||||
};
|
||||
|
||||
dictionary RegistrationOptionList {
|
||||
DOMString scope = "/*";
|
||||
ScalarValueString scope = "/*";
|
||||
};
|
||||
|
25
dom/webidl/ServiceWorkerRegistration.webidl
Normal file
25
dom/webidl/ServiceWorkerRegistration.webidl
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html
|
||||
*
|
||||
*/
|
||||
|
||||
[Pref="dom.serviceWorkers.enabled",
|
||||
Exposed=Window]
|
||||
interface ServiceWorkerRegistration : EventTarget {
|
||||
[Unforgeable] readonly attribute ServiceWorker? installing;
|
||||
[Unforgeable] readonly attribute ServiceWorker? waiting;
|
||||
[Unforgeable] readonly attribute ServiceWorker? active;
|
||||
|
||||
readonly attribute ScalarValueString scope;
|
||||
|
||||
[Throws]
|
||||
Promise<boolean> unregister();
|
||||
|
||||
// event
|
||||
attribute EventHandler onupdatefound;
|
||||
};
|
@ -4,16 +4,29 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
dictionary TestInterfaceJSUnionableDictionary {
|
||||
object objectMember;
|
||||
any anyMember;
|
||||
};
|
||||
|
||||
[JSImplementation="@mozilla.org/dom/test-interface-js;1",
|
||||
Pref="dom.expose_test_interfaces",
|
||||
Constructor(optional any anyArg, optional object objectArg)]
|
||||
Constructor(optional any anyArg, optional object objectArg, optional TestInterfaceJSDictionary dictionaryArg)]
|
||||
interface TestInterfaceJS {
|
||||
readonly attribute any anyArg;
|
||||
readonly attribute object objectArg;
|
||||
[Cached, Pure] readonly attribute TestInterfaceJSDictionary dictionaryArg;
|
||||
attribute any anyAttr;
|
||||
attribute object objectAttr;
|
||||
[Cached, Pure] attribute TestInterfaceJSDictionary dictionaryAttr;
|
||||
any pingPongAny(any arg);
|
||||
object pingPongObject(any obj);
|
||||
object pingPongObject(object obj);
|
||||
any pingPongObjectOrString((object or DOMString) objOrString);
|
||||
TestInterfaceJSDictionary pingPongDictionary(optional TestInterfaceJSDictionary dict);
|
||||
long pingPongDictionaryOrLong(optional (TestInterfaceJSUnionableDictionary or long) dictOrLong);
|
||||
DOMString pingPongMap(MozMap<any> map);
|
||||
long objectSequenceLength(sequence<object> seq);
|
||||
long anySequenceLength(sequence<any> seq);
|
||||
|
||||
// For testing bug 968335.
|
||||
DOMString getCallerPrincipal();
|
||||
|
27
dom/webidl/TestInterfaceJSDictionaries.webidl
Normal file
27
dom/webidl/TestInterfaceJSDictionaries.webidl
Normal file
@ -0,0 +1,27 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
//
|
||||
// These dictionaries are in a separate WebIDL file to avoid circular include
|
||||
// problems. One of the dictionary includes a union as a member, so that
|
||||
// dictionary's header needs to include UnionTypes.h. But the API in
|
||||
// TestInterfaceJS also declares a union of dictionaries, so _that_
|
||||
// dictionary's header needs to be included _by_ UnionTypes.h. The solution
|
||||
// is to separate those two dictionaries into separate header files.
|
||||
//
|
||||
|
||||
dictionary TestInterfaceJSDictionary2 {
|
||||
object innerObject;
|
||||
};
|
||||
|
||||
dictionary TestInterfaceJSDictionary {
|
||||
TestInterfaceJSDictionary2 innerDictionary;
|
||||
object objectMember;
|
||||
any anyMember;
|
||||
(object or DOMString) objectOrStringMember;
|
||||
sequence<any> anySequenceMember;
|
||||
};
|
||||
|
@ -326,6 +326,7 @@ WEBIDL_FILES = [
|
||||
'ServiceWorker.webidl',
|
||||
'ServiceWorkerContainer.webidl',
|
||||
'ServiceWorkerGlobalScope.webidl',
|
||||
'ServiceWorkerRegistration.webidl',
|
||||
'SettingsManager.webidl',
|
||||
'ShadowRoot.webidl',
|
||||
'SharedWorker.webidl',
|
||||
@ -563,7 +564,7 @@ WEBIDL_FILES += [
|
||||
# We only expose our prefable test interfaces in debug builds, just to be on
|
||||
# the safe side.
|
||||
if CONFIG['MOZ_DEBUG']:
|
||||
WEBIDL_FILES += ['TestInterfaceJS.webidl']
|
||||
WEBIDL_FILES += ['TestInterfaceJS.webidl', 'TestInterfaceJSDictionaries.webidl']
|
||||
|
||||
if CONFIG['MOZ_B2G_BT']:
|
||||
if CONFIG['MOZ_B2G_BT_API_V2']:
|
||||
|
25
dom/workers/ServiceWorkerCommon.h
Normal file
25
dom/workers/ServiceWorkerCommon.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_dom_ServiceWorkerCommon_h
|
||||
#define mozilla_dom_ServiceWorkerCommon_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Use multiples of 2 since they can be bitwise ORed when calling
|
||||
// InvalidateServiceWorkerRegistrationWorker.
|
||||
MOZ_BEGIN_ENUM_CLASS(WhichServiceWorker)
|
||||
INSTALLING_WORKER = 1,
|
||||
WAITING_WORKER = 2,
|
||||
ACTIVE_WORKER = 4,
|
||||
MOZ_END_ENUM_CLASS(WhichServiceWorker)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(WhichServiceWorker)
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_ServiceWorkerCommon_h
|
@ -22,7 +22,6 @@
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace workers {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerContainer)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
@ -31,21 +30,16 @@ NS_IMPL_ADDREF_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper,
|
||||
mInstallingWorker,
|
||||
mWaitingWorker,
|
||||
mActiveWorker,
|
||||
mControllerWorker)
|
||||
|
||||
ServiceWorkerContainer::ServiceWorkerContainer(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
StartListeningForEvents();
|
||||
}
|
||||
|
||||
ServiceWorkerContainer::~ServiceWorkerContainer()
|
||||
{
|
||||
StopListeningForEvents();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@ -77,61 +71,6 @@ ServiceWorkerContainer::Register(const nsAString& aScriptURL,
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerContainer::Unregister(const nsAString& aScope,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
if (!swm) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aRv = swm->Unregister(mWindow, aScope, getter_AddRefs(promise));
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> ret = static_cast<Promise*>(promise.get());
|
||||
MOZ_ASSERT(ret);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerContainer::GetInstalling()
|
||||
{
|
||||
if (!mInstallingWorker) {
|
||||
mInstallingWorker = GetWorkerReference(WhichServiceWorker::INSTALLING_WORKER);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ret = mInstallingWorker;
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerContainer::GetWaiting()
|
||||
{
|
||||
if (!mWaitingWorker) {
|
||||
mWaitingWorker = GetWorkerReference(WhichServiceWorker::WAITING_WORKER);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ret = mWaitingWorker;
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerContainer::GetActive()
|
||||
{
|
||||
if (!mActiveWorker) {
|
||||
mActiveWorker = GetWorkerReference(WhichServiceWorker::ACTIVE_WORKER);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ret = mActiveWorker;
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerContainer::GetController()
|
||||
{
|
||||
@ -148,15 +87,25 @@ ServiceWorkerContainer::GetController()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mControllerWorker = static_cast<ServiceWorker*>(serviceWorker.get());
|
||||
mControllerWorker =
|
||||
static_cast<workers::ServiceWorker*>(serviceWorker.get());
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ref = mControllerWorker;
|
||||
nsRefPtr<workers::ServiceWorker> ref = mControllerWorker;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerContainer::GetAll(ErrorResult& aRv)
|
||||
ServiceWorkerContainer::GetRegistrations(ErrorResult& aRv)
|
||||
{
|
||||
// FIXME(nsm): Bug 1002571
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerContainer::GetRegistration(const nsAString& aDocumentURL,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// FIXME(nsm): Bug 1002571
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
@ -171,74 +120,6 @@ ServiceWorkerContainer::GetReady(ErrorResult& aRv)
|
||||
return Promise::Create(global, aRv);
|
||||
}
|
||||
|
||||
// XXXnsm, maybe this can be optimized to only add when a event handler is
|
||||
// registered.
|
||||
void
|
||||
ServiceWorkerContainer::StartListeningForEvents()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
if (swm) {
|
||||
swm->AddContainerEventListener(mWindow->GetDocumentURI(), this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerContainer::StopListeningForEvents()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
if (swm) {
|
||||
swm->RemoveContainerEventListener(mWindow->GetDocumentURI(), this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerContainer::InvalidateWorkerReference(WhichServiceWorker aWhichOnes)
|
||||
{
|
||||
if (aWhichOnes & WhichServiceWorker::INSTALLING_WORKER) {
|
||||
mInstallingWorker = nullptr;
|
||||
}
|
||||
|
||||
if (aWhichOnes & WhichServiceWorker::WAITING_WORKER) {
|
||||
mWaitingWorker = nullptr;
|
||||
}
|
||||
|
||||
if (aWhichOnes & WhichServiceWorker::ACTIVE_WORKER) {
|
||||
mActiveWorker = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerContainer::GetWorkerReference(WhichServiceWorker aWhichOne)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
if (!swm) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> serviceWorker;
|
||||
switch(aWhichOne) {
|
||||
case WhichServiceWorker::INSTALLING_WORKER:
|
||||
rv = swm->GetInstalling(mWindow, getter_AddRefs(serviceWorker));
|
||||
break;
|
||||
case WhichServiceWorker::WAITING_WORKER:
|
||||
rv = swm->GetWaiting(mWindow, getter_AddRefs(serviceWorker));
|
||||
break;
|
||||
case WhichServiceWorker::ACTIVE_WORKER:
|
||||
rv = swm->GetActive(mWindow, getter_AddRefs(serviceWorker));
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid enum value");
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ref = static_cast<ServiceWorker*>(serviceWorker.get());
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
// Testing only.
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerContainer::ClearAllServiceWorkerData(ErrorResult& aRv)
|
||||
@ -271,6 +152,5 @@ ServiceWorkerContainer::GetControllingWorkerScriptURLForPath(
|
||||
{
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
}
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -4,13 +4,11 @@
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_workers_serviceworkercontainer_h__
|
||||
#define mozilla_dom_workers_serviceworkercontainer_h__
|
||||
#ifndef mozilla_dom_serviceworkercontainer_h__
|
||||
#define mozilla_dom_serviceworkercontainer_h__
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
|
||||
#include "ServiceWorkerManager.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
@ -20,8 +18,8 @@ class Promise;
|
||||
struct RegistrationOptionList;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorker;
|
||||
}
|
||||
|
||||
// Lightweight serviceWorker APIs collection.
|
||||
class ServiceWorkerContainer MOZ_FINAL : public DOMEventTargetHelper
|
||||
@ -30,7 +28,6 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
|
||||
|
||||
IMPL_EVENT_HANDLER(updatefound)
|
||||
IMPL_EVENT_HANDLER(controllerchange)
|
||||
IMPL_EVENT_HANDLER(reloadpage)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
@ -51,39 +48,19 @@ public:
|
||||
const RegistrationOptionList& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Unregister(const nsAString& scope, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
GetInstalling();
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
GetWaiting();
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
GetActive();
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
GetController();
|
||||
|
||||
already_AddRefed<Promise>
|
||||
GetAll(ErrorResult& aRv);
|
||||
GetRegistration(const nsAString& aDocumentURL,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
GetRegistrations(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
GetReady(ErrorResult& aRv);
|
||||
|
||||
nsIURI*
|
||||
GetDocumentURI() const
|
||||
{
|
||||
return mWindow->GetDocumentURI();
|
||||
}
|
||||
|
||||
void
|
||||
InvalidateWorkerReference(WhichServiceWorker aWhichOnes);
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
GetWorkerReference(WhichServiceWorker aWhichOne);
|
||||
|
||||
// Testing only.
|
||||
already_AddRefed<Promise>
|
||||
ClearAllServiceWorkerData(ErrorResult& aRv);
|
||||
@ -100,28 +77,14 @@ public:
|
||||
private:
|
||||
~ServiceWorkerContainer();
|
||||
|
||||
void
|
||||
StartListeningForEvents();
|
||||
|
||||
void
|
||||
StopListeningForEvents();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
// The following properties are cached here to ensure JS equality is satisfied
|
||||
// instead of acquiring a new worker instance from the ServiceWorkerManager
|
||||
// for every access. A null value is considered a cache miss.
|
||||
// These three may change to a new worker at any time.
|
||||
nsRefPtr<ServiceWorker> mInstallingWorker;
|
||||
nsRefPtr<ServiceWorker> mWaitingWorker;
|
||||
nsRefPtr<ServiceWorker> mActiveWorker;
|
||||
// This only changes when a worker hijacks everything in its scope by calling
|
||||
// replace().
|
||||
// FIXME(nsm): Bug 982711. Provide API to let SWM invalidate this.
|
||||
nsRefPtr<ServiceWorker> mControllerWorker;
|
||||
nsRefPtr<workers::ServiceWorker> mControllerWorker;
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "RuntimeService.h"
|
||||
#include "ServiceWorker.h"
|
||||
#include "ServiceWorkerContainer.h"
|
||||
#include "ServiceWorkerRegistration.h"
|
||||
#include "ServiceWorkerEvents.h"
|
||||
#include "WorkerInlines.h"
|
||||
#include "WorkerPrivate.h"
|
||||
@ -36,7 +36,7 @@ using namespace mozilla::dom;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
NS_IMPL_ISUPPORTS0(ServiceWorkerRegistration)
|
||||
NS_IMPL_ISUPPORTS0(ServiceWorkerRegistrationInfo)
|
||||
|
||||
UpdatePromise::UpdatePromise()
|
||||
: mState(Pending)
|
||||
@ -80,6 +80,7 @@ UpdatePromise::ResolveAllPromises(const nsACString& aScriptSpec, const nsACStrin
|
||||
|
||||
GlobalObject domGlobal(cx, global);
|
||||
|
||||
// The service worker is created and kept alive as a SharedWorker.
|
||||
nsRefPtr<ServiceWorker> serviceWorker;
|
||||
nsresult rv = rs->CreateServiceWorker(domGlobal,
|
||||
NS_ConvertUTF8toUTF16(aScriptSpec),
|
||||
@ -90,7 +91,14 @@ UpdatePromise::ResolveAllPromises(const nsACString& aScriptSpec, const nsACStrin
|
||||
continue;
|
||||
}
|
||||
|
||||
pendingPromise->MaybeResolve(serviceWorker);
|
||||
// Since ServiceWorkerRegistration is only exposed to windows we can be
|
||||
// certain about this cast.
|
||||
nsCOMPtr<nsPIDOMWindow> window =
|
||||
do_QueryInterface(pendingPromise->GetParentObject());
|
||||
nsRefPtr<ServiceWorkerRegistration> swr =
|
||||
new ServiceWorkerRegistration(window, NS_ConvertUTF8toUTF16(aScope));
|
||||
|
||||
pendingPromise->MaybeResolve(swr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,7 +115,7 @@ UpdatePromise::RejectAllPromises(nsresult aRv)
|
||||
for (uint32_t i = 0; i < array.Length(); ++i) {
|
||||
WeakPtr<Promise>& pendingPromise = array.ElementAt(i);
|
||||
if (pendingPromise) {
|
||||
// Since ServiceWorkerContainer is only exposed to windows we can be
|
||||
// Since ServiceWorkerRegistration is only exposed to windows we can be
|
||||
// certain about this cast.
|
||||
nsCOMPtr<nsPIDOMWindow> window =
|
||||
do_QueryInterface(pendingPromise->GetParentObject());
|
||||
@ -129,7 +137,7 @@ UpdatePromise::RejectAllPromises(const ErrorEventInit& aErrorDesc)
|
||||
for (uint32_t i = 0; i < array.Length(); ++i) {
|
||||
WeakPtr<Promise>& pendingPromise = array.ElementAt(i);
|
||||
if (pendingPromise) {
|
||||
// Since ServiceWorkerContainer is only exposed to windows we can be
|
||||
// Since ServiceWorkerRegistration is only exposed to windows we can be
|
||||
// certain about this cast.
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(pendingPromise->GetParentObject());
|
||||
MOZ_ASSERT(go);
|
||||
@ -208,7 +216,7 @@ public:
|
||||
class ServiceWorkerUpdateInstance MOZ_FINAL : public nsISupports
|
||||
{
|
||||
// Owner of this instance.
|
||||
ServiceWorkerRegistration* mRegistration;
|
||||
ServiceWorkerRegistrationInfo* mRegistration;
|
||||
nsCString mScriptSpec;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
@ -219,7 +227,7 @@ class ServiceWorkerUpdateInstance MOZ_FINAL : public nsISupports
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
ServiceWorkerUpdateInstance(ServiceWorkerRegistration *aRegistration,
|
||||
ServiceWorkerUpdateInstance(ServiceWorkerRegistrationInfo *aRegistration,
|
||||
nsPIDOMWindow* aWindow)
|
||||
: mRegistration(aRegistration),
|
||||
// Capture the current script spec in case register() gets called.
|
||||
@ -297,13 +305,13 @@ FinishFetchOnMainThreadRunnable::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ServiceWorkerRegistration::ServiceWorkerRegistration(const nsACString& aScope)
|
||||
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(const nsACString& aScope)
|
||||
: mControlledDocumentsCounter(0),
|
||||
mScope(aScope),
|
||||
mPendingUninstall(false)
|
||||
{ }
|
||||
|
||||
ServiceWorkerRegistration::~ServiceWorkerRegistration()
|
||||
ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo()
|
||||
{
|
||||
MOZ_ASSERT(!IsControllingDocuments());
|
||||
}
|
||||
@ -339,7 +347,7 @@ ServiceWorkerManager::CleanupServiceWorkerInformation(const nsACString& aDomain,
|
||||
ServiceWorkerDomainInfo* aDomainInfo,
|
||||
void *aUnused)
|
||||
{
|
||||
aDomainInfo->mServiceWorkerRegistrations.Clear();
|
||||
aDomainInfo->mServiceWorkerRegistrationInfos.Clear();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
@ -376,7 +384,7 @@ public:
|
||||
swm->mDomainMap.Put(domain, domainInfo);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> registration =
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
domainInfo->GetRegistration(mScope);
|
||||
|
||||
nsCString spec;
|
||||
@ -412,7 +420,11 @@ public:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mPromise->MaybeResolve(serviceWorker);
|
||||
nsRefPtr<ServiceWorkerRegistration> swr =
|
||||
new ServiceWorkerRegistration(mWindow,
|
||||
NS_ConvertUTF8toUTF16(registration->mScope));
|
||||
|
||||
mPromise->MaybeResolve(swr);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@ -528,7 +540,7 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow, const nsAString& aScope,
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsresult aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
@ -538,7 +550,7 @@ ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aR
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const ErrorEventInit& aErrorDesc)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
@ -552,7 +564,7 @@ ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aR
|
||||
* may access the registration's (new) Promise after calling this method.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::Update(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerManager::Update(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsPIDOMWindow* aWindow)
|
||||
{
|
||||
if (aRegistration->HasUpdatePromise()) {
|
||||
@ -571,8 +583,8 @@ ServiceWorkerManager::Update(ServiceWorkerRegistration* aRegistration,
|
||||
// instance.
|
||||
// FIXME(nsm): Fire "statechange" on installing worker instance.
|
||||
aRegistration->mInstallingWorker = nullptr;
|
||||
InvalidateServiceWorkerContainerWorker(aRegistration,
|
||||
WhichServiceWorker::INSTALLING_WORKER);
|
||||
InvalidateServiceWorkerRegistrationWorker(aRegistration,
|
||||
WhichServiceWorker::INSTALLING_WORKER);
|
||||
}
|
||||
|
||||
aRegistration->mUpdatePromise = new UpdatePromise();
|
||||
@ -587,7 +599,7 @@ ServiceWorkerManager::Update(ServiceWorkerRegistration* aRegistration,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we return an error, ServiceWorkerContainer will reject the Promise.
|
||||
// If we return an error, ServiceWorkerREgistration will reject the Promise.
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::Unregister(nsIDOMWindow* aWindow, const nsAString& aScope,
|
||||
nsISupports** aPromise)
|
||||
@ -613,7 +625,7 @@ ServiceWorkerManager::GetInstance()
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerManager::ResolveRegisterPromises(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const nsACString& aWorkerScriptSpec)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
@ -630,7 +642,7 @@ ServiceWorkerManager::ResolveRegisterPromises(ServiceWorkerRegistration* aRegist
|
||||
|
||||
// Must NS_Free() aString
|
||||
void
|
||||
ServiceWorkerManager::FinishFetch(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerManager::FinishFetch(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsPIDOMWindow* aWindow)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
@ -688,7 +700,7 @@ ServiceWorkerManager::HandleError(JSContext* aCx,
|
||||
|
||||
nsCString scope;
|
||||
scope.Assign(aScope);
|
||||
nsRefPtr<ServiceWorkerRegistration> registration = domainInfo->GetRegistration(scope);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration = domainInfo->GetRegistration(scope);
|
||||
MOZ_ASSERT(registration);
|
||||
|
||||
RootedDictionary<ErrorEventInit> init(aCx);
|
||||
@ -717,11 +729,11 @@ ServiceWorkerManager::HandleError(JSContext* aCx,
|
||||
|
||||
class FinishInstallRunnable MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
|
||||
public:
|
||||
explicit FinishInstallRunnable(
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
|
||||
: mRegistration(aRegistration)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
@ -740,10 +752,10 @@ public:
|
||||
|
||||
class FinishActivationRunnable : public nsRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
|
||||
public:
|
||||
FinishActivationRunnable(const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
|
||||
FinishActivationRunnable(const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
|
||||
: mRegistration(aRegistration)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
@ -763,11 +775,11 @@ public:
|
||||
|
||||
class CancelServiceWorkerInstallationRunnable MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
|
||||
public:
|
||||
explicit CancelServiceWorkerInstallationRunnable(
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
|
||||
: mRegistration(aRegistration)
|
||||
{
|
||||
}
|
||||
@ -780,8 +792,8 @@ public:
|
||||
// FIXME(nsm): Fire statechange.
|
||||
mRegistration->mInstallingWorker = nullptr;
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
swm->InvalidateServiceWorkerContainerWorker(mRegistration,
|
||||
WhichServiceWorker::INSTALLING_WORKER);
|
||||
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
|
||||
WhichServiceWorker::INSTALLING_WORKER);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
@ -791,7 +803,7 @@ public:
|
||||
*/
|
||||
class FinishInstallHandler MOZ_FINAL : public PromiseNativeHandler
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
|
||||
virtual
|
||||
~FinishInstallHandler()
|
||||
@ -799,7 +811,7 @@ class FinishInstallHandler MOZ_FINAL : public PromiseNativeHandler
|
||||
|
||||
public:
|
||||
explicit FinishInstallHandler(
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
|
||||
: mRegistration(aRegistration)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
@ -827,10 +839,10 @@ public:
|
||||
|
||||
class FinishActivateHandler : public PromiseNativeHandler
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
|
||||
public:
|
||||
FinishActivateHandler(const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
|
||||
FinishActivateHandler(const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
|
||||
: mRegistration(aRegistration)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
@ -866,13 +878,13 @@ public:
|
||||
*/
|
||||
class InstallEventRunnable MOZ_FINAL : public WorkerRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
nsCString mScope;
|
||||
|
||||
public:
|
||||
InstallEventRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
|
||||
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
|
||||
mRegistration(aRegistration),
|
||||
mScope(aRegistration.get()->mScope) // copied for access on worker thread.
|
||||
@ -935,11 +947,11 @@ private:
|
||||
|
||||
class ActivateEventRunnable : public WorkerRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> mRegistration;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
|
||||
public:
|
||||
ActivateEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistration>& aRegistration)
|
||||
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
|
||||
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
|
||||
mRegistration(aRegistration)
|
||||
{
|
||||
@ -998,17 +1010,17 @@ private:
|
||||
};
|
||||
|
||||
void
|
||||
ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerManager::Install(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
ServiceWorkerInfo* aServiceWorkerInfo)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
aRegistration->mInstallingWorker = aServiceWorkerInfo;
|
||||
MOZ_ASSERT(aRegistration->mInstallingWorker);
|
||||
InvalidateServiceWorkerContainerWorker(aRegistration,
|
||||
WhichServiceWorker::INSTALLING_WORKER);
|
||||
InvalidateServiceWorkerRegistrationWorker(aRegistration,
|
||||
WhichServiceWorker::INSTALLING_WORKER);
|
||||
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> handle(
|
||||
new nsMainThreadPtrHolder<ServiceWorkerRegistration>(aRegistration));
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> handle(
|
||||
new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>(aRegistration));
|
||||
|
||||
nsRefPtr<ServiceWorker> serviceWorker;
|
||||
nsresult rv =
|
||||
@ -1042,15 +1054,15 @@ ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
|
||||
// a wait is likely to be required only when performing networking or storage
|
||||
// transactions in the first place.
|
||||
|
||||
FireEventOnServiceWorkerContainers(aRegistration,
|
||||
NS_LITERAL_STRING("updatefound"));
|
||||
FireEventOnServiceWorkerRegistrations(aRegistration,
|
||||
NS_LITERAL_STRING("updatefound"));
|
||||
}
|
||||
|
||||
class ActivationRunnable : public nsRunnable
|
||||
{
|
||||
nsRefPtr<ServiceWorkerRegistration> mRegistration;
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
public:
|
||||
explicit ActivationRunnable(ServiceWorkerRegistration* aRegistration)
|
||||
explicit ActivationRunnable(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
: mRegistration(aRegistration)
|
||||
{
|
||||
}
|
||||
@ -1065,13 +1077,13 @@ public:
|
||||
mRegistration->mCurrentWorker = mRegistration->mWaitingWorker.forget();
|
||||
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
swm->InvalidateServiceWorkerContainerWorker(mRegistration,
|
||||
WhichServiceWorker::ACTIVE_WORKER | WhichServiceWorker::WAITING_WORKER);
|
||||
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
|
||||
WhichServiceWorker::ACTIVE_WORKER | WhichServiceWorker::WAITING_WORKER);
|
||||
|
||||
// FIXME(nsm): Steps 7 of the algorithm.
|
||||
|
||||
swm->FireEventOnServiceWorkerContainers(mRegistration,
|
||||
NS_LITERAL_STRING("controllerchange"));
|
||||
swm->FireEventOnServiceWorkerRegistrations(mRegistration,
|
||||
NS_LITERAL_STRING("controllerchange"));
|
||||
|
||||
MOZ_ASSERT(mRegistration->mCurrentWorker);
|
||||
nsRefPtr<ServiceWorker> serviceWorker;
|
||||
@ -1083,8 +1095,8 @@ public:
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistration> handle(
|
||||
new nsMainThreadPtrHolder<ServiceWorkerRegistration>(mRegistration));
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> handle(
|
||||
new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>(mRegistration));
|
||||
|
||||
nsRefPtr<ActivateEventRunnable> r =
|
||||
new ActivateEventRunnable(serviceWorker->GetWorkerPrivate(), handle);
|
||||
@ -1099,7 +1111,7 @@ public:
|
||||
};
|
||||
|
||||
void
|
||||
ServiceWorkerManager::FinishInstall(ServiceWorkerRegistration* aRegistration)
|
||||
ServiceWorkerManager::FinishInstall(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
@ -1118,8 +1130,8 @@ ServiceWorkerManager::FinishInstall(ServiceWorkerRegistration* aRegistration)
|
||||
|
||||
aRegistration->mWaitingWorker = aRegistration->mInstallingWorker.forget();
|
||||
MOZ_ASSERT(aRegistration->mWaitingWorker);
|
||||
InvalidateServiceWorkerContainerWorker(aRegistration,
|
||||
WhichServiceWorker::WAITING_WORKER | WhichServiceWorker::INSTALLING_WORKER);
|
||||
InvalidateServiceWorkerRegistrationWorker(aRegistration,
|
||||
WhichServiceWorker::WAITING_WORKER | WhichServiceWorker::INSTALLING_WORKER);
|
||||
|
||||
// FIXME(nsm): Actually update state of active ServiceWorker instances to
|
||||
// installed.
|
||||
@ -1140,7 +1152,7 @@ ServiceWorkerManager::FinishInstall(ServiceWorkerRegistration* aRegistration)
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::FinishActivate(ServiceWorkerRegistration* aRegistration)
|
||||
ServiceWorkerManager::FinishActivate(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
// FIXME(nsm): Set aRegistration->mCurrentWorker state to activated.
|
||||
// Fire statechange.
|
||||
@ -1178,22 +1190,22 @@ ServiceWorkerManager::CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
|
||||
return rv;
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistration(nsPIDOMWindow* aWindow)
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> document = aWindow->GetExtantDoc();
|
||||
return GetServiceWorkerRegistration(document);
|
||||
return GetServiceWorkerRegistrationInfo(document);
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistration(nsIDocument* aDoc)
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIDocument* aDoc)
|
||||
{
|
||||
nsCOMPtr<nsIURI> documentURI = aDoc->GetDocumentURI();
|
||||
return GetServiceWorkerRegistration(documentURI);
|
||||
return GetServiceWorkerRegistrationInfo(documentURI);
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistration(nsIURI* aURI)
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIURI* aURI)
|
||||
{
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aURI);
|
||||
if (!domainInfo) {
|
||||
@ -1211,8 +1223,8 @@ ServiceWorkerManager::GetServiceWorkerRegistration(nsIURI* aURI)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> registration;
|
||||
domainInfo->mServiceWorkerRegistrations.Get(scope, getter_AddRefs(registration));
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
domainInfo->mServiceWorkerRegistrationInfos.Get(scope, getter_AddRefs(registration));
|
||||
// ordered scopes and registrations better be in sync.
|
||||
MOZ_ASSERT(registration);
|
||||
|
||||
@ -1357,8 +1369,8 @@ ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> registration =
|
||||
GetServiceWorkerRegistration(aDoc);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(aDoc);
|
||||
if (registration && registration->mCurrentWorker) {
|
||||
MOZ_ASSERT(!domainInfo->mControlledDocuments.Contains(aDoc));
|
||||
registration->StartControllingADocument();
|
||||
@ -1381,7 +1393,7 @@ ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> registration;
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
domainInfo->mControlledDocuments.Remove(aDoc, getter_AddRefs(registration));
|
||||
// A document which was uncontrolled does not maintain that state itself, so
|
||||
// it will always call MaybeStopControlling() even if there isn't an
|
||||
@ -1400,7 +1412,7 @@ ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> r = GetServiceWorkerRegistration(uri);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> r = GetServiceWorkerRegistrationInfo(uri);
|
||||
if (!r) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1410,7 +1422,7 @@ ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::AddContainerEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
ServiceWorkerManager::AddRegistrationEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
{
|
||||
MOZ_ASSERT(aDocumentURI);
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
|
||||
@ -1427,13 +1439,14 @@ ServiceWorkerManager::AddContainerEventListener(nsIURI* aDocumentURI, nsIDOMEven
|
||||
|
||||
MOZ_ASSERT(domainInfo);
|
||||
|
||||
ServiceWorkerContainer* container = static_cast<ServiceWorkerContainer*>(aListener);
|
||||
domainInfo->mServiceWorkerContainers.AppendElement(container);
|
||||
// TODO: this is very very bad:
|
||||
ServiceWorkerRegistration* registration = static_cast<ServiceWorkerRegistration*>(aListener);
|
||||
domainInfo->mServiceWorkerRegistrations.AppendElement(registration);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::RemoveContainerEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
ServiceWorkerManager::RemoveRegistrationEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
{
|
||||
MOZ_ASSERT(aDocumentURI);
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
|
||||
@ -1441,14 +1454,14 @@ ServiceWorkerManager::RemoveContainerEventListener(nsIURI* aDocumentURI, nsIDOME
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ServiceWorkerContainer* container = static_cast<ServiceWorkerContainer*>(aListener);
|
||||
domainInfo->mServiceWorkerContainers.RemoveElement(container);
|
||||
ServiceWorkerRegistration* registration = static_cast<ServiceWorkerRegistration*>(aListener);
|
||||
domainInfo->mServiceWorkerRegistrations.RemoveElement(registration);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::FireEventOnServiceWorkerContainers(
|
||||
ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerManager::FireEventOnServiceWorkerRegistrations(
|
||||
ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const nsAString& aName)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
@ -1456,9 +1469,9 @@ ServiceWorkerManager::FireEventOnServiceWorkerContainers(
|
||||
GetDomainInfo(aRegistration->mScriptSpec);
|
||||
|
||||
if (domainInfo) {
|
||||
nsTObserverArray<ServiceWorkerContainer*>::ForwardIterator it(domainInfo->mServiceWorkerContainers);
|
||||
nsTObserverArray<ServiceWorkerRegistration*>::ForwardIterator it(domainInfo->mServiceWorkerRegistrations);
|
||||
while (it.HasMore()) {
|
||||
nsRefPtr<ServiceWorkerContainer> target = it.GetNext();
|
||||
nsRefPtr<ServiceWorkerRegistration> target = it.GetNext();
|
||||
nsIURI* targetURI = target->GetDocumentURI();
|
||||
if (!targetURI) {
|
||||
NS_WARNING("Controlled domain cannot have page with null URI!");
|
||||
@ -1494,8 +1507,8 @@ ServiceWorkerManager::GetServiceWorkerForWindow(nsIDOMWindow* aWindow,
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> registration =
|
||||
GetServiceWorkerRegistration(window);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(window);
|
||||
|
||||
if (!registration) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -1549,7 +1562,7 @@ ServiceWorkerManager::GetDocumentController(nsIDOMWindow* aWindow, nsISupports**
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> registration;
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
if (!domainInfo->mControlledDocuments.Get(doc, getter_AddRefs(registration))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1615,7 +1628,7 @@ ServiceWorkerManager::CreateServiceWorker(const nsACString& aScriptSpec,
|
||||
|
||||
// FIXME(nsm): Create correct principal based on app-ness.
|
||||
// Would it make sense to store the nsIPrincipal of the first register() in
|
||||
// the ServiceWorkerRegistration and use that?
|
||||
// the ServiceWorkerRegistrationInfo and use that?
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
rv = ssm->GetNoAppCodebasePrincipal(info.mBaseURI, getter_AddRefs(info.mPrincipal));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -1642,17 +1655,17 @@ ServiceWorkerManager::CreateServiceWorker(const nsACString& aScriptSpec,
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::InvalidateServiceWorkerContainerWorker(ServiceWorkerRegistration* aRegistration,
|
||||
WhichServiceWorker aWhichOnes)
|
||||
ServiceWorkerManager::InvalidateServiceWorkerRegistrationWorker(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
WhichServiceWorker aWhichOnes)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo =
|
||||
GetDomainInfo(aRegistration->mScriptSpec);
|
||||
|
||||
if (domainInfo) {
|
||||
nsTObserverArray<ServiceWorkerContainer*>::ForwardIterator it(domainInfo->mServiceWorkerContainers);
|
||||
nsTObserverArray<ServiceWorkerRegistration*>::ForwardIterator it(domainInfo->mServiceWorkerRegistrations);
|
||||
while (it.HasMore()) {
|
||||
nsRefPtr<ServiceWorkerContainer> target = it.GetNext();
|
||||
nsRefPtr<ServiceWorkerRegistration> target = it.GetNext();
|
||||
|
||||
nsIURI* targetURI = target->GetDocumentURI();
|
||||
nsCString path;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ServiceWorkerCommon.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "nsTObserverArray.h"
|
||||
@ -24,10 +25,12 @@ class nsIScriptError;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ServiceWorkerRegistration;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorker;
|
||||
class ServiceWorkerContainer;
|
||||
class ServiceWorkerUpdateInstance;
|
||||
|
||||
/**
|
||||
@ -95,22 +98,13 @@ public:
|
||||
{ }
|
||||
};
|
||||
|
||||
// Use multiples of 2 since they can be bitwise ORed when calling
|
||||
// InvalidateServiceWorkerContainerWorker.
|
||||
MOZ_BEGIN_ENUM_CLASS(WhichServiceWorker)
|
||||
INSTALLING_WORKER = 1,
|
||||
WAITING_WORKER = 2,
|
||||
ACTIVE_WORKER = 4,
|
||||
MOZ_END_ENUM_CLASS(WhichServiceWorker)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(WhichServiceWorker)
|
||||
|
||||
// Needs to inherit from nsISupports because NS_ProxyRelease() does not support
|
||||
// non-ISupports classes.
|
||||
class ServiceWorkerRegistration MOZ_FINAL : public nsISupports
|
||||
class ServiceWorkerRegistrationInfo MOZ_FINAL : public nsISupports
|
||||
{
|
||||
uint32_t mControlledDocumentsCounter;
|
||||
|
||||
virtual ~ServiceWorkerRegistration();
|
||||
virtual ~ServiceWorkerRegistrationInfo();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -145,7 +139,7 @@ public:
|
||||
// pendingUninstall and when all controlling documents go away, removed.
|
||||
bool mPendingUninstall;
|
||||
|
||||
explicit ServiceWorkerRegistration(const nsACString& aScope);
|
||||
explicit ServiceWorkerRegistrationInfo(const nsACString& aScope);
|
||||
|
||||
already_AddRefed<ServiceWorkerInfo>
|
||||
Newest()
|
||||
@ -236,35 +230,35 @@ public:
|
||||
nsTArray<nsCString> mOrderedScopes;
|
||||
|
||||
// Scope to registration.
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerRegistration> mServiceWorkerRegistrations;
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerRegistrationInfo> mServiceWorkerRegistrationInfos;
|
||||
|
||||
// This array can't be stored in ServiceWorkerRegistration because one may
|
||||
// not exist when a certain window is opened, but we still want that
|
||||
// window's container to be notified if it's in scope.
|
||||
// The containers inform the SWM on creation and destruction.
|
||||
nsTObserverArray<ServiceWorkerContainer*> mServiceWorkerContainers;
|
||||
nsTObserverArray<ServiceWorkerRegistration*> mServiceWorkerRegistrations;
|
||||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, ServiceWorkerRegistration> mControlledDocuments;
|
||||
nsRefPtrHashtable<nsISupportsHashKey, ServiceWorkerRegistrationInfo> mControlledDocuments;
|
||||
|
||||
ServiceWorkerDomainInfo()
|
||||
{ }
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetRegistration(const nsCString& aScope) const
|
||||
{
|
||||
nsRefPtr<ServiceWorkerRegistration> reg;
|
||||
mServiceWorkerRegistrations.Get(aScope, getter_AddRefs(reg));
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> reg;
|
||||
mServiceWorkerRegistrationInfos.Get(aScope, getter_AddRefs(reg));
|
||||
return reg.forget();
|
||||
}
|
||||
|
||||
ServiceWorkerRegistration*
|
||||
ServiceWorkerRegistrationInfo*
|
||||
CreateNewRegistration(const nsCString& aScope)
|
||||
{
|
||||
ServiceWorkerRegistration* registration =
|
||||
new ServiceWorkerRegistration(aScope);
|
||||
ServiceWorkerRegistrationInfo* registration =
|
||||
new ServiceWorkerRegistrationInfo(aScope);
|
||||
// From now on ownership of registration is with
|
||||
// mServiceWorkerRegistrations.
|
||||
mServiceWorkerRegistrations.Put(aScope, registration);
|
||||
// mServiceWorkerRegistrationInfos.
|
||||
mServiceWorkerRegistrationInfos.Put(aScope, registration);
|
||||
ServiceWorkerManager::AddScope(mOrderedScopes, aScope);
|
||||
return registration;
|
||||
}
|
||||
@ -279,26 +273,26 @@ public:
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerDomainInfo> mDomainMap;
|
||||
|
||||
void
|
||||
ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
|
||||
ResolveRegisterPromises(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const nsACString& aWorkerScriptSpec);
|
||||
|
||||
void
|
||||
RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
|
||||
RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsresult aResult);
|
||||
|
||||
void
|
||||
RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
|
||||
RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const ErrorEventInit& aErrorDesc);
|
||||
|
||||
void
|
||||
FinishFetch(ServiceWorkerRegistration* aRegistration,
|
||||
FinishFetch(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsPIDOMWindow* aWindow);
|
||||
|
||||
void
|
||||
FinishInstall(ServiceWorkerRegistration* aRegistration);
|
||||
FinishInstall(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
FinishActivate(ServiceWorkerRegistration* aRegistration);
|
||||
FinishActivate(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
HandleError(JSContext* aCx,
|
||||
@ -319,10 +313,10 @@ private:
|
||||
~ServiceWorkerManager();
|
||||
|
||||
NS_IMETHOD
|
||||
Update(ServiceWorkerRegistration* aRegistration, nsPIDOMWindow* aWindow);
|
||||
Update(ServiceWorkerRegistrationInfo* aRegistration, nsPIDOMWindow* aWindow);
|
||||
|
||||
void
|
||||
Install(ServiceWorkerRegistration* aRegistration,
|
||||
Install(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
ServiceWorkerInfo* aServiceWorkerInfo);
|
||||
|
||||
NS_IMETHOD
|
||||
@ -356,17 +350,17 @@ private:
|
||||
nsISupports** aServiceWorker);
|
||||
|
||||
void
|
||||
InvalidateServiceWorkerContainerWorker(ServiceWorkerRegistration* aRegistration,
|
||||
WhichServiceWorker aWhichOnes);
|
||||
InvalidateServiceWorkerRegistrationWorker(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
WhichServiceWorker aWhichOnes);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
GetServiceWorkerRegistration(nsPIDOMWindow* aWindow);
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(nsPIDOMWindow* aWindow);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
GetServiceWorkerRegistration(nsIDocument* aDoc);
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(nsIDocument* aDoc);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
GetServiceWorkerRegistration(nsIURI* aURI);
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(nsIURI* aURI);
|
||||
|
||||
static void
|
||||
AddScope(nsTArray<nsCString>& aList, const nsACString& aScope);
|
||||
@ -378,8 +372,8 @@ private:
|
||||
RemoveScope(nsTArray<nsCString>& aList, const nsACString& aScope);
|
||||
|
||||
void
|
||||
FireEventOnServiceWorkerContainers(ServiceWorkerRegistration* aRegistration,
|
||||
const nsAString& aName);
|
||||
FireEventOnServiceWorkerRegistrations(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const nsAString& aName);
|
||||
|
||||
};
|
||||
|
||||
|
197
dom/workers/ServiceWorkerRegistration.cpp
Normal file
197
dom/workers/ServiceWorkerRegistration.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
/* -*- 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 "ServiceWorkerRegistration.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistrationBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "ServiceWorker.h"
|
||||
|
||||
#include "nsIServiceWorkerManager.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
using namespace mozilla::dom::workers;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistration)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ServiceWorkerRegistration, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(ServiceWorkerRegistration, DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistration,
|
||||
DOMEventTargetHelper,
|
||||
mWindow,
|
||||
mInstallingWorker,
|
||||
mWaitingWorker,
|
||||
mActiveWorker)
|
||||
|
||||
ServiceWorkerRegistration::ServiceWorkerRegistration(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aScope)
|
||||
: mWindow(aWindow)
|
||||
, mScope(aScope)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
SetIsDOMBinding();
|
||||
StartListeningForEvents();
|
||||
}
|
||||
|
||||
ServiceWorkerRegistration::~ServiceWorkerRegistration()
|
||||
{
|
||||
StopListeningForEvents();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
ServiceWorkerRegistration::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return ServiceWorkerRegistrationBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerRegistration::GetInstalling()
|
||||
{
|
||||
if (!mInstallingWorker) {
|
||||
mInstallingWorker = GetWorkerReference(WhichServiceWorker::INSTALLING_WORKER);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ret = mInstallingWorker;
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerRegistration::GetWaiting()
|
||||
{
|
||||
if (!mWaitingWorker) {
|
||||
mWaitingWorker = GetWorkerReference(WhichServiceWorker::WAITING_WORKER);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ret = mWaitingWorker;
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerRegistration::GetActive()
|
||||
{
|
||||
if (!mActiveWorker) {
|
||||
mActiveWorker = GetWorkerReference(WhichServiceWorker::ACTIVE_WORKER);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ret = mActiveWorker;
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerRegistration::Unregister(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm =
|
||||
do_GetService(SERVICEWORKERMANAGER_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aRv = swm->Unregister(mWindow, mScope, getter_AddRefs(promise));
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> ret = static_cast<Promise*>(promise.get());
|
||||
MOZ_ASSERT(ret);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
ServiceWorkerRegistration::GetWorkerReference(WhichServiceWorker aWhichOne)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm =
|
||||
do_GetService(SERVICEWORKERMANAGER_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> serviceWorker;
|
||||
switch(aWhichOne) {
|
||||
case WhichServiceWorker::INSTALLING_WORKER:
|
||||
rv = swm->GetInstalling(mWindow, getter_AddRefs(serviceWorker));
|
||||
break;
|
||||
case WhichServiceWorker::WAITING_WORKER:
|
||||
rv = swm->GetWaiting(mWindow, getter_AddRefs(serviceWorker));
|
||||
break;
|
||||
case WhichServiceWorker::ACTIVE_WORKER:
|
||||
rv = swm->GetActive(mWindow, getter_AddRefs(serviceWorker));
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid enum value");
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorker> ref =
|
||||
static_cast<ServiceWorker*>(serviceWorker.get());
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistration::InvalidateWorkerReference(WhichServiceWorker aWhichOnes)
|
||||
{
|
||||
if (aWhichOnes & WhichServiceWorker::INSTALLING_WORKER) {
|
||||
mInstallingWorker = nullptr;
|
||||
}
|
||||
|
||||
if (aWhichOnes & WhichServiceWorker::WAITING_WORKER) {
|
||||
mWaitingWorker = nullptr;
|
||||
}
|
||||
|
||||
if (aWhichOnes & WhichServiceWorker::ACTIVE_WORKER) {
|
||||
mActiveWorker = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// XXXnsm, maybe this can be optimized to only add when a event handler is
|
||||
// registered.
|
||||
void
|
||||
ServiceWorkerRegistration::StartListeningForEvents()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
MOZ_ASSERT(mWindow);
|
||||
|
||||
if (swm) {
|
||||
swm->AddRegistrationEventListener(GetDocumentURI(), this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistration::StopListeningForEvents()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
|
||||
// StopListeningForEvents is called in the dtor, and it can happen that
|
||||
// SnowWhite had already set to null mWindow.
|
||||
if (swm && mWindow) {
|
||||
swm->RemoveRegistrationEventListener(GetDocumentURI(), this);
|
||||
}
|
||||
}
|
||||
|
||||
nsIURI*
|
||||
ServiceWorkerRegistration::GetDocumentURI() const
|
||||
{
|
||||
MOZ_ASSERT(mWindow);
|
||||
return mWindow->GetDocumentURI();
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
99
dom/workers/ServiceWorkerRegistration.h
Normal file
99
dom/workers/ServiceWorkerRegistration.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_dom_ServiceWorkerRegistration_h
|
||||
#define mozilla_dom_ServiceWorkerRegistration_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/ServiceWorkerCommon.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
|
||||
namespace workers {
|
||||
class ServiceWorker;
|
||||
}
|
||||
|
||||
class ServiceWorkerRegistration MOZ_FINAL : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerRegistration,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
IMPL_EVENT_HANDLER(updatefound)
|
||||
|
||||
ServiceWorkerRegistration(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aScope);
|
||||
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx);
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
GetInstalling();
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
GetWaiting();
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
GetActive();
|
||||
|
||||
void
|
||||
GetScope(nsAString& aScope) const
|
||||
{
|
||||
aScope = mScope;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Unregister(ErrorResult& aRv);
|
||||
|
||||
// Useful methods for ServiceWorkerManager:
|
||||
|
||||
nsIURI*
|
||||
GetDocumentURI() const;
|
||||
|
||||
void
|
||||
InvalidateWorkerReference(WhichServiceWorker aWhichOnes);
|
||||
|
||||
private:
|
||||
~ServiceWorkerRegistration();
|
||||
|
||||
already_AddRefed<workers::ServiceWorker>
|
||||
GetWorkerReference(WhichServiceWorker aWhichOne);
|
||||
|
||||
void
|
||||
StartListeningForEvents();
|
||||
|
||||
void
|
||||
StopListeningForEvents();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
// The following properties are cached here to ensure JS equality is satisfied
|
||||
// instead of acquiring a new worker instance from the ServiceWorkerManager
|
||||
// for every access. A null value is considered a cache miss.
|
||||
// These three may change to a new worker at any time.
|
||||
nsRefPtr<workers::ServiceWorker> mInstallingWorker;
|
||||
nsRefPtr<workers::ServiceWorker> mWaitingWorker;
|
||||
nsRefPtr<workers::ServiceWorker> mActiveWorker;
|
||||
|
||||
const nsString mScope;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_ServiceWorkerRegistration_h */
|
@ -6,7 +6,9 @@
|
||||
|
||||
# Public stuff.
|
||||
EXPORTS.mozilla.dom += [
|
||||
'ServiceWorkerCommon.h',
|
||||
'ServiceWorkerContainer.h',
|
||||
'ServiceWorkerRegistration.h',
|
||||
'WorkerPrivate.h',
|
||||
'WorkerRunnable.h',
|
||||
'WorkerScope.h',
|
||||
@ -50,6 +52,7 @@ SOURCES += [
|
||||
'ServiceWorkerContainer.cpp',
|
||||
'ServiceWorkerEvents.cpp',
|
||||
'ServiceWorkerManager.cpp',
|
||||
'ServiceWorkerRegistration.cpp',
|
||||
'SharedWorker.cpp',
|
||||
'URL.cpp',
|
||||
'WorkerPrivate.cpp',
|
||||
|
@ -32,9 +32,21 @@
|
||||
// We are controlled.
|
||||
// Register a new worker for this sub-scope. After that, controller should still be for upper level, but active should change to be this scope's.
|
||||
navigator.serviceWorker.register("../worker2.js", { scope: "./*" }).then(function(e) {
|
||||
my_ok(navigator.serviceWorker.installing &&
|
||||
navigator.serviceWorker.installing.scope.match(/controller\/\*$/),
|
||||
my_ok("installing" in e, "ServiceWorkerRegistration.installing exists.");
|
||||
my_ok(e.installing instanceof ServiceWorker, "ServiceWorkerRegistration.installing is a ServiceWorker.");
|
||||
|
||||
my_ok("waiting" in e, "ServiceWorkerRegistration.waiting exists.");
|
||||
my_ok("active" in e, "ServiceWorkerRegistration.active exists.");
|
||||
|
||||
my_ok(e.installing &&
|
||||
e.installing.scope.match(/controller\/\*$/),
|
||||
"Installing is serviceworker/controller/*");
|
||||
|
||||
my_ok("scope" in e, "ServiceWorkerRegistration.scope exists.");
|
||||
my_ok(e.scope.match(/serviceworkers\/controller\/\*$/), "Scope is serviceworker/*: " + e.scope);
|
||||
|
||||
my_ok("unregister" in e, "ServiceWorkerRegistration.unregister exists.");
|
||||
|
||||
my_ok(navigator.serviceWorker.controller.scope.match(/serviceworkers\/control\*$/),
|
||||
"Controller is still serviceworker/*");
|
||||
finish();
|
||||
|
@ -20,11 +20,11 @@
|
||||
return p;
|
||||
}
|
||||
|
||||
function nextRegister() {
|
||||
function nextRegister(reg) {
|
||||
var p = navigator.serviceWorker.register("install_event_worker.js", { scope: "./*" });
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
navigator.serviceWorker.onupdatefound = function(e) {
|
||||
reg.onupdatefound = function(e) {
|
||||
ok(true, "Received onupdatefound");
|
||||
resolve();
|
||||
};
|
||||
|
@ -57,11 +57,12 @@
|
||||
|
||||
function realWorker() {
|
||||
var p = navigator.serviceWorker.register("worker.js", { scope: "realworker*" });
|
||||
return p.then(function(w) {
|
||||
ok(w instanceof ServiceWorker, "Register a ServiceWorker");
|
||||
info(w.scope);
|
||||
ok(w.scope == (new URL("realworker*", document.baseURI)).href, "Scope should match");
|
||||
ok(w.url == (new URL("worker.js", document.baseURI)).href, "URL should be of the worker");
|
||||
return p.then(function(wr) {
|
||||
ok(wr instanceof ServiceWorkerRegistration, "Register a ServiceWorker");
|
||||
|
||||
info(wr.scope);
|
||||
ok(wr.scope == (new URL("realworker*", document.baseURI)).href, "Scope should match");
|
||||
|
||||
}, function(e) {
|
||||
info("Error: " + e.name);
|
||||
ok(false, "realWorker Registration should have succeeded!");
|
||||
@ -73,14 +74,14 @@
|
||||
var q = navigator.serviceWorker.register("worker3.js", { scope: "foo/*" });
|
||||
|
||||
return Promise.all([
|
||||
p.then(function(w) {
|
||||
p.then(function(wr) {
|
||||
ok(false, "First registration should fail with AbortError");
|
||||
}, function(e) {
|
||||
ok(e.name === "AbortError", "First registration should fail with AbortError");
|
||||
}),
|
||||
|
||||
q.then(function(w) {
|
||||
ok(w instanceof ServiceWorker, "Second registration should succeed");
|
||||
q.then(function(wr) {
|
||||
ok(wr instanceof ServiceWorkerRegistration, "Second registration should succeed");
|
||||
}, function(e) {
|
||||
ok(false, "Second registration should succeed");
|
||||
})
|
||||
@ -97,7 +98,7 @@
|
||||
|
||||
function parseError() {
|
||||
var p = navigator.serviceWorker.register("parse_error_worker.js");
|
||||
return p.then(function(w) {
|
||||
return p.then(function(wr) {
|
||||
ok(false, "Registration should fail with parse error");
|
||||
}, function(e) {
|
||||
info("NSM " + e.name);
|
||||
@ -107,6 +108,7 @@
|
||||
|
||||
// FIXME(nsm): test for parse error when Update step doesn't happen (directly from register).
|
||||
|
||||
/* FIXME bug 1002571 - re-enable this test when GetRegistration is implemented.
|
||||
function updatefound() {
|
||||
var frame = document.createElement("iframe");
|
||||
frame.setAttribute("id", "simpleregister-frame");
|
||||
@ -137,6 +139,7 @@
|
||||
}
|
||||
return p;
|
||||
}
|
||||
*/
|
||||
|
||||
function runTest() {
|
||||
simpleRegister()
|
||||
@ -147,7 +150,6 @@
|
||||
.then(abortPrevious)
|
||||
.then(networkError404)
|
||||
.then(parseError)
|
||||
.then(updatefound)
|
||||
// put more tests here.
|
||||
.then(function() {
|
||||
SimpleTest.finish();
|
||||
|
@ -18,12 +18,9 @@
|
||||
function checkEnabled() {
|
||||
ok(navigator.serviceWorker, "navigator.serviceWorker should exist when ServiceWorkers are enabled.");
|
||||
ok(typeof navigator.serviceWorker.register === "function", "navigator.serviceWorker.register() should be a function.");
|
||||
ok(typeof navigator.serviceWorker.unregister === "function", "navigator.serviceWorker.unregister() should be a function.");
|
||||
ok(typeof navigator.serviceWorker.getAll === "function", "navigator.serviceWorker.getAll() should be a function.");
|
||||
ok(typeof navigator.serviceWorker.getRegistration === "function", "navigator.serviceWorker.getAll() should be a function.");
|
||||
ok(typeof navigator.serviceWorker.getRegistrations === "function", "navigator.serviceWorker.getAll() should be a function.");
|
||||
ok(navigator.serviceWorker.ready instanceof Promise, "navigator.serviceWorker.ready should be a Promise.");
|
||||
ok(navigator.serviceWorker.installing === null, "There should be no installing worker for an uncontrolled scope.");
|
||||
ok(navigator.serviceWorker.waiting === null, "There should be no waiting worker for an uncontrolled scope.");
|
||||
// ok(navigator.serviceWorker.active === null, "There should be no active worker for an uncontrolled scope.");
|
||||
ok(navigator.serviceWorker.controller === null, "There should be no controller worker for an uncontrolled document.");
|
||||
}
|
||||
|
||||
|
@ -302,8 +302,7 @@ XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv)
|
||||
|
||||
WarnOnceAbout(nsIDocument::eUseOfDOM3LoadMethod);
|
||||
|
||||
nsCOMPtr<nsIDocument> callingDoc = nsContentUtils::GetDocumentFromContext();
|
||||
|
||||
nsCOMPtr<nsIDocument> callingDoc = GetEntryDocument();
|
||||
nsIURI *baseURI = mDocumentURI;
|
||||
nsAutoCString charset;
|
||||
|
||||
|
@ -65,6 +65,7 @@
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
/****************************************************************
|
||||
******************** nsWatcherWindowEntry **********************
|
||||
@ -886,7 +887,7 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> referrerWindow =
|
||||
do_QueryInterface(dom::BrokenGetEntryGlobal());
|
||||
do_QueryInterface(GetEntryGlobal());
|
||||
if (!referrerWindow) {
|
||||
referrerWindow = do_QueryInterface(aParent);
|
||||
}
|
||||
@ -1345,18 +1346,8 @@ nsWindowWatcher::URIfromURL(const char *aURL,
|
||||
nsIDOMWindow *aParent,
|
||||
nsIURI **aURI)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> baseWindow;
|
||||
|
||||
/* build the URI relative to the calling JS Context, if any.
|
||||
(note this is the same context used to make the security check
|
||||
in nsGlobalWindow.cpp.) */
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (cx) {
|
||||
nsIScriptContext *scriptcx = nsJSUtils::GetDynamicScriptContext(cx);
|
||||
if (scriptcx) {
|
||||
baseWindow = do_QueryInterface(scriptcx->GetGlobalObject());
|
||||
}
|
||||
}
|
||||
// Build the URI relative to the entry global.
|
||||
nsCOMPtr<nsIDOMWindow> baseWindow = do_QueryInterface(GetEntryGlobal());
|
||||
|
||||
// failing that, build it relative to the parent window, if possible
|
||||
if (!baseWindow)
|
||||
@ -1726,16 +1717,8 @@ nsWindowWatcher::FindItemWithName(const char16_t* aName,
|
||||
already_AddRefed<nsIDocShellTreeItem>
|
||||
nsWindowWatcher::GetCallerTreeItem(nsIDocShellTreeItem* aParentItem)
|
||||
{
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
nsCOMPtr<nsIDocShellTreeItem> callerItem;
|
||||
|
||||
if (cx) {
|
||||
nsCOMPtr<nsIWebNavigation> callerWebNav =
|
||||
do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
|
||||
|
||||
callerItem = do_QueryInterface(callerWebNav);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> callerWebNav = do_GetInterface(GetEntryGlobal());
|
||||
nsCOMPtr<nsIDocShellTreeItem> callerItem = do_QueryInterface(callerWebNav);
|
||||
if (!callerItem) {
|
||||
callerItem = aParentItem;
|
||||
}
|
||||
|
110
gfx/2d/BaseCoord.h
Normal file
110
gfx/2d/BaseCoord.h
Normal file
@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_BASECOORD_H_
|
||||
#define MOZILLA_GFX_BASECOORD_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
/**
|
||||
* Do not use this class directly. Subclass it, pass that subclass as the
|
||||
* Sub parameter, and only use that subclass. This allows methods to safely
|
||||
* cast 'this' to 'Sub*'.
|
||||
*/
|
||||
template <class T, class Sub>
|
||||
struct BaseCoord {
|
||||
T value;
|
||||
|
||||
// Constructors
|
||||
MOZ_CONSTEXPR BaseCoord() : value(0) {}
|
||||
explicit MOZ_CONSTEXPR BaseCoord(T aValue) : value(aValue) {}
|
||||
|
||||
// Note that '=' isn't defined so we'll get the
|
||||
// compiler generated default assignment operator
|
||||
|
||||
operator T() const { return value; }
|
||||
|
||||
friend bool operator==(Sub aA, Sub aB) {
|
||||
return aA.value == aB.value;
|
||||
}
|
||||
friend bool operator!=(Sub aA, Sub aB) {
|
||||
return aA.value != aB.value;
|
||||
}
|
||||
|
||||
friend Sub operator+(Sub aA, Sub aB) {
|
||||
return Sub(aA.value + aB.value);
|
||||
}
|
||||
friend Sub operator-(Sub aA, Sub aB) {
|
||||
return Sub(aA.value - aB.value);
|
||||
}
|
||||
friend Sub operator*(Sub aCoord, T aScale) {
|
||||
return Sub(aCoord.value * aScale);
|
||||
}
|
||||
friend Sub operator*(T aScale, Sub aCoord) {
|
||||
return Sub(aScale * aCoord.value);
|
||||
}
|
||||
friend Sub operator/(Sub aCoord, T aScale) {
|
||||
return Sub(aCoord.value / aScale);
|
||||
}
|
||||
// 'scale / coord' is intentionally omitted because it doesn't make sense.
|
||||
|
||||
Sub& operator+=(Sub aCoord) {
|
||||
value += aCoord.value;
|
||||
return *static_cast<Sub*>(this);
|
||||
}
|
||||
Sub& operator-=(Sub aCoord) {
|
||||
value -= aCoord.value;
|
||||
return *static_cast<Sub*>(this);
|
||||
}
|
||||
Sub& operator*=(T aScale) {
|
||||
value *= aScale;
|
||||
return *static_cast<Sub*>(this);
|
||||
}
|
||||
Sub& operator/=(T aScale) {
|
||||
value /= aScale;
|
||||
return *static_cast<Sub*>(this);
|
||||
}
|
||||
|
||||
// Since BaseCoord is implicitly convertible to its value type T, we need
|
||||
// mixed-type operator overloads to avoid ambiguities at mixed-type call
|
||||
// sites. As we transition more of our code to strongly-typed classes, we
|
||||
// may be able to remove some or all of these overloads.
|
||||
friend bool operator==(Sub aA, T aB) {
|
||||
return aA.value == aB;
|
||||
}
|
||||
friend bool operator==(T aA, Sub aB) {
|
||||
return aA == aB.value;
|
||||
}
|
||||
friend bool operator!=(Sub aA, T aB) {
|
||||
return aA.value != aB;
|
||||
}
|
||||
friend bool operator!=(T aA, Sub aB) {
|
||||
return aA != aB.value;
|
||||
}
|
||||
friend T operator+(Sub aA, T aB) {
|
||||
return aA.value + aB;
|
||||
}
|
||||
friend T operator+(T aA, Sub aB) {
|
||||
return aA + aB.value;
|
||||
}
|
||||
friend T operator-(Sub aA, T aB) {
|
||||
return aA.value - aB;
|
||||
}
|
||||
friend T operator-(T aA, Sub aB) {
|
||||
return aA - aB.value;
|
||||
}
|
||||
|
||||
Sub operator-() const {
|
||||
return Sub(-value);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_GFX_BASECOORD_H_ */
|
@ -17,13 +17,13 @@ namespace gfx {
|
||||
* Sub parameter, and only use that subclass. This allows methods to safely
|
||||
* cast 'this' to 'Sub*'.
|
||||
*/
|
||||
template <class T, class Sub>
|
||||
template <class T, class Sub, class Coord = T>
|
||||
struct BasePoint {
|
||||
T x, y;
|
||||
Coord x, y;
|
||||
|
||||
// Constructors
|
||||
MOZ_CONSTEXPR BasePoint() : x(0), y(0) {}
|
||||
MOZ_CONSTEXPR BasePoint(T aX, T aY) : x(aX), y(aY) {}
|
||||
MOZ_CONSTEXPR BasePoint(Coord aX, Coord aY) : x(aX), y(aY) {}
|
||||
|
||||
void MoveTo(T aX, T aY) { x = aX; y = aY; }
|
||||
void MoveBy(T aDx, T aDy) { x += aDx; y += aDy; }
|
||||
@ -67,15 +67,15 @@ struct BasePoint {
|
||||
}
|
||||
|
||||
T Length() const {
|
||||
return hypot(x, y);
|
||||
return hypot(x.value, y.value);
|
||||
}
|
||||
|
||||
// Round() is *not* rounding to nearest integer if the values are negative.
|
||||
// They are always rounding as floor(n + 0.5).
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=410748#c14
|
||||
Sub& Round() {
|
||||
x = static_cast<T>(floor(x + 0.5));
|
||||
y = static_cast<T>(floor(y + 0.5));
|
||||
x = Coord(floor(T(x) + T(0.5)));
|
||||
y = Coord(floor(T(y) + T(0.5)));
|
||||
return *static_cast<Sub*>(this);
|
||||
}
|
||||
|
||||
|
@ -734,8 +734,8 @@ static const Float GAUSSIAN_SCALE_FACTOR = Float((3 * sqrt(2 * M_PI) / 4) * 1.5)
|
||||
IntSize
|
||||
AlphaBoxBlur::CalculateBlurRadius(const Point& aStd)
|
||||
{
|
||||
IntSize size(static_cast<int32_t>(floor(aStd.x * GAUSSIAN_SCALE_FACTOR + 0.5)),
|
||||
static_cast<int32_t>(floor(aStd.y * GAUSSIAN_SCALE_FACTOR + 0.5)));
|
||||
IntSize size(static_cast<int32_t>(floor(aStd.x * GAUSSIAN_SCALE_FACTOR + 0.5f)),
|
||||
static_cast<int32_t>(floor(aStd.y * GAUSSIAN_SCALE_FACTOR + 0.5f)));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
142
gfx/2d/Coord.h
Normal file
142
gfx/2d/Coord.h
Normal file
@ -0,0 +1,142 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_COORD_H_
|
||||
#define MOZILLA_GFX_COORD_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "Types.h"
|
||||
#include "BaseCoord.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <typename> struct IsPixel;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
template <class units> struct IntCoordTyped;
|
||||
template <class units> struct CoordTyped;
|
||||
|
||||
// CommonType<coord, primitive> is a metafunction that returns the type of the
|
||||
// result of an arithmetic operation on the underlying type of a strongly-typed
|
||||
// coordinate type 'coord', and a primitive type 'primitive'. C++ rules for
|
||||
// arithmetic conversions are designed to avoid losing information - for
|
||||
// example, the result of adding an int and a float is a float - and we want
|
||||
// the same behaviour when mixing our coordinate types with primitive types.
|
||||
// We get C++ to compute the desired result type using 'decltype'.
|
||||
|
||||
template <class coord, class primitive>
|
||||
struct CommonType;
|
||||
|
||||
template <class units, class primitive>
|
||||
struct CommonType<IntCoordTyped<units>, primitive> {
|
||||
typedef decltype(int32_t() + primitive()) type;
|
||||
};
|
||||
|
||||
template <class units, class primitive>
|
||||
struct CommonType<CoordTyped<units>, primitive> {
|
||||
typedef decltype(Float() + primitive()) type;
|
||||
};
|
||||
|
||||
// This is a base class that provides mixed-type operator overloads between
|
||||
// a strongly-typed Coord and a primitive value. It is needed to avoid
|
||||
// ambiguities at mixed-type call sites, because Coord classes are implicitly
|
||||
// convertible to their underlying value type. As we transition more of our code
|
||||
// to strongly-typed classes, we may be able to remove some or all of these
|
||||
// overloads.
|
||||
template <class coord, class primitive>
|
||||
struct CoordOperatorsHelper {
|
||||
friend bool operator==(coord aA, primitive aB) {
|
||||
return aA.value == aB;
|
||||
}
|
||||
friend bool operator==(primitive aA, coord aB) {
|
||||
return aA == aB.value;
|
||||
}
|
||||
friend bool operator!=(coord aA, primitive aB) {
|
||||
return aA.value != aB;
|
||||
}
|
||||
friend bool operator!=(primitive aA, coord aB) {
|
||||
return aA != aB.value;
|
||||
}
|
||||
|
||||
typedef typename CommonType<coord, primitive>::type result_type;
|
||||
|
||||
friend result_type operator+(coord aA, primitive aB) {
|
||||
return aA.value + aB;
|
||||
}
|
||||
friend result_type operator+(primitive aA, coord aB) {
|
||||
return aA + aB.value;
|
||||
}
|
||||
friend result_type operator-(coord aA, primitive aB) {
|
||||
return aA.value - aB;
|
||||
}
|
||||
friend result_type operator-(primitive aA, coord aB) {
|
||||
return aA - aB.value;
|
||||
}
|
||||
friend result_type operator*(coord aCoord, primitive aScale) {
|
||||
return aCoord.value * aScale;
|
||||
}
|
||||
friend result_type operator*(primitive aScale, coord aCoord) {
|
||||
return aScale * aCoord.value;
|
||||
}
|
||||
friend result_type operator/(coord aCoord, primitive aScale) {
|
||||
return aCoord.value / aScale;
|
||||
}
|
||||
// 'scale / coord' is intentionally omitted because it doesn't make sense.
|
||||
};
|
||||
|
||||
// Note: 'IntCoordTyped<units>' and 'CoordTyped<units>' do not derive from
|
||||
// 'units' to work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61959.
|
||||
|
||||
template<class units>
|
||||
struct IntCoordTyped :
|
||||
public BaseCoord< int32_t, IntCoordTyped<units> >,
|
||||
public CoordOperatorsHelper< IntCoordTyped<units>, float >,
|
||||
public CoordOperatorsHelper< IntCoordTyped<units>, double > {
|
||||
static_assert(IsPixel<units>::value,
|
||||
"'units' must be a coordinate system tag");
|
||||
|
||||
typedef BaseCoord< int32_t, IntCoordTyped<units> > Super;
|
||||
|
||||
MOZ_CONSTEXPR IntCoordTyped() : Super() {}
|
||||
MOZ_CONSTEXPR IntCoordTyped(int32_t aValue) : Super(aValue) {}
|
||||
};
|
||||
|
||||
template<class units>
|
||||
struct CoordTyped :
|
||||
public BaseCoord< Float, CoordTyped<units> >,
|
||||
public CoordOperatorsHelper< CoordTyped<units>, int32_t >,
|
||||
public CoordOperatorsHelper< CoordTyped<units>, uint32_t >,
|
||||
public CoordOperatorsHelper< CoordTyped<units>, double > {
|
||||
static_assert(IsPixel<units>::value,
|
||||
"'units' must be a coordinate system tag");
|
||||
|
||||
typedef BaseCoord< Float, CoordTyped<units> > Super;
|
||||
|
||||
MOZ_CONSTEXPR CoordTyped() : Super() {}
|
||||
MOZ_CONSTEXPR CoordTyped(Float aValue) : Super(aValue) {}
|
||||
explicit MOZ_CONSTEXPR CoordTyped(const IntCoordTyped<units>& aCoord) : Super(float(aCoord.value)) {}
|
||||
|
||||
void Round() {
|
||||
this->value = floor(this->value + 0.5);
|
||||
}
|
||||
void Truncate() {
|
||||
this->value = int32_t(this->value);
|
||||
}
|
||||
|
||||
IntCoordTyped<units> Rounded() const {
|
||||
return IntCoordTyped<units>(int32_t(floor(this->value + 0.5)));
|
||||
}
|
||||
IntCoordTyped<units> Truncated() const {
|
||||
return IntCoordTyped<units>(int32_t(this->value));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_GFX_COORD_H_ */
|
@ -2599,7 +2599,7 @@ DrawTargetD2D::SetupEffectForRadialGradient(const RadialGradientPattern *aPatter
|
||||
mPrivateData->mEffect->GetVariableByName("DeviceSpaceToUserSpace")->
|
||||
AsMatrix()->SetMatrix(matrix);
|
||||
|
||||
float A = dc.x * dc.x + dc.y * dc.y - dr * dr;
|
||||
float A = dc.x.value * dc.x.value + dc.y.value * dc.y.value - dr * dr;
|
||||
|
||||
uint32_t offset = 0;
|
||||
switch (stops->mStopCollection->GetExtendMode()) {
|
||||
|
@ -35,8 +35,8 @@ DrawTargetTiled::Init(const TileSet& aTiles)
|
||||
mTiles[i].mTileOrigin.x + mTiles[i].mDrawTarget->GetSize().width);
|
||||
uint32_t newYMost = max(mRect.YMost(),
|
||||
mTiles[i].mTileOrigin.y + mTiles[i].mDrawTarget->GetSize().height);
|
||||
mRect.x = min(mRect.x, mTiles[i].mTileOrigin.x);
|
||||
mRect.y = min(mRect.y, mTiles[i].mTileOrigin.y);
|
||||
mRect.x = min(mRect.x, mTiles[i].mTileOrigin.x.value);
|
||||
mRect.y = min(mRect.y, mTiles[i].mTileOrigin.y.value);
|
||||
mRect.width = newXMost - mRect.x;
|
||||
mRect.height = newYMost - mRect.y;
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ static inline bool IsPatternSupportedByD2D(const Pattern &aPattern)
|
||||
|
||||
Point diff = pat->mCenter2 - pat->mCenter1;
|
||||
|
||||
if (sqrt(diff.x * diff.x + diff.y * diff.y) >= pat->mRadius2) {
|
||||
if (sqrt(diff.x.value * diff.x.value + diff.y.value * diff.y.value) >= pat->mRadius2) {
|
||||
// Inner point lies outside the circle.
|
||||
return false;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ FlattenedPath::QuadraticBezierTo(const Point &aCP1,
|
||||
const Point &aCP2)
|
||||
{
|
||||
MOZ_ASSERT(!mCalculatedLength);
|
||||
// We need to elevate the degree of this quadratic Bézier to cubic, so we're
|
||||
// We need to elevate the degree of this quadratic B<EFBFBD>zier to cubic, so we're
|
||||
// going to add an intermediate control point, and recompute control point 1.
|
||||
// The first and last control points remain the same.
|
||||
// This formula can be found on http://fontforge.sourceforge.net/bezier.html
|
||||
@ -250,7 +250,7 @@ FlattenBezierCurveSegment(const BezierControlPoints &aControlPoints,
|
||||
Point cp21 = currentCP.mCP2 - currentCP.mCP3;
|
||||
Point cp31 = currentCP.mCP3 - currentCP.mCP1;
|
||||
|
||||
Float s3 = (cp31.x * cp21.y - cp31.y * cp21.x) / hypotf(cp21.x, cp21.y);
|
||||
Float s3 = (cp31.x.value * cp21.y.value - cp31.y.value * cp21.x.value) / hypotf(cp21.x, cp21.y);
|
||||
|
||||
t = 2 * Float(sqrt(aTolerance / (3. * abs(s3))));
|
||||
|
||||
@ -276,7 +276,7 @@ FindInflectionApproximationRange(BezierControlPoints aControlPoints,
|
||||
Point cp21 = aControlPoints.mCP2 - aControlPoints.mCP1;
|
||||
Point cp41 = aControlPoints.mCP4 - aControlPoints.mCP1;
|
||||
|
||||
if (cp21.x == 0 && cp21.y == 0) {
|
||||
if (cp21.x == 0.f && cp21.y == 0.f) {
|
||||
// In this case s3 becomes lim[n->0] (cp41.x * n) / n - (cp41.y * n) / n = cp41.x - cp41.y.
|
||||
|
||||
// Use the absolute value so that Min and Max will correspond with the
|
||||
@ -286,7 +286,7 @@ FindInflectionApproximationRange(BezierControlPoints aControlPoints,
|
||||
return;
|
||||
}
|
||||
|
||||
Float s3 = (cp41.x * cp21.y - cp41.y * cp21.x) / hypotf(cp21.x, cp21.y);
|
||||
Float s3 = (cp41.x.value * cp21.y.value - cp41.y.value * cp21.x.value) / hypotf(cp21.x, cp21.y);
|
||||
|
||||
if (s3 == 0) {
|
||||
// This means within the precision we have it can be approximated
|
||||
|
@ -16,8 +16,8 @@ template <typename T>
|
||||
void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
||||
float aStartAngle, float aEndAngle, bool aAntiClockwise)
|
||||
{
|
||||
Point startPoint(aOrigin.x + cos(aStartAngle) * aRadius.width,
|
||||
aOrigin.y + sin(aStartAngle) * aRadius.height);
|
||||
Point startPoint(aOrigin.x + cosf(aStartAngle) * aRadius.width,
|
||||
aOrigin.y + sinf(aStartAngle) * aRadius.height);
|
||||
|
||||
aSink->LineTo(startPoint);
|
||||
|
||||
@ -56,10 +56,10 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
||||
currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection;
|
||||
}
|
||||
|
||||
Point currentStartPoint(aOrigin.x + cos(currentStartAngle) * aRadius.width,
|
||||
aOrigin.y + sin(currentStartAngle) * aRadius.height);
|
||||
Point currentEndPoint(aOrigin.x + cos(currentEndAngle) * aRadius.width,
|
||||
aOrigin.y + sin(currentEndAngle) * aRadius.height);
|
||||
Point currentStartPoint(aOrigin.x + cosf(currentStartAngle) * aRadius.width,
|
||||
aOrigin.y + sinf(currentStartAngle) * aRadius.height);
|
||||
Point currentEndPoint(aOrigin.x + cosf(currentEndAngle) * aRadius.width,
|
||||
aOrigin.y + sinf(currentEndAngle) * aRadius.height);
|
||||
|
||||
// Calculate kappa constant for partial curve. The sign of angle in the
|
||||
// tangent will actually ensure this is negative for a counter clockwise
|
||||
|
@ -141,10 +141,10 @@ PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
|
||||
}
|
||||
|
||||
SkRegion pointRect;
|
||||
pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1)),
|
||||
int32_t(SkFloatToScalar(transformed.y - 1)),
|
||||
int32_t(SkFloatToScalar(transformed.x + 1)),
|
||||
int32_t(SkFloatToScalar(transformed.y + 1)));
|
||||
pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1.f)),
|
||||
int32_t(SkFloatToScalar(transformed.y - 1.f)),
|
||||
int32_t(SkFloatToScalar(transformed.x + 1.f)),
|
||||
int32_t(SkFloatToScalar(transformed.y + 1.f)));
|
||||
|
||||
SkRegion pathRegion;
|
||||
|
||||
@ -174,10 +174,10 @@ PathSkia::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
|
||||
}
|
||||
|
||||
SkRegion pointRect;
|
||||
pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1)),
|
||||
int32_t(SkFloatToScalar(transformed.y - 1)),
|
||||
int32_t(SkFloatToScalar(transformed.x + 1)),
|
||||
int32_t(SkFloatToScalar(transformed.y + 1)));
|
||||
pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1.f)),
|
||||
int32_t(SkFloatToScalar(transformed.y - 1.f)),
|
||||
int32_t(SkFloatToScalar(transformed.x + 1.f)),
|
||||
int32_t(SkFloatToScalar(transformed.y + 1.f)));
|
||||
|
||||
SkRegion pathRegion;
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "Types.h"
|
||||
#include "Coord.h"
|
||||
#include "BaseCoord.h"
|
||||
#include "BasePoint.h"
|
||||
#include "BasePoint3D.h"
|
||||
#include "BasePoint4D.h"
|
||||
@ -33,15 +35,21 @@ namespace gfx {
|
||||
|
||||
template<class units>
|
||||
struct IntPointTyped :
|
||||
public BasePoint< int32_t, IntPointTyped<units> >,
|
||||
public BasePoint< int32_t, IntPointTyped<units>, IntCoordTyped<units> >,
|
||||
public units {
|
||||
static_assert(IsPixel<units>::value,
|
||||
"'units' must be a coordinate system tag");
|
||||
|
||||
typedef BasePoint< int32_t, IntPointTyped<units> > Super;
|
||||
typedef IntCoordTyped<units> Coord;
|
||||
typedef BasePoint< int32_t, IntPointTyped<units>, IntCoordTyped<units> > Super;
|
||||
|
||||
MOZ_CONSTEXPR IntPointTyped() : Super() {}
|
||||
MOZ_CONSTEXPR IntPointTyped(int32_t aX, int32_t aY) : Super(aX, aY) {}
|
||||
MOZ_CONSTEXPR IntPointTyped(int32_t aX, int32_t aY) : Super(Coord(aX), Coord(aY)) {}
|
||||
// The mixed-type constructors (int, Coord) and (Coord, int) are needed to
|
||||
// avoid ambiguities because Coord is implicitly convertible to int.
|
||||
MOZ_CONSTEXPR IntPointTyped(int32_t aX, Coord aY) : Super(Coord(aX), aY) {}
|
||||
MOZ_CONSTEXPR IntPointTyped(Coord aX, int32_t aY) : Super(aX, Coord(aY)) {}
|
||||
MOZ_CONSTEXPR IntPointTyped(Coord aX, Coord aY) : Super(aX, aY) {}
|
||||
|
||||
// XXX When all of the code is ported, the following functions to convert to and from
|
||||
// unknown types should be removed.
|
||||
@ -58,15 +66,21 @@ typedef IntPointTyped<UnknownUnits> IntPoint;
|
||||
|
||||
template<class units>
|
||||
struct PointTyped :
|
||||
public BasePoint< Float, PointTyped<units> >,
|
||||
public BasePoint< Float, PointTyped<units>, CoordTyped<units> >,
|
||||
public units {
|
||||
static_assert(IsPixel<units>::value,
|
||||
"'units' must be a coordinate system tag");
|
||||
|
||||
typedef BasePoint< Float, PointTyped<units> > Super;
|
||||
typedef CoordTyped<units> Coord;
|
||||
typedef BasePoint< Float, PointTyped<units>, CoordTyped<units> > Super;
|
||||
|
||||
MOZ_CONSTEXPR PointTyped() : Super() {}
|
||||
MOZ_CONSTEXPR PointTyped(Float aX, Float aY) : Super(aX, aY) {}
|
||||
MOZ_CONSTEXPR PointTyped(Float aX, Float aY) : Super(Coord(aX), Coord(aY)) {}
|
||||
// The mixed-type constructors (Float, Coord) and (Coord, Float) are needed to
|
||||
// avoid ambiguities because Coord is implicitly convertible to Float.
|
||||
MOZ_CONSTEXPR PointTyped(Float aX, Coord aY) : Super(Coord(aX), aY) {}
|
||||
MOZ_CONSTEXPR PointTyped(Coord aX, Float aY) : Super(aX, Coord(aY)) {}
|
||||
MOZ_CONSTEXPR PointTyped(Coord aX, Coord aY) : Super(aX.value, aY.value) {}
|
||||
MOZ_CONSTEXPR MOZ_IMPLICIT PointTyped(const IntPointTyped<units>& point) : Super(float(point.x), float(point.y)) {}
|
||||
|
||||
// XXX When all of the code is ported, the following functions to convert to and from
|
||||
@ -84,8 +98,14 @@ typedef PointTyped<UnknownUnits> Point;
|
||||
|
||||
template<class units>
|
||||
IntPointTyped<units> RoundedToInt(const PointTyped<units>& aPoint) {
|
||||
return IntPointTyped<units>(int32_t(floorf(aPoint.x + 0.5f)),
|
||||
int32_t(floorf(aPoint.y + 0.5f)));
|
||||
return IntPointTyped<units>(aPoint.x.Rounded(),
|
||||
aPoint.y.Rounded());
|
||||
}
|
||||
|
||||
template<class units>
|
||||
IntPointTyped<units> TruncatedToInt(const PointTyped<units>& aPoint) {
|
||||
return IntPointTyped<units>(aPoint.x.Truncated(),
|
||||
aPoint.y.Truncated());
|
||||
}
|
||||
|
||||
template<class units>
|
||||
|
@ -240,15 +240,15 @@ SVGTurbulenceRenderer<Type,Stitch,f32x4_t,i32x4_t,u8x16_t>::Noise2(Point aVec, c
|
||||
uint8_t i = mLatticeSelector[b0.x & sBM];
|
||||
uint8_t j = mLatticeSelector[b1.x & sBM];
|
||||
|
||||
const f32x4_t* qua = mGradient[(i + b0.y) & sBM];
|
||||
const f32x4_t* qub = mGradient[(i + b1.y) & sBM];
|
||||
const f32x4_t* qva = mGradient[(j + b0.y) & sBM];
|
||||
const f32x4_t* qvb = mGradient[(j + b1.y) & sBM];
|
||||
const f32x4_t* qua = mGradient[(i + b0.y.value) & sBM];
|
||||
const f32x4_t* qub = mGradient[(i + b1.y.value) & sBM];
|
||||
const f32x4_t* qva = mGradient[(j + b0.y.value) & sBM];
|
||||
const f32x4_t* qvb = mGradient[(j + b1.y.value) & sBM];
|
||||
|
||||
return BiMix(simd::WSumF32(qua[0], qua[1], r.x, r.y),
|
||||
simd::WSumF32(qva[0], qva[1], r.x - 1, r.y),
|
||||
simd::WSumF32(qub[0], qub[1], r.x, r.y - 1),
|
||||
simd::WSumF32(qvb[0], qvb[1], r.x - 1, r.y - 1),
|
||||
simd::WSumF32(qva[0], qva[1], r.x - 1.f, r.y),
|
||||
simd::WSumF32(qub[0], qub[1], r.x, r.y - 1.f),
|
||||
simd::WSumF32(qvb[0], qvb[1], r.x - 1.f, r.y - 1.f),
|
||||
SCurve(r));
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ EXPORTS.mozilla += [
|
||||
|
||||
EXPORTS.mozilla.gfx += [
|
||||
'2D.h',
|
||||
'BaseCoord.h',
|
||||
'BaseMargin.h',
|
||||
'BasePoint.h',
|
||||
'BasePoint3D.h',
|
||||
@ -18,6 +19,7 @@ EXPORTS.mozilla.gfx += [
|
||||
'BaseSize.h',
|
||||
'Blur.h',
|
||||
'BorrowedContext.h',
|
||||
'Coord.h',
|
||||
'DataSurfaceHelpers.h',
|
||||
'Filters.h',
|
||||
'Helpers.h',
|
||||
|
@ -26,8 +26,8 @@ TestPoint::Addition()
|
||||
|
||||
a += b;
|
||||
|
||||
VERIFY(a.x == 7);
|
||||
VERIFY(a.y == -3);
|
||||
VERIFY(a.x == 7.f);
|
||||
VERIFY(a.y == -3.f);
|
||||
}
|
||||
|
||||
void
|
||||
@ -41,6 +41,6 @@ TestPoint::Subtraction()
|
||||
|
||||
a -= b;
|
||||
|
||||
VERIFY(a.x == -3);
|
||||
VERIFY(a.y == 7);
|
||||
VERIFY(a.x == -3.f);
|
||||
VERIFY(a.y == 7.f);
|
||||
}
|
||||
|
@ -507,6 +507,38 @@ struct ParamTraits<nsIntSize>
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ParamTraits< mozilla::gfx::CoordTyped<T> >
|
||||
{
|
||||
typedef mozilla::gfx::CoordTyped<T> paramType;
|
||||
|
||||
static void Write(Message* msg, const paramType& param)
|
||||
{
|
||||
WriteParam(msg, param.value);
|
||||
}
|
||||
|
||||
static bool Read(const Message* msg, void** iter, paramType* result)
|
||||
{
|
||||
return (ReadParam(msg, iter, &result->value));
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ParamTraits< mozilla::gfx::IntCoordTyped<T> >
|
||||
{
|
||||
typedef mozilla::gfx::IntCoordTyped<T> paramType;
|
||||
|
||||
static void Write(Message* msg, const paramType& param)
|
||||
{
|
||||
WriteParam(msg, param.value);
|
||||
}
|
||||
|
||||
static bool Read(const Message* msg, void** iter, paramType* result)
|
||||
{
|
||||
return (ReadParam(msg, iter, &result->value));
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct ParamTraits< mozilla::gfx::ScaleFactor<T, U> >
|
||||
{
|
||||
|
@ -197,7 +197,7 @@ protected:
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(Compositor)
|
||||
|
||||
Compositor(PCompositorParent* aParent = nullptr)
|
||||
explicit Compositor(PCompositorParent* aParent = nullptr)
|
||||
: mCompositorID(0)
|
||||
, mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
|
||||
, mParent(aParent)
|
||||
|
@ -42,7 +42,7 @@ struct Effect
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(Effect)
|
||||
|
||||
Effect(EffectTypes aType) : mType(aType) {}
|
||||
explicit Effect(EffectTypes aType) : mType(aType) {}
|
||||
|
||||
EffectTypes mType;
|
||||
|
||||
@ -98,7 +98,7 @@ struct EffectMask : public Effect
|
||||
|
||||
struct EffectBlendMode : public Effect
|
||||
{
|
||||
EffectBlendMode(gfx::CompositionOp aBlendMode)
|
||||
explicit EffectBlendMode(gfx::CompositionOp aBlendMode)
|
||||
: Effect(EffectTypes::BLEND_MODE)
|
||||
, mBlendMode(aBlendMode)
|
||||
{ }
|
||||
@ -112,7 +112,7 @@ struct EffectBlendMode : public Effect
|
||||
// Render to a render target rather than the screen.
|
||||
struct EffectRenderTarget : public TexturedEffect
|
||||
{
|
||||
EffectRenderTarget(CompositingRenderTarget *aRenderTarget)
|
||||
explicit EffectRenderTarget(CompositingRenderTarget *aRenderTarget)
|
||||
: TexturedEffect(EffectTypes::RENDER_TARGET, aRenderTarget, true, gfx::Filter::LINEAR)
|
||||
, mRenderTarget(aRenderTarget)
|
||||
{}
|
||||
@ -183,7 +183,7 @@ struct EffectComponentAlpha : public TexturedEffect
|
||||
|
||||
struct EffectSolidColor : public Effect
|
||||
{
|
||||
EffectSolidColor(const gfx::Color &aColor)
|
||||
explicit EffectSolidColor(const gfx::Color &aColor)
|
||||
: Effect(EffectTypes::SOLID_COLOR)
|
||||
, mColor(aColor)
|
||||
{}
|
||||
|
@ -563,6 +563,22 @@ struct ScrollableLayerGuid {
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool operator<(const ScrollableLayerGuid& other) const
|
||||
{
|
||||
if (mLayersId < other.mLayersId) {
|
||||
return true;
|
||||
}
|
||||
if (mLayersId == other.mLayersId) {
|
||||
if (mPresShellId < other.mPresShellId) {
|
||||
return true;
|
||||
}
|
||||
if (mPresShellId == other.mPresShellId) {
|
||||
return mScrollId < other.mScrollId;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <int LogLevel>
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
*/
|
||||
class SurfaceReleaser : public nsRunnable {
|
||||
public:
|
||||
SurfaceReleaser(RawRef aRef) : mRef(aRef) {}
|
||||
explicit SurfaceReleaser(RawRef aRef) : mRef(aRef) {}
|
||||
NS_IMETHOD Run() {
|
||||
mRef->Release();
|
||||
return NS_OK;
|
||||
@ -350,7 +350,7 @@ public:
|
||||
|
||||
enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
|
||||
|
||||
ImageContainer(int flag = 0);
|
||||
explicit ImageContainer(int flag = 0);
|
||||
|
||||
/**
|
||||
* Create an Image in one of the given formats.
|
||||
@ -666,7 +666,7 @@ private:
|
||||
class AutoLockImage
|
||||
{
|
||||
public:
|
||||
AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
|
||||
explicit AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
|
||||
AutoLockImage(ImageContainer *aContainer, RefPtr<gfx::SourceSurface> *aSurface) : mContainer(aContainer) {
|
||||
*aSurface = mContainer->LockCurrentAsSourceSurface(&mSize, getter_AddRefs(mImage));
|
||||
}
|
||||
@ -821,7 +821,7 @@ public:
|
||||
|
||||
virtual gfx::IntSize GetSize() { return mSize; }
|
||||
|
||||
PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
|
||||
explicit PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
|
||||
|
||||
virtual SharedPlanarYCbCrImage *AsSharedPlanarYCbCrImage() { return nullptr; }
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user